mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	* Changes to make vendored packages accept new home. * Fix go2idl to import vendored packages.
		
			
				
	
	
		
			387 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2009 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package ast
 | |
| 
 | |
| import "fmt"
 | |
| 
 | |
| // A Visitor's Visit method is invoked for each node encountered by Walk.
 | |
| // If the result visitor w is not nil, Walk visits each of the children
 | |
| // of node with the visitor w, followed by a call of w.Visit(nil).
 | |
| type Visitor interface {
 | |
| 	Visit(node Node) (w Visitor)
 | |
| }
 | |
| 
 | |
| // Helper functions for common node lists. They may be empty.
 | |
| 
 | |
| func walkIdentList(v Visitor, list []*Ident) {
 | |
| 	for _, x := range list {
 | |
| 		Walk(v, x)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func walkExprList(v Visitor, list []Expr) {
 | |
| 	for _, x := range list {
 | |
| 		Walk(v, x)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func walkStmtList(v Visitor, list []Stmt) {
 | |
| 	for _, x := range list {
 | |
| 		Walk(v, x)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func walkDeclList(v Visitor, list []Decl) {
 | |
| 	for _, x := range list {
 | |
| 		Walk(v, x)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // TODO(gri): Investigate if providing a closure to Walk leads to
 | |
| //            simpler use (and may help eliminate Inspect in turn).
 | |
| 
 | |
| // Walk traverses an AST in depth-first order: It starts by calling
 | |
| // v.Visit(node); node must not be nil. If the visitor w returned by
 | |
| // v.Visit(node) is not nil, Walk is invoked recursively with visitor
 | |
| // w for each of the non-nil children of node, followed by a call of
 | |
| // w.Visit(nil).
 | |
| //
 | |
| func Walk(v Visitor, node Node) {
 | |
| 	if v = v.Visit(node); v == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// walk children
 | |
| 	// (the order of the cases matches the order
 | |
| 	// of the corresponding node types in ast.go)
 | |
| 	switch n := node.(type) {
 | |
| 	// Comments and fields
 | |
| 	case *Comment:
 | |
| 		// nothing to do
 | |
| 
 | |
| 	case *CommentGroup:
 | |
| 		for _, c := range n.List {
 | |
| 			Walk(v, c)
 | |
| 		}
 | |
| 
 | |
| 	case *Field:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		walkIdentList(v, n.Names)
 | |
| 		Walk(v, n.Type)
 | |
| 		if n.Tag != nil {
 | |
| 			Walk(v, n.Tag)
 | |
| 		}
 | |
| 		if n.Comment != nil {
 | |
| 			Walk(v, n.Comment)
 | |
| 		}
 | |
| 
 | |
| 	case *FieldList:
 | |
| 		for _, f := range n.List {
 | |
| 			Walk(v, f)
 | |
| 		}
 | |
| 
 | |
| 	// Expressions
 | |
| 	case *BadExpr, *Ident, *BasicLit:
 | |
| 		// nothing to do
 | |
| 
 | |
| 	case *Ellipsis:
 | |
| 		if n.Elt != nil {
 | |
| 			Walk(v, n.Elt)
 | |
| 		}
 | |
| 
 | |
| 	case *FuncLit:
 | |
| 		Walk(v, n.Type)
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	case *CompositeLit:
 | |
| 		if n.Type != nil {
 | |
| 			Walk(v, n.Type)
 | |
| 		}
 | |
| 		walkExprList(v, n.Elts)
 | |
| 
 | |
| 	case *ParenExpr:
 | |
| 		Walk(v, n.X)
 | |
| 
 | |
| 	case *SelectorExpr:
 | |
| 		Walk(v, n.X)
 | |
| 		Walk(v, n.Sel)
 | |
| 
 | |
| 	case *IndexExpr:
 | |
| 		Walk(v, n.X)
 | |
| 		Walk(v, n.Index)
 | |
| 
 | |
| 	case *SliceExpr:
 | |
| 		Walk(v, n.X)
 | |
| 		if n.Low != nil {
 | |
| 			Walk(v, n.Low)
 | |
| 		}
 | |
| 		if n.High != nil {
 | |
| 			Walk(v, n.High)
 | |
| 		}
 | |
| 		if n.Max != nil {
 | |
| 			Walk(v, n.Max)
 | |
| 		}
 | |
| 
 | |
| 	case *TypeAssertExpr:
 | |
| 		Walk(v, n.X)
 | |
| 		if n.Type != nil {
 | |
| 			Walk(v, n.Type)
 | |
| 		}
 | |
| 
 | |
| 	case *CallExpr:
 | |
| 		Walk(v, n.Fun)
 | |
| 		walkExprList(v, n.Args)
 | |
| 
 | |
| 	case *StarExpr:
 | |
| 		Walk(v, n.X)
 | |
| 
 | |
| 	case *UnaryExpr:
 | |
| 		Walk(v, n.X)
 | |
| 
 | |
| 	case *BinaryExpr:
 | |
| 		Walk(v, n.X)
 | |
| 		Walk(v, n.Y)
 | |
| 
 | |
| 	case *KeyValueExpr:
 | |
| 		Walk(v, n.Key)
 | |
| 		Walk(v, n.Value)
 | |
| 
 | |
| 	// Types
 | |
| 	case *ArrayType:
 | |
| 		if n.Len != nil {
 | |
| 			Walk(v, n.Len)
 | |
| 		}
 | |
| 		Walk(v, n.Elt)
 | |
| 
 | |
| 	case *StructType:
 | |
| 		Walk(v, n.Fields)
 | |
| 
 | |
| 	case *FuncType:
 | |
| 		if n.Params != nil {
 | |
| 			Walk(v, n.Params)
 | |
| 		}
 | |
| 		if n.Results != nil {
 | |
| 			Walk(v, n.Results)
 | |
| 		}
 | |
| 
 | |
| 	case *InterfaceType:
 | |
| 		Walk(v, n.Methods)
 | |
| 
 | |
| 	case *MapType:
 | |
| 		Walk(v, n.Key)
 | |
| 		Walk(v, n.Value)
 | |
| 
 | |
| 	case *ChanType:
 | |
| 		Walk(v, n.Value)
 | |
| 
 | |
| 	// Statements
 | |
| 	case *BadStmt:
 | |
| 		// nothing to do
 | |
| 
 | |
| 	case *DeclStmt:
 | |
| 		Walk(v, n.Decl)
 | |
| 
 | |
| 	case *EmptyStmt:
 | |
| 		// nothing to do
 | |
| 
 | |
| 	case *LabeledStmt:
 | |
| 		Walk(v, n.Label)
 | |
| 		Walk(v, n.Stmt)
 | |
| 
 | |
| 	case *ExprStmt:
 | |
| 		Walk(v, n.X)
 | |
| 
 | |
| 	case *SendStmt:
 | |
| 		Walk(v, n.Chan)
 | |
| 		Walk(v, n.Value)
 | |
| 
 | |
| 	case *IncDecStmt:
 | |
| 		Walk(v, n.X)
 | |
| 
 | |
| 	case *AssignStmt:
 | |
| 		walkExprList(v, n.Lhs)
 | |
| 		walkExprList(v, n.Rhs)
 | |
| 
 | |
| 	case *GoStmt:
 | |
| 		Walk(v, n.Call)
 | |
| 
 | |
| 	case *DeferStmt:
 | |
| 		Walk(v, n.Call)
 | |
| 
 | |
| 	case *ReturnStmt:
 | |
| 		walkExprList(v, n.Results)
 | |
| 
 | |
| 	case *BranchStmt:
 | |
| 		if n.Label != nil {
 | |
| 			Walk(v, n.Label)
 | |
| 		}
 | |
| 
 | |
| 	case *BlockStmt:
 | |
| 		walkStmtList(v, n.List)
 | |
| 
 | |
| 	case *IfStmt:
 | |
| 		if n.Init != nil {
 | |
| 			Walk(v, n.Init)
 | |
| 		}
 | |
| 		Walk(v, n.Cond)
 | |
| 		Walk(v, n.Body)
 | |
| 		if n.Else != nil {
 | |
| 			Walk(v, n.Else)
 | |
| 		}
 | |
| 
 | |
| 	case *CaseClause:
 | |
| 		walkExprList(v, n.List)
 | |
| 		walkStmtList(v, n.Body)
 | |
| 
 | |
| 	case *SwitchStmt:
 | |
| 		if n.Init != nil {
 | |
| 			Walk(v, n.Init)
 | |
| 		}
 | |
| 		if n.Tag != nil {
 | |
| 			Walk(v, n.Tag)
 | |
| 		}
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	case *TypeSwitchStmt:
 | |
| 		if n.Init != nil {
 | |
| 			Walk(v, n.Init)
 | |
| 		}
 | |
| 		Walk(v, n.Assign)
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	case *CommClause:
 | |
| 		if n.Comm != nil {
 | |
| 			Walk(v, n.Comm)
 | |
| 		}
 | |
| 		walkStmtList(v, n.Body)
 | |
| 
 | |
| 	case *SelectStmt:
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	case *ForStmt:
 | |
| 		if n.Init != nil {
 | |
| 			Walk(v, n.Init)
 | |
| 		}
 | |
| 		if n.Cond != nil {
 | |
| 			Walk(v, n.Cond)
 | |
| 		}
 | |
| 		if n.Post != nil {
 | |
| 			Walk(v, n.Post)
 | |
| 		}
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	case *RangeStmt:
 | |
| 		if n.Key != nil {
 | |
| 			Walk(v, n.Key)
 | |
| 		}
 | |
| 		if n.Value != nil {
 | |
| 			Walk(v, n.Value)
 | |
| 		}
 | |
| 		Walk(v, n.X)
 | |
| 		Walk(v, n.Body)
 | |
| 
 | |
| 	// Declarations
 | |
| 	case *ImportSpec:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		if n.Name != nil {
 | |
| 			Walk(v, n.Name)
 | |
| 		}
 | |
| 		Walk(v, n.Path)
 | |
| 		if n.Comment != nil {
 | |
| 			Walk(v, n.Comment)
 | |
| 		}
 | |
| 
 | |
| 	case *ValueSpec:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		walkIdentList(v, n.Names)
 | |
| 		if n.Type != nil {
 | |
| 			Walk(v, n.Type)
 | |
| 		}
 | |
| 		walkExprList(v, n.Values)
 | |
| 		if n.Comment != nil {
 | |
| 			Walk(v, n.Comment)
 | |
| 		}
 | |
| 
 | |
| 	case *TypeSpec:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		Walk(v, n.Name)
 | |
| 		Walk(v, n.Type)
 | |
| 		if n.Comment != nil {
 | |
| 			Walk(v, n.Comment)
 | |
| 		}
 | |
| 
 | |
| 	case *BadDecl:
 | |
| 		// nothing to do
 | |
| 
 | |
| 	case *GenDecl:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		for _, s := range n.Specs {
 | |
| 			Walk(v, s)
 | |
| 		}
 | |
| 
 | |
| 	case *FuncDecl:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		if n.Recv != nil {
 | |
| 			Walk(v, n.Recv)
 | |
| 		}
 | |
| 		Walk(v, n.Name)
 | |
| 		Walk(v, n.Type)
 | |
| 		if n.Body != nil {
 | |
| 			Walk(v, n.Body)
 | |
| 		}
 | |
| 
 | |
| 	// Files and packages
 | |
| 	case *File:
 | |
| 		if n.Doc != nil {
 | |
| 			Walk(v, n.Doc)
 | |
| 		}
 | |
| 		Walk(v, n.Name)
 | |
| 		walkDeclList(v, n.Decls)
 | |
| 		// don't walk n.Comments - they have been
 | |
| 		// visited already through the individual
 | |
| 		// nodes
 | |
| 
 | |
| 	case *Package:
 | |
| 		for _, f := range n.Files {
 | |
| 			Walk(v, f)
 | |
| 		}
 | |
| 
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
 | |
| 	}
 | |
| 
 | |
| 	v.Visit(nil)
 | |
| }
 | |
| 
 | |
| type inspector func(Node) bool
 | |
| 
 | |
| func (f inspector) Visit(node Node) Visitor {
 | |
| 	if f(node) {
 | |
| 		return f
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Inspect traverses an AST in depth-first order: It starts by calling
 | |
| // f(node); node must not be nil. If f returns true, Inspect invokes f
 | |
| // recursively for each of the non-nil children of node, followed by a
 | |
| // call of f(nil).
 | |
| //
 | |
| func Inspect(node Node, f func(Node) bool) {
 | |
| 	Walk(inspector(f), node)
 | |
| }
 |