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  }