Skip to content

Commit 412a64f

Browse files
committed
GROOVY-9945
1 parent ac96a1c commit 412a64f

File tree

5 files changed

+167
-9
lines changed

5 files changed

+167
-9
lines changed

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

+25
Original file line numberDiff line numberDiff line change
@@ -866,4 +866,29 @@ public void testTypeChecked9935() {
866866
runConformTest(sources, "42");
867867
}
868868
}
869+
870+
@Test
871+
public void testTypeChecked9945() {
872+
//@formatter:off
873+
String[] sources = {
874+
"Main.groovy",
875+
"interface I<T> {\n" +
876+
"}\n" +
877+
"class A<T> implements I<Character> {\n" +
878+
" void m(T t) {\n" +
879+
" print t\n" +
880+
" }\n" +
881+
"}\n" +
882+
"class B<T> extends A<T> {\n" +
883+
"}\n" +
884+
"@groovy.transform.TypeChecked\n" +
885+
"void test() {\n" +
886+
" new B<Integer>().m(42)\n" +
887+
"}\n" +
888+
"test()\n",
889+
};
890+
//@formatter:on
891+
892+
runConformTest(sources, "42");
893+
}
869894
}

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

+14
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ public boolean matches(ClassNode classNode) {
265265
// if the classnode we compare to is a generics placeholder (like <E>) then we
266266
// only need to check that the names are equal
267267
if (genericsTypes==null) return true;
268+
/* GRECLIPSE edit
268269
if (isWildcard()) {
269270
if (lowerBound!=null) return genericsTypes[0].getName().equals(lowerBound.getUnresolvedName());
270271
if (upperBounds!=null) {
@@ -274,8 +275,21 @@ public boolean matches(ClassNode classNode) {
274275
}
275276
return false;
276277
}
278+
277279
}
278280
return genericsTypes[0].getName().equals(name);
281+
*/
282+
String name0 = genericsTypes[0].getName();
283+
if (isWildcard()) {
284+
if (getLowerBound() != null) {
285+
return name0.equals(getLowerBound().getUnresolvedName());
286+
}
287+
if (getUpperBounds() != null) {
288+
return name0.equals(getUpperBounds()[0].getUnresolvedName());
289+
}
290+
}
291+
return name0.equals(getName());
292+
// GRECLIPSE end
279293
}
280294
if (wildcard || placeholder) {
281295
// if the current generics spec is a wildcard spec or a placeholder spec

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

+44-9
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode
783783

784784
// Backported from 3.0.0
785785
private static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
786+
/* GRECLIPSE edit -- GROOVY-9945
786787
ClassNode parameterizedType = null;
787788
788789
if (null == genericsClass.getGenericsTypes()) {
@@ -820,8 +821,48 @@ private static ClassNode findParameterizedType(ClassNode genericsClass, ClassNod
820821
}
821822
822823
return parameterizedType;
824+
*/
825+
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
826+
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
827+
return null;
828+
}
829+
830+
if (actualType.equals(genericsClass)) {
831+
return actualType;
832+
}
833+
834+
java.util.Set<ClassNode> done = new java.util.HashSet<>();
835+
LinkedList<ClassNode> todo = new LinkedList<>();
836+
todo.add(actualType);
837+
ClassNode type;
838+
839+
while ((type = todo.poll()) != null) {
840+
if (type.equals(genericsClass)) {
841+
return type;
842+
}
843+
if (done.add(type)) {
844+
boolean parameterized = (type.getGenericsTypes() != null);
845+
for (ClassNode cn : type.getInterfaces()) {
846+
if (parameterized)
847+
cn = parameterizeType(type, cn);
848+
todo.add(cn);
849+
}
850+
if (!actualType.isInterface()) {
851+
ClassNode cn = type.getUnresolvedSuperClass();
852+
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
853+
if (parameterized)
854+
cn = parameterizeType(type, cn);
855+
todo.add(cn);
856+
}
857+
}
858+
}
859+
}
860+
861+
return null;
862+
// GRECLIPSE end
823863
}
824864

865+
/* GRECLIPSE edit
825866
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
826867
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
827868
}
@@ -848,6 +889,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
848889
849890
return superClassNodeList;
850891
}
892+
*/
851893

852894
private static final EvictableCache<ParameterizedTypeCacheKey, SoftReference<ClassNode>> PARAMETERIZED_TYPE_CACHE = new ConcurrentSoftCache<>(64);
853895

@@ -969,18 +1011,11 @@ public static boolean hasPlaceHolders(final ClassNode parameterizedType) {
9691011
return checkPlaceHolders(parameterizedType, genericsType -> genericsType.isPlaceholder());
9701012
}
9711013

