Skip to content

Commit

Permalink
GROOVY-11488: STC: null check
Browse files Browse the repository at this point in the history
3_0_X backport
  • Loading branch information
eric-milles committed Oct 1, 2024
1 parent 7b12b78 commit 124530d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4029,6 +4029,7 @@ public void visitIfElse(final IfStatement ifElse) {
}
}

@Deprecated
protected void visitInstanceofNot(final BinaryExpression be) {
BlockStatement currentBlock = typeCheckingContext.enclosingBlocks.getFirst();
assert currentBlock != null;
Expand All @@ -4037,13 +4038,14 @@ protected void visitInstanceofNot(final BinaryExpression be) {
} else {
// saving type of variables to restoring them after returning from block
Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
getTypeCheckingContext().pushTemporaryTypeInfo();
typeCheckingContext.pushTemporaryTypeInfo();
typeCheckingContext.blockStatements2Types.put(currentBlock, oldTracker);
}
pushInstanceOfTypeInfo(be.getLeftExpression(), be.getRightExpression());
}

@Override
@Deprecated
public void visitBlockStatement(final BlockStatement block) {
if (block != null) {
typeCheckingContext.enclosingBlocks.addFirst(block);
Expand All @@ -4054,12 +4056,13 @@ public void visitBlockStatement(final BlockStatement block) {
}
}

@Deprecated
public void visitClosingBlock(final BlockStatement block) {
BlockStatement peekBlock = typeCheckingContext.enclosingBlocks.removeFirst();
boolean found = typeCheckingContext.blockStatements2Types.containsKey(peekBlock);
BlockStatement theBlock = typeCheckingContext.enclosingBlocks.pop();
boolean found = typeCheckingContext.blockStatements2Types.containsKey(theBlock);
if (found) {
Map<VariableExpression, List<ClassNode>> oldTracker = typeCheckingContext.blockStatements2Types.remove(peekBlock);
getTypeCheckingContext().popTemporaryTypeInfo();
Map<VariableExpression, List<ClassNode>> oldTracker = typeCheckingContext.blockStatements2Types.remove(theBlock);
typeCheckingContext.popTemporaryTypeInfo();
popAssignmentTracking(oldTracker);
}
}
Expand All @@ -4075,6 +4078,7 @@ public void visitClosingBlock(final BlockStatement block) {
* Return expression , which contains instanceOf (without not)
* Return null, if not found
*/
@Deprecated
protected BinaryExpression findInstanceOfNotReturnExpression(final IfStatement ifElse) {
Statement elseBlock = ifElse.getElseBlock();
if (!(elseBlock instanceof EmptyStatement)) {
Expand Down Expand Up @@ -4111,6 +4115,7 @@ protected BinaryExpression findInstanceOfNotReturnExpression(final IfStatement i
* Return expression , which contains instanceOf (without not)
* Return null, if not found
*/
@Deprecated
protected BinaryExpression findNotInstanceOfReturnExpression(final IfStatement ifElse) {
Statement elseBlock = ifElse.getElseBlock();
if (!(elseBlock instanceof EmptyStatement)) {
Expand Down Expand Up @@ -4186,13 +4191,15 @@ private void restoreTypeBeforeConditional() {

protected Map<VariableExpression, ClassNode> popAssignmentTracking(final Map<VariableExpression, List<ClassNode>> oldTracker) {
Map<VariableExpression, ClassNode> assignments = new HashMap<>();
typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
types.stream().filter(t -> t != null && t != UNKNOWN_PARAMETER_TYPE) // GROOVY-6099, GROOVY-10294
.reduce(WideningCategories::lowestUpperBound).ifPresent(type -> {
assignments.put(var, type);
storeType(var, type);
if (typeCheckingContext.ifElseForWhileAssignmentTracker != null){ // GROOVY-11488
typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
types.stream().filter(t -> t != null && t != UNKNOWN_PARAMETER_TYPE) // GROOVY-6099, GROOVY-10294
.reduce(WideningCategories::lowestUpperBound).ifPresent(type -> {
assignments.put(var, type);
storeType(var, type);
});
});
});
}
typeCheckingContext.ifElseForWhileAssignmentTracker = oldTracker;
// GROOVY-9786, GROOVY-11450: nested conditional assignments
if (oldTracker != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ public void popTemporaryTypeInfo() {
* }
* // Here var1 instance of Runnable
*/
@Deprecated
protected final IdentityHashMap<BlockStatement, Map<VariableExpression, List<ClassNode>>> blockStatements2Types = new IdentityHashMap<>();

protected Set<MethodNode> alreadyVisitedMethods = new HashSet<>();
Expand Down Expand Up @@ -188,6 +189,7 @@ public void popTemporaryTypeInfo() {
protected final LinkedList<ClassNode> enclosingClassNodes = new LinkedList<>();
protected final LinkedList<MethodNode> enclosingMethods = new LinkedList<>();
protected final LinkedList<Expression> enclosingMethodCalls = new LinkedList<>();
@Deprecated
protected final LinkedList<BlockStatement> enclosingBlocks = new LinkedList<>();
protected final LinkedList<SwitchStatement> switchStatements = new LinkedList<>();
protected final LinkedList<EnclosingClosure> enclosingClosures = new LinkedList<>();
Expand Down
17 changes: 16 additions & 1 deletion src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,21 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
''', 'Cannot find matching method java.lang.Object#toUpperCase()'
}

// GROOVY-11488
void testNotInstanceOf7() {
assertScript '''
def test(object) {
if (false) {
return 'not possible'
} else if (object !instanceof Object[]) {
return 'not array'
}
}
assert test(null) == 'not array'
assert test(new Object[0]) == null
'''
}

// GROOVY-10217
void testInstanceOfThenSubscriptOperator() {
assertScript '''
Expand Down Expand Up @@ -1404,7 +1419,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
'''
}

// GROOVY-
// GROOVY-6207
void testGetAnnotationFails() {
assertScript '''
import groovy.transform.*
Expand Down

0 comments on commit 124530d

Please sign in to comment.