Skip to content

Commit a513d63

Browse files
committed
GROOVY-9995
1 parent b4e715c commit a513d63

4 files changed

Lines changed: 89 additions & 18 deletions

File tree

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,4 +1334,29 @@ public void testTypeChecked9991() {
13341334

13351335
runConformTest(sources, "false");
13361336
}
1337+
1338+
@Test
1339+
public void testTypeChecked9995() {
1340+
//@formatter:off
1341+
String[] sources = {
1342+
"Main.groovy",
1343+
"@groovy.transform.TupleConstructor(defaults=false)\n" +
1344+
"class A<T extends Number> {\n" +
1345+
" T p\n" +
1346+
"}\n" +
1347+
"@groovy.transform.TypeChecked\n" +
1348+
"void test() {\n" +
1349+
" Closure<A<Long>> c = { ->\n" +
1350+
" long x = 1\n" +
1351+
" new A<>(x)\n" +
1352+
" }\n" +
1353+
" Long y = c().p\n" +
1354+
" print y\n" +
1355+
"}\n" +
1356+
"test()\n",
1357+
};
1358+
//@formatter:on
1359+
1360+
runConformTest(sources, "1");
1361+
}
13371362
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -871,10 +871,14 @@ public void visitBinaryExpression(final BinaryExpression expression) {
871871
}
872872
lType = getType(leftExpression);
873873
} else {
874-
// GRECLIPSE add -- GROOVY-9977
874+
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
875875
lType = getType(leftExpression);
876-
if (op == ASSIGN && isFunctionalInterface(lType)) {
877-
processFunctionalInterfaceAssignment(lType, rightExpression);
876+
if (op == ASSIGN) {
877+
if (isFunctionalInterface(lType)) {
878+
processFunctionalInterfaceAssignment(lType, rightExpression);
879+
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
880+
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
881+
}
878882
}
879883
// GRECLIPSE end
880884
rightExpression.visit(this);
@@ -1042,6 +1046,10 @@ && isAssignment(enclosingBinaryExpression.getOperation().getType())) {
10421046
}
10431047

10441048
// GRECLIPSE add
1049+
private static boolean isClosureWithType(final ClassNode type) {
1050+
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
1051+
}
1052+
10451053
private static boolean isFunctionalInterface(final ClassNode type) {
10461054
return type.isInterface() && isSAMType(type);
10471055
}
@@ -2060,7 +2068,7 @@ public void visitField(final FieldNode node) {
20602068
// GRECLIPSE end
20612069
Expression init = node.getInitialExpression();
20622070
if (init != null) {
2063-
// GRECLIPSE add -- GROOVY-9977
2071+
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
20642072
ClassNode lType = getType(node);
20652073
if (isFunctionalInterface(lType)) {
20662074
processFunctionalInterfaceAssignment(lType, init);
@@ -2069,6 +2077,8 @@ public void visitField(final FieldNode node) {
20692077
ClassNode rType = getType(init);
20702078
if (init instanceof ConstructorCallExpression) {
20712079
inferDiamondType((ConstructorCallExpression) init, lType);
2080+
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
2081+
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
20722082
}
20732083
// GRECLIPSE end
20742084
FieldExpression left = new FieldExpression(node);
@@ -2443,7 +2453,7 @@ private ClassNode infer(ClassNode target, ClassNode source) {
24432453

24442454
protected ClassNode checkReturnType(final ReturnStatement statement) {
24452455
Expression expression = statement.getExpression();
2446-
/* GRECLIPSE edit -- GROOVY-9907
2456+
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
24472457
ClassNode type = getType(expression);
24482458
24492459
if (typeCheckingContext.getEnclosingClosure() != null) {
@@ -2456,11 +2466,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
24562466
*/
24572467
ClassNode type;
24582468
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
2459-
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
2469+
type = getInferredReturnType(expression);
24602470
} else {
24612471
type = getType(expression);
24622472
}
24632473
if (typeCheckingContext.getEnclosingClosure() != null) {
2474+
if (expression instanceof ConstructorCallExpression) {
2475+
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
2476+
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
2477+
}
24642478
return type;
24652479
}
24662480
// GRECLIPSE end

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
767767
}
768768
} else {
769769
lType = getType(leftExpression);
770-
/* GRECLIPSE edit -- GROOVY-9977
770+
/* GRECLIPSE edit -- GROOVY-9977, GROOVY-9995
771771
boolean isFunctionalInterface = isFunctionalInterface(lType);
772772
if (isFunctionalInterface && rightExpression instanceof MethodReferenceExpression) {
773773
LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference(lType);
@@ -781,8 +781,12 @@ public void visitBinaryExpression(final BinaryExpression expression) {
781781
inferParameterAndReturnTypesOfClosureOnRHS(lType, (ClosureExpression) rightExpression);
782782
}
783783
*/
784-
if (op == ASSIGN && isFunctionalInterface(lType)) {
785-
processFunctionalInterfaceAssignment(lType, rightExpression);
784+
if (op == ASSIGN) {
785+
if (isFunctionalInterface(lType)) {
786+
processFunctionalInterfaceAssignment(lType, rightExpression);
787+
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
788+
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
789+
}
786790
}
787791
// GRECLIPSE end
788792
rightExpression.visit(this);
@@ -1048,6 +1052,12 @@ private boolean ensureValidSetter(final Expression expression, final Expression
10481052
}
10491053
}
10501054

1055+
// GRECLIPSE add
1056+
private static boolean isClosureWithType(final ClassNode type) {
1057+
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
1058+
}
1059+
// GRECLIPSE end
1060+
10511061
private boolean isCompoundAssignment(final Expression exp) {
10521062
if (!(exp instanceof BinaryExpression)) return false;
10531063
int type = ((BinaryExpression) exp).getOperation().getType();
@@ -1938,10 +1948,12 @@ public void visitField(final FieldNode node) {
19381948
// GRECLIPSE end
19391949
Expression init = node.getInitialExpression();
19401950
if (init != null) {
1941-
// GRECLIPSE add -- GROOVY-9977
1951+
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
19421952
ClassNode lType = getType(node);
19431953
if (isFunctionalInterface(lType)) {
19441954
processFunctionalInterfaceAssignment(lType, init);
1955+
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
1956+
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
19451957
}
19461958
init.visit(this);
19471959
ClassNode rType = getType(init);
@@ -2253,7 +2265,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) {
22532265

22542266
protected ClassNode checkReturnType(final ReturnStatement statement) {
22552267
Expression expression = statement.getExpression();
2256-
/* GRECLIPSE edit -- GROOVY-9907
2268+
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
22572269
ClassNode type = getType(expression);
22582270
22592271
if (typeCheckingContext.getEnclosingClosure() != null) {
@@ -2266,11 +2278,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
22662278
*/
22672279
ClassNode type;
22682280
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
2269-
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
2281+
type = getInferredReturnType(expression);
22702282
} else {
22712283
type = getType(expression);
22722284
}
22732285
if (typeCheckingContext.getEnclosingClosure() != null) {
2286+
if (expression instanceof ConstructorCallExpression) {
2287+
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
2288+
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
2289+
}
22742290
return type;
22752291
}
22762292
// GRECLIPSE end

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
767767
}
768768
} else {
769769
lType = getType(leftExpression);
770-
/* GRECLIPSE edit -- GROOVY-9977
770+
/* GRECLIPSE edit -- GROOVY-9977, GROOVY-9995
771771
boolean isFunctionalInterface = isFunctionalInterface(lType);
772772
if (isFunctionalInterface && rightExpression instanceof MethodReferenceExpression) {
773773
LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference(lType);
@@ -781,8 +781,12 @@ public void visitBinaryExpression(final BinaryExpression expression) {
781781
inferParameterAndReturnTypesOfClosureOnRHS(lType, (ClosureExpression) rightExpression);
782782
}
783783
*/
784-
if (op == ASSIGN && isFunctionalInterface(lType)) {
785-
processFunctionalInterfaceAssignment(lType, rightExpression);
784+
if (op == ASSIGN) {
785+
if (isFunctionalInterface(lType)) {
786+
processFunctionalInterfaceAssignment(lType, rightExpression);
787+
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
788+
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
789+
}
786790
}
787791
// GRECLIPSE end
788792
rightExpression.visit(this);
@@ -1046,6 +1050,12 @@ private boolean ensureValidSetter(final Expression expression, final Expression
10461050
}
10471051
}
10481052

1053+
// GRECLIPSE add
1054+
private static boolean isClosureWithType(final ClassNode type) {
1055+
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
1056+
}
1057+
// GRECLIPSE end
1058+
10491059
private boolean isCompoundAssignment(final Expression exp) {
10501060
if (!(exp instanceof BinaryExpression)) return false;
10511061
int type = ((BinaryExpression) exp).getOperation().getType();
@@ -1925,10 +1935,12 @@ public void visitField(final FieldNode node) {
19251935
// GRECLIPSE end
19261936
Expression init = node.getInitialExpression();
19271937
if (init != null) {
1928-
// GRECLIPSE add -- GROOVY-9977
1938+
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
19291939
ClassNode lType = getType(node);
19301940
if (isFunctionalInterface(lType)) {
19311941
processFunctionalInterfaceAssignment(lType, init);
1942+
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
1943+
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
19321944
}
19331945
init.visit(this);
19341946
ClassNode rType = getType(init);
@@ -2240,7 +2252,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) {
22402252

22412253
protected ClassNode checkReturnType(final ReturnStatement statement) {
22422254
Expression expression = statement.getExpression();
2243-
/* GRECLIPSE edit -- GROOVY-9907
2255+
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
22442256
ClassNode type = getType(expression);
22452257
22462258
if (typeCheckingContext.getEnclosingClosure() != null) {
@@ -2253,11 +2265,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
22532265
*/
22542266
ClassNode type;
22552267
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
2256-
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
2268+
type = getInferredReturnType(expression);
22572269
} else {
22582270
type = getType(expression);
22592271
}
22602272
if (typeCheckingContext.getEnclosingClosure() != null) {
2273+
if (expression instanceof ConstructorCallExpression) {
2274+
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
2275+
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
2276+
}
22612277
return type;
22622278
}
22632279
// GRECLIPSE end

0 commit comments

Comments
 (0)