123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- package js
- // IVisitor represents the AST Visitor
- // Each INode encountered by `Walk` is passed to `Enter`, children nodes will be ignored if the returned IVisitor is nil
- // `Exit` is called upon the exit of a node
- type IVisitor interface {
- Enter(n INode) IVisitor
- Exit(n INode)
- }
- // Walk traverses an AST in depth-first order
- func Walk(v IVisitor, n INode) {
- if n == nil {
- return
- }
- if v = v.Enter(n); v == nil {
- return
- }
- defer v.Exit(n)
- switch n := n.(type) {
- case *AST:
- Walk(v, &n.BlockStmt)
- case *Var:
- return
- case *BlockStmt:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, n.List[i])
- }
- }
- case *EmptyStmt:
- return
- case *ExprStmt:
- Walk(v, n.Value)
- case *IfStmt:
- Walk(v, n.Body)
- Walk(v, n.Else)
- Walk(v, n.Cond)
- case *DoWhileStmt:
- Walk(v, n.Body)
- Walk(v, n.Cond)
- case *WhileStmt:
- Walk(v, n.Body)
- Walk(v, n.Cond)
- case *ForStmt:
- if n.Body != nil {
- Walk(v, n.Body)
- }
- Walk(v, n.Init)
- Walk(v, n.Cond)
- Walk(v, n.Post)
- case *ForInStmt:
- if n.Body != nil {
- Walk(v, n.Body)
- }
- Walk(v, n.Init)
- Walk(v, n.Value)
- case *ForOfStmt:
- if n.Body != nil {
- Walk(v, n.Body)
- }
- Walk(v, n.Init)
- Walk(v, n.Value)
- case *CaseClause:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, n.List[i])
- }
- }
- Walk(v, n.Cond)
- case *SwitchStmt:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- Walk(v, n.Init)
- case *BranchStmt:
- return
- case *ReturnStmt:
- Walk(v, n.Value)
- case *WithStmt:
- Walk(v, n.Body)
- Walk(v, n.Cond)
- case *LabelledStmt:
- Walk(v, n.Value)
- case *ThrowStmt:
- Walk(v, n.Value)
- case *TryStmt:
- if n.Body != nil {
- Walk(v, n.Body)
- }
- if n.Catch != nil {
- Walk(v, n.Catch)
- }
- if n.Finally != nil {
- Walk(v, n.Finally)
- }
- Walk(v, n.Binding)
- case *DebuggerStmt:
- return
- case *Alias:
- return
- case *ImportStmt:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- case *ExportStmt:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- Walk(v, n.Decl)
- case *DirectivePrologueStmt:
- return
- case *PropertyName:
- Walk(v, &n.Literal)
- Walk(v, n.Computed)
- case *BindingArray:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- Walk(v, n.Rest)
- case *BindingObjectItem:
- if n.Key != nil {
- Walk(v, n.Key)
- }
- Walk(v, &n.Value)
- case *BindingObject:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- if n.Rest != nil {
- Walk(v, n.Rest)
- }
- case *BindingElement:
- Walk(v, n.Binding)
- Walk(v, n.Default)
- case *VarDecl:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- case *Params:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- Walk(v, n.Rest)
- case *FuncDecl:
- Walk(v, &n.Body)
- Walk(v, &n.Params)
- if n.Name != nil {
- Walk(v, n.Name)
- }
- case *MethodDecl:
- Walk(v, &n.Body)
- Walk(v, &n.Params)
- Walk(v, &n.Name)
- case *Field:
- Walk(v, &n.Name)
- Walk(v, n.Init)
- case *ClassDecl:
- if n.Name != nil {
- Walk(v, n.Name)
- }
- Walk(v, n.Extends)
- for _, item := range n.List {
- if item.StaticBlock != nil {
- Walk(v, item.StaticBlock)
- } else if item.Method != nil {
- Walk(v, item.Method)
- } else {
- Walk(v, &item.Field)
- }
- }
- case *LiteralExpr:
- return
- case *Element:
- Walk(v, n.Value)
- case *ArrayExpr:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- case *Property:
- if n.Name != nil {
- Walk(v, n.Name)
- }
- Walk(v, n.Value)
- Walk(v, n.Init)
- case *ObjectExpr:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- case *TemplatePart:
- Walk(v, n.Expr)
- case *TemplateExpr:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- Walk(v, n.Tag)
- case *GroupExpr:
- Walk(v, n.X)
- case *IndexExpr:
- Walk(v, n.X)
- Walk(v, n.Y)
- case *DotExpr:
- Walk(v, n.X)
- Walk(v, &n.Y)
- case *NewTargetExpr:
- return
- case *ImportMetaExpr:
- return
- case *Arg:
- Walk(v, n.Value)
- case *Args:
- if n.List != nil {
- for i := 0; i < len(n.List); i++ {
- Walk(v, &n.List[i])
- }
- }
- case *NewExpr:
- if n.Args != nil {
- Walk(v, n.Args)
- }
- Walk(v, n.X)
- case *CallExpr:
- Walk(v, &n.Args)
- Walk(v, n.X)
- case *UnaryExpr:
- Walk(v, n.X)
- case *BinaryExpr:
- Walk(v, n.X)
- Walk(v, n.Y)
- case *CondExpr:
- Walk(v, n.Cond)
- Walk(v, n.X)
- Walk(v, n.Y)
- case *YieldExpr:
- Walk(v, n.X)
- case *ArrowFunc:
- Walk(v, &n.Body)
- Walk(v, &n.Params)
- case *CommaExpr:
- for _, item := range n.List {
- Walk(v, item)
- }
- default:
- return
- }
- }
|