Skip to content

Commit 74e24d8

Browse files
committed
GROOVY-8304, GROOVY-8409, GROOVY-9803, GROOVY-9902 & GROOVY-10067 (pt.2)
1 parent b344a94 commit 74e24d8

File tree

16 files changed

+947
-346
lines changed

16 files changed

+947
-346
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/GenericInferencingTests.java

+24-23
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.eclipse.jdt.core.ICompilationUnit;
2828
import org.eclipse.jdt.core.compiler.IProblem;
2929
import org.eclipse.jdt.core.groovy.tests.ReconcilerUtils;
30-
import org.junit.Ignore;
3130
import org.junit.Test;
3231

3332
public final class GenericInferencingTests extends InferencingTestSuite {
@@ -919,26 +918,28 @@ public void testClosure6c() {
919918

920919
@Test // GROOVY-9803
921920
public void testClosure7() {
922-
String contents =
923-
"class C<T> {\n" +
924-
" static <U> C<U> of(U item) {}\n" +
925-
" def <V> C<V> map(F<? super T, ? super V> func) {}\n" +
926-
"}\n" +
927-
"class D {\n" +
928-
" static <W> Set<W> wrap(W o) {}\n" +
929-
"}\n" +
930-
"interface F<X,Y> {\n" +
931-
" Y apply(X x)\n" +
932-
"}\n" +
933-
"@groovy.transform.TypeChecked\n" +
934-
"void test() {\n" +
935-
" def c = C.of(123)\n" +
936-
" def d = c.map(D.&wrap)\n" +
937-
" def e = d.map{x -> x.first()}\n" +
938-
"}\n";
939-
assertType(contents, "wrap", "java.util.Set<java.lang.Integer>");
940-
assertType(contents, "x", "java.util.Set<java.lang.Integer>");
941-
assertType(contents, "e", "C<java.lang.Integer>");
921+
for (String toSet : new String[] {"D.&wrap", "Collections.&singleton", "{x -> [x].toSet()}", "{Collections.singleton(it)}"}) {
922+
String contents =
923+
"class C<T> {\n" +
924+
" static <U> C<U> of(U item) {}\n" +
925+
" def <V> C<V> map(F<? super T, ? super V> func) {}\n" +
926+
"}\n" +
927+
"class D {\n" +
928+
" static <W> Set<W> wrap(W o) {}\n" +
929+
"}\n" +
930+
"interface F<X,Y> {\n" +
931+
" Y apply(X x)\n" +
932+
"}\n" +
933+
"@groovy.transform.TypeChecked\n" +
934+
"void test() {\n" +
935+
" def c = C.of(123)\n" +
936+
" def d = c.map(" + toSet + ")\n" +
937+
" def e = d.map{x -> x.first()}\n" +
938+
"}\n";
939+
assertType(contents, "d", "C<java.util.Set<java.lang.Integer>>");
940+
assertType(contents, "x", "java.util.Set<java.lang.Integer>");
941+
assertType(contents, "e", "C<java.lang.Integer>");
942+
}
942943
}
943944

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

1575-
@Test @Ignore
1576+
@Test
15761577
public void testJira1718() throws Exception {
15771578
createUnit("p2", "Renderer",
15781579
"package p2\n" +
@@ -1630,7 +1631,7 @@ public void testJira1718() throws Exception {
16301631
" if (htmlRenderer == null) {\n" +
16311632
" htmlRenderer = new DefaultRenderer(targetType)\n" +
16321633
" }\n" +
1633-
" 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]
1634+
" 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]
16341635
" }\n" +
16351636
"}\n");
16361637

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GroovySimpleTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -2515,8 +2515,8 @@ public void testMissingTypesForGeneratedBindingsGivesNPE_GRE273() {
25152515
" \n" +
25162516
" boolean isValid(String newValue) {\n" +
25172517
" try {\n" +
2518-
" return validators.inject(true) {\n" +
2519-
" prev, cur -> prev && cur.call([newValue, source])\n" +
2518+
" return validators.inject(true) { valid, validator ->\n" +
2519+
" valid && validator.call([newValue, source])\n" +
25202520
" }\n" +
25212521
" } catch (e) {\n" +
25222522
" return false\n" +

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/StaticCompilationTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1834,7 +1834,7 @@ public void testCompileStatic8389a() {
18341834
runConformTest(sources, "method:property");
18351835
}
18361836

1837-
@Test @Ignore("https://issues.apache.org/jira/browse/GROOVY-8409")
1837+
@Test
18381838
public void testCompileStatic8409() {
18391839
for (char t : new char[] {'R', 'S', 'T', 'U'}) { // BiFunction uses R, T and U
18401840
//@formatter:off

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+188-28
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,148 @@ public void testTypeChecked10() {
237237
runConformTest(sources);
238238
}
239239

240+
@Test
241+
public void testTypeChecked11() {
242+
//@formatter:off
243+
String[] sources = {
244+
"Main.groovy",
245+
"import static java.util.stream.Collectors.toList\n" +
246+
"@groovy.transform.TypeChecked\n" +
247+
"void test() {\n" +
248+
" List<CharSequence> xxx = ['x'].collect()\n" +
249+
" List<CharSequence> yyy = ['y'].stream().toList()\n" +
250+
" List<CharSequence> zzz = ['z'].stream().collect(toList())\n" +
251+
"}\n",
252+
};
253+
//@formatter:on
254+
255+
runNegativeTest(sources,
256+
"----------\n" +
257+
"1. ERROR in Main.groovy (at line 4)\n" +
258+
"\tList<CharSequence> xxx = ['x'].collect()\n" +
259+
"\t ^^^^^^^^^^^^^^^\n" +
260+
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List<java.lang.String> to: java.util.List<java.lang.CharSequence>\n" +
261+
"----------\n" +
262+
"2. ERROR in Main.groovy (at line 5)\n" +
263+
"\tList<CharSequence> yyy = ['y'].stream().toList()\n" +
264+
"\t ^^^^^^^^^^^^^^^^^^^^^^^\n" +
265+
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List<java.lang.String> to: java.util.List<java.lang.CharSequence>\n" +
266+
"----------\n");
267+
}
268+
269+
@Test
270+
public void testTypeChecked12() {
271+
//@formatter:off
272+
String[] sources = {
273+
"Main.groovy",
274+
"import org.codehaus.groovy.runtime.DefaultGroovyMethods as DGM\n" +
275+
"@groovy.transform.TypeChecked\n" +
276+
"void test() {\n" +
277+
" def strings = ['x','yy','zzz']\n" +
278+
" print(strings.inject(0) { result, string -> result += string.length() })\n" +
279+
" print(strings.inject { result, string -> result += string.toUpperCase() })\n" +
280+
" print(DGM.inject(strings) { result, string -> result += string.toUpperCase() })\n" +
281+
"}\n" +
282+
"test()\n",
283+
};
284+
//@formatter:on
285+
286+
runConformTest(sources, "6xYYZZZxYYZZZ");
287+
}
288+
289+
@Test
290+
public void testTypeChecked13() {
291+
//@formatter:off
292+
String[] sources = {
293+
"Main.groovy",
294+
"interface OngoingStubbing<T> /*extends IOngoingStubbing*/ {\n" +
295+
" OngoingStubbing<T> thenReturn(T value)\n" +
296+
"}\n" +
297+
"static <T> OngoingStubbing<T> when(T methodCall) {\n" +
298+
" [thenReturn: { T value -> null }] as OngoingStubbing<T>\n" +
299+
"}\n" +
300+
"Optional<String> foo() {\n" +
301+
"}\n" +
302+
"@groovy.transform.TypeChecked\n" +
303+
"void test() {\n" +
304+
" when(foo()).thenReturn(Optional.empty())\n" +
305+
"}\n" +
306+
"test()\n",
307+
};
308+
//@formatter:on
309+
310+
runConformTest(sources);
311+
}
312+
313+
@Test
314+
public void testTypeChecked14() {
315+
//@formatter:off
316+
String[] sources = {
317+
"Main.groovy",
318+
"@groovy.transform.TypeChecked\n" +
319+
"void test(Pojo pojo) {\n" +
320+
" Foo raw = pojo.getFoo('')\n" +
321+
" raw.bar = raw.baz\n" +
322+
"}\n" +
323+
"test(new Pojo())\n",
324+
325+
"Pojo.java",
326+
"public class Pojo {\n" +
327+
" public <R extends I> Foo<R> getFoo(String key) {\n" +
328+
" return new Foo<>();\n" +
329+
" }\n" +
330+
"}\n",
331+
332+
"Types.groovy",
333+
"interface I {\n" +
334+
"}\n" +
335+
"class Foo<T extends I> {\n" +
336+
" T bar\n" +
337+
" T baz\n" +
338+
"}\n",
339+
};
340+
//@formatter:on
341+
342+
runConformTest(sources);
343+
}
344+
345+
@Test
346+
public void testTypeChecked15() {
347+
//@formatter:off
348+
String[] sources = {
349+
"Main.groovy",
350+
"def <T,U extends Configurable<T>> U configure(Class<U> type, @DelegatesTo(type='T',strategy=Closure.DELEGATE_FIRST) Closure<?> spec) {\n" +
351+
" Configurable<T> obj = (Configurable<T>) type.newInstance()\n" +
352+
" obj.configure(spec)\n" +
353+
" obj\n" +
354+
"}\n" +
355+
"trait Configurable<X> { X configObject\n" +
356+
" void configure(Closure<Void> spec) {\n" +
357+
" configObject.with(spec)\n" +
358+
" }\n" +
359+
"}\n" +
360+
"class Item implements Configurable<ItemConfig> {\n" +
361+
" Item() {\n" +
362+
" configObject = new ItemConfig()\n" +
363+
" }\n" +
364+
"}\n" +
365+
"class ItemConfig {\n" +
366+
" String name, version\n" +
367+
"}\n" +
368+
"@groovy.transform.TypeChecked\n" +
369+
"def test() {\n" +
370+
" configure(Item) {\n" +
371+
" name = 'test'\n" +
372+
" version = '1'\n" +
373+
" }\n" +
374+
"}\n" +
375+
"print test().configObject.name\n",
376+
};
377+
//@formatter:on
378+
379+
runConformTest(sources, "test");
380+
}
381+
240382
@Test
241383
public void testTypeChecked6232() {
242384
//@formatter:off
@@ -597,6 +739,22 @@ public void testTypeChecked7363() {
597739
runNegativeTest(sources, "");
598740
}
599741

742+
@Test
743+
public void testTypeChecked7804() {
744+
//@formatter:off
745+
String[] sources = {
746+
"Main.groovy",
747+
"@groovy.transform.TypeChecked\n" + // Supplier also uses "T"
748+
"def <T> T test(java.util.function.Supplier<T> supplier) {\n" +
749+
" supplier.get()\n" +
750+
"}\n" +
751+
"print(test { -> 'foo' })\n",
752+
};
753+
//@formatter:on
754+
755+
runConformTest(sources, "foo");
756+
}
757+
600758
@Test
601759
public void testTypeChecked7945() {
602760
//@formatter:off
@@ -1415,15 +1573,15 @@ public void testTypeChecked9902() {
14151573
" def <T> TypedProperty<T, Unknown> prop(Class<T> clazz) {\n" +
14161574
" new TypedProperty<T, Unknown>(clazz: clazz)\n" +
14171575
" }\n" +
1418-
// Note: type argument of Holder cannot be supplied to value attribute of @DelegatesTo
1419-
" def <T> T of(@DelegatesTo(value=Holder, strategy=Closure.DELEGATE_FIRST) Closure<T> c) {\n" +
1576+
" def <U> U of(@DelegatesTo(value=Holder, strategy=Closure.DELEGATE_FIRST) Closure<U> c) {\n" +
1577+
// ^^^^^^ type argument cannot be supplied using value attribute
14201578
" this.with(c)\n" +
14211579
" }\n" +
14221580
"}\n" +
1423-
"class TypedProperty<X, Y> {\n" +
1424-
" Class<X> clazz\n" +
1425-
" void eq(X x) {\n" +
1426-
" assert x.class == clazz : \"x.class is ${x.class} not ${clazz}\"\n" +
1581+
"class TypedProperty<V, Unused> {\n" +
1582+
" Class<V> clazz\n" +
1583+
" void eq(V that) {\n" +
1584+
" assert that.class == this.lclazz : \"that.class is ${that.class} not ${this.clazz}\"\n" +
14271585
" }\n" +
14281586
"}\n" +
14291587
"@groovy.transform.TypeChecked\n" +
@@ -1448,12 +1606,12 @@ public void testTypeChecked9902() {
14481606
"2. ERROR in Main.groovy (at line 21)\n" +
14491607
"\tstringProperty.eq(1234)\n" +
14501608
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
1451-
"Groovy:[Static type checking] - Cannot call TypedProperty#eq(java.lang.String) with arguments [int]\n" +
1609+
"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" +
14521610
"----------\n" +
14531611
"3. ERROR in Main.groovy (at line 22)\n" +
14541612
"\tnumberProperty.eq('xx')\n" +
14551613
"\t^^^^^^^^^^^^^^^^^^^^^^^\n" +
1456-
"Groovy:[Static type checking] - Cannot call TypedProperty#eq(java.lang.Number) with arguments [java.lang.String]\n" +
1614+
"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" +
14571615
"----------\n");
14581616
}
14591617

@@ -1504,23 +1662,25 @@ public void testTypeChecked9907() {
15041662

15051663
@Test
15061664
public void testTypeChecked9915() {
1507-
//@formatter:off
1508-
String[] sources = {
1509-
"Main.groovy",
1510-
"@groovy.transform.TypeChecked\n" +
1511-
"class C {\n" +
1512-
" void m() {\n" +
1513-
" init(Collections.emptyList())\n" + // Cannot call C#init(List<String>) with arguments [List<T>]
1514-
" }\n" +
1515-
" private static void init(List<String> strings) {\n" +
1516-
" print strings\n" +
1517-
" }\n" +
1518-
"}\n" +
1519-
"new C().m()\n",
1520-
};
1521-
//@formatter:on
1665+
for (String type : new String[] {"List", "Iterable", "Collection"}) {
1666+
//@formatter:off
1667+
String[] sources = {
1668+
"Main.groovy",
1669+
"@groovy.transform.TypeChecked\n" +
1670+
"class C {\n" +
1671+
" void m() {\n" +
1672+
" init(Collections.emptyList())\n" + // Cannot call C#init(List<String>) with arguments [List<T>]
1673+
" }\n" +
1674+
" private static void init(" + type + "<String> strings) {\n" +
1675+
" print strings\n" +
1676+
" }\n" +
1677+
"}\n" +
1678+
"new C().m()\n",
1679+
};
1680+
//@formatter:on
15221681

1523-
runConformTest(sources, "[]");
1682+
runConformTest(sources, "[]");
1683+
}
15241684
}
15251685

15261686
@Test
@@ -2483,11 +2643,11 @@ public void testTypeChecked10067() {
24832643
" f((Integer) getNumber())\n" +
24842644
" g((Integer) getNumber())\n" +
24852645
" i = getNumber()\n" +
2486-
//" f(getNumber())\n" +
2487-
//" g(getNumber())\n" +
2646+
" f(getNumber())\n" +
2647+
" g(getNumber())\n" +
24882648
" i = number\n" +
2489-
//" f(number)\n" +
2490-
//" g(number)\n" +
2649+
" f(number)\n" +
2650+
" g(number)\n" +
24912651
"}\n" +
24922652
"test()\n",
24932653
};

base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/GenericsType.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ private boolean compareGenericsWithBound(final ClassNode classNode, final ClassN
438438
GenericsTypeName name = new GenericsTypeName(classNodeType.getName());
439439
if (redirectBoundType.isPlaceholder()) {
440440
GenericsTypeName gtn = new GenericsTypeName(redirectBoundType.getName());
441-
match = name.equals(gtn);
441+
match = name.equals(gtn)
442+
|| name.equals(new GenericsTypeName("#" + redirectBoundType.getName()));
442443
if (!match) {
443444
GenericsType genericsType = boundPlaceHolders.get(gtn);
444445
if (genericsType!=null) {

base/org.codehaus.groovy25/src/org/codehaus/groovy/control/ResolveVisitor.java

+6
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,7 @@ private void resolveGenericsHeader(GenericsType[] types, GenericsType rootType,
17501750
} else {
17511751
if (!isWild) {
17521752
if (toDealWithGenerics) {
1753+
/* GRECLIPSE edit
17531754
GenericsType originalGt = genericParameterNames.get(gtn);
17541755
genericParameterNames.put(gtn, type);
17551756
type.setPlaceholder(true);
@@ -1759,6 +1760,11 @@ private void resolveGenericsHeader(GenericsType[] types, GenericsType rootType,
17591760
} else {
17601761
classNode.setRedirect(originalGt.getType());
17611762
}
1763+
*/
1764+
type.setPlaceholder(true);
1765+
GenericsType last = genericParameterNames.put(gtn, type);
1766+
classNode.setRedirect(last != null ? last.getType().redirect() : ClassHelper.OBJECT_TYPE);
1767+
// GRECLIPSE end
17621768
}
17631769
}
17641770
}

0 commit comments

Comments
 (0)