diff --git a/exhaustive.go b/exhaustive.go new file mode 100644 index 0000000..8410339 --- /dev/null +++ b/exhaustive.go @@ -0,0 +1,588 @@ +package main + +import ( + "fmt" + + "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" +) + +// Exuhastive is an interface that makes sure there is a case for every possible +// PHP AST node type. +type Exhaustive interface { + + // node + + handleNodeRoot(*node.Root) error + handleNodeIdentifier(*node.Identifier) error + handleNodeParameter(*node.Parameter) error + handleNodeNullable(*node.Nullable) error + handleNodeArgument(*node.Argument) error + handleNodeArgumentList(*node.ArgumentList) error + + // name + + handleNameNamePart(*name.NamePart) error + handleNameName(*name.Name) error + handleNameFullyQualified(*name.FullyQualified) error + handleNameRelative(*name.Relative) error + + // scalar + + handleScalarLnumber(*scalar.Lnumber) error + handleScalarDnumber(*scalar.Dnumber) error + handleScalarString(*scalar.String) error + handleScalarEncapsedStringPart(*scalar.EncapsedStringPart) error + handleScalarEncapsed(*scalar.Encapsed) error + handleScalarHeredoc(*scalar.Heredoc) error + handleScalarMagicConstant(*scalar.MagicConstant) error + + // assign + + handleAssign(*assign.Assign) error + handleAssignReference(*assign.Reference) error + handleAssignBitwiseAnd(*assign.BitwiseAnd) error + handleAssignBitwiseOr(*assign.BitwiseOr) error + handleAssignBitwiseXor(*assign.BitwiseXor) error + handleAssignCoalesce(*assign.Coalesce) error + handleAssignConcat(*assign.Concat) error + handleAssignDiv(*assign.Div) error + handleAssignMinus(*assign.Minus) error + handleAssignMod(*assign.Mod) error + handleAssignMul(*assign.Mul) error + handleAssignPlus(*assign.Plus) error + handleAssignPow(*assign.Pow) error + handleAssignShiftLeft(*assign.ShiftLeft) error + handleAssignShiftRight(*assign.ShiftRight) error + + // binary + + handleBinaryBitwiseAnd(*binary.BitwiseAnd) error + handleBinaryBitwiseOr(*binary.BitwiseOr) error + handleBinaryBitwiseXor(*binary.BitwiseXor) error + handleBinaryBooleanAnd(*binary.BooleanAnd) error + handleBinaryBooleanOr(*binary.BooleanOr) error + handleBinaryCoalesce(*binary.Coalesce) error + handleBinaryConcat(*binary.Concat) error + handleBinaryDiv(*binary.Div) error + handleBinaryEqual(*binary.Equal) error + handleBinaryGreaterOrEqual(*binary.GreaterOrEqual) error + handleBinaryGreater(*binary.Greater) error + handleBinaryIdentical(*binary.Identical) error + handleBinaryLogicalAnd(*binary.LogicalAnd) error + handleBinaryLogicalOr(*binary.LogicalOr) error + handleBinaryLogicalXor(*binary.LogicalXor) error + handleBinaryMinus(*binary.Minus) error + handleBinaryMod(*binary.Mod) error + handleBinaryMul(*binary.Mul) error + handleBinaryNotEqual(*binary.NotEqual) error + handleBinaryNotIdentical(*binary.NotIdentical) error + handleBinaryPlus(*binary.Plus) error + handleBinaryPow(*binary.Pow) error + handleBinaryShiftLeft(*binary.ShiftLeft) error + handleBinaryShiftRight(*binary.ShiftRight) error + handleBinarySmallerOrEqual(*binary.SmallerOrEqual) error + handleBinarySmaller(*binary.Smaller) error + handleBinarySpaceship(*binary.Spaceship) error + + // cast + + handleCastArray(*cast.Array) error + handleCastBool(*cast.Bool) error + handleCastDouble(*cast.Double) error + handleCastInt(*cast.Int) error + handleCastObject(*cast.Object) error + handleCastString(*cast.String) error + handleCastUnset(*cast.Unset) error + + // expr + + handleExprArrayDimFetch(*expr.ArrayDimFetch) error + handleExprArrayItem(*expr.ArrayItem) error + handleExprArray(*expr.Array) error + handleExprArrowFunction(*expr.ArrowFunction) error + handleExprBitwiseNot(*expr.BitwiseNot) error + handleExprBooleanNot(*expr.BooleanNot) error + handleExprClassConstFetch(*expr.ClassConstFetch) error + handleExprClone(*expr.Clone) error + handleExprClosureUse(*expr.ClosureUse) error + handleExprClosure(*expr.Closure) error + handleExprConstFetch(*expr.ConstFetch) error + handleExprEmpty(*expr.Empty) error + handleExprErrorSuppress(*expr.ErrorSuppress) error + handleExprEval(*expr.Eval) error + handleExprExit(*expr.Exit) error + handleExprFunctionCall(*expr.FunctionCall) error + handleExprInclude(*expr.Include) error + handleExprIncludeOnce(*expr.IncludeOnce) error + handleExprInstanceOf(*expr.InstanceOf) error + handleExprIsset(*expr.Isset) error + handleExprList(*expr.List) error + handleExprMethodCall(*expr.MethodCall) error + handleExprNew(*expr.New) error + handleExprPostDec(*expr.PostDec) error + handleExprPostInc(*expr.PostInc) error + handleExprPreDec(*expr.PreDec) error + handleExprPreInc(*expr.PreInc) error + handleExprPrint(*expr.Print) error + handleExprPropertyFetch(*expr.PropertyFetch) error + handleExprReference(*expr.Reference) error + handleExprRequire(*expr.Require) error + handleExprRequireOnce(*expr.RequireOnce) error + handleExprShellExec(*expr.ShellExec) error + handleExprShortArray(*expr.ShortArray) error + handleExprShortList(*expr.ShortList) error + handleExprStaticCall(*expr.StaticCall) error + handleExprStaticPropertyFetch(*expr.StaticPropertyFetch) error + handleExprTernary(*expr.Ternary) error + handleExprUnaryMinus(*expr.UnaryMinus) error + handleExprUnaryPlus(*expr.UnaryPlus) error + handleExprVariable(*expr.Variable) error + handleExprYieldFrom(*expr.YieldFrom) error + handleExprYield(*expr.Yield) error + + // stmt + // grep -Ri 'struct {' stmt/* | sed -re 's/.*type (.+) struct.*/*stmt.\1/' | sort + + handleStmtAltElse(*stmt.AltElse) error + handleStmtAltElseIf(*stmt.AltElseIf) error + handleStmtAltFor(*stmt.AltFor) error + handleStmtAltForeach(*stmt.AltForeach) error + handleStmtAltIf(*stmt.AltIf) error + handleStmtAltSwitch(*stmt.AltSwitch) error + handleStmtAltWhile(*stmt.AltWhile) error + handleStmtBreak(*stmt.Break) error + handleStmtCase(*stmt.Case) error + handleStmtCaseList(*stmt.CaseList) error + handleStmtCatch(*stmt.Catch) error + handleStmtClass(*stmt.Class) error + handleStmtClassExtends(*stmt.ClassExtends) error + handleStmtClassImplements(*stmt.ClassImplements) error + handleStmtClassMethod(*stmt.ClassMethod) error + handleStmtClassConstList(*stmt.ClassConstList) error + handleStmtConstList(*stmt.ConstList) error + handleStmtConstant(*stmt.Constant) error + handleStmtContinue(*stmt.Continue) error + handleStmtDeclare(*stmt.Declare) error + handleStmtDefault(*stmt.Default) error + handleStmtDo(*stmt.Do) error + handleStmtEcho(*stmt.Echo) error + handleStmtElseIf(*stmt.ElseIf) error + handleStmtElse(*stmt.Else) error + handleStmtExpression(*stmt.Expression) error + handleStmtFinally(*stmt.Finally) error + handleStmtFor(*stmt.For) error + handleStmtForeach(*stmt.Foreach) error + handleStmtFunction(*stmt.Function) error + handleStmtGlobal(*stmt.Global) error + handleStmtGoto(*stmt.Goto) error + handleStmtGroupUse(*stmt.GroupUse) error + handleStmtHaltCompiler(*stmt.HaltCompiler) error + handleStmtIf(*stmt.If) error + handleStmtInlineHtml(*stmt.InlineHtml) error + handleStmtInterface(*stmt.Interface) error + handleStmtInterfaceExtends(*stmt.InterfaceExtends) error + handleStmtLabel(*stmt.Label) error + handleStmtNamespace(*stmt.Namespace) error + handleStmtNop(*stmt.Nop) error + handleStmtPropertyList(*stmt.PropertyList) error + handleStmtProperty(*stmt.Property) error + handleStmtReturn(*stmt.Return) error + handleStmtStaticVar(*stmt.StaticVar) error + handleStmtStatic(*stmt.Static) error + handleStmtStmtList(*stmt.StmtList) error + handleStmtSwitch(*stmt.Switch) error + handleStmtThrow(*stmt.Throw) error + handleStmtTraitAdaptationList(*stmt.TraitAdaptationList) error + handleStmtTraitMethodRef(*stmt.TraitMethodRef) error + handleStmtTraitUseAlias(*stmt.TraitUseAlias) error + handleStmtTraitUsePrecedence(*stmt.TraitUsePrecedence) error + handleStmtTraitUse(*stmt.TraitUse) error + handleStmtTrait(*stmt.Trait) error + handleStmtTry(*stmt.Try) error + handleStmtUnset(*stmt.Unset) error + handleStmtUseList(*stmt.UseList) error + handleStmtUse(*stmt.Use) error + handleStmtWhile(*stmt.While) error +} + +func switchExhaustive(e Exhaustive, n_ *node.Node) error { + n := *n_ // no copy + + switch n := n.(type) { + + // node + + case *node.Argument: + return e.handleNodeArgument(n) + case *node.ArgumentList: + return e.handleNodeArgumentList(n) + case *node.Identifier: + return e.handleNodeIdentifier(n) + case *node.Nullable: + return e.handleNodeNullable(n) + case *node.Parameter: + return e.handleNodeParameter(n) + case *node.Root: + return e.handleNodeRoot(n) + + // name + + case *name.FullyQualified: + return e.handleNameFullyQualified(n) + case *name.Name: + return e.handleNameName(n) + case *name.NamePart: + return e.handleNameNamePart(n) + // case *name.Names: // that's an interface + case *name.Relative: + return e.handleNameRelative(n) + + // scalar + + case *scalar.Dnumber: + return e.handleScalarDnumber(n) + case *scalar.Encapsed: + return e.handleScalarEncapsed(n) + case *scalar.EncapsedStringPart: + return e.handleScalarEncapsedStringPart(n) + case *scalar.Heredoc: + return e.handleScalarHeredoc(n) + case *scalar.Lnumber: + return e.handleScalarLnumber(n) + case *scalar.MagicConstant: + return e.handleScalarMagicConstant(n) + case *scalar.String: + return e.handleScalarString(n) + + // assign + + case *assign.Assign: + return e.handleAssign(n) + case *assign.BitwiseAnd: + return e.handleAssignBitwiseAnd(n) + case *assign.BitwiseOr: + return e.handleAssignBitwiseOr(n) + case *assign.BitwiseXor: + return e.handleAssignBitwiseXor(n) + case *assign.Coalesce: + return e.handleAssignCoalesce(n) + case *assign.Concat: + return e.handleAssignConcat(n) + case *assign.Div: + return e.handleAssignDiv(n) + case *assign.Minus: + return e.handleAssignMinus(n) + case *assign.Mod: + return e.handleAssignMod(n) + case *assign.Mul: + return e.handleAssignMul(n) + case *assign.Plus: + return e.handleAssignPlus(n) + case *assign.Pow: + return e.handleAssignPow(n) + case *assign.Reference: + return e.handleAssignReference(n) + case *assign.ShiftLeft: + return e.handleAssignShiftLeft(n) + case *assign.ShiftRight: + return e.handleAssignShiftRight(n) + + // binary + + case *binary.BitwiseAnd: + return e.handleBinaryBitwiseAnd(n) + case *binary.BitwiseOr: + return e.handleBinaryBitwiseOr(n) + case *binary.BitwiseXor: + return e.handleBinaryBitwiseXor(n) + case *binary.BooleanAnd: + return e.handleBinaryBooleanAnd(n) + case *binary.BooleanOr: + return e.handleBinaryBooleanOr(n) + case *binary.Coalesce: + return e.handleBinaryCoalesce(n) + case *binary.Concat: + return e.handleBinaryConcat(n) + case *binary.Div: + return e.handleBinaryDiv(n) + case *binary.Equal: + return e.handleBinaryEqual(n) + case *binary.Greater: + return e.handleBinaryGreater(n) + case *binary.GreaterOrEqual: + return e.handleBinaryGreaterOrEqual(n) + case *binary.Identical: + return e.handleBinaryIdentical(n) + case *binary.LogicalAnd: + return e.handleBinaryLogicalAnd(n) + case *binary.LogicalOr: + return e.handleBinaryLogicalOr(n) + case *binary.LogicalXor: + return e.handleBinaryLogicalXor(n) + case *binary.Minus: + return e.handleBinaryMinus(n) + case *binary.Mod: + return e.handleBinaryMod(n) + case *binary.Mul: + return e.handleBinaryMul(n) + case *binary.NotEqual: + return e.handleBinaryNotEqual(n) + case *binary.NotIdentical: + return e.handleBinaryNotIdentical(n) + case *binary.Plus: + return e.handleBinaryPlus(n) + case *binary.Pow: + return e.handleBinaryPow(n) + case *binary.ShiftLeft: + return e.handleBinaryShiftLeft(n) + case *binary.ShiftRight: + return e.handleBinaryShiftRight(n) + case *binary.SmallerOrEqual: + return e.handleBinarySmallerOrEqual(n) + case *binary.Smaller: + return e.handleBinarySmaller(n) + case *binary.Spaceship: + return e.handleBinarySpaceship(n) + + // cast + + case *cast.Array: + return e.handleCastArray(n) + case *cast.Bool: + return e.handleCastBool(n) + case *cast.Double: + return e.handleCastDouble(n) + case *cast.Int: + return e.handleCastInt(n) + case *cast.Object: + return e.handleCastObject(n) + case *cast.String: + return e.handleCastString(n) + case *cast.Unset: + return e.handleCastUnset(n) + + // expr + + case *expr.Array: + return e.handleExprArray(n) + case *expr.ArrayDimFetch: + return e.handleExprArrayDimFetch(n) + case *expr.ArrayItem: + return e.handleExprArrayItem(n) + case *expr.ArrowFunction: + return e.handleExprArrowFunction(n) + case *expr.BitwiseNot: + return e.handleExprBitwiseNot(n) + case *expr.BooleanNot: + return e.handleExprBooleanNot(n) + case *expr.ClassConstFetch: + return e.handleExprClassConstFetch(n) + case *expr.Clone: + return e.handleExprClone(n) + case *expr.Closure: + return e.handleExprClosure(n) + case *expr.ClosureUse: + return e.handleExprClosureUse(n) + case *expr.ConstFetch: + return e.handleExprConstFetch(n) + case *expr.Empty: + return e.handleExprEmpty(n) + case *expr.ErrorSuppress: + return e.handleExprErrorSuppress(n) + case *expr.Eval: + return e.handleExprEval(n) + case *expr.Exit: + return e.handleExprExit(n) + case *expr.FunctionCall: + return e.handleExprFunctionCall(n) + case *expr.Include: + return e.handleExprInclude(n) + case *expr.IncludeOnce: + return e.handleExprIncludeOnce(n) + case *expr.InstanceOf: + return e.handleExprInstanceOf(n) + case *expr.Isset: + return e.handleExprIsset(n) + case *expr.List: + return e.handleExprList(n) + case *expr.MethodCall: + return e.handleExprMethodCall(n) + case *expr.New: + return e.handleExprNew(n) + case *expr.PostDec: + return e.handleExprPostDec(n) + case *expr.PostInc: + return e.handleExprPostInc(n) + case *expr.PreDec: + return e.handleExprPreDec(n) + case *expr.PreInc: + return e.handleExprPreInc(n) + case *expr.Print: + return e.handleExprPrint(n) + case *expr.PropertyFetch: + return e.handleExprPropertyFetch(n) + case *expr.Reference: + return e.handleExprReference(n) + case *expr.Require: + return e.handleExprRequire(n) + case *expr.RequireOnce: + return e.handleExprRequireOnce(n) + case *expr.ShellExec: + return e.handleExprShellExec(n) + case *expr.ShortArray: + return e.handleExprShortArray(n) + case *expr.ShortList: + return e.handleExprShortList(n) + case *expr.StaticCall: + return e.handleExprStaticCall(n) + case *expr.StaticPropertyFetch: + return e.handleExprStaticPropertyFetch(n) + case *expr.Ternary: + return e.handleExprTernary(n) + case *expr.UnaryMinus: + return e.handleExprUnaryMinus(n) + case *expr.UnaryPlus: + return e.handleExprUnaryPlus(n) + case *expr.Variable: + return e.handleExprVariable(n) + case *expr.Yield: + return e.handleExprYield(n) + case *expr.YieldFrom: + return e.handleExprYieldFrom(n) + + // stmt + + case *stmt.AltElse: + return e.handleStmtAltElse(n) + case *stmt.AltElseIf: + return e.handleStmtAltElseIf(n) + case *stmt.AltFor: + return e.handleStmtAltFor(n) + case *stmt.AltForeach: + return e.handleStmtAltForeach(n) + case *stmt.AltIf: + return e.handleStmtAltIf(n) + case *stmt.AltSwitch: + return e.handleStmtAltSwitch(n) + case *stmt.AltWhile: + return e.handleStmtAltWhile(n) + case *stmt.Break: + return e.handleStmtBreak(n) + case *stmt.Case: + return e.handleStmtCase(n) + case *stmt.CaseList: + return e.handleStmtCaseList(n) + case *stmt.Catch: + return e.handleStmtCatch(n) + case *stmt.Class: + return e.handleStmtClass(n) + case *stmt.ClassConstList: + return e.handleStmtClassConstList(n) + case *stmt.ClassExtends: + return e.handleStmtClassExtends(n) + case *stmt.ClassImplements: + return e.handleStmtClassImplements(n) + case *stmt.ClassMethod: + return e.handleStmtClassMethod(n) + case *stmt.Constant: + return e.handleStmtConstant(n) + case *stmt.ConstList: + return e.handleStmtConstList(n) + case *stmt.Continue: + return e.handleStmtContinue(n) + case *stmt.Declare: + return e.handleStmtDeclare(n) + case *stmt.Default: + return e.handleStmtDefault(n) + case *stmt.Do: + return e.handleStmtDo(n) + case *stmt.Echo: + return e.handleStmtEcho(n) + case *stmt.Else: + return e.handleStmtElse(n) + case *stmt.ElseIf: + return e.handleStmtElseIf(n) + case *stmt.Expression: + return e.handleStmtExpression(n) + case *stmt.Finally: + return e.handleStmtFinally(n) + case *stmt.For: + return e.handleStmtFor(n) + case *stmt.Foreach: + return e.handleStmtForeach(n) + case *stmt.Function: + return e.handleStmtFunction(n) + case *stmt.Global: + return e.handleStmtGlobal(n) + case *stmt.Goto: + return e.handleStmtGoto(n) + case *stmt.GroupUse: + return e.handleStmtGroupUse(n) + case *stmt.HaltCompiler: + return e.handleStmtHaltCompiler(n) + case *stmt.If: + return e.handleStmtIf(n) + case *stmt.InlineHtml: + return e.handleStmtInlineHtml(n) + case *stmt.Interface: + return e.handleStmtInterface(n) + case *stmt.InterfaceExtends: + return e.handleStmtInterfaceExtends(n) + case *stmt.Label: + return e.handleStmtLabel(n) + case *stmt.Namespace: + return e.handleStmtNamespace(n) + case *stmt.Nop: + return e.handleStmtNop(n) + case *stmt.Property: + return e.handleStmtProperty(n) + case *stmt.PropertyList: + return e.handleStmtPropertyList(n) + case *stmt.Return: + return e.handleStmtReturn(n) + case *stmt.Static: + return e.handleStmtStatic(n) + case *stmt.StaticVar: + return e.handleStmtStaticVar(n) + case *stmt.StmtList: + return e.handleStmtStmtList(n) + case *stmt.Switch: + return e.handleStmtSwitch(n) + case *stmt.Throw: + return e.handleStmtThrow(n) + case *stmt.Trait: + return e.handleStmtTrait(n) + case *stmt.TraitAdaptationList: + return e.handleStmtTraitAdaptationList(n) + case *stmt.TraitMethodRef: + return e.handleStmtTraitMethodRef(n) + case *stmt.TraitUse: + return e.handleStmtTraitUse(n) + case *stmt.TraitUseAlias: + return e.handleStmtTraitUseAlias(n) + case *stmt.TraitUsePrecedence: + return e.handleStmtTraitUsePrecedence(n) + case *stmt.Try: + return e.handleStmtTry(n) + case *stmt.Unset: + return e.handleStmtUnset(n) + case *stmt.Use: + return e.handleStmtUse(n) + case *stmt.UseList: + return e.handleStmtUseList(n) + case *stmt.While: + return e.handleStmtWhile(n) + + // + + default: + panic(fmt.Sprintf("missing exhaustive case for type '%t'", n)) + } +}