| | |
| | |
| | |
| |
|
| | |
| |
|
| | package syntax |
| |
|
| | import "fmt" |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func Inspect(root Node, f func(Node) bool) { |
| | Walk(root, inspector(f)) |
| | } |
| |
|
| | type inspector func(Node) bool |
| |
|
| | func (v inspector) Visit(node Node) Visitor { |
| | if v(node) { |
| | return v |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func Walk(root Node, v Visitor) { |
| | walker{v}.node(root) |
| | } |
| |
|
| | |
| | |
| | |
| | type Visitor interface { |
| | Visit(node Node) (w Visitor) |
| | } |
| |
|
| | type walker struct { |
| | v Visitor |
| | } |
| |
|
| | func (w walker) node(n Node) { |
| | if n == nil { |
| | panic("nil node") |
| | } |
| |
|
| | w.v = w.v.Visit(n) |
| | if w.v == nil { |
| | return |
| | } |
| |
|
| | switch n := n.(type) { |
| | |
| | case *File: |
| | w.node(n.PkgName) |
| | w.declList(n.DeclList) |
| |
|
| | |
| | case *ImportDecl: |
| | if n.LocalPkgName != nil { |
| | w.node(n.LocalPkgName) |
| | } |
| | w.node(n.Path) |
| |
|
| | case *ConstDecl: |
| | w.nameList(n.NameList) |
| | if n.Type != nil { |
| | w.node(n.Type) |
| | } |
| | if n.Values != nil { |
| | w.node(n.Values) |
| | } |
| |
|
| | case *TypeDecl: |
| | w.node(n.Name) |
| | w.fieldList(n.TParamList) |
| | w.node(n.Type) |
| |
|
| | case *VarDecl: |
| | w.nameList(n.NameList) |
| | if n.Type != nil { |
| | w.node(n.Type) |
| | } |
| | if n.Values != nil { |
| | w.node(n.Values) |
| | } |
| |
|
| | case *FuncDecl: |
| | if n.Recv != nil { |
| | w.node(n.Recv) |
| | } |
| | w.node(n.Name) |
| | w.fieldList(n.TParamList) |
| | w.node(n.Type) |
| | if n.Body != nil { |
| | w.node(n.Body) |
| | } |
| |
|
| | |
| | case *BadExpr: |
| | case *Name: |
| | case *BasicLit: |
| |
|
| | case *CompositeLit: |
| | if n.Type != nil { |
| | w.node(n.Type) |
| | } |
| | w.exprList(n.ElemList) |
| |
|
| | case *KeyValueExpr: |
| | w.node(n.Key) |
| | w.node(n.Value) |
| |
|
| | case *FuncLit: |
| | w.node(n.Type) |
| | w.node(n.Body) |
| |
|
| | case *ParenExpr: |
| | w.node(n.X) |
| |
|
| | case *SelectorExpr: |
| | w.node(n.X) |
| | w.node(n.Sel) |
| |
|
| | case *IndexExpr: |
| | w.node(n.X) |
| | w.node(n.Index) |
| |
|
| | case *SliceExpr: |
| | w.node(n.X) |
| | for _, x := range n.Index { |
| | if x != nil { |
| | w.node(x) |
| | } |
| | } |
| |
|
| | case *AssertExpr: |
| | w.node(n.X) |
| | w.node(n.Type) |
| |
|
| | case *TypeSwitchGuard: |
| | if n.Lhs != nil { |
| | w.node(n.Lhs) |
| | } |
| | w.node(n.X) |
| |
|
| | case *Operation: |
| | w.node(n.X) |
| | if n.Y != nil { |
| | w.node(n.Y) |
| | } |
| |
|
| | case *CallExpr: |
| | w.node(n.Fun) |
| | w.exprList(n.ArgList) |
| |
|
| | case *ListExpr: |
| | w.exprList(n.ElemList) |
| |
|
| | |
| | case *ArrayType: |
| | if n.Len != nil { |
| | w.node(n.Len) |
| | } |
| | w.node(n.Elem) |
| |
|
| | case *SliceType: |
| | w.node(n.Elem) |
| |
|
| | case *DotsType: |
| | w.node(n.Elem) |
| |
|
| | case *StructType: |
| | w.fieldList(n.FieldList) |
| | for _, t := range n.TagList { |
| | if t != nil { |
| | w.node(t) |
| | } |
| | } |
| |
|
| | case *Field: |
| | if n.Name != nil { |
| | w.node(n.Name) |
| | } |
| | w.node(n.Type) |
| |
|
| | case *InterfaceType: |
| | w.fieldList(n.MethodList) |
| |
|
| | case *FuncType: |
| | w.fieldList(n.ParamList) |
| | w.fieldList(n.ResultList) |
| |
|
| | case *MapType: |
| | w.node(n.Key) |
| | w.node(n.Value) |
| |
|
| | case *ChanType: |
| | w.node(n.Elem) |
| |
|
| | |
| | case *EmptyStmt: |
| |
|
| | case *LabeledStmt: |
| | w.node(n.Label) |
| | w.node(n.Stmt) |
| |
|
| | case *BlockStmt: |
| | w.stmtList(n.List) |
| |
|
| | case *ExprStmt: |
| | w.node(n.X) |
| |
|
| | case *SendStmt: |
| | w.node(n.Chan) |
| | w.node(n.Value) |
| |
|
| | case *DeclStmt: |
| | w.declList(n.DeclList) |
| |
|
| | case *AssignStmt: |
| | w.node(n.Lhs) |
| | if n.Rhs != nil { |
| | w.node(n.Rhs) |
| | } |
| |
|
| | case *BranchStmt: |
| | if n.Label != nil { |
| | w.node(n.Label) |
| | } |
| | |
| |
|
| | case *CallStmt: |
| | w.node(n.Call) |
| |
|
| | case *ReturnStmt: |
| | if n.Results != nil { |
| | w.node(n.Results) |
| | } |
| |
|
| | case *IfStmt: |
| | if n.Init != nil { |
| | w.node(n.Init) |
| | } |
| | w.node(n.Cond) |
| | w.node(n.Then) |
| | if n.Else != nil { |
| | w.node(n.Else) |
| | } |
| |
|
| | case *ForStmt: |
| | if n.Init != nil { |
| | w.node(n.Init) |
| | } |
| | if n.Cond != nil { |
| | w.node(n.Cond) |
| | } |
| | if n.Post != nil { |
| | w.node(n.Post) |
| | } |
| | w.node(n.Body) |
| |
|
| | case *SwitchStmt: |
| | if n.Init != nil { |
| | w.node(n.Init) |
| | } |
| | if n.Tag != nil { |
| | w.node(n.Tag) |
| | } |
| | for _, s := range n.Body { |
| | w.node(s) |
| | } |
| |
|
| | case *SelectStmt: |
| | for _, s := range n.Body { |
| | w.node(s) |
| | } |
| |
|
| | |
| | case *RangeClause: |
| | if n.Lhs != nil { |
| | w.node(n.Lhs) |
| | } |
| | w.node(n.X) |
| |
|
| | case *CaseClause: |
| | if n.Cases != nil { |
| | w.node(n.Cases) |
| | } |
| | w.stmtList(n.Body) |
| |
|
| | case *CommClause: |
| | if n.Comm != nil { |
| | w.node(n.Comm) |
| | } |
| | w.stmtList(n.Body) |
| |
|
| | default: |
| | panic(fmt.Sprintf("internal error: unknown node type %T", n)) |
| | } |
| |
|
| | w.v.Visit(nil) |
| | } |
| |
|
| | func (w walker) declList(list []Decl) { |
| | for _, n := range list { |
| | w.node(n) |
| | } |
| | } |
| |
|
| | func (w walker) exprList(list []Expr) { |
| | for _, n := range list { |
| | w.node(n) |
| | } |
| | } |
| |
|
| | func (w walker) stmtList(list []Stmt) { |
| | for _, n := range list { |
| | w.node(n) |
| | } |
| | } |
| |
|
| | func (w walker) nameList(list []*Name) { |
| | for _, n := range list { |
| | w.node(n) |
| | } |
| | } |
| |
|
| | func (w walker) fieldList(list []*Field) { |
| | for _, n := range list { |
| | w.node(n) |
| | } |
| | } |
| |
|