Skip to content

Commit 124530d

Browse files
committed
GROOVY-11488: STC: null check
3_0_X backport
1 parent 7b12b78 commit 124530d

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+18-11
Original file line numberDiff line numberDiff line change
@@ -4029,6 +4029,7 @@ public void visitIfElse(final IfStatement ifElse) {
40294029
}
40304030
}
40314031

4032+
@Deprecated
40324033
protected void visitInstanceofNot(final BinaryExpression be) {
40334034
BlockStatement currentBlock = typeCheckingContext.enclosingBlocks.getFirst();
40344035
assert currentBlock != null;
@@ -4037,13 +4038,14 @@ protected void visitInstanceofNot(final BinaryExpression be) {
40374038
} else {
40384039
// saving type of variables to restoring them after returning from block
40394040
Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
4040-
getTypeCheckingContext().pushTemporaryTypeInfo();
4041+
typeCheckingContext.pushTemporaryTypeInfo();
40414042
typeCheckingContext.blockStatements2Types.put(currentBlock, oldTracker);
40424043
}
40434044
pushInstanceOfTypeInfo(be.getLeftExpression(), be.getRightExpression());
40444045
}
40454046

40464047
@Override
4048+
@Deprecated
40474049
public void visitBlockStatement(final BlockStatement block) {
40484050
if (block != null) {
40494051
typeCheckingContext.enclosingBlocks.addFirst(block);
@@ -4054,12 +4056,13 @@ public void visitBlockStatement(final BlockStatement block) {
40544056
}
40554057
}
40564058

4059+
@Deprecated
40574060
public void visitClosingBlock(final BlockStatement block) {
4058-
BlockStatement peekBlock = typeCheckingContext.enclosingBlocks.removeFirst();
4059-
boolean found = typeCheckingContext.blockStatements2Types.containsKey(peekBlock);
4061+
BlockStatement theBlock = typeCheckingContext.enclosingBlocks.pop();
4062+
boolean found = typeCheckingContext.blockStatements2Types.containsKey(theBlock);
40604063
if (found) {
4061-
Map<VariableExpression, List<ClassNode>> oldTracker = typeCheckingContext.blockStatements2Types.remove(peekBlock);
4062-
getTypeCheckingContext().popTemporaryTypeInfo();
4064+
Map<VariableExpression, List<ClassNode>> oldTracker = typeCheckingContext.blockStatements2Types.remove(theBlock);
4065+
typeCheckingContext.popTemporaryTypeInfo();
40634066
popAssignmentTracking(oldTracker);
40644067
}
40654068
}
@@ -4075,6 +4078,7 @@ public void visitClosingBlock(final BlockStatement block) {
40754078
* Return expression , which contains instanceOf (without not)
40764079
* Return null, if not found
40774080
*/
4081+
@Deprecated
40784082
protected BinaryExpression findInstanceOfNotReturnExpression(final IfStatement ifElse) {
40794083
Statement elseBlock = ifElse.getElseBlock();
40804084
if (!(elseBlock instanceof EmptyStatement)) {
@@ -4111,6 +4115,7 @@ protected BinaryExpression findInstanceOfNotReturnExpression(final IfStatement i
41114115
* Return expression , which contains instanceOf (without not)
41124116
* Return null, if not found
41134117
*/
4118+
@Deprecated
41144119
protected BinaryExpression findNotInstanceOfReturnExpression(final IfStatement ifElse) {
41154120
Statement elseBlock = ifElse.getElseBlock();
41164121
if (!(elseBlock instanceof EmptyStatement)) {
@@ -4186,13 +4191,15 @@ private void restoreTypeBeforeConditional() {
41864191

41874192
protected Map<VariableExpression, ClassNode> popAssignmentTracking(final Map<VariableExpression, List<ClassNode>> oldTracker) {
41884193
Map<VariableExpression, ClassNode> assignments = new HashMap<>();
4189-
typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
4190-
types.stream().filter(t -> t != null && t != UNKNOWN_PARAMETER_TYPE) // GROOVY-6099, GROOVY-10294
4191-
.reduce(WideningCategories::lowestUpperBound).ifPresent(type -> {
4192-
assignments.put(var, type);
4193-
storeType(var, type);
4194+
if (typeCheckingContext.ifElseForWhileAssignmentTracker != null){ // GROOVY-11488
4195+
typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
4196+
types.stream().filter(t -> t != null && t != UNKNOWN_PARAMETER_TYPE) // GROOVY-6099, GROOVY-10294
4197+
.reduce(WideningCategories::lowestUpperBound).ifPresent(type -> {
4198+
assignments.put(var, type);
4199+
storeType(var, type);
4200+
});
41944201
});
4195-
});
4202+
}
41964203
typeCheckingContext.ifElseForWhileAssignmentTracker = oldTracker;
41974204
// GROOVY-9786, GROOVY-11450: nested conditional assignments
41984205
if (oldTracker != null) {

src/main/java/org/codehaus/groovy/transform/stc/TypeCheckingContext.java

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public void popTemporaryTypeInfo() {
160160
* }
161161
* // Here var1 instance of Runnable
162162
*/
163+
@Deprecated
163164
protected final IdentityHashMap<BlockStatement, Map<VariableExpression, List<ClassNode>>> blockStatements2Types = new IdentityHashMap<>();
164165

165166
protected Set<MethodNode> alreadyVisitedMethods = new HashSet<>();
@@ -188,6 +189,7 @@ public void popTemporaryTypeInfo() {
188189
protected final LinkedList<ClassNode> enclosingClassNodes = new LinkedList<>();
189190
protected final LinkedList<MethodNode> enclosingMethods = new LinkedList<>();
190191
protected final LinkedList<Expression> enclosingMethodCalls = new LinkedList<>();
192+
@Deprecated
191193
protected final LinkedList<BlockStatement> enclosingBlocks = new LinkedList<>();
192194
protected final LinkedList<SwitchStatement> switchStatements = new LinkedList<>();
193195
protected final LinkedList<EnclosingClosure> enclosingClosures = new LinkedList<>();

src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy

+16-1
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,21 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
617617
''', 'Cannot find matching method java.lang.Object#toUpperCase()'
618618
}
619619

620+
// GROOVY-11488
621+
void testNotInstanceOf7() {
622+
assertScript '''
623+
def test(object) {
624+
if (false) {
625+
return 'not possible'
626+
} else if (object !instanceof Object[]) {
627+
return 'not array'
628+
}
629+
}
630+
assert test(null) == 'not array'
631+
assert test(new Object[0]) == null
632+
'''
633+
}
634+
620635
// GROOVY-10217
621636
void testInstanceOfThenSubscriptOperator() {
622637
assertScript '''
@@ -1404,7 +1419,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
14041419
'''
14051420
}
14061421

1407-
// GROOVY-
1422+
// GROOVY-6207
14081423
void testGetAnnotationFails() {
14091424
assertScript '''
14101425
import groovy.transform.*

0 commit comments

Comments
 (0)