From 0d91486d5ad6034007e10dd619babe9420ceb4a2 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Tue, 19 Jul 2022 12:53:55 -0500 Subject: [PATCH] GROOVY-9059 --- .../core/tests/basic/GenericsTests.java | 78 ++++++++++++------- .../groovy/ast/tools/GenericsUtils.java | 22 +++--- .../groovy/ast/tools/GenericsUtils.java | 19 +++-- .../groovy/ast/tools/GenericsUtils.java | 17 ++-- 4 files changed, 77 insertions(+), 59 deletions(-) diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GenericsTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GenericsTests.java index 342899eb52..fd4040247b 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GenericsTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GenericsTests.java @@ -2076,7 +2076,7 @@ public void testReferencingFieldsGenerics_GreferingToJ() { } @Test - public void testAbstractCovariance_1() { + public void testAbstractCovariance1() { //@formatter:off String[] sources = { "Foo.groovy", @@ -2091,7 +2091,7 @@ public void testAbstractCovariance_1() { } @Test - public void testAbstractCovariance_2() { + public void testAbstractCovariance2() { //@formatter:off String[] sources = { "Foo.groovy", @@ -2110,25 +2110,19 @@ public void testAbstractCovariance_2() { "----------\n"); } - @Test - public void testAbstractCovariance_3() { + @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059 + public void testAbstractCovariance3() { //@formatter:off String[] sources = { - "Face1.java", - "@FunctionalInterface\n" + - "interface Face1 {\n" + - " O apply(I in);\n" + - "}\n", - - "Face2.java", - "interface Face2 extends Face1 {\n" + - " Object another();\n" + + "Face.java", + "interface Face {\n" + + " O process(O o);\n" + "}\n", "Impl.groovy", - "class Impl implements Face2 {\n" + - " @Override String apply(Number n) { '' }\n" + - " @Override Object another() { null }\n" + + "class Impl implements Face { \n" + + " @Override\n" + + " def Chars process(Chars chars) { chars }\n" + "}\n", }; //@formatter:on @@ -2137,7 +2131,7 @@ public void testAbstractCovariance_3() { } @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059 - public void testAbstractCovariance_GROOVY9059() { + public void testAbstractCovariance4() { //@formatter:off String[] sources = { "Face.java", @@ -2146,9 +2140,9 @@ public void testAbstractCovariance_GROOVY9059() { "}\n", "Impl.groovy", - "class Impl implements Face { \n" + + "def impl = new Face() { \n" + " @Override\n" + - " public Chars process(Chars chars) { chars }\n" + + " def Chars process(Chars chars) { chars }\n" + "}\n", }; //@formatter:on @@ -2157,7 +2151,7 @@ public void testAbstractCovariance_GROOVY9059() { } @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059 - public void testAbstractCovariance_GROOVY9059a() { + public void testAbstractCovariance5() { //@formatter:off String[] sources = { "Face.java", @@ -2167,8 +2161,8 @@ public void testAbstractCovariance_GROOVY9059a() { "Impl.groovy", "def impl = new Face() { \n" + - " @Override\n" + - " public Chars process(Chars chars) { chars }\n" + + " @Override @SuppressWarnings('unchecked')\n" + + " CharSequence process(CharSequence chars) { chars }\n" + "}\n", }; //@formatter:on @@ -2177,7 +2171,7 @@ public void testAbstractCovariance_GROOVY9059a() { } @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059 - public void testAbstractCovariance_GROOVY9059b() { + public void testAbstractCovariance6() { //@formatter:off String[] sources = { "Face.java", @@ -2186,9 +2180,9 @@ public void testAbstractCovariance_GROOVY9059b() { "}\n", "Impl.groovy", - "def impl = new Face() { \n" + + "def impl = new Face() { \n" + " @Override @SuppressWarnings('unchecked')\n" + - " public CharSequence process(CharSequence chars) { chars }\n" + + " String process(String string) { string }\n" + "}\n", }; //@formatter:on @@ -2197,18 +2191,44 @@ public void testAbstractCovariance_GROOVY9059b() { } @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-9059 - public void testAbstractCovariance_GROOVY9059c() { + public void testAbstractCovariance7() { //@formatter:off String[] sources = { - "Face.java", + "Face.groovy", "interface Face {\n" + - " O process(O o);\n" + + " def O process(O o)\n" + "}\n", "Impl.groovy", "def impl = new Face() { \n" + " @Override @SuppressWarnings('unchecked')\n" + - " public String process(String string) { string }\n" + + " String process(String string) { string }\n" + + "}\n", + }; + //@formatter:on + + runWarningFreeTest(sources); + } + + @Test // https://issues.apache.org/jira/projects/GROOVY/issues/GROOVY-10675 + public void testAbstractCovariance8() { + //@formatter:off + String[] sources = { + "Face1.java", + "@FunctionalInterface\n" + + "interface Face1 {\n" + + " O apply(I in);\n" + + "}\n", + + "Face2.java", + "interface Face2 extends Face1 {\n" + + " Object another();\n" + + "}\n", + + "Impl.groovy", + "class Impl implements Face2 {\n" + + " @Override String apply(Number n) { '' }\n" + + " @Override Object another() { null }\n" + "}\n", }; //@formatter:on diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java index c7aab579e7..b6a4fd4ba6 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/tools/GenericsUtils.java @@ -272,7 +272,7 @@ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode t } return target; } - // GRECLIPSE add -- GROOVY-8984, GROOVY-9891 + // GRECLIPSE add -- GROOVY-8984 if (hint.isGenericsPlaceHolder()) { ClassNode bound = hint.redirect(); return parameterizeType(bound, target); @@ -402,16 +402,17 @@ public static ClassNode correctToGenericsSpecRecurse(Map gene } */ if (type != null && type.isGenericsPlaceHolder()) { + if (type.hasMultiRedirect()) { + // convert "S -> T -> U" to "T -> U" + type = type.asGenericsType().getUpperBounds()[0]; + // continue to resolve "T -> U" if "T" is a placeholder + return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); + } if (type.getGenericsTypes() == null) { // correct "T -> U" (no generics) ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName()); placeholder.setGenericsPlaceHolder(true); return makeClassSafeWithGenerics(type, new GenericsType(placeholder)); - } else if (type.hasMultiRedirect()) { - // convert "S -> T -> U" to "T -> U" - type = type.asGenericsType().getUpperBounds()[0]; - // continue to resolve "T -> U" if "T" is a placeholder - return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); } } // GRECLIPSE end @@ -457,15 +458,14 @@ public static ClassNode correctToGenericsSpec(Map genericsSpe if (type.isPlaceholder()) { String name = type.getName(); ret = genericsSpec.get(name); - } - // GRECLIPSE add -- GROOVY-8984, GROOVY-9891 - else if (type.isWildcard()) { - //ret = type.getLowerBound(); // use lower or upper + } else if (type.isWildcard()) { // GROOVY-9891 + /* GRECLIPSE edit -- GROOVY-8984: "? super T" RHS + ret = type.getLowerBound(); // use lower or upper + */ if (ret == null && type.getUpperBounds() != null) { ret = type.getUpperBounds()[0]; // ? supports 1 } } - // GRECLIPSE end if (ret == null) ret = type.getType(); return ret; } diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java index d9664cad02..b38472f82d 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/tools/GenericsUtils.java @@ -382,23 +382,22 @@ public static ClassNode correctToGenericsSpecRecurse(Map gene exclusions = plus(exclusions, name); // GROOVY-7722 type = genericsSpec.get(name); if (type != null && type.isGenericsPlaceHolder()) { + // GRECLIPSE add -- GROOVY-9059 + if (type.hasMultiRedirect()) { + // convert "S -> T -> U" to "T -> U" + type = type.asGenericsType().getUpperBounds()[0]; + // continue to resolve "T -> U" if "T" is a placeholder + return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); + } + // GRECLIPSE end if (type.getGenericsTypes() == null) { // correct "T -> U" (no generics) ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName()); placeholder.setGenericsPlaceHolder(true); return makeClassSafeWithGenerics(type, new GenericsType(placeholder)); - /* GRECLIPSE edit -- GROOVY-9059 } else if (!name.equals(type.getUnresolvedName())) { return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); } - */ - } else if (type.hasMultiRedirect()) { - // convert "S -> T -> U" to "T -> U" - type = type.asGenericsType().getUpperBounds()[0]; - // continue to resolve "T -> U" if "T" is a placeholder - return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); - } - // GRECLIPSE end } } if (type == null) type = ClassHelper.OBJECT_TYPE; @@ -445,7 +444,7 @@ public static ClassNode correctToGenericsSpec(Map genericsSpe String name = type.getName(); ret = genericsSpec.get(name); } else if (type.isWildcard()) { // GROOVY-9891 - /* GRECLIPSE edit -- GROOVY-8984 + /* GRECLIPSE edit -- GROOVY-8984: "? super T" RHS ret = type.getLowerBound(); // use lower or upper */ if (ret == null && type.getUpperBounds() != null) { diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java index f316d92e1f..3458c6863c 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/tools/GenericsUtils.java @@ -389,23 +389,22 @@ public static ClassNode correctToGenericsSpecRecurse(Map gene exclusions = plus(exclusions, name); // GROOVY-7722 type = genericsSpec.get(name); if (type != null && type.isGenericsPlaceHolder()) { + // GRECLIPSE add -- GROOVY-9059 + if (type.hasMultiRedirect()) { + // convert "S -> T -> U" to "T -> U" + type = type.asGenericsType().getUpperBounds()[0]; + // continue to resolve "T -> U" if "T" is a placeholder + return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); + } + // GRECLIPSE end if (type.getGenericsTypes() == null) { // correct "T -> U" (no generics) ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName()); placeholder.setGenericsPlaceHolder(true); return makeClassSafeWithGenerics(type, new GenericsType(placeholder)); - /* GRECLIPSE edit -- GROOVY-9059 } else if (!name.equals(type.getUnresolvedName())) { return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); } - */ - } else if (type.hasMultiRedirect()) { - // convert "S -> T -> U" to "T -> U" - type = type.asGenericsType().getUpperBounds()[0]; - // continue to resolve "T -> U" if "T" is a placeholder - return correctToGenericsSpecRecurse(genericsSpec, type, exclusions); - } - // GRECLIPSE end } } if (type == null) type = ClassHelper.OBJECT_TYPE.getPlainNodeReference();