Skip to content

Commit

Permalink
GROOVY-9881
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Jan 20, 2021
1 parent 89341d0 commit eda2958
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5435,6 +5435,81 @@ public void testCompileStatic9872() {
runConformTest(sources, "[kv:kv]");
}

@Test
public void testCompileStatic9881() {
if (Float.parseFloat(System.getProperty("java.specification.version")) > 8)
vmArguments = new String[] {"--add-opens", "java.base/java.util.function=ALL-UNNAMED"};

//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.CompileStatic\n" +
"void test() {\n" +
" print new Value(123).replace { -> 'foo' }\n" +
" print new Value(123).replace { Integer v -> 'bar' }\n" +
"}\n" +
"test()\n",

"Value.groovy",
"import java.util.function.*\n" +
"class Value<V> {\n" +
" final V val\n" +
" Value(V v) {\n" +
" this.val = v\n" +
" }\n" +
" String toString() {\n" +
" val as String\n" +
" }\n" +
" def <T> Value<T> replace(Supplier<T> supplier) {\n" +
" new Value<>(supplier.get())\n" +
" }\n" +
" def <T> Value<T> replace(Function<? super V, ? extends T> function) {\n" +
" new Value(function.apply(val))\n" +
" }\n" +
"}\n",
};
//@formatter:on

runConformTest(sources, "foobar");
}

@Test
public void testCompileStatic9881a() {
assumeTrue(isParrotParser());

//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.CompileStatic\n" +
"void test() {\n" +
" print new Value(123).replace(() -> 'foo')\n" +
" print new Value(123).replace((Integer v) -> 'bar')\n" +
"}\n" +
"test()\n",

"Value.groovy",
"import java.util.function.*\n" +
"class Value<V> {\n" +
" final V val\n" +
" Value(V v) {\n" +
" this.val = v\n" +
" }\n" +
" String toString() {\n" +
" val as String\n" +
" }\n" +
" def <T> Value<T> replace(Supplier<T> supplier) {\n" +
" new Value<>(supplier.get())\n" +
" }\n" +
" def <T> Value<T> replace(Function<? super V, ? extends T> function) {\n" +
" new Value(function.apply(val))\n" +
" }\n" +
"}\n",
};
//@formatter:on

runConformTest(sources, "foobar");
}

