func walkIdentList(v Visitor, list []*Ident) {
for _, x := range list {
- walk(v, x);
+ Walk(v, x);
}
}
func walkExprList(v Visitor, list []Expr) {
for _, x := range list {
- walk(v, x);
+ Walk(v, x);
}
}
func walkStmtList(v Visitor, list []Stmt) {
for _, s := range list {
- walk(v, s);
+ Walk(v, s);
}
}
}
-func walk(v Visitor, n Node) {
- if n != nil {
- Walk(v, n);
- }
-}
-
-
-// Walk recursively traverses an AST invokes v.Visit(n) for each
-// node n encountered (starting with node). If v.Visit(n) returns
-// true, Walk is invoked for each of the children of n.
+// Walk traverses an AST in depth-first order and invokes v.Visit(n) for each
+// non-nil node n encountered, starting with node. If v.Visit(n) returns true,
+// Walk visits each of the children of n.
//
func Walk(v Visitor, node interface{}) {
- if !v.Visit(node) {
+ if node != nil && !v.Visit(node) {
return;
}
case *Field:
walkCommentGroup(v, n.Doc);
walkIdentList(v, n.Names);
- walk(v, n.Type);
+ Walk(v, n.Type);
for _, x := range n.Tag {
Walk(v, x);
}
}
case *FuncLit:
- walk(v, n.Type);
+ Walk(v, n.Type);
walkBlockStmt(v, n.Body);
case *CompositeLit:
- walk(v, n.Type);
+ Walk(v, n.Type);
walkExprList(v, n.Elts);
case *ParenExpr:
- walk(v, n.X);
+ Walk(v, n.X);
case *SelectorExpr:
- walk(v, n.X);
+ Walk(v, n.X);
if n.Sel != nil {
Walk(v, n.Sel);
}
case *IndexExpr:
- walk(v, n.X);
- walk(v, n.Index);
- walk(v, n.End);
+ Walk(v, n.X);
+ Walk(v, n.Index);
+ Walk(v, n.End);
case *TypeAssertExpr:
- walk(v, n.X);
- walk(v, n.Type);
+ Walk(v, n.X);
+ Walk(v, n.Type);
case *CallExpr:
- walk(v, n.Fun);
+ Walk(v, n.Fun);
walkExprList(v, n.Args);
case *StarExpr:
- walk(v, n.X);
+ Walk(v, n.X);
case *UnaryExpr:
- walk(v, n.X);
+ Walk(v, n.X);
case *BinaryExpr:
- walk(v, n.X);
- walk(v, n.Y);
+ Walk(v, n.X);
+ Walk(v, n.Y);
case *KeyValueExpr:
- walk(v, n.Key);
- walk(v, n.Value);
+ Walk(v, n.Key);
+ Walk(v, n.Value);
// Types
case *ArrayType:
- walk(v, n.Len);
- walk(v, n.Elt);
+ Walk(v, n.Len);
+ Walk(v, n.Elt);
case *StructType:
walkFieldList(v, n.Fields);
walkFieldList(v, n.Methods);
case *MapType:
- walk(v, n.Key);
- walk(v, n.Value);
+ Walk(v, n.Key);
+ Walk(v, n.Value);
case *ChanType:
- walk(v, n.Value);
+ Walk(v, n.Value);
// Statements
case *DeclStmt:
- walk(v, n.Decl);
+ Walk(v, n.Decl);
case *LabeledStmt:
walkIdent(v, n.Label);
- walk(v, n.Stmt);
+ Walk(v, n.Stmt);
case *ExprStmt:
- walk(v, n.X);
+ Walk(v, n.X);
case *IncDecStmt:
- walk(v, n.X);
+ Walk(v, n.X);
case *AssignStmt:
walkExprList(v, n.Lhs);
walkStmtList(v, n.List);
case *IfStmt:
- walk(v, n.Init);
- walk(v, n.Cond);
+ Walk(v, n.Init);
+ Walk(v, n.Cond);
walkBlockStmt(v, n.Body);
- walk(v, n.Else);
+ Walk(v, n.Else);
case *CaseClause:
walkExprList(v, n.Values);
walkStmtList(v, n.Body);
case *SwitchStmt:
- walk(v, n.Init);
- walk(v, n.Tag);
+ Walk(v, n.Init);
+ Walk(v, n.Tag);
walkBlockStmt(v, n.Body);
case *TypeCaseClause:
walkStmtList(v, n.Body);
case *TypeSwitchStmt:
- walk(v, n.Init);
- walk(v, n.Assign);
+ Walk(v, n.Init);
+ Walk(v, n.Assign);
walkBlockStmt(v, n.Body);
case *CommClause:
- walk(v, n.Lhs);
- walk(v, n.Rhs);
+ Walk(v, n.Lhs);
+ Walk(v, n.Rhs);
walkStmtList(v, n.Body);
case *SelectStmt:
walkBlockStmt(v, n.Body);
case *ForStmt:
- walk(v, n.Init);
- walk(v, n.Cond);
- walk(v, n.Post);
+ Walk(v, n.Init);
+ Walk(v, n.Cond);
+ Walk(v, n.Post);
walkBlockStmt(v, n.Body);
case *RangeStmt:
- walk(v, n.Key);
- walk(v, n.Value);
- walk(v, n.X);
+ Walk(v, n.Key);
+ Walk(v, n.Value);
+ Walk(v, n.X);
walkBlockStmt(v, n.Body);
// Declarations
case *ValueSpec:
walkCommentGroup(v, n.Doc);
walkIdentList(v, n.Names);
- walk(v, n.Type);
+ Walk(v, n.Type);
walkExprList(v, n.Values);
walkCommentGroup(v, n.Comment);
case *TypeSpec:
walkCommentGroup(v, n.Doc);
walkIdent(v, n.Name);
- walk(v, n.Type);
+ Walk(v, n.Type);
walkCommentGroup(v, n.Comment);
case *GenDecl:
Walk(v, n.Recv);
}
walkIdent(v, n.Name);
- walk(v, n.Type);
+ Walk(v, n.Type);
walkBlockStmt(v, n.Body);
// Files and packages
walkCommentGroup(v, n.Doc);
walkIdent(v, n.Name);
for _, d := range n.Decls {
- walk(v, d);
+ Walk(v, d);
}
walkCommentGroup(v, n.Comments);