Skip to content

Commit

Permalink
GROOVY-9995
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Mar 23, 2021
1 parent b4e715c commit a513d63
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1334,4 +1334,29 @@ public void testTypeChecked9991() {

runConformTest(sources, "false");
}

@Test
public void testTypeChecked9995() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TupleConstructor(defaults=false)\n" +
"class A<T extends Number> {\n" +
" T p\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" Closure<A<Long>> c = { ->\n" +
" long x = 1\n" +
" new A<>(x)\n" +
" }\n" +
" Long y = c().p\n" +
" print y\n" +
"}\n" +
"test()\n",
};
//@formatter:on

runConformTest(sources, "1");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -871,10 +871,14 @@ public void visitBinaryExpression(final BinaryExpression expression) {
}
lType = getType(leftExpression);
} else {
// GRECLIPSE add -- GROOVY-9977
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
lType = getType(leftExpression);
if (op == ASSIGN && isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
if (op == ASSIGN) {
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
}
// GRECLIPSE end
rightExpression.visit(this);
Expand Down Expand Up @@ -1042,6 +1046,10 @@ && isAssignment(enclosingBinaryExpression.getOperation().getType())) {
}

// GRECLIPSE add
private static boolean isClosureWithType(final ClassNode type) {
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
}

private static boolean isFunctionalInterface(final ClassNode type) {
return type.isInterface() && isSAMType(type);
}
Expand Down Expand Up @@ -2060,7 +2068,7 @@ public void visitField(final FieldNode node) {
// GRECLIPSE end
Expression init = node.getInitialExpression();
if (init != null) {
// GRECLIPSE add -- GROOVY-9977
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
ClassNode lType = getType(node);
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, init);
Expand All @@ -2069,6 +2077,8 @@ public void visitField(final FieldNode node) {
ClassNode rType = getType(init);
if (init instanceof ConstructorCallExpression) {
inferDiamondType((ConstructorCallExpression) init, lType);
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
// GRECLIPSE end
FieldExpression left = new FieldExpression(node);
Expand Down Expand Up @@ -2443,7 +2453,7 @@ private ClassNode infer(ClassNode target, ClassNode source) {

protected ClassNode checkReturnType(final ReturnStatement statement) {
Expression expression = statement.getExpression();
/* GRECLIPSE edit -- GROOVY-9907
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
ClassNode type = getType(expression);
if (typeCheckingContext.getEnclosingClosure() != null) {
Expand All @@ -2456,11 +2466,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
*/
ClassNode type;
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
type = getInferredReturnType(expression);
} else {
type = getType(expression);
}
if (typeCheckingContext.getEnclosingClosure() != null) {
if (expression instanceof ConstructorCallExpression) {
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
}
return type;
}
// GRECLIPSE end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
}
} else {
lType = getType(leftExpression);
/* GRECLIPSE edit -- GROOVY-9977
/* GRECLIPSE edit -- GROOVY-9977, GROOVY-9995
boolean isFunctionalInterface = isFunctionalInterface(lType);
if (isFunctionalInterface && rightExpression instanceof MethodReferenceExpression) {
LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference(lType);
Expand All @@ -781,8 +781,12 @@ public void visitBinaryExpression(final BinaryExpression expression) {
inferParameterAndReturnTypesOfClosureOnRHS(lType, (ClosureExpression) rightExpression);
}
*/
if (op == ASSIGN && isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
if (op == ASSIGN) {
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
}
// GRECLIPSE end
rightExpression.visit(this);
Expand Down Expand Up @@ -1048,6 +1052,12 @@ private boolean ensureValidSetter(final Expression expression, final Expression
}
}

// GRECLIPSE add
private static boolean isClosureWithType(final ClassNode type) {
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
}
// GRECLIPSE end

private boolean isCompoundAssignment(final Expression exp) {
if (!(exp instanceof BinaryExpression)) return false;
int type = ((BinaryExpression) exp).getOperation().getType();
Expand Down Expand Up @@ -1938,10 +1948,12 @@ public void visitField(final FieldNode node) {
// GRECLIPSE end
Expression init = node.getInitialExpression();
if (init != null) {
// GRECLIPSE add -- GROOVY-9977
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
ClassNode lType = getType(node);
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, init);
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
init.visit(this);
ClassNode rType = getType(init);
Expand Down Expand Up @@ -2253,7 +2265,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) {

protected ClassNode checkReturnType(final ReturnStatement statement) {
Expression expression = statement.getExpression();
/* GRECLIPSE edit -- GROOVY-9907
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
ClassNode type = getType(expression);
if (typeCheckingContext.getEnclosingClosure() != null) {
Expand All @@ -2266,11 +2278,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
*/
ClassNode type;
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
type = getInferredReturnType(expression);
} else {
type = getType(expression);
}
if (typeCheckingContext.getEnclosingClosure() != null) {
if (expression instanceof ConstructorCallExpression) {
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
}
return type;
}
// GRECLIPSE end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
}
} else {
lType = getType(leftExpression);
/* GRECLIPSE edit -- GROOVY-9977
/* GRECLIPSE edit -- GROOVY-9977, GROOVY-9995
boolean isFunctionalInterface = isFunctionalInterface(lType);
if (isFunctionalInterface && rightExpression instanceof MethodReferenceExpression) {
LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference(lType);
Expand All @@ -781,8 +781,12 @@ public void visitBinaryExpression(final BinaryExpression expression) {
inferParameterAndReturnTypesOfClosureOnRHS(lType, (ClosureExpression) rightExpression);
}
*/
if (op == ASSIGN && isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
if (op == ASSIGN) {
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, rightExpression);
} else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
}
// GRECLIPSE end
rightExpression.visit(this);
Expand Down Expand Up @@ -1046,6 +1050,12 @@ private boolean ensureValidSetter(final Expression expression, final Expression
}
}

// GRECLIPSE add
private static boolean isClosureWithType(final ClassNode type) {
return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
}
// GRECLIPSE end

private boolean isCompoundAssignment(final Expression exp) {
if (!(exp instanceof BinaryExpression)) return false;
int type = ((BinaryExpression) exp).getOperation().getType();
Expand Down Expand Up @@ -1925,10 +1935,12 @@ public void visitField(final FieldNode node) {
// GRECLIPSE end
Expression init = node.getInitialExpression();
if (init != null) {
// GRECLIPSE add -- GROOVY-9977
// GRECLIPSE add -- GROOVY-9977, GROOVY-9995
ClassNode lType = getType(node);
if (isFunctionalInterface(lType)) {
processFunctionalInterfaceAssignment(lType, init);
} else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
init.visit(this);
ClassNode rType = getType(init);
Expand Down Expand Up @@ -2240,7 +2252,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) {

protected ClassNode checkReturnType(final ReturnStatement statement) {
Expression expression = statement.getExpression();
/* GRECLIPSE edit -- GROOVY-9907
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9995
ClassNode type = getType(expression);
if (typeCheckingContext.getEnclosingClosure() != null) {
Expand All @@ -2253,11 +2265,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
*/
ClassNode type;
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
type = getInferredReturnType(expression);
} else {
type = getType(expression);
}
if (typeCheckingContext.getEnclosingClosure() != null) {
if (expression instanceof ConstructorCallExpression) {
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
}
return type;
}
// GRECLIPSE end
Expand Down

0 comments on commit a513d63

Please sign in to comment.