Skip to content

Commit

Permalink
GROOVY-6786, GROOVY-9902
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Jan 21, 2021
1 parent 9c2f026 commit 8311a93
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,31 @@ public void testTypeChecked9() {
runNegativeTest(sources, "");
}

@Test
public void testTypeChecked6786() {
//@formatter:off
String[] sources = {
"Main.groovy",
"class C<X> {\n" +
" Container<X> container\n" +
" @groovy.transform.TypeChecked\n" +
" void refresh() {\n" +
" def items = findAllItems()\n" +
" container.addAll(items)\n" + // Cannot call Container#addAll(java.util.Collection<? extends X>) with arguments [java.util.Collection<X>]
" }\n" +
" Collection<X> findAllItems() {\n" +
" }\n" +
"}\n" +
"interface Container<Y> {\n" +
" void addAll(Collection<? extends Y> collection)\n" +
"}\n" +
"new C()\n",
};
//@formatter:on

runNegativeTest(sources, "");
}

@Test
public void testTypeChecked6882() {
//@formatter:off
Expand Down Expand Up @@ -633,6 +658,59 @@ public void testTypeChecked9873() {
runConformTest(sources, "123", options);
}

@Test
public void testTypeChecked9902() {
//@formatter:off
String[] sources = {
"Main.groovy",
"class Holder<Unknown> {\n" +
" TypedProperty<Number, Unknown> numberProperty = prop(Number)\n" +
" TypedProperty<String, Unknown> stringProperty = prop(String)\n" +
" def <T> TypedProperty<T, Unknown> prop(Class<T> clazz) {\n" +
" new TypedProperty<T, Unknown>(clazz: clazz)\n" +
" }\n" +
// Note: type argument of Holder cannot be supplied to value attribute of @DelegatesTo
" def <T> T of(@DelegatesTo(value=Holder, strategy=Closure.DELEGATE_FIRST) Closure<T> c) {\n" +
" this.with(c)\n" +
" }\n" +
"}\n" +
"class TypedProperty<X, Y> {\n" +
" Class<X> clazz\n" +
" void eq(X x) {\n" +
" assert x.class == clazz : \"x.class is ${x.class} not ${clazz}\"\n" +
" }\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test(Holder<Object> h) {\n" +
" h.stringProperty.eq(\"${0}\")\n" + // STC error
" h.of {\n" + // <-- 2nd type parameter discarded
" stringProperty.eq(1234)\n" + // expect STC error
" numberProperty.eq('xx')\n" + // expect STC error
" }\n" +
"}\n" +
"test(new Holder<Object>())\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 19)\n" +
"\th.stringProperty.eq(\"${0}\")\n" +
"\t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot call TypedProperty <String, Object>#eq(java.lang.String) with arguments [groovy.lang.GString] \n" +
"----------\n" +
"2. ERROR in Main.groovy (at line 21)\n" +
"\tstringProperty.eq(1234)\n" +
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot call TypedProperty <String, Unknown>#eq(java.lang.String) with arguments [int] \n" +
"----------\n" +
"3. ERROR in Main.groovy (at line 22)\n" +
"\tnumberProperty.eq('xx')\n" +
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot call TypedProperty <Number, Unknown>#eq(java.lang.Number) with arguments [java.lang.String] \n" +
"----------\n");
}

@Test
public void testTypeChecked9903() {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ private boolean compareGenericsWithBound(final ClassNode classNode, final ClassN
if (genericsType.isPlaceholder()) {
match = true;
} else if (genericsType.isWildcard()) {
/* GRECLIPSE edit -- GROOVY-9460
/* GRECLIPSE edit -- GROOVY-6786, GROOVY-9460, GROOVY-9902
if (genericsType.getUpperBounds()!=null) {
for (ClassNode up : genericsType.getUpperBounds()) {
match |= redirectBoundType.isCompatibleWith(up);
Expand All @@ -417,10 +417,10 @@ private boolean compareGenericsWithBound(final ClassNode classNode, final ClassN
}
}
*/
if (genericsType.getUpperBounds() != null) { // multiple bounds not allowed for ?
match = redirectBoundType.isCompatibleWith(genericsType.getUpperBounds()[0]);
if (genericsType.getUpperBounds() != null) { // ? supports single bound only
match = classNodeType.isCompatibleWith(genericsType.getUpperBounds()[0]);
} else if (genericsType.getLowerBound() != null) {
match = redirectBoundType.isCompatibleWith(genericsType.getLowerBound());
match = classNodeType.isCompatibleWith(genericsType.getLowerBound());
} else {
match = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1463,9 +1463,11 @@ static void addMethodLevelDeclaredGenerics(MethodNode method, Map<GenericsTypeNa
}

protected static boolean typeCheckMethodsWithGenerics(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod) {
/* GRECLIPSE edit -- GROOVY-9902
if (isUsingUncheckedGenerics(receiver)) {
return true;
}
*/
if (CLASS_Type.equals(receiver)
&& receiver.isUsingGenerics()
&& !candidateMethod.getDeclaringClass().equals(receiver)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,15 @@ private static boolean compareGenericsWithBound(final ClassNode classNode, final
match = true;
} else if (genericsType.isWildcard()) {
if (genericsType.getUpperBounds() != null) { // multiple bounds not allowed for ?
/* GRECLIPSE edit -- GROOVY-6786, GROOVY-9902
match = redirectBoundType.isCompatibleWith(genericsType.getUpperBounds()[0]);
} else if (genericsType.getLowerBound() != null) {
match = redirectBoundType.isCompatibleWith(genericsType.getLowerBound());
*/
match = classNodeType.isCompatibleWith(genericsType.getUpperBounds()[0]);
} else if (genericsType.getLowerBound() != null) {
match = classNodeType.isCompatibleWith(genericsType.getLowerBound());
// GRECLIPSE end
} else {
match = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1388,9 +1388,11 @@ static void addMethodLevelDeclaredGenerics(final MethodNode method, final Map<Ge
}

protected static boolean typeCheckMethodsWithGenerics(final ClassNode receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod) {
/* GRECLIPSE edit -- GROOVY-9902
if (isUsingUncheckedGenerics(receiver)) {
return true;
}
*/
if (CLASS_Type.equals(receiver)
&& receiver.isUsingGenerics()
&& !candidateMethod.getDeclaringClass().equals(receiver)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,15 @@ private static boolean compareGenericsWithBound(final ClassNode classNode, final
match = true;
} else if (genericsType.isWildcard()) {
if (genericsType.getUpperBounds() != null) { // multiple bounds not allowed for ?
/* GRECLIPSE edit -- GROOVY-6786, GROOVY-9902
match = redirectBoundType.isCompatibleWith(genericsType.getUpperBounds()[0]);
} else if (genericsType.getLowerBound() != null) {
match = redirectBoundType.isCompatibleWith(genericsType.getLowerBound());
*/
match = classNodeType.isCompatibleWith(genericsType.getUpperBounds()[0]);
} else if (genericsType.getLowerBound() != null) {
match = classNodeType.isCompatibleWith(genericsType.getLowerBound());
// GRECLIPSE end
} else {
match = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1386,9 +1386,11 @@ static void addMethodLevelDeclaredGenerics(final MethodNode method, final Map<Ge
}

protected static boolean typeCheckMethodsWithGenerics(final ClassNode receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod) {
/* GRECLIPSE edit -- GROOVY-9902
if (isUsingUncheckedGenerics(receiver)) {
return true;
}
*/
if (CLASS_Type.equals(receiver)
&& receiver.isUsingGenerics()
&& !candidateMethod.getDeclaringClass().equals(receiver)
Expand Down

0 comments on commit 8311a93

Please sign in to comment.