Skip to content

Commit

Permalink
GROOVY-8304, GROOVY-8409, GROOVY-9803, GROOVY-9902 & GROOVY-10067 (pt.2)
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed May 13, 2021
1 parent b344a94 commit 74e24d8
Show file tree
Hide file tree
Showing 16 changed files with 947 additions and 346 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.groovy.tests.ReconcilerUtils;
import org.junit.Ignore;
import org.junit.Test;

public final class GenericInferencingTests extends InferencingTestSuite {
Expand Down Expand Up @@ -919,26 +918,28 @@ public void testClosure6c() {

@Test // GROOVY-9803
public void testClosure7() {
String contents =
"class C<T> {\n" +
" static <U> C<U> of(U item) {}\n" +
" def <V> C<V> map(F<? super T, ? super V> func) {}\n" +
"}\n" +
"class D {\n" +
" static <W> Set<W> wrap(W o) {}\n" +
"}\n" +
"interface F<X,Y> {\n" +
" Y apply(X x)\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" def c = C.of(123)\n" +
" def d = c.map(D.&wrap)\n" +
" def e = d.map{x -> x.first()}\n" +
"}\n";
assertType(contents, "wrap", "java.util.Set<java.lang.Integer>");
assertType(contents, "x", "java.util.Set<java.lang.Integer>");
assertType(contents, "e", "C<java.lang.Integer>");
for (String toSet : new String[] {"D.&wrap", "Collections.&singleton", "{x -> [x].toSet()}", "{Collections.singleton(it)}"}) {
String contents =
"class C<T> {\n" +
" static <U> C<U> of(U item) {}\n" +
" def <V> C<V> map(F<? super T, ? super V> func) {}\n" +
"}\n" +
"class D {\n" +
" static <W> Set<W> wrap(W o) {}\n" +
"}\n" +
"interface F<X,Y> {\n" +
" Y apply(X x)\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" def c = C.of(123)\n" +
" def d = c.map(" + toSet + ")\n" +
" def e = d.map{x -> x.first()}\n" +
"}\n";
assertType(contents, "d", "C<java.util.Set<java.lang.Integer>>");
assertType(contents, "x", "java.util.Set<java.lang.Integer>");
assertType(contents, "e", "C<java.lang.Integer>");
}
}

@Test // https://github.com/groovy/groovy-eclipse/issues/1194
Expand Down Expand Up @@ -1572,7 +1573,7 @@ public void testCircularReference() {
assertType(contents, offset, offset + "withStuff".length(), "Concrete");
}

@Test @Ignore
@Test
public void testJira1718() throws Exception {
createUnit("p2", "Renderer",
"package p2\n" +
Expand Down Expand Up @@ -1630,7 +1631,7 @@ public void testJira1718() throws Exception {
" if (htmlRenderer == null) {\n" +
" htmlRenderer = new DefaultRenderer(targetType)\n" +
" }\n" +
" htmlRenderer.render(object, context)\n" + // TODO: Cannot call p2.Renderer<java.lang.Object>#render(java.lang.Object<java.lang.Object>, java.lang.String) with arguments [T, java.lang.String]
" htmlRenderer.render(object, context)\n" + // Cannot call p2.Renderer#render(java.lang.Object<java.lang.Object>, java.lang.String) with arguments [T, java.lang.String]
" }\n" +
"}\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2515,8 +2515,8 @@ public void testMissingTypesForGeneratedBindingsGivesNPE_GRE273() {
" \n" +
" boolean isValid(String newValue) {\n" +
" try {\n" +
" return validators.inject(true) {\n" +
" prev, cur -> prev && cur.call([newValue, source])\n" +
" return validators.inject(true) { valid, validator ->\n" +
" valid && validator.call([newValue, source])\n" +
" }\n" +
" } catch (e) {\n" +
" return false\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1834,7 +1834,7 @@ public void testCompileStatic8389a() {
runConformTest(sources, "method:property");
}

@Test @Ignore("https://issues.apache.org/jira/browse/GROOVY-8409")
@Test
public void testCompileStatic8409() {
for (char t : new char[] {'R', 'S', 'T', 'U'}) { // BiFunction uses R, T and U
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,148 @@ public void testTypeChecked10() {
runConformTest(sources);
}

@Test
public void testTypeChecked11() {
//@formatter:off
String[] sources = {
"Main.groovy",
"import static java.util.stream.Collectors.toList\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" List<CharSequence> xxx = ['x'].collect()\n" +
" List<CharSequence> yyy = ['y'].stream().toList()\n" +
" List<CharSequence> zzz = ['z'].stream().collect(toList())\n" +
"}\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 4)\n" +
"\tList<CharSequence> xxx = ['x'].collect()\n" +
"\t ^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List<java.lang.String> to: java.util.List<java.lang.CharSequence>\n" +
"----------\n" +
"2. ERROR in Main.groovy (at line 5)\n" +
"\tList<CharSequence> yyy = ['y'].stream().toList()\n" +
"\t ^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List<java.lang.String> to: java.util.List<java.lang.CharSequence>\n" +
"----------\n");
}

@Test
public void testTypeChecked12() {
//@formatter:off
String[] sources = {
"Main.groovy",
"import org.codehaus.groovy.runtime.DefaultGroovyMethods as DGM\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" def strings = ['x','yy','zzz']\n" +
" print(strings.inject(0) { result, string -> result += string.length() })\n" +
" print(strings.inject { result, string -> result += string.toUpperCase() })\n" +
" print(DGM.inject(strings) { result, string -> result += string.toUpperCase() })\n" +
"}\n" +
"test()\n",
};
//@formatter:on

runConformTest(sources, "6xYYZZZxYYZZZ");
}

@Test
public void testTypeChecked13() {
//@formatter:off
String[] sources = {
"Main.groovy",
"interface OngoingStubbing<T> /*extends IOngoingStubbing*/ {\n" +
" OngoingStubbing<T> thenReturn(T value)\n" +
"}\n" +
"static <T> OngoingStubbing<T> when(T methodCall) {\n" +
" [thenReturn: { T value -> null }] as OngoingStubbing<T>\n" +
"}\n" +
"Optional<String> foo() {\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" when(foo()).thenReturn(Optional.empty())\n" +
"}\n" +
"test()\n",
};
//@formatter:on

runConformTest(sources);
}

@Test
public void testTypeChecked14() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"void test(Pojo pojo) {\n" +
" Foo raw = pojo.getFoo('')\n" +
" raw.bar = raw.baz\n" +
"}\n" +
"test(new Pojo())\n",

"Pojo.java",
"public class Pojo {\n" +
" public <R extends I> Foo<R> getFoo(String key) {\n" +
" return new Foo<>();\n" +
" }\n" +
"}\n",

"Types.groovy",
"interface I {\n" +
"}\n" +
"class Foo<T extends I> {\n" +
" T bar\n" +
" T baz\n" +
"}\n",
};
//@formatter:on

runConformTest(sources);
}

@Test
public void testTypeChecked15() {
//@formatter:off
String[] sources = {
"Main.groovy",
"def <T,U extends Configurable<T>> U configure(Class<U> type, @DelegatesTo(type='T',strategy=Closure.DELEGATE_FIRST) Closure<?> spec) {\n" +
" Configurable<T> obj = (Configurable<T>) type.newInstance()\n" +
" obj.configure(spec)\n" +
" obj\n" +
"}\n" +
"trait Configurable<X> { X configObject\n" +
" void configure(Closure<Void> spec) {\n" +
" configObject.with(spec)\n" +
" }\n" +
"}\n" +
"class Item implements Configurable<ItemConfig> {\n" +
" Item() {\n" +
" configObject = new ItemConfig()\n" +
" }\n" +
"}\n" +
"class ItemConfig {\n" +
" String name, version\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"def test() {\n" +
" configure(Item) {\n" +
" name = 'test'\n" +
" version = '1'\n" +
" }\n" +
"}\n" +
"print test().configObject.name\n",
};
//@formatter:on

runConformTest(sources, "test");
}

@Test
public void testTypeChecked6232() {
//@formatter:off
Expand Down Expand Up @@ -597,6 +739,22 @@ public void testTypeChecked7363() {
runNegativeTest(sources, "");
}

@Test
public void testTypeChecked7804() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" + // Supplier also uses "T"
"def <T> T test(java.util.function.Supplier<T> supplier) {\n" +
" supplier.get()\n" +
"}\n" +
"print(test { -> 'foo' })\n",
};
//@formatter:on

runConformTest(sources, "foo");
}

@Test
public void testTypeChecked7945() {
//@formatter:off
Expand Down Expand Up @@ -1415,15 +1573,15 @@ public void testTypeChecked9902() {
" 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" +
" def <U> U of(@DelegatesTo(value=Holder, strategy=Closure.DELEGATE_FIRST) Closure<U> c) {\n" +
// ^^^^^^ type argument cannot be supplied using value attribute
" 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" +
"class TypedProperty<V, Unused> {\n" +
" Class<V> clazz\n" +
" void eq(V that) {\n" +
" assert that.class == this.lclazz : \"that.class is ${that.class} not ${this.clazz}\"\n" +
" }\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
Expand All @@ -1448,12 +1606,12 @@ public void testTypeChecked9902() {
"2. ERROR in Main.groovy (at line 21)\n" +
"\tstringProperty.eq(1234)\n" +
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot call TypedProperty#eq(java.lang.String) with arguments [int]\n" +
"Groovy:[Static type checking] - Cannot find matching method TypedProperty#eq(int). Please check if the declared type is correct and if the method exists.\n" +
"----------\n" +
"3. ERROR in Main.groovy (at line 22)\n" +
"\tnumberProperty.eq('xx')\n" +
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot call TypedProperty#eq(java.lang.Number) with arguments [java.lang.String]\n" +
"Groovy:[Static type checking] - Cannot find matching method TypedProperty#eq(java.lang.String). Please check if the declared type is correct and if the method exists.\n" +
"----------\n");
}

Expand Down Expand Up @@ -1504,23 +1662,25 @@ public void testTypeChecked9907() {

@Test
public void testTypeChecked9915() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"class C {\n" +
" void m() {\n" +
" init(Collections.emptyList())\n" + // Cannot call C#init(List<String>) with arguments [List<T>]
" }\n" +
" private static void init(List<String> strings) {\n" +
" print strings\n" +
" }\n" +
"}\n" +
"new C().m()\n",
};
//@formatter:on
for (String type : new String[] {"List", "Iterable", "Collection"}) {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"class C {\n" +
" void m() {\n" +
" init(Collections.emptyList())\n" + // Cannot call C#init(List<String>) with arguments [List<T>]
" }\n" +
" private static void init(" + type + "<String> strings) {\n" +
" print strings\n" +
" }\n" +
"}\n" +
"new C().m()\n",
};
//@formatter:on

runConformTest(sources, "[]");
runConformTest(sources, "[]");
}
}

@Test
Expand Down Expand Up @@ -2483,11 +2643,11 @@ public void testTypeChecked10067() {
" f((Integer) getNumber())\n" +
" g((Integer) getNumber())\n" +
" i = getNumber()\n" +
//" f(getNumber())\n" +
//" g(getNumber())\n" +
" f(getNumber())\n" +
" g(getNumber())\n" +
" i = number\n" +
//" f(number)\n" +
//" g(number)\n" +
" f(number)\n" +
" g(number)\n" +
"}\n" +
"test()\n",
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,8 @@ private boolean compareGenericsWithBound(final ClassNode classNode, final ClassN
GenericsTypeName name = new GenericsTypeName(classNodeType.getName());
if (redirectBoundType.isPlaceholder()) {
GenericsTypeName gtn = new GenericsTypeName(redirectBoundType.getName());
match = name.equals(gtn);
match = name.equals(gtn)
|| name.equals(new GenericsTypeName("#" + redirectBoundType.getName()));
if (!match) {
GenericsType genericsType = boundPlaceHolders.get(gtn);
if (genericsType!=null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,7 @@ private void resolveGenericsHeader(GenericsType[] types, GenericsType rootType,
} else {
if (!isWild) {
if (toDealWithGenerics) {
/* GRECLIPSE edit
GenericsType originalGt = genericParameterNames.get(gtn);
genericParameterNames.put(gtn, type);
type.setPlaceholder(true);
Expand All @@ -1759,6 +1760,11 @@ private void resolveGenericsHeader(GenericsType[] types, GenericsType rootType,
} else {
classNode.setRedirect(originalGt.getType());
}
*/
type.setPlaceholder(true);
GenericsType last = genericParameterNames.put(gtn, type);
classNode.setRedirect(last != null ? last.getType().redirect() : ClassHelper.OBJECT_TYPE);
// GRECLIPSE end
}
}
}
Expand Down
Loading

0 comments on commit 74e24d8

Please sign in to comment.