Skip to content

Commit

Permalink
GROOVY-9945
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Feb 17, 2021
1 parent ac96a1c commit 412a64f
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -866,4 +866,29 @@ public void testTypeChecked9935() {
runConformTest(sources, "42");
}
}

@Test
public void testTypeChecked9945() {
//@formatter:off
String[] sources = {
"Main.groovy",
"interface I<T> {\n" +
"}\n" +
"class A<T> implements I<Character> {\n" +
" void m(T t) {\n" +
" print t\n" +
" }\n" +
"}\n" +
"class B<T> extends A<T> {\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"void test() {\n" +
" new B<Integer>().m(42)\n" +
"}\n" +
"test()\n",
};
//@formatter:on

runConformTest(sources, "42");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ public boolean matches(ClassNode classNode) {
// if the classnode we compare to is a generics placeholder (like <E>) then we
// only need to check that the names are equal
if (genericsTypes==null) return true;
/* GRECLIPSE edit
if (isWildcard()) {
if (lowerBound!=null) return genericsTypes[0].getName().equals(lowerBound.getUnresolvedName());
if (upperBounds!=null) {
Expand All @@ -274,8 +275,21 @@ public boolean matches(ClassNode classNode) {
}
return false;
}
}
return genericsTypes[0].getName().equals(name);
*/
String name0 = genericsTypes[0].getName();
if (isWildcard()) {
if (getLowerBound() != null) {
return name0.equals(getLowerBound().getUnresolvedName());
}
if (getUpperBounds() != null) {
return name0.equals(getUpperBounds()[0].getUnresolvedName());
}
}
return name0.equals(getName());
// GRECLIPSE end
}
if (wildcard || placeholder) {
// if the current generics spec is a wildcard spec or a placeholder spec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode

// Backported from 3.0.0
private static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
/* GRECLIPSE edit -- GROOVY-9945
ClassNode parameterizedType = null;
if (null == genericsClass.getGenericsTypes()) {
Expand Down Expand Up @@ -820,8 +821,48 @@ private static ClassNode findParameterizedType(ClassNode genericsClass, ClassNod
}
return parameterizedType;
*/
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
return null;
}

if (actualType.equals(genericsClass)) {
return actualType;
}

java.util.Set<ClassNode> done = new java.util.HashSet<>();
LinkedList<ClassNode> todo = new LinkedList<>();
todo.add(actualType);
ClassNode type;

while ((type = todo.poll()) != null) {
if (type.equals(genericsClass)) {
return type;
}
if (done.add(type)) {
boolean parameterized = (type.getGenericsTypes() != null);
for (ClassNode cn : type.getInterfaces()) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
if (!actualType.isInterface()) {
ClassNode cn = type.getUnresolvedSuperClass();
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
}
}
}

return null;
// GRECLIPSE end
}

/* GRECLIPSE edit
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
}
Expand All @@ -848,6 +889,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
return superClassNodeList;
}
*/

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

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

/**
* Check whether the ClassNode has non generics placeholders, aka not placeholder
* <p>
* Backported from 3.0.0
*
* @param parameterizedType the class node
* @return the result
* @since 2.5.9
*/
/* GRECLIPSE edit
private static boolean hasNonPlaceHolders(final ClassNode parameterizedType) {
return checkPlaceHolders(parameterizedType, genericsType -> !genericsType.isPlaceholder());
}
*/

// GRECLIPSE add
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ public static ClassNode findParameterizedType(final ClassNode genericsClass, fin
* @return the parameterized type
*/
public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
/* GRECLIPSE edit -- GROOVY-9945
ClassNode parameterizedType = null;
if (null == genericsClass.getGenericsTypes()) {
Expand Down Expand Up @@ -792,8 +793,48 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode
}
return parameterizedType;
*/
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
return null;
}

if (actualType.equals(genericsClass)) {
return actualType;
}

java.util.Set<ClassNode> done = new java.util.HashSet<>();
LinkedList<ClassNode> todo = new LinkedList<>();
todo.add(actualType);
ClassNode type;

while ((type = todo.poll()) != null) {
if (type.equals(genericsClass)) {
return type;
}
if (done.add(type)) {
boolean parameterized = (type.getGenericsTypes() != null);
for (ClassNode cn : type.getInterfaces()) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
if (!actualType.isInterface()) {
ClassNode cn = type.getUnresolvedSuperClass();
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
}
}
}

return null;
// GRECLIPSE end
}

/* GRECLIPSE edit
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
}
Expand All @@ -820,6 +861,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
return superClassNodeList;
}
*/

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ public static ClassNode findParameterizedType(final ClassNode genericsClass, fin
* @return the parameterized type
*/
public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType) {
/* GRECLIPSE edit -- GROOVY-9945
ClassNode parameterizedType = null;
if (null == genericsClass.getGenericsTypes()) {
Expand Down Expand Up @@ -792,8 +793,48 @@ public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode
}
return parameterizedType;
*/
final GenericsType[] genericsTypes = genericsClass.getGenericsTypes();
if (genericsTypes == null || genericsClass.isGenericsPlaceHolder()) {
return null;
}

if (actualType.equals(genericsClass)) {
return actualType;
}

java.util.Set<ClassNode> done = new java.util.HashSet<>();
LinkedList<ClassNode> todo = new LinkedList<>();
todo.add(actualType);
ClassNode type;

while ((type = todo.poll()) != null) {
if (type.equals(genericsClass)) {
return type;
}
if (done.add(type)) {
boolean parameterized = (type.getGenericsTypes() != null);
for (ClassNode cn : type.getInterfaces()) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
if (!actualType.isInterface()) {
ClassNode cn = type.getUnresolvedSuperClass();
if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
if (parameterized)
cn = parameterizeType(type, cn);
todo.add(cn);
}
}
}
}

return null;
// GRECLIPSE end
}

/* GRECLIPSE edit
private static boolean isGenericsTypeArraysLengthEqual(GenericsType[] declaringGenericsTypes, GenericsType[] actualGenericsTypes) {
return null != actualGenericsTypes && declaringGenericsTypes.length == actualGenericsTypes.length;
}
Expand All @@ -820,6 +861,7 @@ private static List<ClassNode> getAllUnresolvedSuperClasses(ClassNode actualRece
return superClassNodeList;
}
*/

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

Expand Down

0 comments on commit 412a64f

Please sign in to comment.