Skip to content

Commit 0d91486

Browse files
committed
GROOVY-9059
1 parent 9cb4c71 commit 0d91486

File tree

4 files changed

+77
-59
lines changed

4 files changed

+77
-59
lines changed

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

+49-29
Original file line numberDiff line numberDiff line change
@@ -2076,7 +2076,7 @@ public void testReferencingFieldsGenerics_GreferingToJ() {
20762076
}
20772077

20782078
@Test
2079-
public void testAbstractCovariance_1() {
2079+
public void testAbstractCovariance1() {
20802080
//@formatter:off
20812081
String[] sources = {
20822082
"Foo.groovy",
@@ -2091,7 +2091,7 @@ public void testAbstractCovariance_1() {
20912091
}
20922092

20932093
@Test
2094-
public void testAbstractCovariance_2() {
2094+
public void testAbstractCovariance2() {
20952095
//@formatter:off
20962096
String[] sources = {
20972097
"Foo.groovy",
@@ -2110,25 +2110,19 @@ public void testAbstractCovariance_2() {
21102110
"----------\n");
21112111
}
21122112

2113-
@Test
2114-
public void testAbstractCovariance_3() {
2113+
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059
2114+
public void testAbstractCovariance3() {
21152115
//@formatter:off
21162116
String[] sources = {
2117-
"Face1.java",
2118-
"@FunctionalInterface\n" +
2119-
"interface Face1<I, O> {\n" +
2120-
" O apply(I in);\n" +
2121-
"}\n",
2122-
2123-
"Face2.java",
2124-
"interface Face2<X, Y> extends Face1<X, Y> {\n" +
2125-
" Object another();\n" +
2117+
"Face.java",
2118+
"interface Face<T> {\n" +
2119+
" <O extends T> O process(O o);\n" +
21262120
"}\n",
21272121

21282122
"Impl.groovy",
2129-
"class Impl implements Face2<Number, String> {\n" +
2130-
" @Override String apply(Number n) { '' }\n" +
2131-
" @Override Object another() { null }\n" +
2123+
"class Impl implements Face<CharSequence> { \n" +
2124+
" @Override\n" +
2125+
" def <Chars extends CharSequence> Chars process(Chars chars) { chars }\n" +
21322126
"}\n",
21332127
};
21342128
//@formatter:on
@@ -2137,7 +2131,7 @@ public void testAbstractCovariance_3() {
21372131
}
21382132

21392133
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059
2140-
public void testAbstractCovariance_GROOVY9059() {
2134+
public void testAbstractCovariance4() {
21412135
//@formatter:off
21422136
String[] sources = {
21432137
"Face.java",
@@ -2146,9 +2140,9 @@ public void testAbstractCovariance_GROOVY9059() {
21462140
"}\n",
21472141

21482142
"Impl.groovy",
2149-
"class Impl implements Face<CharSequence> { \n" +
2143+
"def impl = new Face<CharSequence>() { \n" +
21502144
" @Override\n" +
2151-
" public <Chars extends CharSequence> Chars process(Chars chars) { chars }\n" +
2145+
" def <Chars extends CharSequence> Chars process(Chars chars) { chars }\n" +
21522146
"}\n",
21532147
};
21542148
//@formatter:on
@@ -2157,7 +2151,7 @@ public void testAbstractCovariance_GROOVY9059() {
21572151
}
21582152

21592153
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059
2160-
public void testAbstractCovariance_GROOVY9059a() {
2154+
public void testAbstractCovariance5() {
21612155
//@formatter:off
21622156
String[] sources = {
21632157
"Face.java",
@@ -2167,8 +2161,8 @@ public void testAbstractCovariance_GROOVY9059a() {
21672161

21682162
"Impl.groovy",
21692163
"def impl = new Face<CharSequence>() { \n" +
2170-
" @Override\n" +
2171-
" public <Chars extends CharSequence> Chars process(Chars chars) { chars }\n" +
2164+
" @Override @SuppressWarnings('unchecked')\n" +
2165+
" CharSequence process(CharSequence chars) { chars }\n" +
21722166
"}\n",
21732167
};
21742168
//@formatter:on
@@ -2177,7 +2171,7 @@ public void testAbstractCovariance_GROOVY9059a() {
21772171
}
21782172

21792173
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059
2180-
public void testAbstractCovariance_GROOVY9059b() {
2174+
public void testAbstractCovariance6() {
21812175
//@formatter:off
21822176
String[] sources = {
21832177
"Face.java",
@@ -2186,9 +2180,9 @@ public void testAbstractCovariance_GROOVY9059b() {
21862180
"}\n",
21872181

21882182
"Impl.groovy",
2189-
"def impl = new Face<CharSequence>() { \n" +
2183+
"def impl = new Face<String>() { \n" +
21902184
" @Override @SuppressWarnings('unchecked')\n" +
2191-
" public CharSequence process(CharSequence chars) { chars }\n" +
2185+
" String process(String string) { string }\n" +
21922186
"}\n",
21932187
};
21942188
//@formatter:on
@@ -2197,18 +2191,44 @@ public void testAbstractCovariance_GROOVY9059b() {
21972191
}
21982192

21992193
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059
2200-
public void testAbstractCovariance_GROOVY9059c() {
2194+
public void testAbstractCovariance7() {
22012195
//@formatter:off
22022196
String[] sources = {
2203-
"Face.java",
2197+
"Face.groovy",
22042198
"interface Face<T> {\n" +
2205-
" <O extends T> O process(O o);\n" +
2199+
" def <O extends T> O process(O o)\n" +
22062200
"}\n",
22072201

22082202
"Impl.groovy",
22092203
"def impl = new Face<String>() { \n" +
22102204
" @Override @SuppressWarnings('unchecked')\n" +
2211-
" public String process(String string) { string }\n" +
2205+
" String process(String string) { string }\n" +
2206+
"}\n",
2207+
};
2208+
//@formatter:on
2209+
2210+
runWarningFreeTest(sources);
2211+
}
2212+
2213+
@Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-10675
2214+
public void testAbstractCovariance8() {
2215+
//@formatter:off
2216+
String[] sources = {
2217+
"Face1.java",
2218+
"@FunctionalInterface\n" +
2219+
"interface Face1<I, O> {\n" +
2220+
" O apply(I in);\n" +
2221+
"}\n",
2222+
2223+
"Face2.java",
2224+
"interface Face2<X, Y> extends Face1<X, Y> {\n" +
2225+
" Object another();\n" +
2226+
"}\n",
2227+
2228+
"Impl.groovy",
2229+
"class Impl implements Face2<Number, String> {\n" +
2230+
" @Override String apply(Number n) { '' }\n" +
2231+
" @Override Object another() { null }\n" +
22122232
"}\n",
22132233
};
22142234
//@formatter:on

base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode t
272272
}
273273
return target;
274274
}
275-
// GRECLIPSE add -- GROOVY-8984, GROOVY-9891
275+
// GRECLIPSE add -- GROOVY-8984
276276
if (hint.isGenericsPlaceHolder()) {
277277
ClassNode bound = hint.redirect();
278278
return parameterizeType(bound, target);
@@ -402,16 +402,17 @@ public static ClassNode correctToGenericsSpecRecurse(Map<String, ClassNode> gene
402402
}
403403
*/
404404
if (type != null && type.isGenericsPlaceHolder()) {
405+
if (type.hasMultiRedirect()) {
406+
// convert "S -> T -> U" to "T -> U"
407+
type = type.asGenericsType().getUpperBounds()[0];
408+
// continue to resolve "T -> U" if "T" is a placeholder
409+
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
410+
}
405411
if (type.getGenericsTypes() == null) {
406412
// correct "T -> U" (no generics)
407413
ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName());
408414
placeholder.setGenericsPlaceHolder(true);
409415
return makeClassSafeWithGenerics(type, new GenericsType(placeholder));
410-
} else if (type.hasMultiRedirect()) {
411-
// convert "S -> T -> U" to "T -> U"
412-
type = type.asGenericsType().getUpperBounds()[0];
413-
// continue to resolve "T -> U" if "T" is a placeholder
414-
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
415416
}
416417
}
417418
// GRECLIPSE end
@@ -457,15 +458,14 @@ public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpe
457458
if (type.isPlaceholder()) {
458459
String name = type.getName();
459460
ret = genericsSpec.get(name);
460-
}
461-
// GRECLIPSE add -- GROOVY-8984, GROOVY-9891
462-
else if (type.isWildcard()) {
463-
//ret = type.getLowerBound(); // use lower or upper
461+
} else if (type.isWildcard()) { // GROOVY-9891
462+
/* GRECLIPSE edit -- GROOVY-8984: "? super T" RHS
463+
ret = type.getLowerBound(); // use lower or upper
464+
*/
464465
if (ret == null && type.getUpperBounds() != null) {
465466
ret = type.getUpperBounds()[0]; // ? supports 1
466467
}
467468
}
468-
// GRECLIPSE end
469469
if (ret == null) ret = type.getType();
470470
return ret;
471471
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+9-10
Original file line numberDiff line numberDiff line change
@@ -382,23 +382,22 @@ public static ClassNode correctToGenericsSpecRecurse(Map<String, ClassNode> gene
382382
exclusions = plus(exclusions, name); // GROOVY-7722
383383
type = genericsSpec.get(name);
384384
if (type != null && type.isGenericsPlaceHolder()) {
385+
// GRECLIPSE add -- GROOVY-9059
386+
if (type.hasMultiRedirect()) {
387+
// convert "S -> T -> U" to "T -> U"
388+
type = type.asGenericsType().getUpperBounds()[0];
389+
// continue to resolve "T -> U" if "T" is a placeholder
390+
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
391+
}
392+
// GRECLIPSE end
385393
if (type.getGenericsTypes() == null) {
386394
// correct "T -> U" (no generics)
387395
ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName());
388396
placeholder.setGenericsPlaceHolder(true);
389397
return makeClassSafeWithGenerics(type, new GenericsType(placeholder));
390-
/* GRECLIPSE edit -- GROOVY-9059
391398
} else if (!name.equals(type.getUnresolvedName())) {
392399
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
393400
}
394-
*/
395-
} else if (type.hasMultiRedirect()) {
396-
// convert "S -> T -> U" to "T -> U"
397-
type = type.asGenericsType().getUpperBounds()[0];
398-
// continue to resolve "T -> U" if "T" is a placeholder
399-
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
400-
}
401-
// GRECLIPSE end
402401
}
403402
}
404403
if (type == null) type = ClassHelper.OBJECT_TYPE;
@@ -445,7 +444,7 @@ public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpe
445444
String name = type.getName();
446445
ret = genericsSpec.get(name);
447446
} else if (type.isWildcard()) { // GROOVY-9891
448-
/* GRECLIPSE edit -- GROOVY-8984
447+
/* GRECLIPSE edit -- GROOVY-8984: "? super T" RHS
449448
ret = type.getLowerBound(); // use lower or upper
450449
*/
451450
if (ret == null && type.getUpperBounds() != null) {

base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -389,23 +389,22 @@ public static ClassNode correctToGenericsSpecRecurse(Map<String, ClassNode> gene
389389
exclusions = plus(exclusions, name); // GROOVY-7722
390390
type = genericsSpec.get(name);
391391
if (type != null && type.isGenericsPlaceHolder()) {
392+
// GRECLIPSE add -- GROOVY-9059
393+
if (type.hasMultiRedirect()) {
394+
// convert "S -> T -> U" to "T -> U"
395+
type = type.asGenericsType().getUpperBounds()[0];
396+
// continue to resolve "T -> U" if "T" is a placeholder
397+
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
398+
}
399+
// GRECLIPSE end
392400
if (type.getGenericsTypes() == null) {
393401
// correct "T -> U" (no generics)
394402
ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName());
395403
placeholder.setGenericsPlaceHolder(true);
396404
return makeClassSafeWithGenerics(type, new GenericsType(placeholder));
397-
/* GRECLIPSE edit -- GROOVY-9059
398405
} else if (!name.equals(type.getUnresolvedName())) {
399406
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
400407
}
401-
*/
402-
} else if (type.hasMultiRedirect()) {
403-
// convert "S -> T -> U" to "T -> U"
404-
type = type.asGenericsType().getUpperBounds()[0];
405-
// continue to resolve "T -> U" if "T" is a placeholder
406-
return correctToGenericsSpecRecurse(genericsSpec, type, exclusions);
407-
}
408-
// GRECLIPSE end
409408
}
410409
}
411410
if (type == null) type = ClassHelper.OBJECT_TYPE.getPlainNodeReference();

0 commit comments

Comments
 (0)