package ast
import
type Visitor interface {
Visit(node Node) (w Visitor)
}
func ( Visitor, []*Ident) {
for , := range {
Walk(, )
}
}
func ( Visitor, []Expr) {
for , := range {
Walk(, )
}
}
func ( Visitor, []Stmt) {
for , := range {
Walk(, )
}
}
func ( Visitor, []Decl) {
for , := range {
Walk(, )
}
}
func ( Visitor, Node) {
if = .Visit(); == nil {
return
}
switch n := .(type) {
case *Comment:
case *CommentGroup:
for , := range .List {
(, )
}
case *Field:
if .Doc != nil {
(, .Doc)
}
walkIdentList(, .Names)
if .Type != nil {
(, .Type)
}
if .Tag != nil {
(, .Tag)
}
if .Comment != nil {
(, .Comment)
}
case *FieldList:
for , := range .List {
(, )
}
case *BadExpr, *Ident, *BasicLit:
case *Ellipsis:
if .Elt != nil {
(, .Elt)
}
case *FuncLit:
(, .Type)
(, .Body)
case *CompositeLit:
if .Type != nil {
(, .Type)
}
walkExprList(, .Elts)
case *ParenExpr:
(, .X)
case *SelectorExpr:
(, .X)
(, .Sel)
case *IndexExpr:
(, .X)
(, .Index)
case *IndexListExpr:
(, .X)
for , := range .Indices {
(, )
}
case *SliceExpr:
(, .X)
if .Low != nil {
(, .Low)
}
if .High != nil {
(, .High)
}
if .Max != nil {
(, .Max)
}
case *TypeAssertExpr:
(, .X)
if .Type != nil {
(, .Type)
}
case *CallExpr:
(, .Fun)
walkExprList(, .Args)
case *StarExpr:
(, .X)
case *UnaryExpr:
(, .X)
case *BinaryExpr:
(, .X)
(, .Y)
case *KeyValueExpr:
(, .Key)
(, .Value)
case *ArrayType:
if .Len != nil {
(, .Len)
}
(, .Elt)
case *StructType:
(, .Fields)
case *FuncType:
if .TypeParams != nil {
(, .TypeParams)
}
if .Params != nil {
(, .Params)
}
if .Results != nil {
(, .Results)
}
case *InterfaceType:
(, .Methods)
case *MapType:
(, .Key)
(, .Value)
case *ChanType:
(, .Value)
case *BadStmt:
case *DeclStmt:
(, .Decl)
case *EmptyStmt:
case *LabeledStmt:
(, .Label)
(, .Stmt)
case *ExprStmt:
(, .X)
case *SendStmt:
(, .Chan)
(, .Value)
case *IncDecStmt:
(, .X)
case *AssignStmt:
walkExprList(, .Lhs)
walkExprList(, .Rhs)
case *GoStmt:
(, .Call)
case *DeferStmt:
(, .Call)
case *ReturnStmt:
walkExprList(, .Results)
case *BranchStmt:
if .Label != nil {
(, .Label)
}
case *BlockStmt:
walkStmtList(, .List)
case *IfStmt:
if .Init != nil {
(, .Init)
}
(, .Cond)
(, .Body)
if .Else != nil {
(, .Else)
}
case *CaseClause:
walkExprList(, .List)
walkStmtList(, .Body)
case *SwitchStmt:
if .Init != nil {
(, .Init)
}
if .Tag != nil {
(, .Tag)
}
(, .Body)
case *TypeSwitchStmt:
if .Init != nil {
(, .Init)
}
(, .Assign)
(, .Body)
case *CommClause:
if .Comm != nil {
(, .Comm)
}
walkStmtList(, .Body)
case *SelectStmt:
(, .Body)
case *ForStmt:
if .Init != nil {
(, .Init)
}
if .Cond != nil {
(, .Cond)
}
if .Post != nil {
(, .Post)
}
(, .Body)
case *RangeStmt:
if .Key != nil {
(, .Key)
}
if .Value != nil {
(, .Value)
}
(, .X)
(, .Body)
case *ImportSpec:
if .Doc != nil {
(, .Doc)
}
if .Name != nil {
(, .Name)
}
(, .Path)
if .Comment != nil {
(, .Comment)
}
case *ValueSpec:
if .Doc != nil {
(, .Doc)
}
walkIdentList(, .Names)
if .Type != nil {
(, .Type)
}
walkExprList(, .Values)
if .Comment != nil {
(, .Comment)
}
case *TypeSpec:
if .Doc != nil {
(, .Doc)
}
(, .Name)
if .TypeParams != nil {
(, .TypeParams)
}
(, .Type)
if .Comment != nil {
(, .Comment)
}
case *BadDecl:
case *GenDecl:
if .Doc != nil {
(, .Doc)
}
for , := range .Specs {
(, )
}
case *FuncDecl:
if .Doc != nil {
(, .Doc)
}
if .Recv != nil {
(, .Recv)
}
(, .Name)
(, .Type)
if .Body != nil {
(, .Body)
}
case *File:
if .Doc != nil {
(, .Doc)
}
(, .Name)
walkDeclList(, .Decls)
case *Package:
for , := range .Files {
(, )
}
default:
panic(fmt.Sprintf("ast.Walk: unexpected node type %T", ))
}
.Visit(nil)
}
type inspector func(Node) bool
func ( inspector) ( Node) Visitor {
if () {
return
}
return nil
}
func ( Node, func(Node) bool) {
Walk(inspector(), )
}