Class VariableScopeVisitor
- All Implemented Interfaces:
GroovyClassVisitor,GroovyCodeVisitor,ErrorCollecting
For JEP 394 instanceof pattern variables (GROOVY-12242), this
class is the single authoritative source of scope decisions.
VariableScopeVisitor.InstanceofFlowBindings answers which pattern variables are definitely
bound on each control-flow path; this visitor:
- declares each pattern variable only where it is live, so out-of-scope
references become
DynamicVariable(runtimeMissingPropertyExceptionin dynamic Groovy — the same rule@TypeCheckedenforces at compile time); and - attaches the same
VariableScopeVisitor.InstanceofFlowBindingsinstance as AST metadata so later phases (classgen) can read path-live names without re-running the analysis.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classFlow-sensitive result for JEP 394instanceofpattern bindings (GROOVY-12242) — the Groovy equivalent of the JLS §6.3.1 “introduced by” sets. -
Constructor Summary
ConstructorsConstructorDescriptionVariableScopeVisitor(SourceUnit source) Creates a new variable scope visitor that does not recurse into inner classes.VariableScopeVisitor(SourceUnit source, boolean recurseInnerClasses) Creates a new variable scope visitor with optional recursion into inner classes. -
Method Summary
Modifier and TypeMethodDescriptionprotected SourceUnitProvides access to theSourceUnitfor error reporting during visitation.voidprepareVisit(ClassNode node) Sets the current class node context.protected voidVisits an individualAnnotationNode, traversing all member expression values.voidvisitArrayExpression(ArrayExpression expression) Visits anArrayExpression, traversing element expressions and size expressions.voidvisitAssertStatement(AssertStatement statement) Visits anAssertStatement, invoking the statement hook before parent traversal.voidvisitBinaryExpression(BinaryExpression expression) Visits binary expressions with flow-aware scoping for&&/||so pattern variables follow Java short-circuit rules (GROOVY-12242 / JEP 394):a && b— true-path bindings ofaare in scope inba || b— true-path bindings ofaare not in scope inb; false-path bindings ofaaree !instanceof T t/!(e instanceof T t)— pattern declare is isolated on the left of short-circuit ops; only flow-live sets are re-introducedvoidvisitBlockStatement(BlockStatement statement) Visits aBlockStatement, invoking the statement hook before parent traversal.voidvisitCastExpression(CastExpression expression) Visits aCastExpression, traversing the operand expression.voidvisitCatchStatement(CatchStatement statement) Visits aCatchStatement, processing variable annotations and invoking the statement hook.voidvisitClass(ClassNode node) Visits aClassNode, processing its annotations, package, imports, contents, and object initializers.voidvisitClassExpression(ClassExpression expression) Visits aClassExpression.voidvisitClosureExpression(ClosureExpression expression) Visits aClosureExpressionwith annotation processing, traversing parameter annotations before delegating to parent traversal.voidvisitConstantExpression(ConstantExpression expression) Visits aConstantExpression.voidVisits aConstructorCallExpression, traversing its argument list.protected voidvisitConstructorOrMethod(MethodNode node, boolean isConstructor) Visits a constructor or method node (implementation detail for both visit methods).voidvisitDeclarationExpression(DeclarationExpression expression) Visits aDeclarationExpressionwith annotation processing, traversing expression annotations before delegating to parent traversal.voidvisitDoWhileLoop(DoWhileStatement statement) Visits ado/whileloop (GROOVY-12242).voidvisitExpressionStatement(ExpressionStatement statement) Visits anExpressionStatement, invoking the statement hook before parent traversal.voidvisitField(FieldNode node) Visits aFieldNode, processing its annotations and initial value expression if present.voidvisitFieldExpression(FieldExpression expression) Visits aFieldExpression.voidvisitForLoop(ForStatement statement) Visits aForStatement, invoking statement hooks and processing loop variable annotations.voidvisitIfElse(IfStatement statement) Visits anif/elsestatement, establishing correct lexical scopes for JEP 394instanceofpattern variables (GROOVY-12242) and attachingVariableScopeVisitor.InstanceofFlowBindingsmetadata so later phases need not re-derive the flow analysis.voidvisitMethodCallExpression(MethodCallExpression expression) Visits aMethodCallExpression, traversing the object expression, method expression, and argument list.voidvisitProperty(PropertyNode node) Visits aPropertyNode, processing its annotations, initial value expression, and getter/setter blocks if present.voidvisitPropertyExpression(PropertyExpression expression) Visits aPropertyExpression, traversing the object and property name expressions.voidvisitReturnStatement(ReturnStatement statement) Visits aReturnStatement, invoking the statement hook before parent traversal.voidvisitSwitch(SwitchStatement statement) Visits aSwitchStatement, invoking the statement hook before parent traversal.voidvisitTernaryExpression(TernaryExpression expression) Visits a ternary / Elvis expression with flow scoping for pattern variables: true-path bindings are in scope in the then-branch; false-path bindings in the else-branch (GROOVY-12242 / JEP 394).voidvisitVariableExpression(VariableExpression expression) Visits aVariableExpression.voidvisitWhileLoop(WhileStatement statement) Visits awhileloop with partial JEP 394 flow scoping forinstanceofpattern variables (GROOVY-12242).Methods inherited from class org.codehaus.groovy.ast.ClassCodeVisitorSupport
addError, visitAnnotations, visitAnnotations, visitBreakStatement, visitCaseStatement, visitClassCodeContainer, visitConstructor, visitContinueStatement, visitImports, visitMethod, visitObjectInitializerStatements, visitPackage, visitStatement, visitStatementAnnotations, visitSynchronizedStatement, visitThrowStatement, visitTryCatchFinallyMethods inherited from class org.codehaus.groovy.ast.CodeVisitorSupport
afterSwitchCaseStatementsVisited, afterSwitchConditionExpressionVisited, visitArgumentlistExpression, visitAttributeExpression, visitBitwiseNegationExpression, visitBooleanExpression, visitBytecodeExpression, visitClosureListExpression, visitEmptyStatement, visitGStringExpression, visitLambdaExpression, visitListExpression, visitMapEntryExpression, visitMapExpression, visitMethodPointerExpression, visitMethodReferenceExpression, visitNotExpression, visitPostfixExpression, visitPrefixExpression, visitRangeExpression, visitShortTernaryExpression, visitSpreadExpression, visitSpreadMapExpression, visitStaticMethodCallExpression, visitTupleExpression, visitUnaryMinusExpression, visitUnaryPlusExpressionMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.codehaus.groovy.ast.GroovyCodeVisitor
visit, visit, visitEmptyExpression, visitListOfExpressions
-
Constructor Details
-
VariableScopeVisitor
Creates a new variable scope visitor with optional recursion into inner classes.- Parameters:
source- the source unit being processedrecurseInnerClasses- whether to recurse into inner classes
-
VariableScopeVisitor
Creates a new variable scope visitor that does not recurse into inner classes.- Parameters:
source- the source unit being processed
-
-
Method Details
-
getSourceUnit
Provides access to theSourceUnitfor error reporting during visitation. Implementations must override this method.- Specified by:
getSourceUnitin classClassCodeVisitorSupport- Returns:
- the source unit for this visitor
-
prepareVisit
Sets the current class node context. -
visitClass
Visits aClassNode, processing its annotations, package, imports, contents, and object initializers.- Specified by:
visitClassin interfaceGroovyClassVisitor- Overrides:
visitClassin classClassCodeVisitorSupport- Parameters:
node- the class node to visit
-
visitField
Visits aFieldNode, processing its annotations and initial value expression if present.- Specified by:
visitFieldin interfaceGroovyClassVisitor- Overrides:
visitFieldin classClassCodeVisitorSupport- Parameters:
node- the field node to visit
-
visitProperty
Visits aPropertyNode, processing its annotations, initial value expression, and getter/setter blocks if present.- Specified by:
visitPropertyin interfaceGroovyClassVisitor- Overrides:
visitPropertyin classClassCodeVisitorSupport- Parameters:
node- the property node to visit
-
visitAnnotation
Visits an individualAnnotationNode, traversing all member expression values. Subclasses may override to perform custom annotation processing.- Overrides:
visitAnnotationin classClassCodeVisitorSupport- Parameters:
node- the annotation node to visit
-
visitConstructorOrMethod
Visits a constructor or method node (implementation detail for both visit methods). Processes the node's annotations, all parameter annotations, and code block.- Overrides:
visitConstructorOrMethodin classClassCodeVisitorSupport- Parameters:
node- the method or constructor nodeisConstructor- true if node is a constructor, false if it is a method
-
visitAssertStatement
Visits anAssertStatement, invoking the statement hook before parent traversal.- Specified by:
visitAssertStatementin interfaceGroovyCodeVisitor- Overrides:
visitAssertStatementin classClassCodeVisitorSupport- Parameters:
statement- the assert statement to visit
-
visitBlockStatement
Visits aBlockStatement, invoking the statement hook before parent traversal.- Specified by:
visitBlockStatementin interfaceGroovyCodeVisitor- Overrides:
visitBlockStatementin classClassCodeVisitorSupport- Parameters:
statement- the block statement to visit- See Also:
-
visitCatchStatement
Visits aCatchStatement, processing variable annotations and invoking the statement hook.- Specified by:
visitCatchStatementin interfaceGroovyCodeVisitor- Overrides:
visitCatchStatementin classClassCodeVisitorSupport- Parameters:
statement- the catch statement to visit
-
visitDoWhileLoop
Visits ado/whileloop (GROOVY-12242).The body runs before the condition, so pattern variables from the condition are not in scope in the body (same as Java). The condition is visited in a nested scope so short-circuit RHS works and pattern names do not leak after the loop. Like
visitWhileLoop(org.codehaus.groovy.ast.stmt.WhileStatement), there is no after-loop introduction ofwhenFalsebindings.- Specified by:
visitDoWhileLoopin interfaceGroovyCodeVisitor- Overrides:
visitDoWhileLoopin classClassCodeVisitorSupport- Parameters:
statement- the do-while statement to visit
-
visitExpressionStatement
Visits anExpressionStatement, invoking the statement hook before parent traversal.- Specified by:
visitExpressionStatementin interfaceGroovyCodeVisitor- Overrides:
visitExpressionStatementin classClassCodeVisitorSupport- Parameters:
statement- the expression statement to visit
-
visitForLoop
Visits aForStatement, invoking statement hooks and processing loop variable annotations.- Specified by:
visitForLoopin interfaceGroovyCodeVisitor- Overrides:
visitForLoopin classClassCodeVisitorSupport- Parameters:
statement- the for statement to visit
-
visitIfElse
Visits anif/elsestatement, establishing correct lexical scopes for JEP 394instanceofpattern variables (GROOVY-12242) and attachingVariableScopeVisitor.InstanceofFlowBindingsmetadata so later phases need not re-derive the flow analysis.Rules applied (JLS §6.3.2.2 / JEP 394):
- §6.3.2.2-200-A:
e.whenTrue()are in scope in the then-block (S). - §6.3.2.2-200-B:
e.whenFalse()are in scope in the else-block (T). - §6.3.2.2-200-C-A: if T cannot complete normally and S can, and the var
is in
e.whenTrue(), the var is introduced after the if-else. - §6.3.2.2-200-C-B: if S cannot complete normally and T can (or there is
no T), and the var is in
e.whenFalse(), the var is introduced after the if-else.
DynamicVariable(runtimeMissingPropertyException).@TypeCheckedenforces the same rules at compile time; both modes share this visitor.- Specified by:
visitIfElsein interfaceGroovyCodeVisitor- Overrides:
visitIfElsein classClassCodeVisitorSupport- Parameters:
statement- the if statement to visit
- §6.3.2.2-200-A:
-
visitReturnStatement
Visits aReturnStatement, invoking the statement hook before parent traversal.- Specified by:
visitReturnStatementin interfaceGroovyCodeVisitor- Overrides:
visitReturnStatementin classClassCodeVisitorSupport- Parameters:
statement- the return statement to visit
-
visitSwitch
Visits aSwitchStatement, invoking the statement hook before parent traversal.- Specified by:
visitSwitchin interfaceGroovyCodeVisitor- Overrides:
visitSwitchin classClassCodeVisitorSupport- Parameters:
statement- the switch statement to visit
-
visitWhileLoop
Visits awhileloop with partial JEP 394 flow scoping forinstanceofpattern variables (GROOVY-12242).What is supported (aligned with the if-then rule for the body):
- Short-circuit visibility inside the condition (
&&/||). e.whenTrue()pattern variables are in scope in the loop body.
Intentional divergence from JLS §6.3.2.3 (while): Groovy does not introduce
e.whenFalse()after the loop when the body cannot complete normally. Full after-loop introduction would need definite abrupt-completion analysis of every exit path (includingbreak/continueof nested loops) and is left out for 6.0 — pattern variables never leak past the loop. Documented as a deliberate partial implementation, not an oversight.- Specified by:
visitWhileLoopin interfaceGroovyCodeVisitor- Overrides:
visitWhileLoopin classClassCodeVisitorSupport- Parameters:
statement- the while statement to visit
- Short-circuit visibility inside the condition (
-
visitArrayExpression
Visits anArrayExpression, traversing element expressions and size expressions.- Specified by:
visitArrayExpressionin interfaceGroovyCodeVisitor- Overrides:
visitArrayExpressionin classCodeVisitorSupport- Parameters:
expression- the array expression
-
visitBinaryExpression
Visits binary expressions with flow-aware scoping for&&/||so pattern variables follow Java short-circuit rules (GROOVY-12242 / JEP 394):a && b— true-path bindings ofaare in scope inba || b— true-path bindings ofaare not in scope inb; false-path bindings ofaaree !instanceof T t/!(e instanceof T t)— pattern declare is isolated on the left of short-circuit ops; only flow-live sets are re-introduced
- Specified by:
visitBinaryExpressionin interfaceGroovyCodeVisitor- Overrides:
visitBinaryExpressionin classCodeVisitorSupport- Parameters:
expression- the binary expression
-
visitTernaryExpression
Visits a ternary / Elvis expression with flow scoping for pattern variables: true-path bindings are in scope in the then-branch; false-path bindings in the else-branch (GROOVY-12242 / JEP 394). Also attachesVariableScopeVisitor.InstanceofFlowBindingsmetadata for later phases.- Specified by:
visitTernaryExpressionin interfaceGroovyCodeVisitor- Overrides:
visitTernaryExpressionin classCodeVisitorSupport- Parameters:
expression- the ternary expression
-
visitCastExpression
Visits aCastExpression, traversing the operand expression.- Specified by:
visitCastExpressionin interfaceGroovyCodeVisitor- Overrides:
visitCastExpressionin classCodeVisitorSupport- Parameters:
expression- the cast expression
-
visitClassExpression
Visits aClassExpression. No traversal is performed as class expressions contain no child expressions.- Specified by:
visitClassExpressionin interfaceGroovyCodeVisitor- Overrides:
visitClassExpressionin classCodeVisitorSupport- Parameters:
expression- the class expression
-
visitClosureExpression
Visits aClosureExpressionwith annotation processing, traversing parameter annotations before delegating to parent traversal.- Specified by:
visitClosureExpressionin interfaceGroovyCodeVisitor- Overrides:
visitClosureExpressionin classClassCodeVisitorSupport- Parameters:
expression- the closure expression to visit
-
visitConstantExpression
Visits aConstantExpression. No traversal is performed as constants contain no child expressions.- Specified by:
visitConstantExpressionin interfaceGroovyCodeVisitor- Overrides:
visitConstantExpressionin classCodeVisitorSupport- Parameters:
expression- the constant expression
-
visitConstructorCallExpression
Visits aConstructorCallExpression, traversing its argument list.- Specified by:
visitConstructorCallExpressionin interfaceGroovyCodeVisitor- Overrides:
visitConstructorCallExpressionin classCodeVisitorSupport- Parameters:
expression- the constructor call expression
-
visitDeclarationExpression
Visits aDeclarationExpressionwith annotation processing, traversing expression annotations before delegating to parent traversal.- Specified by:
visitDeclarationExpressionin interfaceGroovyCodeVisitor- Overrides:
visitDeclarationExpressionin classClassCodeVisitorSupport- Parameters:
expression- the declaration expression to visit
-
visitFieldExpression
Visits aFieldExpression. No traversal is performed as field expressions contain no child expressions.- Specified by:
visitFieldExpressionin interfaceGroovyCodeVisitor- Overrides:
visitFieldExpressionin classCodeVisitorSupport- Parameters:
expression- the field expression
-
visitMethodCallExpression
Visits aMethodCallExpression, traversing the object expression, method expression, and argument list.- Specified by:
visitMethodCallExpressionin interfaceGroovyCodeVisitor- Overrides:
visitMethodCallExpressionin classCodeVisitorSupport- Parameters:
expression- the method call expression
-
visitPropertyExpression
Visits aPropertyExpression, traversing the object and property name expressions.- Specified by:
visitPropertyExpressionin interfaceGroovyCodeVisitor- Overrides:
visitPropertyExpressionin classCodeVisitorSupport- Parameters:
expression- the property expression
-
visitVariableExpression
Visits aVariableExpression. No traversal is performed as variable expressions contain no child expressions.- Specified by:
visitVariableExpressionin interfaceGroovyCodeVisitor- Overrides:
visitVariableExpressionin classCodeVisitorSupport- Parameters:
expression- the variable expression
-