From 25877adda4748668a9c1165078770f86bf0251a1 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 25 Mar 2023 21:55:24 +0100 Subject: [PATCH] feat: add enter and leave checks for traversers - Improved performance (can short circuit/not continue when done) - Backwards compatible because added interfaces - Now generating the implementation for easier updates --- go.mod | 1 + go.sum | 40 + pkg/visitor/traverser/traverser.go | 1290 +----------- pkg/visitor/traverser/traverser_gen.go | 173 ++ pkg/visitor/traverser/traverser_impl.go | 2424 +++++++++++++++++++++++ pkg/visitor/traverser/traverser_test.go | 67 + 6 files changed, 2722 insertions(+), 1273 deletions(-) create mode 100644 pkg/visitor/traverser/traverser_gen.go create mode 100644 pkg/visitor/traverser/traverser_impl.go create mode 100644 pkg/visitor/traverser/traverser_test.go diff --git a/go.mod b/go.mod index d8bf69d..fceeaf6 100644 --- a/go.mod +++ b/go.mod @@ -11,4 +11,5 @@ require ( require ( github.com/google/go-cmp v0.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect + golang.org/x/tools v0.7.0 ) diff --git a/go.sum b/go.sum index 082e37f..bc46a72 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,46 @@ github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/yookoala/realpath v1.0.0 h1:7OA9pj4FZd+oZDsyvXWQvjn5oBdcHRTV44PpdMSuImQ= github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= diff --git a/pkg/visitor/traverser/traverser.go b/pkg/visitor/traverser/traverser.go index cbc5d6b..093511f 100644 --- a/pkg/visitor/traverser/traverser.go +++ b/pkg/visitor/traverser/traverser.go @@ -4,6 +4,16 @@ import ( "github.com/VKCOM/php-parser/pkg/ast" ) +//go:generate go run traverser_gen.go + +type CheckEntrance interface { + EnterNode(ast.Vertex) bool +} + +type NotifyLeave interface { + LeaveNode(ast.Vertex) +} + type Traverser struct { v ast.Visitor } @@ -20,1282 +30,16 @@ func (t *Traverser) Traverse(n ast.Vertex) { } } -func (t *Traverser) Root(n *ast.Root) { - n.Accept(t.v) - - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) Nullable(n *ast.Nullable) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) Parameter(n *ast.Parameter) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - - for _, nn := range n.Modifiers { - nn.Accept(t) - } - - t.Traverse(n.Type) - t.Traverse(n.Var) - t.Traverse(n.DefaultValue) -} - -func (t *Traverser) Identifier(n *ast.Identifier) { - n.Accept(t.v) -} - -func (t *Traverser) Argument(n *ast.Argument) { - n.Accept(t.v) - - t.Traverse(n.Name) - t.Traverse(n.Expr) -} - -func (t *Traverser) MatchArm(n *ast.MatchArm) { - n.Accept(t.v) - - for _, nn := range n.Exprs { - nn.Accept(t) - } - t.Traverse(n.ReturnExpr) -} - -func (t *Traverser) Union(n *ast.Union) { - n.Accept(t.v) - - for _, nn := range n.Types { - nn.Accept(t) - } -} - -func (t *Traverser) Intersection(n *ast.Intersection) { - n.Accept(t.v) - - for _, nn := range n.Types { - nn.Accept(t) - } -} - -func (t *Traverser) Attribute(n *ast.Attribute) { - n.Accept(t.v) - - t.Traverse(n.Name) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) AttributeGroup(n *ast.AttributeGroup) { - n.Accept(t.v) - - for _, nn := range n.Attrs { - nn.Accept(t) - } -} - -func (t *Traverser) StmtBreak(n *ast.StmtBreak) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtCase(n *ast.StmtCase) { - n.Accept(t.v) - - t.Traverse(n.Cond) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtCatch(n *ast.StmtCatch) { - n.Accept(t.v) - - for _, nn := range n.Types { - nn.Accept(t) - } - t.Traverse(n.Var) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtEnum(n *ast.StmtEnum) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - t.Traverse(n.Name) - t.Traverse(n.Type) - - for _, nn := range n.Implements { - nn.Accept(t) - } - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) EnumCase(n *ast.EnumCase) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - t.Traverse(n.Name) - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtClass(n *ast.StmtClass) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Modifiers { - nn.Accept(t) - } - t.Traverse(n.Name) - for _, nn := range n.Args { - nn.Accept(t) - } - t.Traverse(n.Extends) - for _, nn := range n.Implements { - nn.Accept(t) - } - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtClassConstList(n *ast.StmtClassConstList) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Modifiers { - nn.Accept(t) - } - for _, nn := range n.Consts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtClassMethod(n *ast.StmtClassMethod) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Modifiers { - nn.Accept(t) - } - t.Traverse(n.Name) - for _, nn := range n.Params { - nn.Accept(t) - } - t.Traverse(n.ReturnType) - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtConstList(n *ast.StmtConstList) { - n.Accept(t.v) - - for _, nn := range n.Consts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtConstant(n *ast.StmtConstant) { - n.Accept(t.v) - - t.Traverse(n.Name) - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtContinue(n *ast.StmtContinue) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtDeclare(n *ast.StmtDeclare) { - n.Accept(t.v) - - for _, nn := range n.Consts { - nn.Accept(t) - } - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtDefault(n *ast.StmtDefault) { - n.Accept(t.v) - - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtDo(n *ast.StmtDo) { - n.Accept(t.v) - - t.Traverse(n.Stmt) - t.Traverse(n.Cond) -} - -func (t *Traverser) StmtEcho(n *ast.StmtEcho) { - n.Accept(t.v) - - for _, nn := range n.Exprs { - nn.Accept(t) - } -} - -func (t *Traverser) StmtElse(n *ast.StmtElse) { - n.Accept(t.v) - - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtElseIf(n *ast.StmtElseIf) { - n.Accept(t.v) - - t.Traverse(n.Cond) - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtExpression(n *ast.StmtExpression) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtFinally(n *ast.StmtFinally) { - n.Accept(t.v) - - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtFor(n *ast.StmtFor) { - n.Accept(t.v) - - for _, nn := range n.Init { - nn.Accept(t) - } - for _, nn := range n.Cond { - nn.Accept(t) - } - for _, nn := range n.Loop { - nn.Accept(t) - } - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtForeach(n *ast.StmtForeach) { - n.Accept(t.v) - - t.Traverse(n.Expr) - t.Traverse(n.Key) - t.Traverse(n.Var) - t.Traverse(n.Stmt) -} - -func (t *Traverser) StmtFunction(n *ast.StmtFunction) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - t.Traverse(n.Name) - for _, nn := range n.Params { - nn.Accept(t) - } - t.Traverse(n.ReturnType) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtGlobal(n *ast.StmtGlobal) { - n.Accept(t.v) - - for _, nn := range n.Vars { - nn.Accept(t) - } -} - -func (t *Traverser) StmtGoto(n *ast.StmtGoto) { - n.Accept(t.v) - - t.Traverse(n.Label) -} - -func (t *Traverser) StmtHaltCompiler(n *ast.StmtHaltCompiler) { - n.Accept(t.v) -} - -func (t *Traverser) StmtIf(n *ast.StmtIf) { - n.Accept(t.v) - - t.Traverse(n.Cond) - t.Traverse(n.Stmt) - for _, nn := range n.ElseIf { - nn.Accept(t) - } - t.Traverse(n.Else) -} - -func (t *Traverser) StmtInlineHtml(n *ast.StmtInlineHtml) { - n.Accept(t.v) -} - -func (t *Traverser) StmtInterface(n *ast.StmtInterface) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - t.Traverse(n.Name) - for _, nn := range n.Extends { - nn.Accept(t) - } - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtLabel(n *ast.StmtLabel) { - n.Accept(t.v) - - t.Traverse(n.Name) -} - -func (t *Traverser) StmtNamespace(n *ast.StmtNamespace) { - n.Accept(t.v) - - t.Traverse(n.Name) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtNop(n *ast.StmtNop) { - n.Accept(t.v) -} - -func (t *Traverser) StmtProperty(n *ast.StmtProperty) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtPropertyList(n *ast.StmtPropertyList) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Modifiers { - nn.Accept(t) - } - t.Traverse(n.Type) - for _, nn := range n.Props { - nn.Accept(t) - } -} - -func (t *Traverser) StmtReturn(n *ast.StmtReturn) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtStatic(n *ast.StmtStatic) { - n.Accept(t.v) - - for _, nn := range n.Vars { - nn.Accept(t) - } -} - -func (t *Traverser) StmtStaticVar(n *ast.StmtStaticVar) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtStmtList(n *ast.StmtStmtList) { - n.Accept(t.v) - - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtSwitch(n *ast.StmtSwitch) { - n.Accept(t.v) - - t.Traverse(n.Cond) - for _, nn := range n.Cases { - nn.Accept(t) - } -} - -func (t *Traverser) StmtThrow(n *ast.StmtThrow) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) StmtTrait(n *ast.StmtTrait) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - t.Traverse(n.Name) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) StmtTraitUse(n *ast.StmtTraitUse) { - n.Accept(t.v) - - for _, nn := range n.Traits { - nn.Accept(t) - } - for _, nn := range n.Adaptations { - nn.Accept(t) - } -} - -func (t *Traverser) StmtTraitUseAlias(n *ast.StmtTraitUseAlias) { - n.Accept(t.v) - - t.Traverse(n.Trait) - t.Traverse(n.Method) - t.Traverse(n.Modifier) - t.Traverse(n.Alias) -} - -func (t *Traverser) StmtTraitUsePrecedence(n *ast.StmtTraitUsePrecedence) { - n.Accept(t.v) - - t.Traverse(n.Trait) - t.Traverse(n.Method) - for _, nn := range n.Insteadof { - nn.Accept(t) - } -} - -func (t *Traverser) StmtTry(n *ast.StmtTry) { - n.Accept(t.v) - - for _, nn := range n.Stmts { - nn.Accept(t) - } - for _, nn := range n.Catches { - nn.Accept(t) - } - t.Traverse(n.Finally) -} - -func (t *Traverser) StmtUnset(n *ast.StmtUnset) { - n.Accept(t.v) - - for _, nn := range n.Vars { - nn.Accept(t) - } -} - -func (t *Traverser) StmtUse(n *ast.StmtUseList) { - n.Accept(t.v) - - t.Traverse(n.Type) - for _, nn := range n.Uses { - nn.Accept(t) - } -} - -func (t *Traverser) StmtGroupUse(n *ast.StmtGroupUseList) { - n.Accept(t.v) - - t.Traverse(n.Type) - t.Traverse(n.Prefix) - for _, nn := range n.Uses { - nn.Accept(t) - } -} - -func (t *Traverser) StmtUseDeclaration(n *ast.StmtUse) { - n.Accept(t.v) - - t.Traverse(n.Type) - t.Traverse(n.Use) - t.Traverse(n.Alias) -} - -func (t *Traverser) StmtWhile(n *ast.StmtWhile) { - n.Accept(t.v) - - t.Traverse(n.Cond) - t.Traverse(n.Stmt) -} - -func (t *Traverser) ExprArray(n *ast.ExprArray) { - n.Accept(t.v) - - for _, nn := range n.Items { - nn.Accept(t) - } -} - -func (t *Traverser) ExprArrayDimFetch(n *ast.ExprArrayDimFetch) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Dim) -} - -func (t *Traverser) ExprArrayItem(n *ast.ExprArrayItem) { - n.Accept(t.v) - - t.Traverse(n.Key) - t.Traverse(n.Val) -} - -func (t *Traverser) ExprArrowFunction(n *ast.ExprArrowFunction) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Params { - nn.Accept(t) - } - t.Traverse(n.ReturnType) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprBitwiseNot(n *ast.ExprBitwiseNot) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprBooleanNot(n *ast.ExprBooleanNot) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprBrackets(n *ast.ExprBrackets) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprClassConstFetch(n *ast.ExprClassConstFetch) { - n.Accept(t.v) - - t.Traverse(n.Class) - t.Traverse(n.Const) -} - -func (t *Traverser) ExprClone(n *ast.ExprClone) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprClosure(n *ast.ExprClosure) { - n.Accept(t.v) - - for _, nn := range n.AttrGroups { - nn.Accept(t) - } - for _, nn := range n.Params { - nn.Accept(t) - } - for _, nn := range n.Uses { - nn.Accept(t) - } - t.Traverse(n.ReturnType) - for _, nn := range n.Stmts { - nn.Accept(t) - } -} - -func (t *Traverser) ExprClosureUse(n *ast.ExprClosureUse) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ExprConstFetch(n *ast.ExprConstFetch) { - n.Accept(t.v) - - t.Traverse(n.Const) -} - -func (t *Traverser) ExprEmpty(n *ast.ExprEmpty) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprErrorSuppress(n *ast.ExprErrorSuppress) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprEval(n *ast.ExprEval) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprExit(n *ast.ExprExit) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprFunctionCall(n *ast.ExprFunctionCall) { - n.Accept(t.v) - - t.Traverse(n.Function) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) ExprInclude(n *ast.ExprInclude) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprIncludeOnce(n *ast.ExprIncludeOnce) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprInstanceOf(n *ast.ExprInstanceOf) { - n.Accept(t.v) - - t.Traverse(n.Expr) - t.Traverse(n.Class) -} - -func (t *Traverser) ExprIsset(n *ast.ExprIsset) { - n.Accept(t.v) - - for _, nn := range n.Vars { - nn.Accept(t) - } -} - -func (t *Traverser) ExprList(n *ast.ExprList) { - n.Accept(t.v) - - for _, nn := range n.Items { - nn.Accept(t) +func (t *Traverser) checkEntrance(n ast.Vertex) bool { + if ssv, ok := t.v.(CheckEntrance); ok { + return ssv.EnterNode(n) } -} - -func (t *Traverser) ExprMethodCall(n *ast.ExprMethodCall) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Method) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) ExprNullsafeMethodCall(n *ast.ExprNullsafeMethodCall) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Method) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) ExprNew(n *ast.ExprNew) { - n.Accept(t.v) - - t.Traverse(n.Class) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) ExprPostDec(n *ast.ExprPostDec) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ExprPostInc(n *ast.ExprPostInc) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ExprPreDec(n *ast.ExprPreDec) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ExprPreInc(n *ast.ExprPreInc) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ExprPrint(n *ast.ExprPrint) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprPropertyFetch(n *ast.ExprPropertyFetch) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Prop) -} - -func (t *Traverser) ExprNullsafePropertyFetch(n *ast.ExprNullsafePropertyFetch) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Prop) -} - -func (t *Traverser) ExprRequire(n *ast.ExprRequire) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprRequireOnce(n *ast.ExprRequireOnce) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprShellExec(n *ast.ExprShellExec) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) - } -} - -func (t *Traverser) ExprStaticCall(n *ast.ExprStaticCall) { - n.Accept(t.v) - - t.Traverse(n.Class) - t.Traverse(n.Call) - for _, nn := range n.Args { - nn.Accept(t) - } -} - -func (t *Traverser) ExprStaticPropertyFetch(n *ast.ExprStaticPropertyFetch) { - n.Accept(t.v) - - t.Traverse(n.Class) - t.Traverse(n.Prop) -} - -func (t *Traverser) ExprTernary(n *ast.ExprTernary) { - n.Accept(t.v) - - t.Traverse(n.Cond) - t.Traverse(n.IfTrue) - t.Traverse(n.IfFalse) -} - -func (t *Traverser) ExprUnaryMinus(n *ast.ExprUnaryMinus) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprUnaryPlus(n *ast.ExprUnaryPlus) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprVariable(n *ast.ExprVariable) { - n.Accept(t.v) - - t.Traverse(n.Name) -} - -func (t *Traverser) ExprYield(n *ast.ExprYield) { - n.Accept(t.v) - - t.Traverse(n.Key) - t.Traverse(n.Val) -} - -func (t *Traverser) ExprYieldFrom(n *ast.ExprYieldFrom) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssign(n *ast.ExprAssign) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignReference(n *ast.ExprAssignReference) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignBitwiseAnd(n *ast.ExprAssignBitwiseAnd) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignBitwiseOr(n *ast.ExprAssignBitwiseOr) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignBitwiseXor(n *ast.ExprAssignBitwiseXor) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignCoalesce(n *ast.ExprAssignCoalesce) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignConcat(n *ast.ExprAssignConcat) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignDiv(n *ast.ExprAssignDiv) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignMinus(n *ast.ExprAssignMinus) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignMod(n *ast.ExprAssignMod) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignMul(n *ast.ExprAssignMul) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignPlus(n *ast.ExprAssignPlus) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignPow(n *ast.ExprAssignPow) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignShiftLeft(n *ast.ExprAssignShiftLeft) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprAssignShiftRight(n *ast.ExprAssignShiftRight) { - n.Accept(t.v) - - t.Traverse(n.Var) - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprBinaryBitwiseAnd(n *ast.ExprBinaryBitwiseAnd) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryBitwiseOr(n *ast.ExprBinaryBitwiseOr) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryBitwiseXor(n *ast.ExprBinaryBitwiseXor) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryBooleanAnd(n *ast.ExprBinaryBooleanAnd) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryBooleanOr(n *ast.ExprBinaryBooleanOr) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryCoalesce(n *ast.ExprBinaryCoalesce) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryConcat(n *ast.ExprBinaryConcat) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryDiv(n *ast.ExprBinaryDiv) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryEqual(n *ast.ExprBinaryEqual) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryGreater(n *ast.ExprBinaryGreater) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryGreaterOrEqual(n *ast.ExprBinaryGreaterOrEqual) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryIdentical(n *ast.ExprBinaryIdentical) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryLogicalAnd(n *ast.ExprBinaryLogicalAnd) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryLogicalOr(n *ast.ExprBinaryLogicalOr) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryLogicalXor(n *ast.ExprBinaryLogicalXor) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryMinus(n *ast.ExprBinaryMinus) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryMod(n *ast.ExprBinaryMod) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryMul(n *ast.ExprBinaryMul) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryNotEqual(n *ast.ExprBinaryNotEqual) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryNotIdentical(n *ast.ExprBinaryNotIdentical) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryPlus(n *ast.ExprBinaryPlus) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryPow(n *ast.ExprBinaryPow) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryShiftLeft(n *ast.ExprBinaryShiftLeft) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinaryShiftRight(n *ast.ExprBinaryShiftRight) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinarySmaller(n *ast.ExprBinarySmaller) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprBinarySmallerOrEqual(n *ast.ExprBinarySmallerOrEqual) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} -func (t *Traverser) ExprBinarySpaceship(n *ast.ExprBinarySpaceship) { - n.Accept(t.v) - - t.Traverse(n.Left) - t.Traverse(n.Right) -} - -func (t *Traverser) ExprCastArray(n *ast.ExprCastArray) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastBool(n *ast.ExprCastBool) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastDouble(n *ast.ExprCastDouble) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastInt(n *ast.ExprCastInt) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastObject(n *ast.ExprCastObject) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastString(n *ast.ExprCastString) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprCastUnset(n *ast.ExprCastUnset) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ExprMatch(n *ast.ExprMatch) { - n.Accept(t.v) - - t.Traverse(n.Expr) - for _, nn := range n.Arms { - nn.Accept(t) - } -} - -func (t *Traverser) ExprThrow(n *ast.ExprThrow) { - n.Accept(t.v) - - t.Traverse(n.Expr) -} - -func (t *Traverser) ScalarDnumber(n *ast.ScalarDnumber) { - n.Accept(t.v) -} - -func (t *Traverser) ScalarEncapsed(n *ast.ScalarEncapsed) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) - } -} - -func (t *Traverser) ScalarEncapsedStringPart(n *ast.ScalarEncapsedStringPart) { - n.Accept(t.v) -} - -func (t *Traverser) ScalarEncapsedStringVar(n *ast.ScalarEncapsedStringVar) { - n.Accept(t.v) - - t.Traverse(n.Name) - t.Traverse(n.Dim) -} - -func (t *Traverser) ScalarEncapsedStringBrackets(n *ast.ScalarEncapsedStringBrackets) { - n.Accept(t.v) - - t.Traverse(n.Var) -} - -func (t *Traverser) ScalarHeredoc(n *ast.ScalarHeredoc) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) - } -} - -func (t *Traverser) ScalarLnumber(n *ast.ScalarLnumber) { - n.Accept(t.v) -} - -func (t *Traverser) ScalarMagicConstant(n *ast.ScalarMagicConstant) { - n.Accept(t.v) -} - -func (t *Traverser) ScalarString(n *ast.ScalarString) { - n.Accept(t.v) -} - -func (t *Traverser) NameName(n *ast.Name) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) - } -} - -func (t *Traverser) NameFullyQualified(n *ast.NameFullyQualified) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) - } + return true } -func (t *Traverser) NameRelative(n *ast.NameRelative) { - n.Accept(t.v) - - for _, nn := range n.Parts { - nn.Accept(t) +func (t *Traverser) leave(n ast.Vertex) { + if ssv, ok := t.v.(NotifyLeave); ok { + ssv.LeaveNode(n) } } - -func (t *Traverser) NameNamePart(n *ast.NamePart) { - n.Accept(t.v) -} diff --git a/pkg/visitor/traverser/traverser_gen.go b/pkg/visitor/traverser/traverser_gen.go new file mode 100644 index 0000000..ea6a763 --- /dev/null +++ b/pkg/visitor/traverser/traverser_gen.go @@ -0,0 +1,173 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "fmt" + "go/ast" + "log" + "os" + "path/filepath" + "text/template" + + phpast "github.com/VKCOM/php-parser/pkg/ast" + "golang.org/x/tools/go/packages" +) + +type nodeType struct { + // The type name. + Name string + // The function name. + FuncName string + // Map of field names to whether the field is an array or not. + Traversable map[string]bool +} + +type templData struct { + Types []nodeType +} + +var fileTempl = template.Must( + template.New("").Parse(`// Code generated by "go generate go run traverser_gen.go"; DO NOT EDIT. + +package traverser + +import ( + "github.com/VKCOM/php-parser/pkg/ast" + // Importing packages here, so that go mod tidy does not remove the dependency on it. + // It is used in traverser_gen.go but that is ignored with go mod tidy. + "golang.org/x/tools/go/packages" +) +{{range $typ := .Types}} +func (t *Traverser) {{$typ.FuncName}}(n *ast.{{$typ.Name}}) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) +{{range $name, $isArray := $typ.Traversable}} +{{- if $isArray}} + for _, nn := range n.{{$name}} { + nn.Accept(t) + } +{{else}} + t.Traverse(n.{{$name}}) +{{end}} +{{- end}} + t.leave(n) +} +{{end}}`), +) + +func main() { + ast := astOfFile("../../ast/node.go") + nodeTypes := getNodeTypes(ast) + + file, err := os.Create("traverser_impl.go") + if err != nil { + panic(fmt.Errorf("open 'traverser_impl.go': %w", err)) + } + + fileTempl.Execute(file, templData{Types: nodeTypes}) +} + +func astOfFile(path string) *ast.File { + nodesFile, err := filepath.Abs(path) + if err != nil { + panic(fmt.Errorf("getting '%s' absolute path: %w", path, err)) + } + + cfg := &packages.Config{ + Mode: packages.NeedName | packages.NeedFiles | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax, + Tests: false, + } + pkgs, err := packages.Load(cfg, fmt.Sprintf("file=%s", nodesFile)) + if err != nil { + panic(fmt.Errorf("loading '%s' package: %w", nodesFile, err)) + } + + if len(pkgs) == 0 { + panic(fmt.Errorf("could not get any package for file '%s'", nodesFile)) + } + + pkg := pkgs[0] + var syntax *ast.File + for i, fn := range pkg.GoFiles { + if fn == nodesFile { + syntax = pkg.Syntax[i] + break + } + } + + if syntax == nil { + panic(fmt.Errorf("could not get ast of file: '%s'", nodesFile)) + } + + return syntax +} + +func getNodeTypes(syntax *ast.File) []nodeType { + types := []nodeType{} + for _, decl := range syntax.Decls { + typedDecl, ok := decl.(*ast.GenDecl) + if !ok { + log.Printf("%T not *ast.GenDecl", decl) + continue + } + + for _, spec := range typedDecl.Specs { + typedSpec, ok := spec.(*ast.TypeSpec) + if !ok { + if _, ok := spec.(*ast.ImportSpec); !ok { + log.Printf("%T not *ast.TypeSpec", spec) + } + continue + } + + structType, ok := typedSpec.Type.(*ast.StructType) + if !ok { + log.Printf("%T not *ast.StructType", spec) + continue + } + + nType := nodeType{ + Name: typedSpec.Name.String(), + FuncName: typedSpec.Name.String(), + Traversable: map[string]bool{}, + } + if funcName, ok := phpast.TypeToVisitorNameMap[typedSpec.Name.String()]; ok { + nType.FuncName = funcName + } + + for _, field := range structType.Fields.List { + if traversable, isArray := checkType(field.Type); traversable { + for _, n := range field.Names { + nType.Traversable[n.String()] = isArray + } + } + } + + types = append(types, nType) + } + } + + return types +} + +func checkType(t ast.Expr) (traversable bool, isArray bool) { + switch ft := t.(type) { + case *ast.ArrayType: + ok, _ := checkType(ft.Elt) + return ok, true + case *ast.Ident: + switch ft.Name { + case "Vertex": + return true, false + default: + return false, false + } + default: + return false, false + } +} diff --git a/pkg/visitor/traverser/traverser_impl.go b/pkg/visitor/traverser/traverser_impl.go new file mode 100644 index 0000000..75b9474 --- /dev/null +++ b/pkg/visitor/traverser/traverser_impl.go @@ -0,0 +1,2424 @@ +// Code generated by "go generate go run traverser_gen.go"; DO NOT EDIT. + +package traverser + +import ( + "github.com/VKCOM/php-parser/pkg/ast" + // Importing packages here, so that go mod tidy does not remove the dependency on it. + // It is used in traverser_gen.go but that is ignored with go mod tidy. + "golang.org/x/tools/go/packages" +) + +func (t *Traverser) Root(n *ast.Root) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) Nullable(n *ast.Nullable) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) Union(n *ast.Union) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Types { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) Intersection(n *ast.Intersection) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Types { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) Parameter(n *ast.Parameter) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.DefaultValue) + + for _, nn := range n.Modifiers { + nn.Accept(t) + } + + t.Traverse(n.Type) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) Identifier(n *ast.Identifier) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) Argument(n *ast.Argument) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) Attribute(n *ast.Attribute) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) AttributeGroup(n *ast.AttributeGroup) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Attrs { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ScalarDnumber(n *ast.ScalarDnumber) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) ScalarEncapsed(n *ast.ScalarEncapsed) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ScalarEncapsedStringPart(n *ast.ScalarEncapsedStringPart) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) ScalarEncapsedStringVar(n *ast.ScalarEncapsedStringVar) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Dim) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) ScalarEncapsedStringBrackets(n *ast.ScalarEncapsedStringBrackets) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ScalarHeredoc(n *ast.ScalarHeredoc) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ScalarLnumber(n *ast.ScalarLnumber) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) ScalarMagicConstant(n *ast.ScalarMagicConstant) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) ScalarString(n *ast.ScalarString) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) StmtBreak(n *ast.StmtBreak) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) StmtCase(n *ast.StmtCase) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtCatch(n *ast.StmtCatch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + for _, nn := range n.Types { + nn.Accept(t) + } + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) StmtEnum(n *ast.StmtEnum) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Implements { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.Traverse(n.Type) + + t.leave(n) +} + +func (t *Traverser) EnumCase(n *ast.EnumCase) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.Expr) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) StmtClass(n *ast.StmtClass) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.Extends) + + for _, nn := range n.Implements { + nn.Accept(t) + } + + for _, nn := range n.Modifiers { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtClassConstList(n *ast.StmtClassConstList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Consts { + nn.Accept(t) + } + + for _, nn := range n.Modifiers { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtClassMethod(n *ast.StmtClassMethod) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Modifiers { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Params { + nn.Accept(t) + } + + t.Traverse(n.ReturnType) + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtConstList(n *ast.StmtConstList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Consts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtConstant(n *ast.StmtConstant) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) StmtContinue(n *ast.StmtContinue) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) StmtDeclare(n *ast.StmtDeclare) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Consts { + nn.Accept(t) + } + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtDefault(n *ast.StmtDefault) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtDo(n *ast.StmtDo) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtEcho(n *ast.StmtEcho) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Exprs { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtElse(n *ast.StmtElse) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtElseIf(n *ast.StmtElseIf) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtExpression(n *ast.StmtExpression) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) StmtFinally(n *ast.StmtFinally) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtFor(n *ast.StmtFor) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Cond { + nn.Accept(t) + } + + for _, nn := range n.Init { + nn.Accept(t) + } + + for _, nn := range n.Loop { + nn.Accept(t) + } + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtForeach(n *ast.StmtForeach) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Key) + + t.Traverse(n.Stmt) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) StmtFunction(n *ast.StmtFunction) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Params { + nn.Accept(t) + } + + t.Traverse(n.ReturnType) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtGlobal(n *ast.StmtGlobal) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Vars { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtGoto(n *ast.StmtGoto) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Label) + + t.leave(n) +} + +func (t *Traverser) StmtHaltCompiler(n *ast.StmtHaltCompiler) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) StmtIf(n *ast.StmtIf) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + t.Traverse(n.Else) + + for _, nn := range n.ElseIf { + nn.Accept(t) + } + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) StmtInlineHtml(n *ast.StmtInlineHtml) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) StmtInterface(n *ast.StmtInterface) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Extends { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtLabel(n *ast.StmtLabel) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) StmtNamespace(n *ast.StmtNamespace) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Name) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtNop(n *ast.StmtNop) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} + +func (t *Traverser) StmtProperty(n *ast.StmtProperty) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) StmtPropertyList(n *ast.StmtPropertyList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Modifiers { + nn.Accept(t) + } + + for _, nn := range n.Props { + nn.Accept(t) + } + + t.Traverse(n.Type) + + t.leave(n) +} + +func (t *Traverser) StmtReturn(n *ast.StmtReturn) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) StmtStatic(n *ast.StmtStatic) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Vars { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtStaticVar(n *ast.StmtStaticVar) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) StmtStmtList(n *ast.StmtStmtList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtSwitch(n *ast.StmtSwitch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Cases { + nn.Accept(t) + } + + t.Traverse(n.Cond) + + t.leave(n) +} + +func (t *Traverser) StmtThrow(n *ast.StmtThrow) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) StmtTrait(n *ast.StmtTrait) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.Name) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtTraitUse(n *ast.StmtTraitUse) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Adaptations { + nn.Accept(t) + } + + for _, nn := range n.Traits { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtTraitUseAlias(n *ast.StmtTraitUseAlias) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Alias) + + t.Traverse(n.Method) + + t.Traverse(n.Modifier) + + t.Traverse(n.Trait) + + t.leave(n) +} + +func (t *Traverser) StmtTraitUsePrecedence(n *ast.StmtTraitUsePrecedence) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Insteadof { + nn.Accept(t) + } + + t.Traverse(n.Method) + + t.Traverse(n.Trait) + + t.leave(n) +} + +func (t *Traverser) StmtTry(n *ast.StmtTry) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Catches { + nn.Accept(t) + } + + t.Traverse(n.Finally) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtUnset(n *ast.StmtUnset) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Vars { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtUse(n *ast.StmtUseList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Type) + + for _, nn := range n.Uses { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtGroupUse(n *ast.StmtGroupUseList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Prefix) + + t.Traverse(n.Type) + + for _, nn := range n.Uses { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) StmtUseDeclaration(n *ast.StmtUse) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Alias) + + t.Traverse(n.Type) + + t.Traverse(n.Use) + + t.leave(n) +} + +func (t *Traverser) StmtWhile(n *ast.StmtWhile) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + t.Traverse(n.Stmt) + + t.leave(n) +} + +func (t *Traverser) ExprArray(n *ast.ExprArray) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Items { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ExprArrayDimFetch(n *ast.ExprArrayDimFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Dim) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprArrayItem(n *ast.ExprArrayItem) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Key) + + t.Traverse(n.Val) + + t.leave(n) +} + +func (t *Traverser) ExprArrowFunction(n *ast.ExprArrowFunction) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + t.Traverse(n.Expr) + + for _, nn := range n.Params { + nn.Accept(t) + } + + t.Traverse(n.ReturnType) + + t.leave(n) +} + +func (t *Traverser) ExprBitwiseNot(n *ast.ExprBitwiseNot) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprBooleanNot(n *ast.ExprBooleanNot) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprBrackets(n *ast.ExprBrackets) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprClassConstFetch(n *ast.ExprClassConstFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Class) + + t.Traverse(n.Const) + + t.leave(n) +} + +func (t *Traverser) ExprClone(n *ast.ExprClone) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprClosure(n *ast.ExprClosure) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.AttrGroups { + nn.Accept(t) + } + + for _, nn := range n.Params { + nn.Accept(t) + } + + t.Traverse(n.ReturnType) + + for _, nn := range n.Stmts { + nn.Accept(t) + } + + for _, nn := range n.Uses { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ExprClosureUse(n *ast.ExprClosureUse) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprConstFetch(n *ast.ExprConstFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Const) + + t.leave(n) +} + +func (t *Traverser) ExprEmpty(n *ast.ExprEmpty) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprErrorSuppress(n *ast.ExprErrorSuppress) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprEval(n *ast.ExprEval) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprExit(n *ast.ExprExit) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprFunctionCall(n *ast.ExprFunctionCall) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Function) + + t.leave(n) +} + +func (t *Traverser) ExprInclude(n *ast.ExprInclude) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprIncludeOnce(n *ast.ExprIncludeOnce) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprInstanceOf(n *ast.ExprInstanceOf) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Class) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprIsset(n *ast.ExprIsset) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Vars { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ExprList(n *ast.ExprList) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Items { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ExprMethodCall(n *ast.ExprMethodCall) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Method) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprNullsafeMethodCall(n *ast.ExprNullsafeMethodCall) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Method) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprNew(n *ast.ExprNew) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Class) + + t.leave(n) +} + +func (t *Traverser) ExprPostDec(n *ast.ExprPostDec) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprPostInc(n *ast.ExprPostInc) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprPreDec(n *ast.ExprPreDec) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprPreInc(n *ast.ExprPreInc) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprPrint(n *ast.ExprPrint) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprPropertyFetch(n *ast.ExprPropertyFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Prop) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprNullsafePropertyFetch(n *ast.ExprNullsafePropertyFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Prop) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprRequire(n *ast.ExprRequire) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprRequireOnce(n *ast.ExprRequireOnce) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprShellExec(n *ast.ExprShellExec) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) ExprStaticCall(n *ast.ExprStaticCall) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Args { + nn.Accept(t) + } + + t.Traverse(n.Call) + + t.Traverse(n.Class) + + t.leave(n) +} + +func (t *Traverser) ExprStaticPropertyFetch(n *ast.ExprStaticPropertyFetch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Class) + + t.Traverse(n.Prop) + + t.leave(n) +} + +func (t *Traverser) ExprTernary(n *ast.ExprTernary) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Cond) + + t.Traverse(n.IfFalse) + + t.Traverse(n.IfTrue) + + t.leave(n) +} + +func (t *Traverser) ExprUnaryMinus(n *ast.ExprUnaryMinus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprUnaryPlus(n *ast.ExprUnaryPlus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprVariable(n *ast.ExprVariable) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Name) + + t.leave(n) +} + +func (t *Traverser) ExprYield(n *ast.ExprYield) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Key) + + t.Traverse(n.Val) + + t.leave(n) +} + +func (t *Traverser) ExprYieldFrom(n *ast.ExprYieldFrom) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastArray(n *ast.ExprCastArray) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastBool(n *ast.ExprCastBool) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastDouble(n *ast.ExprCastDouble) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastInt(n *ast.ExprCastInt) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastObject(n *ast.ExprCastObject) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastString(n *ast.ExprCastString) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprCastUnset(n *ast.ExprCastUnset) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprAssign(n *ast.ExprAssign) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignReference(n *ast.ExprAssignReference) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignBitwiseAnd(n *ast.ExprAssignBitwiseAnd) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignBitwiseOr(n *ast.ExprAssignBitwiseOr) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignBitwiseXor(n *ast.ExprAssignBitwiseXor) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignCoalesce(n *ast.ExprAssignCoalesce) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignConcat(n *ast.ExprAssignConcat) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignDiv(n *ast.ExprAssignDiv) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignMinus(n *ast.ExprAssignMinus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignMod(n *ast.ExprAssignMod) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignMul(n *ast.ExprAssignMul) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignPlus(n *ast.ExprAssignPlus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignPow(n *ast.ExprAssignPow) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignShiftLeft(n *ast.ExprAssignShiftLeft) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprAssignShiftRight(n *ast.ExprAssignShiftRight) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.Traverse(n.Var) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryBitwiseAnd(n *ast.ExprBinaryBitwiseAnd) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryBitwiseOr(n *ast.ExprBinaryBitwiseOr) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryBitwiseXor(n *ast.ExprBinaryBitwiseXor) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryBooleanAnd(n *ast.ExprBinaryBooleanAnd) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryBooleanOr(n *ast.ExprBinaryBooleanOr) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryCoalesce(n *ast.ExprBinaryCoalesce) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryConcat(n *ast.ExprBinaryConcat) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryDiv(n *ast.ExprBinaryDiv) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryEqual(n *ast.ExprBinaryEqual) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryGreater(n *ast.ExprBinaryGreater) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryGreaterOrEqual(n *ast.ExprBinaryGreaterOrEqual) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryIdentical(n *ast.ExprBinaryIdentical) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryLogicalAnd(n *ast.ExprBinaryLogicalAnd) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryLogicalOr(n *ast.ExprBinaryLogicalOr) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryLogicalXor(n *ast.ExprBinaryLogicalXor) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryMinus(n *ast.ExprBinaryMinus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryMod(n *ast.ExprBinaryMod) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryMul(n *ast.ExprBinaryMul) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryNotEqual(n *ast.ExprBinaryNotEqual) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryNotIdentical(n *ast.ExprBinaryNotIdentical) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryPlus(n *ast.ExprBinaryPlus) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryPow(n *ast.ExprBinaryPow) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryShiftLeft(n *ast.ExprBinaryShiftLeft) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinaryShiftRight(n *ast.ExprBinaryShiftRight) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinarySmaller(n *ast.ExprBinarySmaller) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinarySmallerOrEqual(n *ast.ExprBinarySmallerOrEqual) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprBinarySpaceship(n *ast.ExprBinarySpaceship) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Left) + + t.Traverse(n.Right) + + t.leave(n) +} + +func (t *Traverser) ExprMatch(n *ast.ExprMatch) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Arms { + nn.Accept(t) + } + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) ExprThrow(n *ast.ExprThrow) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.Traverse(n.Expr) + + t.leave(n) +} + +func (t *Traverser) MatchArm(n *ast.MatchArm) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Exprs { + nn.Accept(t) + } + + t.Traverse(n.ReturnExpr) + + t.leave(n) +} + +func (t *Traverser) NameName(n *ast.Name) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) NameFullyQualified(n *ast.NameFullyQualified) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) NameRelative(n *ast.NameRelative) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + for _, nn := range n.Parts { + nn.Accept(t) + } + + t.leave(n) +} + +func (t *Traverser) NameNamePart(n *ast.NamePart) { + if !t.checkEntrance(n) { + return + } + + n.Accept(t.v) + + t.leave(n) +} diff --git a/pkg/visitor/traverser/traverser_test.go b/pkg/visitor/traverser/traverser_test.go new file mode 100644 index 0000000..453505c --- /dev/null +++ b/pkg/visitor/traverser/traverser_test.go @@ -0,0 +1,67 @@ +package traverser_test + +import ( + "testing" + + "github.com/VKCOM/php-parser/pkg/ast" + "github.com/VKCOM/php-parser/pkg/visitor" + "github.com/VKCOM/php-parser/pkg/visitor/traverser" +) + +// testCase is a traverser that does not go into any class statement or its children. +// If it does, the test fails. +type testCase struct { + t *testing.T + visitor.Null + traversedFunction bool +} + +var _ ast.Visitor = &testCase{} + +func (t *testCase) EnterNode(n ast.Vertex) bool { + t.t.Logf("EnterNode: %T", n) + if _, ok := n.(*ast.StmtClass); ok { + return false + } + + return true +} + +func (t *testCase) LeaveNode(n ast.Vertex) { + t.t.Logf("LeaveNode: %T", n) + if _, ok := n.(*ast.Root); ok { + if !t.traversedFunction { + t.t.Error("traverser did not traverse function") + } + } +} + +func (t *testCase) StmtClass(n *ast.StmtClass) { + t.t.Errorf("traverser got to class") +} + +func (t *testCase) StmtClassMethod(n *ast.StmtClassMethod) { + t.t.Errorf("traverser got to method") +} + +func (t *testCase) StmtFunction(n *ast.StmtFunction) { + t.traversedFunction = true +} + +func TestEnterNodeIsRespected(t *testing.T) { + tc := &testCase{t: t} + tv := traverser.NewTraverser(tc) + + root := &ast.Root{ + Stmts: []ast.Vertex{ + &ast.StmtFunction{}, + &ast.StmtClass{ + Stmts: []ast.Vertex{ + &ast.StmtClassMethod{}, + }, + }, + }, + } + + root.Accept(tv) +}