github.com/kubevela/workflow@v0.6.0/pkg/cue/model/sets/walk.go (about) 1 /* 2 Copyright 2022 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sets 18 19 import ( 20 "strconv" 21 "strings" 22 23 "cuelang.org/go/cue/ast" 24 "cuelang.org/go/cue/token" 25 ) 26 27 type nodewalker struct { 28 pos []string 29 tags map[string]string 30 process walkProcess 31 } 32 33 type walkCtx interface { 34 Pos() []string 35 Tags() map[string]string 36 } 37 38 type walkProcess func(node ast.Node, ctx walkCtx) 39 40 func newWalker(process walkProcess) *nodewalker { 41 return &nodewalker{ 42 pos: []string{}, 43 process: process, 44 tags: map[string]string{}, 45 } 46 } 47 48 func (nwk *nodewalker) walk(node ast.Node) { 49 if nwk.process != nil { 50 nwk.process(node, nwk) 51 } 52 switch n := node.(type) { 53 54 case *ast.Field: 55 label := LabelStr(n.Label) 56 if label == "" || strings.HasPrefix(label, "#") { 57 return 58 } 59 if n.Value != nil { 60 origin := nwk.pos 61 oriTags := nwk.tags 62 nwk.tags = map[string]string{} 63 for k, v := range oriTags { 64 nwk.tags[k] = v 65 } 66 nwk.pos = append(nwk.pos, LabelStr(n.Label)) 67 tags := findCommentTag(n.Comments()) 68 for tk, tv := range tags { 69 nwk.tags[tk] = tv 70 } 71 72 nwk.walk(n.Value) 73 nwk.tags = oriTags 74 nwk.pos = origin 75 } 76 77 case *ast.StructLit: 78 nwk.walkDeclList(n.Elts) 79 80 case *ast.ListLit: 81 nwk.walkExprList(n.Elts) 82 83 case *ast.BinaryExpr: 84 nwk.walk(n.X) 85 nwk.walk(n.Y) 86 87 case *ast.UnaryExpr: 88 nwk.walk(n.X) 89 90 case *ast.EmbedDecl: 91 nwk.walk(n.Expr) 92 93 case *ast.Comprehension: 94 nwk.walk(n.Value) 95 96 // Files 97 case *ast.File: 98 nwk.walkDeclList(n.Decls) 99 100 case *ast.SliceExpr: 101 if list, ok := n.X.(*ast.ListLit); ok { 102 nwk.walkExprSlice(list.Elts, n.Low, n.High) 103 } 104 105 case *ast.CallExpr: 106 // close func need to be ignored 107 if it, ok := n.Fun.(*ast.Ident); ok && it.Name == "close" && len(n.Args) == 1 { 108 nwk.walk(n.Args[0]) 109 } else { 110 nwk.walkExprList(n.Args) 111 } 112 113 default: 114 115 } 116 117 } 118 119 func (nwk *nodewalker) walkExprList(list []ast.Expr) { 120 for i, x := range list { 121 origin := nwk.pos 122 nwk.pos = append(nwk.pos, strconv.Itoa(i)) 123 nwk.walk(x) 124 nwk.pos = origin 125 } 126 } 127 128 func (nwk *nodewalker) walkExprSlice(list []ast.Expr, low ast.Expr, high ast.Expr) { 129 var ( 130 lowIndex = 0 131 highIndex = len(list) 132 ) 133 if v, ok := low.(*ast.BasicLit); ok && v.Kind == token.INT { 134 lowIndex, _ = strconv.Atoi(v.Value) 135 } 136 if v, ok := high.(*ast.BasicLit); ok && v.Kind == token.INT { 137 highIndex, _ = strconv.Atoi(v.Value) 138 } 139 for i, x := range list { 140 if i < lowIndex || i >= highIndex { 141 continue 142 } 143 origin := nwk.pos 144 nwk.pos = append(nwk.pos, strconv.Itoa(i-lowIndex)) 145 nwk.walk(x) 146 nwk.pos = origin 147 } 148 } 149 150 func (nwk *nodewalker) walkDeclList(list []ast.Decl) { 151 for _, x := range list { 152 nwk.walk(x) 153 } 154 } 155 156 func (nwk *nodewalker) Pos() []string { 157 return nwk.pos 158 } 159 160 func (nwk *nodewalker) Tags() map[string]string { 161 return nwk.tags 162 }