Files

204 lines
3.2 KiB
Go

package ast
// Inspect walks n in source order, descending while fn returns true, without allocating.
func Inspect(n Node, fn func(Node) bool) {
if n == nil || !fn(n) {
return
}
walk(n, func(c Node) { Inspect(c, fn) })
}
// Children returns n's direct child nodes in source order.
func Children(n Node) []Node {
var out []Node
walk(n, func(c Node) { out = append(out, c) })
return out
}
func walk(n Node, visit func(Node)) {
ident := func(id *Ident) {
if id != nil {
visit(id)
}
}
expr := func(e Expr) {
if e != nil {
visit(e)
}
}
typ := func(t TypeExpr) {
if t != nil {
visit(t)
}
}
stmt := func(s Stmt) {
if s != nil {
visit(s)
}
}
attrs := func(list []*Attr) {
for _, a := range list {
visit(a)
}
}
switch x := n.(type) {
case *File:
ident(x.Package)
for _, i := range x.Imports {
visit(i)
}
for _, d := range x.Decls {
visit(d)
}
case *Attr:
ident(x.Name)
for _, a := range x.Args {
visit(a)
}
case *AttrArg:
ident(x.Key)
expr(x.Value)
case *CompositeLit:
typ(x.Type)
for _, e := range x.Elems {
visit(e)
}
case *Element:
ident(x.Key)
expr(x.Value)
case *ParenExpr:
expr(x.X)
case *SelectorExpr:
expr(x.X)
ident(x.Sel)
case *IndexExpr:
expr(x.X)
expr(x.Index)
case *CallExpr:
expr(x.Fun)
for _, t := range x.TypeArgs {
typ(t)
}
for _, a := range x.Args {
expr(a)
}
case *UnaryExpr:
expr(x.X)
case *BinaryExpr:
expr(x.X)
expr(x.Y)
case *NamedType:
ident(x.Pkg)
ident(x.Name)
for _, t := range x.Args {
typ(t)
}
case *SliceType:
typ(x.Elem)
case *VarStmt:
ident(x.Name)
typ(x.Type)
expr(x.Value)
case *ShortVarStmt:
ident(x.Name)
expr(x.Value)
case *AssignStmt:
expr(x.Target)
expr(x.Value)
case *IncDecStmt:
expr(x.X)
case *ExprStmt:
expr(x.X)
case *ReturnStmt:
expr(x.Value)
case *BlockStmt:
for _, s := range x.Stmts {
stmt(s)
}
case *IfStmt:
expr(x.Cond)
if x.Then != nil {
visit(x.Then)
}
stmt(x.Else)
case *ForStmt:
stmt(x.Init)
expr(x.Cond)
stmt(x.Post)
if x.Body != nil {
visit(x.Body)
}
case *SwitchStmt:
expr(x.Tag)
for _, c := range x.Cases {
visit(c)
}
case *CaseClause:
for _, v := range x.Values {
expr(v)
}
for _, s := range x.Body {
stmt(s)
}
case *ConstDecl:
ident(x.Name)
typ(x.Type)
expr(x.Value)
case *StructDecl:
ident(x.Name)
for _, f := range x.Fields {
visit(f)
}
case *Field:
ident(x.Name)
typ(x.Type)
case *EnumDecl:
ident(x.Name)
for _, m := range x.Members {
ident(m)
}
case *FuncDecl:
attrs(x.Attrs)
ident(x.Name)
for _, p := range x.Params {
visit(p)
}
typ(x.Result)
if x.Body != nil {
visit(x.Body)
}
case *Param:
ident(x.Name)
typ(x.Type)
case *ScriptDecl:
attrs(x.Attrs)
ident(x.Name)
for _, s := range x.Signals {
visit(s)
}
for _, v := range x.Vars {
visit(v)
}
for _, f := range x.Funcs {
visit(f)
}
case *SignalDecl:
ident(x.Name)
for _, p := range x.Params {
visit(p)
}
case *StartExpr:
ident(x.Name)
for _, a := range x.Args {
expr(a)
}
case *YieldStmt:
expr(x.Value)
case *ScriptVar:
attrs(x.Attrs)
ident(x.Name)
typ(x.Type)
expr(x.Value)
}
}