Skip to content

Commit

Permalink
GROOVY-6603
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Dec 27, 2021
1 parent e0a9ab0 commit 526ba6f
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ public void testClosureParamsAnnotation1() {
//@formatter:off
String contents =
"import groovy.transform.stc.*\n" +
"def match(@ClosureParams(value=SimpleType, options=['java.util.regex.Pattern']) Closure block) {\n" +
"def match(@ClosureParams(value=SimpleType, options='java.util.regex.Pattern') Closure block) {\n" +
" block(item)\n" +
"}\n" +
"\n" +
Expand Down Expand Up @@ -1426,7 +1426,7 @@ public void testClosureParamsAnnotation3() {
String contents =
"import groovy.transform.stc.*\n" +
"class C {\n" +
" C(String s, @ClosureParams(value=SimpleType, options='java.util.List<java.lang.Integer>') Closure c) {\n" +
" C(String s, @ClosureParams(value=FromString, options='java.util.List<java.lang.Integer>') Closure c) {\n" +
" }\n" +
"}\n" +
"new C('str', { list -> null })\n";
Expand All @@ -1440,7 +1440,7 @@ public void testClosureParamsAnnotation4() {
String contents =
"import groovy.transform.stc.*\n" +
"class C {\n" +
" static m(String s, @ClosureParams(value=SimpleType, options='java.util.List<java.lang.Integer>') Closure c) {\n" +
" static m(String s, @ClosureParams(value=FromString, options='java.util.List<java.lang.Integer>') Closure c) {\n" +
" }\n" +
" static test() {\n" +
" m('str', { list -> null })\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public void testTypeChecked7() {
"Main.groovy",
"import groovy.transform.stc.*\n" +
"class C {\n" +
" C(String s, @ClosureParams(value=SimpleType, options='java.util.List') Closure<Integer> c) {\n" +
" C(String s, @ClosureParams(value=FromString,options='java.util.List<java.lang.Integer>') Closure<Integer> c) {\n" +
" }\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
Expand Down Expand Up @@ -633,6 +633,66 @@ public void testTypeChecked6455() {
runConformTest(sources);
}

@Test
public void testTypeChecked6603() {
//@formatter:off
String[] sources = {
"Main.groovy",
"import groovy.transform.stc.*\n" +
"@groovy.transform.TypeChecked\n" +
"void test(@ClosureParams(value=FromString,options='java.lang.Number') Closure<?> c) {\n" +
" c('x')\n" +
"}\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 4)\n" +
"\tc('x')\n" +
"\t ^^^\n" +
"Groovy:[Static type checking] - Cannot call closure that accepts [java.lang.Number] with [java.lang.String]\n" +
"----------\n");
}

@Test
public void testTypeChecked6603a() {
//@formatter:off
String[] sources = {
"Main.groovy",
"import groovy.transform.stc.*\n" +
"@groovy.transform.TypeChecked\n" +
"void test(@ClosureParams(value=FromString,options='java.util.List<java.lang.Number>') Closure<?> c) {\n" +
" c(['x'])\n" +
"}\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 4)\n" +
"\tc(['x'])\n" +
"\t ^^^^^\n" +
"Groovy:[Static type checking] - Cannot call closure that accepts [java.util.List<java.lang.Number>] with [java.util.List<java.lang.String>]\n" +
"----------\n");
}

@Test
public void testTypeChecked6603b() {
//@formatter:off
String[] sources = {
"Main.groovy",
"import groovy.transform.stc.*\n" +
"@groovy.transform.TypeChecked\n" +
"void test(@ClosureParams(value=FromString,options='java.util.Collection<java.lang.String>') Closure<?> c) {\n" +
" c(Collections.singletonList('x'))\n" +
"}\n",
};
//@formatter:on

runNegativeTest(sources, "");
}

@Test
public void testTypeChecked6731() {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2696,6 +2696,18 @@ private void negativeOrPositiveUnary(Expression expression, String name) {
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
typeCheckingContext.pushEnclosingMethod(node);
if (!isSkipMode(node) && !shouldSkipMethodNode(node)) {
// GRECLIPSE add -- GROOVY-6603
for (Parameter parameter : node.getParameters()) {
for (AnnotationNode annotation : parameter.getAnnotations()) {
if (annotation.getClassNode().equals(CLOSUREPARAMS_CLASSNODE)) {
List<ClassNode[]> signatures = getSignaturesFromHint(null, node, annotation.getMember("value"), annotation.getMember("options"));
if (signatures.size() == 1) {
parameter.putNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS, Arrays.stream(signatures.get(0)).map(t -> new Parameter(t,"")).toArray(Parameter[]::new));
}
}
}
}
// GRECLIPSE end
super.visitConstructorOrMethod(node, isConstructor);
// GRECLIPSE add
if (node.hasDefaultValue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,18 @@ private void negativeOrPositiveUnary(final Expression expression, final String n
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
typeCheckingContext.pushEnclosingMethod(node);
if (!isSkipMode(node) && !shouldSkipMethodNode(node)) {
// GRECLIPSE add -- GROOVY-6603
for (Parameter parameter : node.getParameters()) {
for (AnnotationNode annotation : parameter.getAnnotations()) {
if (annotation.getClassNode().equals(CLOSUREPARAMS_CLASSNODE)) {
List<ClassNode[]> signatures = getSignaturesFromHint(null, node, annotation.getMember("value"), annotation.getMember("options"));
if (signatures.size() == 1) {
parameter.putNodeMetaData(CLOSURE_ARGUMENTS, Arrays.stream(signatures.get(0)).map(t -> new Parameter(t,"")).toArray(Parameter[]::new));
}
}
}
}
// GRECLIPSE end
super.visitConstructorOrMethod(node, isConstructor);
// GRECLIPSE add
if (node.hasDefaultValue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2595,6 +2595,19 @@ protected void startMethodInference(final MethodNode node, final ErrorCollector
@Override
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
typeCheckingContext.pushEnclosingMethod(node);
for (Parameter parameter : node.getParameters()) {
for (AnnotationNode annotation : parameter.getAnnotations()) {
if (annotation.getClassNode().equals(CLOSUREPARAMS_CLASSNODE)) {
// GROOVY-6603: propagate closure parameter types
Expression value = annotation.getMember("value");
Expression options = annotation.getMember("options");
List<ClassNode[]> signatures = getSignaturesFromHint(null, node, value, options);
if (signatures.size() == 1) {
parameter.putNodeMetaData(CLOSURE_ARGUMENTS, Arrays.stream(signatures.get(0)).map(t -> new Parameter(t,"")).toArray(Parameter[]::new));
}
}
}
}
super.visitConstructorOrMethod(node, isConstructor);
if (node.hasDefaultValue()) {
for (Parameter parameter : node.getParameters()) {
Expand Down Expand Up @@ -3366,7 +3379,7 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
if (parameters != null) {
typeCheckClosureCall(callArguments, args, parameters);
}
ClassNode type = getType(((ASTNode) variable));
ClassNode type = getType((ASTNode) variable);
if (type.equals(CLOSURE_TYPE)) { // GROOVY-10098, et al.
GenericsType[] genericsTypes = type.getGenericsTypes();
if (genericsTypes != null && genericsTypes.length == 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2020 the original author or authors.
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1452,7 +1452,7 @@ final class ContentAssistLocationTests extends CompletionTestSuite {

//--------------------------------------------------------------------------

private void assertLocation(String contents, ContentAssistLocation expected, @ClosureParams(value=SimpleType, options=['org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext']) @DelegatesTo(value=ContentAssistContext, strategy=Closure.DELEGATE_FIRST) Closure<Void> withContext = null) {
private void assertLocation(String contents, ContentAssistLocation expected, @ClosureParams(value=SimpleType, options='org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext') @DelegatesTo(value=ContentAssistContext, strategy=Closure.DELEGATE_FIRST) Closure<Void> withContext = null) {
def unit = addGroovySource(contents.replace('#', ''), nextUnitName()), offset = contents.indexOf('#')
def context = new GroovyCompletionProposalComputer().createContentAssistContext(unit, offset, new Document(unit.buffer.contents))

Expand Down

0 comments on commit 526ba6f

Please sign in to comment.