Skip to content

Commit

Permalink
STC: support explicit type arguments for non-extension method w/ closure
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Dec 30, 2021
1 parent 95b86a8 commit 9577649
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,6 @@ public void testTypeChecked18() {
//@formatter:off
String[] sources = {
"Main.groovy",
"class C {\n" +
" boolean b\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" print(new Pogo().isFlag())\n" +
Expand Down Expand Up @@ -481,6 +478,28 @@ public void testTypeChecked19() {
runConformTest(sources, "test");
}

@Test
public void testTypeChecked20() {
//@formatter:off
String[] sources = {
"Main.groovy",
"def <T> T m(java.util.function.Consumer<? super T> c) {\n" +
" c.accept(null)\n" +
" null\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" this.<Number>m { n ->\n" +
" n?.toBigInteger()\n" +
" }\n" +
"}\n" +
"test()\n",
};
//@formatter:on

runConformTest(sources);
}

@Test
public void testTypeChecked5450() {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3416,28 +3416,40 @@ protected void silentlyVisitMethodNode(final MethodNode directMethodCallCandidat
startMethodInference(directMethodCallCandidate, collector);
}

protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListExpression arguments, boolean visitClosures, final MethodNode selectedMethod) {
protected void visitMethodCallArguments(final ClassNode receiver, final ArgumentListExpression arguments, final boolean visitClosures, final MethodNode selectedMethod) {
/* GRECLIPSE edit
Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
List<Expression> expressions = new LinkedList<Expression>(arguments.getExpressions());
if (selectedMethod instanceof ExtensionMethodNode) {
params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
expressions.add(0, varX("$self", receiver));
}
ArgumentListExpression newArgs = args(expressions);

for (int i = 0, expressionsSize = expressions.size(); i < expressionsSize; i++) {
*/
Parameter[] params;
List<Expression> expressions = new ArrayList<>();
if (selectedMethod instanceof ExtensionMethodNode) {
params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
expressions.add(varX("$self", receiver));
} else {
params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
}
expressions.addAll(arguments.getExpressions());
if (expressions.isEmpty()) return;
// GRECLIPSE end
for (int i = 0, n = expressions.size(); i < n; i++) {
final Expression expression = expressions.get(i);
if (visitClosures && expression instanceof ClosureExpression
|| !visitClosures && !(expression instanceof ClosureExpression)) {
if (i < params.length && visitClosures) {
Parameter param = params[i];
checkClosureWithDelegatesTo(receiver, selectedMethod, newArgs, params, expression, param);
checkClosureWithDelegatesTo(receiver, selectedMethod, args(expressions), params, expression, param);
if (selectedMethod instanceof ExtensionMethodNode) {
if (i > 0) {
inferClosureParameterTypes(receiver, arguments, (ClosureExpression) expression, param, selectedMethod);
}
} else {
inferClosureParameterTypes(receiver, newArgs, (ClosureExpression) expression, param, selectedMethod);
inferClosureParameterTypes(receiver, arguments, (ClosureExpression) expression, param, selectedMethod);
}
// GRECLIPSE add -- GROOVY-9971
ClassNode targetType = param.getType();
Expand All @@ -3449,12 +3461,10 @@ protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListEx
// GRECLIPSE end
}
expression.visit(this);
if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) != null) {
expression.removeNodeMetaData(StaticTypesMarker.DELEGATION_METADATA);
}
expression.removeNodeMetaData(StaticTypesMarker.DELEGATION_METADATA);
}
}
if (expressions.size() > 0 && expressions.get(0) instanceof MapExpression && params.length > 0) {
if (params.length > 0 && expressions.get(0) instanceof MapExpression) {
checkNamedParamsAnnotation(params[0], (MapExpression) expressions.get(0));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3119,14 +3119,25 @@ protected void silentlyVisitMethodNode(final MethodNode directMethodCallCandidat
}

protected void visitMethodCallArguments(final ClassNode receiver, final ArgumentListExpression arguments, final boolean visitClosures, final MethodNode selectedMethod) {
/* GRECLIPSE edit
Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
List<Expression> expressions = new LinkedList<>(arguments.getExpressions());
if (selectedMethod instanceof ExtensionMethodNode) {
params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
expressions.add(0, varX("$self", receiver));
}
ArgumentListExpression newArgs = args(expressions);

*/
Parameter[] params;
List<Expression> expressions = new ArrayList<>();
if (selectedMethod instanceof ExtensionMethodNode) {
params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
expressions.add(varX("$self", receiver));
} else {
params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
}
expressions.addAll(arguments.getExpressions());
// GRECLIPSE end
int nExpressions = expressions.size();
for (int i = 0; i < nExpressions; i += 1) {
Expression expression = expressions.get(i);
Expand All @@ -3136,13 +3147,13 @@ protected void visitMethodCallArguments(final ClassNode receiver, final Argument
Parameter target = params[i];
ClassNode targetType = target.getType();
ClosureExpression source = (ClosureExpression) expression;
checkClosureWithDelegatesTo(receiver, selectedMethod, newArgs, params, source, target);
checkClosureWithDelegatesTo(receiver, selectedMethod, args(expressions), params, source, target);
if (selectedMethod instanceof ExtensionMethodNode) {
if (i > 0) {
inferClosureParameterTypes(receiver, arguments, source, target, selectedMethod);
}
} else {
inferClosureParameterTypes(receiver, newArgs, source, target, selectedMethod);
inferClosureParameterTypes(receiver, arguments, source, target, selectedMethod);
}
if (isFunctionalInterface(targetType)) {
storeInferredReturnType(source, GenericsUtils.parameterizeSAM(targetType).getV2());
Expand Down

0 comments on commit 9577649

Please sign in to comment.