972-
/**
973-
* Check whether the ClassNode has non generics placeholders, aka not placeholder
974-
* <p>
975-
* Backported from 3.0.0
976-
*
977-
* @param parameterizedType the class node
978-
* @return the result
979-
* @since 2.5.9
980-
*/
1014+
/* GRECLIPSE edit
9811015
private static boolean hasNonPlaceHolders(final ClassNode parameterizedType) {
9821016
return checkPlaceHolders(parameterizedType, genericsType -> !genericsType.isPlaceholder());
9831017
}
1018+
*/
9841019

9851020
// GRECLIPSE add
9861021
/**

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

+42
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ public static ClassNode findParameterizedType(final ClassNode genericsClass, fin
753753
* @return the parameterized type
754754
*/
755755
public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
756+
/* GRECLIPSE edit -- GROOVY-9945
756757
ClassNode parameterizedType = null;
757758
758759
if (null == genericsClass.getGenericsTypes()) {
@@ -792,8 +793,48 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode
792793
}
793794
794795
return parameterizedType;
796+
*/
797+
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
798+
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
799+
return null;
800+
}
801+
802+
if (actualType.equals(genericsClass)) {
803+
return actualType;
804+
}
805+
806+
java.util.Set<ClassNode> done = new java.util.HashSet<>();
807+
LinkedList<ClassNode> todo = new LinkedList<>();
808+
todo.add(actualType);
809+
ClassNode type;
810+
811+
while ((type = todo.poll()) != null) {
812+
if (type.equals(genericsClass)) {
813+
return type;
814+
}
815+
if (done.add(type)) {
816+
boolean parameterized = (type.getGenericsTypes() != null);
817+
for (ClassNode cn : type.getInterfaces()) {
818+
if (parameterized)
819+
cn = parameterizeType(type, cn);
820+
todo.add(cn);
821+
}
822+
if (!actualType.isInterface()) {
823+
ClassNode cn = type.getUnresolvedSuperClass();
824+
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
825+
if (parameterized)
826+
cn = parameterizeType(type, cn);
827+
todo.add(cn);
828+
}
829+
}
830+
}
831+
}
832+
833+
return null;
834+
// GRECLIPSE end
795835
}
796836

837+
/* GRECLIPSE edit
797838
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
798839
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
799840
}
@@ -820,6 +861,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
820861
821862
return superClassNodeList;
822863
}
864+
*/
823865

824866
private static final EvictableCache<ParameterizedTypeCacheKey, SoftReference<ClassNode>> PARAMETERIZED_TYPE_CACHE = new ConcurrentSoftCache<>(64);
825867

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

+42
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ public static ClassNode findParameterizedType(final ClassNode genericsClass, fin
753753
* @return the parameterized type
754754
*/
755755
public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
756+
/* GRECLIPSE edit -- GROOVY-9945
756757
ClassNode parameterizedType = null;
757758
758759
if (null == genericsClass.getGenericsTypes()) {
@@ -792,8 +793,48 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode
792793
}
793794
794795
return parameterizedType;
796+
*/
797+
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
798+
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
799+
return null;
800+
}
801+
802+
if (actualType.equals(genericsClass)) {
803+
return actualType;
804+
}
805+
806+
java.util.Set<ClassNode> done = new java.util.HashSet<>();
807+
LinkedList<ClassNode> todo = new LinkedList<>();
808+
todo.add(actualType);
809+
ClassNode type;
810+
811+
while ((type = todo.poll()) != null) {
812+
if (type.equals(genericsClass)) {
813+
return type;
814+
}
815+
if (done.add(type)) {
816+
boolean parameterized = (type.getGenericsTypes() != null);
817+
for (ClassNode cn : type.getInterfaces()) {
818+
if (parameterized)
819+
cn = parameterizeType(type, cn);
820+
todo.add(cn);
821+
}
822+
if (!actualType.isInterface()) {
823+
ClassNode cn = type.getUnresolvedSuperClass();
824+
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
825+
if (parameterized)
826+
cn = parameterizeType(type, cn);
827+
todo.add(cn);
828+
}
829+
}
830+
}
831+
}
832+
833+
return null;
834+
// GRECLIPSE end
795835
}
796836

837+
/* GRECLIPSE edit
797838
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
798839
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
799840
}
@@ -820,6 +861,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
820861
821862
return superClassNodeList;
822863
}
864+
*/
823865

824866
private static final EvictableCache<ParameterizedTypeCacheKey, SoftReference<ClassNode>> PARAMETERIZED_TYPE_CACHE = new ConcurrentSoftCache<>(64);
825867

0 commit comments

Comments
 (0)