@Test
public void testCompileStatic9882() {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import static org.codehaus.groovy.ast.ClassHelper.byte_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.char_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.findSAM;
import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.getUnwrapper;
import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
Expand Down Expand Up @@ -961,16 +962,30 @@ && isPrimitiveType(unwrapCompare)
if (receiver == UNKNOWN_PARAMETER_TYPE) {
return dist;
}
// GRECLIPSE add -- GROOVY-9852, GROOVY-9881
if (compare.isInterface()) { MethodNode sam;
if (receiver.implementsInterface(compare)) {
return dist + getMaximumInterfaceDistance(receiver, compare);
} else if (receiver.equals(CLOSURE_TYPE) && (sam = findSAM(compare)) != null) {
// GROOVY-9881: in case of multiple overloads, give preference to equal parameter count
Integer closureParamCount = receiver.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
if (closureParamCount != null && closureParamCount == sam.getParameters().length) dist -= 1;

ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? ClassHelper.getWrapper(receiver) : receiver;
return dist + 13; // GROOVY-9852: @FunctionalInterface vs Object
}
}
// GRECLIPSE end
ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? getWrapper(receiver) : receiver;
while (ref != null) {
/* GRECLIPSE edit
if (compare.equals(ref)) {
break;
}
if (compare.isInterface() && ref.implementsInterface(compare)) {
dist += getMaximumInterfaceDistance(ref, compare);
break;
}
*/
ref = ref.getSuperClass();
dist++;
if (ref == null) dist++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5256,13 +5256,27 @@ protected ClassNode getType(final ASTNode exp) {
return ((Parameter) exp).getOriginType();
}
if (exp instanceof ClosureExpression) {
/* GRECLIPSE edit -- GROOVY-9881
ClassNode irt = getInferredReturnType(exp);
if (irt != null) {
irt = wrapTypeIfNecessary(irt);
ClassNode result = CLOSURE_TYPE.getPlainNodeReference();
result.setGenericsTypes(new GenericsType[]{new GenericsType(irt)});
return result;
}
*/
ClassNode type = CLOSURE_TYPE.getPlainNodeReference();
ClassNode returnType = getInferredReturnType(exp);
if (returnType != null) {
type.setGenericsTypes(new GenericsType[]{
new GenericsType(wrapTypeIfNecessary(returnType))
});
}
Parameter[] parameters = ((ClosureExpression) exp).getParameters();
int nParameters = parameters == null ? 0 : parameters.length == 0 ? -1 : parameters.length;
type.putNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS, nParameters);
return type;
// GRECLIPSE end
} else if (exp instanceof MethodCall) {
MethodNode target = (MethodNode) exp.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (target != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.apache.groovy.util.Maps;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
Expand Down Expand Up @@ -93,6 +92,7 @@
import static org.codehaus.groovy.ast.ClassHelper.byte_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.char_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.findSAM;
import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.getUnwrapper;
import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
Expand Down Expand Up @@ -913,16 +913,30 @@ && isPrimitiveType(unwrapCompare)
if (receiver == UNKNOWN_PARAMETER_TYPE) {
return dist;
}
// GRECLIPSE add -- GROOVY-9852, GROOVY-9881
if (compare.isInterface()) { MethodNode sam;
if (receiver.implementsInterface(compare)) {
return dist + getMaximumInterfaceDistance(receiver, compare);
} else if (receiver.equals(CLOSURE_TYPE) && (sam = findSAM(compare)) != null) {
// GROOVY-9881: in case of multiple overloads, give preference to equal parameter count
Integer closureParamCount = receiver.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
if (closureParamCount != null && closureParamCount == sam.getParameters().length) dist -= 1;

ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? ClassHelper.getWrapper(receiver) : receiver;
return dist + 13; // GROOVY-9852: @FunctionalInterface vs Object
}
}
// GRECLIPSE end
ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? getWrapper(receiver) : receiver;
while (ref != null) {
/* GRECLIPSE edit
if (compare.equals(ref)) {
break;
}
if (compare.isInterface() && ref.implementsInterface(compare)) {
dist += getMaximumInterfaceDistance(ref, compare);
break;
}
*/
ref = ref.getSuperClass();
dist += 1;
if (OBJECT_TYPE.equals(ref))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4989,13 +4989,28 @@ protected ClassNode getType(final ASTNode exp) {
return ((Parameter) exp).getOriginType();
}
if (exp instanceof ClosureExpression) {
/* GRECLIPSE edit -- GROOVY-9881
ClassNode irt = getInferredReturnType(exp);
if (irt != null) {
irt = wrapTypeIfNecessary(irt);
ClassNode result = CLOSURE_TYPE.getPlainNodeReference();
result.setGenericsTypes(new GenericsType[]{new GenericsType(irt)});
return result;
}
*/
ClassNode type = CLOSURE_TYPE.getPlainNodeReference();
ClassNode returnType = getInferredReturnType(exp);
if (returnType != null) {
type.setGenericsTypes(new GenericsType[]{
new GenericsType(wrapTypeIfNecessary(returnType))
});
}
Parameter[] parameters = ((ClosureExpression) exp).getParameters();
int nParameters = parameters == null ? 0
: parameters.length == 0 ? -1 : parameters.length;
type.putNodeMetaData(CLOSURE_ARGUMENTS, nParameters);
return type;
// GRECLIPSE end
} else if (exp instanceof MethodCall) {
MethodNode target = exp.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (target != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.apache.groovy.util.Maps;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
Expand Down Expand Up @@ -93,6 +92,7 @@
import static org.codehaus.groovy.ast.ClassHelper.byte_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.char_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.findSAM;
import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.getUnwrapper;
import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
Expand Down Expand Up @@ -912,16 +912,30 @@ && isPrimitiveType(unwrapCompare)
if (receiver == UNKNOWN_PARAMETER_TYPE) {
return dist;
}
// GRECLIPSE add -- GROOVY-9852, GROOVY-9881
if (compare.isInterface()) { MethodNode sam;
if (receiver.implementsInterface(compare)) {
return dist + getMaximumInterfaceDistance(receiver, compare);
} else if (receiver.equals(CLOSURE_TYPE) && (sam = findSAM(compare)) != null) {
// GROOVY-9881: in case of multiple overloads, give preference to equal parameter count
Integer closureParamCount = receiver.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
if (closureParamCount != null && closureParamCount == sam.getParameters().length) dist -= 1;

ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? ClassHelper.getWrapper(receiver) : receiver;
return dist + 13; // GROOVY-9852: @FunctionalInterface vs Object
}
}
// GRECLIPSE end
ClassNode ref = isPrimitiveType(receiver) && !isPrimitiveType(compare) ? getWrapper(receiver) : receiver;
while (ref != null) {
/* GRECLIPSE edit
if (compare.equals(ref)) {
break;
}
if (compare.isInterface() && ref.implementsInterface(compare)) {
dist += getMaximumInterfaceDistance(ref, compare);
break;
}
*/
ref = ref.getSuperClass();
dist += 1;
if (OBJECT_TYPE.equals(ref))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4955,13 +4955,28 @@ protected ClassNode getType(final ASTNode exp) {
return ((Parameter) exp).getOriginType();
}
if (exp instanceof ClosureExpression) {
/* GRECLIPSE edit -- GROOVY-9881
ClassNode irt = getInferredReturnType(exp);
if (irt != null) {
irt = wrapTypeIfNecessary(irt);
ClassNode result = CLOSURE_TYPE.getPlainNodeReference();
result.setGenericsTypes(new GenericsType[]{new GenericsType(irt)});
return result;
}
*/
ClassNode type = CLOSURE_TYPE.getPlainNodeReference();
ClassNode returnType = getInferredReturnType(exp);
if (returnType != null) {
type.setGenericsTypes(new GenericsType[]{
new GenericsType(wrapTypeIfNecessary(returnType))
});
}
Parameter[] parameters = ((ClosureExpression) exp).getParameters();
int nParameters = parameters == null ? 0
: parameters.length == 0 ? -1 : parameters.length;
type.putNodeMetaData(CLOSURE_ARGUMENTS, nParameters);
return type;
// GRECLIPSE end
} else if (exp instanceof MethodCall) {
MethodNode target = exp.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (target != null) {
Expand Down

0 comments on commit eda2958

Please sign in to comment.