package parseutil import ( "errors" "fmt" "reflect" "github.com/z7zmey/php-parser/node" "github.com/z7zmey/php-parser/node/expr" "github.com/z7zmey/php-parser/node/expr/assign" "github.com/z7zmey/php-parser/node/expr/binary" "github.com/z7zmey/php-parser/node/expr/cast" "github.com/z7zmey/php-parser/node/name" "github.com/z7zmey/php-parser/node/scalar" "github.com/z7zmey/php-parser/node/stmt" ) func MutatingWalkerNoop(n *node.Node) error { return nil } var ( ErrDoNotWalkDeeper = errors.New("ErrDoNotWalkDeeper") ) // MutatingWalker walks the AST by pointer to interface. // This allows for modification of interior AST nodes while walking, unlike the // upstream php-parser.Walker() interface that walks by value. type MutatingWalker struct { EnterNode func(n *node.Node) error LeaveNode func(n *node.Node) error } // func (mw MutatingWalker) walkEach(pNodes ...*node.Node) error { for _, pNode := range pNodes { err := mw.walkSingle(pNode) if err != nil { return err } } return nil } func (mw MutatingWalker) walkSlice(arr []node.Node) error { for idx, _ := range arr { err := mw.walkSingle(&arr[idx]) if err != nil { return err } } return nil } func (mw MutatingWalker) walkSingle(n *node.Node) error { err := mw.EnterNode(n) if err != nil { if err == ErrDoNotWalkDeeper { return nil } return err } if *n == nil || reflect.ValueOf(*n).IsNil() { // don't enter it } else { err = switchExhaustive(mw, n) if err != nil { return err } } err = mw.LeaveNode(n) if err != nil { return err } return nil } // node func (mw MutatingWalker) handleNodeRoot(n *node.Root) error { return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleNodeIdentifier(n *node.Identifier) error { return nil } func (mw MutatingWalker) handleNodeParameter(n *node.Parameter) error { return mw.walkEach(&n.DefaultValue, &n.Variable, &n.VariableType) } func (mw MutatingWalker) handleNodeNullable(n *node.Nullable) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleNodeArgument(n *node.Argument) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleNodeArgumentList(n *node.ArgumentList) error { return mw.walkSlice(n.Arguments) } // name func (mw MutatingWalker) handleNameNamePart(n *name.NamePart) error { return nil } func (mw MutatingWalker) handleNameName(n *name.Name) error { return mw.walkSlice(n.Parts) } func (mw MutatingWalker) handleNameFullyQualified(n *name.FullyQualified) error { return mw.walkSlice(n.Parts) } func (mw MutatingWalker) handleNameRelative(n *name.Relative) error { return mw.walkSlice(n.Parts) } // scalar func (mw MutatingWalker) handleScalarLnumber(n *scalar.Lnumber) error { return nil } func (mw MutatingWalker) handleScalarDnumber(n *scalar.Dnumber) error { return nil } func (mw MutatingWalker) handleScalarString(n *scalar.String) error { return nil } func (mw MutatingWalker) handleScalarEncapsedStringPart(n *scalar.EncapsedStringPart) error { return nil } func (mw MutatingWalker) handleScalarEncapsed(n *scalar.Encapsed) error { return mw.walkSlice(n.Parts) } func (mw MutatingWalker) handleScalarHeredoc(n *scalar.Heredoc) error { return mw.walkSlice(n.Parts) } func (mw MutatingWalker) handleScalarMagicConstant(n *scalar.MagicConstant) error { return nil } // assign func (mw MutatingWalker) handleAssign(n *assign.Assign) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignReference(n *assign.Reference) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignBitwiseAnd(n *assign.BitwiseAnd) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignBitwiseOr(n *assign.BitwiseOr) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignBitwiseXor(n *assign.BitwiseXor) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignCoalesce(n *assign.Coalesce) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignConcat(n *assign.Concat) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignDiv(n *assign.Div) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignMinus(n *assign.Minus) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignMod(n *assign.Mod) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignMul(n *assign.Mul) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignPlus(n *assign.Plus) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignPow(n *assign.Pow) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignShiftLeft(n *assign.ShiftLeft) error { return mw.walkEach(&n.Variable, &n.Expression) } func (mw MutatingWalker) handleAssignShiftRight(n *assign.ShiftRight) error { return mw.walkEach(&n.Variable, &n.Expression) } // binary func (mw MutatingWalker) handleBinaryBitwiseAnd(n *binary.BitwiseAnd) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryBitwiseOr(n *binary.BitwiseOr) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryBitwiseXor(n *binary.BitwiseXor) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryBooleanAnd(n *binary.BooleanAnd) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryBooleanOr(n *binary.BooleanOr) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryCoalesce(n *binary.Coalesce) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryConcat(n *binary.Concat) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryDiv(n *binary.Div) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryEqual(n *binary.Equal) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryGreaterOrEqual(n *binary.GreaterOrEqual) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryGreater(n *binary.Greater) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryIdentical(n *binary.Identical) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryLogicalAnd(n *binary.LogicalAnd) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryLogicalOr(n *binary.LogicalOr) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryLogicalXor(n *binary.LogicalXor) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryMinus(n *binary.Minus) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryMod(n *binary.Mod) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryMul(n *binary.Mul) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryNotEqual(n *binary.NotEqual) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryNotIdentical(n *binary.NotIdentical) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryPlus(n *binary.Plus) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryPow(n *binary.Pow) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryShiftLeft(n *binary.ShiftLeft) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinaryShiftRight(n *binary.ShiftRight) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinarySmallerOrEqual(n *binary.SmallerOrEqual) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinarySmaller(n *binary.Smaller) error { return mw.walkEach(&n.Left, &n.Right) } func (mw MutatingWalker) handleBinarySpaceship(n *binary.Spaceship) error { return mw.walkEach(&n.Left, &n.Right) } // cast func (mw MutatingWalker) handleCastArray(n *cast.Array) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastBool(n *cast.Bool) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastDouble(n *cast.Double) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastInt(n *cast.Int) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastObject(n *cast.Object) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastString(n *cast.String) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleCastUnset(n *cast.Unset) error { return mw.walkSingle(&n.Expr) } // expr func (mw MutatingWalker) handleExprArrayDimFetch(n *expr.ArrayDimFetch) error { return mw.walkEach(&n.Dim, &n.Variable) } func (mw MutatingWalker) handleExprArrayItem(n *expr.ArrayItem) error { return mw.walkEach(&n.Key, &n.Val) } func (mw MutatingWalker) handleExprArray(n *expr.Array) error { return mw.walkSlice(n.Items) } func (mw MutatingWalker) handleExprArrowFunction(n *expr.ArrowFunction) error { err := mw.walkSlice(n.Params) if err != nil { return err } return mw.walkEach(&n.Expr, &n.ReturnType) } func (mw MutatingWalker) handleExprBitwiseNot(n *expr.BitwiseNot) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprBooleanNot(n *expr.BooleanNot) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprClassConstFetch(n *expr.ClassConstFetch) error { return mw.walkEach(&n.Class, &n.ConstantName) } func (mw MutatingWalker) handleExprClone(n *expr.Clone) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprClosureUse(n *expr.ClosureUse) error { return mw.walkSlice(n.Uses) } func (mw MutatingWalker) handleExprClosure(n *expr.Closure) error { err := mw.walkSlice(n.Params) if err != nil { return err } err = mw.walkSlice(n.Stmts) if err != nil { return err } // n.ClosureUse is not boxed as a node.Node // Box it, and then reinstate it after we have handled all *node.Node types var boxedClosureUse node.Node = n.ClosureUse err = mw.walkEach(&boxedClosureUse, &n.ReturnType) if err != nil { return err } cu, ok := boxedClosureUse.(*expr.ClosureUse) if !ok { return fmt.Errorf("illegal modification from '*expr.ClosureUse' to incompatible type '%t'", boxedClosureUse) } n.ClosureUse = cu // reinstate // Done return nil } func (mw MutatingWalker) handleExprConstFetch(n *expr.ConstFetch) error { return mw.walkSingle(&n.Constant) } func (mw MutatingWalker) handleExprEmpty(n *expr.Empty) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprErrorSuppress(n *expr.ErrorSuppress) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprEval(n *expr.Eval) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprExit(n *expr.Exit) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprFunctionCall(n *expr.FunctionCall) error { var boxedArgumentList node.Node = n.ArgumentList err := mw.walkEach(&boxedArgumentList, &n.Function) if err != nil { return err } al, ok := boxedArgumentList.(*node.ArgumentList) if !ok { return fmt.Errorf("illegal modification from '*node.ArgumentList' to incompatible type '%t'", boxedArgumentList) } n.ArgumentList = al // reinstate return nil } func (mw MutatingWalker) handleExprInclude(n *expr.Include) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprIncludeOnce(n *expr.IncludeOnce) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprInstanceOf(n *expr.InstanceOf) error { return mw.walkEach(&n.Class, &n.Expr) } func (mw MutatingWalker) handleExprIsset(n *expr.Isset) error { return mw.walkSlice(n.Variables) } func (mw MutatingWalker) handleExprList(n *expr.List) error { return mw.walkSlice(n.Items) } func (mw MutatingWalker) handleExprMethodCall(n *expr.MethodCall) error { var boxedArgumentList node.Node = n.ArgumentList err := mw.walkEach(&boxedArgumentList, &n.Method, &n.Variable) if err != nil { return err } al, ok := boxedArgumentList.(*node.ArgumentList) if !ok { return fmt.Errorf("illegal modification from '*node.ArgumentList' to incompatible type '%t'", boxedArgumentList) } n.ArgumentList = al // reinstate return nil } func (mw MutatingWalker) handleExprNew(n *expr.New) error { var boxedArgumentList node.Node = n.ArgumentList err := mw.walkEach(&boxedArgumentList, &n.Class) if err != nil { return err } al, ok := boxedArgumentList.(*node.ArgumentList) if !ok { return fmt.Errorf("illegal modification from '*node.ArgumentList' to incompatible type '%t'", boxedArgumentList) } n.ArgumentList = al // reinstate return nil } func (mw MutatingWalker) handleExprPostDec(n *expr.PostDec) error { return mw.walkSingle(&n.Variable) } func (mw MutatingWalker) handleExprPostInc(n *expr.PostInc) error { return mw.walkSingle(&n.Variable) } func (mw MutatingWalker) handleExprPreDec(n *expr.PreDec) error { return mw.walkSingle(&n.Variable) } func (mw MutatingWalker) handleExprPreInc(n *expr.PreInc) error { return mw.walkSingle(&n.Variable) } func (mw MutatingWalker) handleExprPrint(n *expr.Print) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprPropertyFetch(n *expr.PropertyFetch) error { return mw.walkEach(&n.Property, &n.Variable) } func (mw MutatingWalker) handleExprReference(n *expr.Reference) error { return mw.walkSingle(&n.Variable) } func (mw MutatingWalker) handleExprRequire(n *expr.Require) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprRequireOnce(n *expr.RequireOnce) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprShellExec(n *expr.ShellExec) error { return mw.walkSlice(n.Parts) } func (mw MutatingWalker) handleExprShortArray(n *expr.ShortArray) error { return mw.walkSlice(n.Items) } func (mw MutatingWalker) handleExprShortList(n *expr.ShortList) error { return mw.walkSlice(n.Items) } func (mw MutatingWalker) handleExprStaticCall(n *expr.StaticCall) error { var boxedArgumentList node.Node = n.ArgumentList err := mw.walkEach(&boxedArgumentList, &n.Call, &n.Class) if err != nil { return err } al, ok := boxedArgumentList.(*node.ArgumentList) if !ok { return fmt.Errorf("illegal modification from '*node.ArgumentList' to incompatible type '%t'", boxedArgumentList) } n.ArgumentList = al // reinstate return nil } func (mw MutatingWalker) handleExprStaticPropertyFetch(n *expr.StaticPropertyFetch) error { return mw.walkEach(&n.Class, &n.Property) } func (mw MutatingWalker) handleExprTernary(n *expr.Ternary) error { return mw.walkEach(&n.Condition, &n.IfTrue, &n.IfFalse) } func (mw MutatingWalker) handleExprUnaryMinus(n *expr.UnaryMinus) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprUnaryPlus(n *expr.UnaryPlus) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprVariable(n *expr.Variable) error { return mw.walkSingle(&n.VarName) } func (mw MutatingWalker) handleExprYieldFrom(n *expr.YieldFrom) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleExprYield(n *expr.Yield) error { return mw.walkEach(&n.Key, &n.Value) } // stmt func (mw MutatingWalker) handleStmtAltElse(n *stmt.AltElse) error { return mw.walkSingle(&n.Stmt) } func (mw MutatingWalker) handleStmtAltElseIf(n *stmt.AltElseIf) error { return mw.walkEach(&n.Cond, &n.Stmt) } func (mw MutatingWalker) handleStmtAltFor(n *stmt.AltFor) error { err := mw.walkSlice(n.Cond) if err != nil { return err } err = mw.walkSlice(n.Init) if err != nil { return err } err = mw.walkSlice(n.Loop) if err != nil { return err } return mw.walkSingle(&n.Stmt) } func (mw MutatingWalker) handleStmtAltForeach(n *stmt.AltForeach) error { return mw.walkEach(&n.Expr, &n.Key, &n.Stmt, &n.Variable) } func (mw MutatingWalker) handleStmtAltIf(n *stmt.AltIf) error { err := mw.walkSlice(n.ElseIf) if err != nil { return err } return mw.walkEach(&n.Cond, &n.Else, &n.Stmt) } func (mw MutatingWalker) handleStmtAltSwitch(n *stmt.AltSwitch) error { var boxedCaseList node.Node = n.CaseList err := mw.walkEach(&boxedCaseList, &n.Cond) if err != nil { return err } cl, ok := boxedCaseList.(*stmt.CaseList) if !ok { return fmt.Errorf("illegal modification from '*stmt.CaseList' to incompatible type '%t'", boxedCaseList) } n.CaseList = cl // reinstate return nil } func (mw MutatingWalker) handleStmtAltWhile(n *stmt.AltWhile) error { return mw.walkEach(&n.Cond, &n.Stmt) } func (mw MutatingWalker) handleStmtBreak(n *stmt.Break) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleStmtCase(n *stmt.Case) error { err := mw.walkSlice(n.Stmts) if err != nil { return err } return mw.walkSingle(&n.Cond) } func (mw MutatingWalker) handleStmtCaseList(n *stmt.CaseList) error { return mw.walkSlice(n.Cases) } func (mw MutatingWalker) handleStmtCatch(n *stmt.Catch) error { err := mw.walkSlice(n.Types) if err != nil { return err } err = mw.walkSingle(&n.Variable) if err != nil { return err } return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtClass(n *stmt.Class) error { var ( boxedArgumentList node.Node = n.ArgumentList boxedClassExtends node.Node = n.Extends boxedClassImplements node.Node = n.Implements ) err := mw.walkEach(&n.ClassName, &boxedArgumentList, &boxedClassExtends, &boxedClassImplements) if err != nil { return err } al, ok := boxedArgumentList.(*node.ArgumentList) if !ok { return fmt.Errorf("illegal modification from '*node.ArgumentList' to incompatible type '%t'", boxedArgumentList) } n.ArgumentList = al // reinstate ce, ok := boxedClassExtends.(*stmt.ClassExtends) if !ok { return fmt.Errorf("illegal modification from '*stmt.ClassExtends' to incompatible type '%t'", boxedClassExtends) } n.Extends = ce // reinstate ci, ok := boxedClassImplements.(*stmt.ClassImplements) if !ok { return fmt.Errorf("illegal modification from '*stmt.ClassImplements' to incompatible type '%t'", boxedClassImplements) } n.Implements = ci // reinstate // err = mw.walkSlice(n.Modifiers) if err != nil { return err } return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtClassExtends(n *stmt.ClassExtends) error { return mw.walkSingle(&n.ClassName) } func (mw MutatingWalker) handleStmtClassImplements(n *stmt.ClassImplements) error { return mw.walkSlice(n.InterfaceNames) } func (mw MutatingWalker) handleStmtClassMethod(n *stmt.ClassMethod) error { err := mw.walkEach(&n.MethodName, &n.ReturnType) if err != nil { return err } err = mw.walkSlice(n.Modifiers) if err != nil { return err } err = mw.walkSlice(n.Params) if err != nil { return err } return mw.walkSingle(&n.Stmt) // we could have embedded it in the leading walkEach, but, try and keep the ordering a little bit } func (mw MutatingWalker) handleStmtClassConstList(n *stmt.ClassConstList) error { err := mw.walkSlice(n.Modifiers) if err != nil { return err } return mw.walkSlice(n.Consts) } func (mw MutatingWalker) handleStmtConstList(n *stmt.ConstList) error { return mw.walkSlice(n.Consts) } func (mw MutatingWalker) handleStmtConstant(n *stmt.Constant) error { return mw.walkEach(&n.ConstantName, &n.Expr) } func (mw MutatingWalker) handleStmtContinue(n *stmt.Continue) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleStmtDeclare(n *stmt.Declare) error { err := mw.walkSlice(n.Consts) if err != nil { return err } return mw.walkSingle(&n.Stmt) } func (mw MutatingWalker) handleStmtDefault(n *stmt.Default) error { return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtDo(n *stmt.Do) error { return mw.walkEach(&n.Stmt, &n.Cond) } func (mw MutatingWalker) handleStmtEcho(n *stmt.Echo) error { return mw.walkSlice(n.Exprs) } func (mw MutatingWalker) handleStmtElseIf(n *stmt.ElseIf) error { return mw.walkEach(&n.Cond, &n.Stmt) } func (mw MutatingWalker) handleStmtElse(n *stmt.Else) error { return mw.walkEach(&n.Stmt) } func (mw MutatingWalker) handleStmtExpression(n *stmt.Expression) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleStmtFinally(n *stmt.Finally) error { return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtFor(n *stmt.For) error { err := mw.walkSlice(n.Cond) if err != nil { return err } err = mw.walkSlice(n.Init) if err != nil { return err } err = mw.walkSlice(n.Loop) if err != nil { return err } return mw.walkSingle(&n.Stmt) } func (mw MutatingWalker) handleStmtForeach(n *stmt.Foreach) error { return mw.walkEach(&n.Expr, &n.Key, &n.Stmt, &n.Variable) } func (mw MutatingWalker) handleStmtFunction(n *stmt.Function) error { err := mw.walkEach(&n.FunctionName, &n.ReturnType) if err != nil { return err } err = mw.walkSlice(n.Params) if err != nil { return err } return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtGlobal(n *stmt.Global) error { return mw.walkSlice(n.Vars) } func (mw MutatingWalker) handleStmtGoto(n *stmt.Goto) error { return mw.walkSingle(&n.Label) } func (mw MutatingWalker) handleStmtGroupUse(n *stmt.GroupUse) error { err := mw.walkEach(&n.Prefix, &n.UseType) if err != nil { return err } return mw.walkSlice(n.UseList) } func (mw MutatingWalker) handleStmtHaltCompiler(n *stmt.HaltCompiler) error { return nil } func (mw MutatingWalker) handleStmtIf(n *stmt.If) error { err := mw.walkEach(&n.Cond, &n.Stmt) if err != nil { return err } err = mw.walkSlice(n.ElseIf) if err != nil { return err } return mw.walkSingle(&n.Else) } func (mw MutatingWalker) handleStmtInlineHtml(n *stmt.InlineHtml) error { return nil } func (mw MutatingWalker) handleStmtInterface(n *stmt.Interface) error { var boxedInterfaceExtends node.Node = n.Extends err := mw.walkEach(&n.InterfaceName, &boxedInterfaceExtends) if err != nil { return err } ie, ok := boxedInterfaceExtends.(*stmt.InterfaceExtends) if !ok { return fmt.Errorf("illegal modification from '*stmt.InterfaceExtends' to incompatible type '%t'", boxedInterfaceExtends) } n.Extends = ie // reinstate // return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtInterfaceExtends(n *stmt.InterfaceExtends) error { return mw.walkSlice(n.InterfaceNames) } func (mw MutatingWalker) handleStmtLabel(n *stmt.Label) error { return mw.walkSingle(&n.LabelName) } func (mw MutatingWalker) handleStmtNamespace(n *stmt.Namespace) error { err := mw.walkSingle(&n.NamespaceName) if err != nil { return err } return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtNop(n *stmt.Nop) error { return nil } func (mw MutatingWalker) handleStmtPropertyList(n *stmt.PropertyList) error { err := mw.walkSlice(n.Modifiers) if err != nil { return err } err = mw.walkSingle(&n.Type) if err != nil { return err } return mw.walkSlice(n.Properties) } func (mw MutatingWalker) handleStmtProperty(n *stmt.Property) error { return mw.walkEach(&n.Expr, &n.Variable) } func (mw MutatingWalker) handleStmtReturn(n *stmt.Return) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleStmtStaticVar(n *stmt.StaticVar) error { return mw.walkEach(&n.Variable, &n.Expr) } func (mw MutatingWalker) handleStmtStatic(n *stmt.Static) error { return mw.walkSlice(n.Vars) } func (mw MutatingWalker) handleStmtStmtList(n *stmt.StmtList) error { for i, _ := range n.Stmts { mw.walkSingle(&n.Stmts[i]) } return nil } func (mw MutatingWalker) handleStmtSwitch(n *stmt.Switch) error { var boxedCaseList node.Node = n.CaseList err := mw.walkEach(&boxedCaseList, &n.Cond) if err != nil { return err } cl, ok := boxedCaseList.(*stmt.CaseList) if !ok { return fmt.Errorf("illegal modification from '*stmt.CaseList' to incompatible type '%t'", boxedCaseList) } n.CaseList = cl // reinstate return nil } func (mw MutatingWalker) handleStmtThrow(n *stmt.Throw) error { return mw.walkSingle(&n.Expr) } func (mw MutatingWalker) handleStmtTraitAdaptationList(n *stmt.TraitAdaptationList) error { return mw.walkSlice(n.Adaptations) } func (mw MutatingWalker) handleStmtTraitMethodRef(n *stmt.TraitMethodRef) error { return mw.walkEach(&n.Method, &n.Trait) } func (mw MutatingWalker) handleStmtTraitUseAlias(n *stmt.TraitUseAlias) error { return mw.walkEach(&n.Alias, &n.Modifier, &n.Ref) } func (mw MutatingWalker) handleStmtTraitUsePrecedence(n *stmt.TraitUsePrecedence) error { err := mw.walkSlice(n.Insteadof) if err != nil { return err } return mw.walkSingle(&n.Ref) } func (mw MutatingWalker) handleStmtTraitUse(n *stmt.TraitUse) error { err := mw.walkSingle(&n.TraitAdaptationList) if err != nil { return err } return mw.walkSlice(n.Traits) } func (mw MutatingWalker) handleStmtTrait(n *stmt.Trait) error { err := mw.walkSingle(&n.TraitName) if err != nil { return err } return mw.walkSlice(n.Stmts) } func (mw MutatingWalker) handleStmtTry(n *stmt.Try) error { err := mw.walkSlice(n.Stmts) if err != nil { return err } err = mw.walkSlice(n.Catches) if err != nil { return err } return mw.walkSingle(&n.Finally) } func (mw MutatingWalker) handleStmtUnset(n *stmt.Unset) error { return mw.walkSlice(n.Vars) } func (mw MutatingWalker) handleStmtUseList(n *stmt.UseList) error { err := mw.walkSlice(n.Uses) if err != nil { return err } return mw.walkSingle(&n.UseType) } func (mw MutatingWalker) handleStmtUse(n *stmt.Use) error { return mw.walkEach(&n.Alias, &n.Use, &n.UseType) } func (mw MutatingWalker) handleStmtWhile(n *stmt.While) error { return mw.walkEach(&n.Cond, &n.Stmt) } var _ Exhaustive = MutatingWalker{} // interface assertion // func (mw MutatingWalker) Walk(n *node.Node) error { return mw.walkSingle(n) }