Skip to content

Commit

Permalink
GROOVY-10166
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Sep 10, 2021
1 parent 29ebe97 commit 23a8af4
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,24 @@ public void testTypeChecked7363() {
runNegativeTest(sources, "");
}

@Test
public void testTypeChecked7753() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.Field\n" +
"String x = 'X'\n" +
"@groovy.transform.TypeChecked\n" +
"public List<String> getStrings() {\n" +
" x ? [x] : Collections.emptyList()\n" +
"}\n" +
"print strings\n",
};
//@formatter:on

runConformTest(sources, "[X]");
}

@Test
public void testTypeChecked7804() {
//@formatter:off
Expand Down Expand Up @@ -3100,6 +3118,45 @@ public void testTypeChecked10111a() {
runConformTest(sources);
}

@Test
public void testTypeChecked10166() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"@SuppressWarnings('rawtypes')\n" +
"abstract class A<T extends C> {\n" +
" T getC() {\n" +
" }\n" +
" Map toMap() {\n" +
" c.getMap(this)\n" +
" }\n" +
"}\n" +
"@groovy.transform.TypeChecked\n" +
"@SuppressWarnings('rawtypes')\n" +
"class C<T extends A> {\n" +
" Map getMap(T a) {\n" +
" }\n" +
" T getObj(Map m) {\n" +
" A a = null\n" +
" a.c.get(1)\n" +
" }\n" +
" T get(int i) {\n" +
" }\n" +
"}\n" +
"new C()\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 17)\n" +
"\ta.c.get(1)\n" +
"\t^^^^^^^^^^\n" +
"Groovy:[Static type checking] - Cannot find matching method A#get(int). Please check if the declared type is correct and if the method exists.\n" +
"----------\n");
}

@Test
public void testTypeChecked10179() {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.plus;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
Expand Down Expand Up @@ -142,8 +141,8 @@ public static GenericsType buildWildcardType(final ClassNode... types) {
return gt;
}

public static Map<GenericsTypeName, GenericsType> extractPlaceholders(ClassNode cn) {
Map<GenericsTypeName, GenericsType> ret = new HashMap<GenericsTypeName, GenericsType>();
public static Map<GenericsType.GenericsTypeName, GenericsType> extractPlaceholders(ClassNode cn) {
Map<GenericsType.GenericsTypeName, GenericsType> ret = new HashMap<>();
extractPlaceholders(cn, ret);
return ret;
}
Expand All @@ -155,7 +154,7 @@ public static Map<GenericsTypeName, GenericsType> extractPlaceholders(ClassNode
* @param node the class node to check
* @param map the generics type information collector
*/
public static void extractPlaceholders(ClassNode node, Map<GenericsTypeName, GenericsType> map) {
public static void extractPlaceholders(ClassNode node, Map<GenericsType.GenericsTypeName, GenericsType> map) {
if (node == null) return;

if (node.isArray()) {
Expand Down Expand Up @@ -198,7 +197,7 @@ public static void extractPlaceholders(ClassNode node, Map<GenericsTypeName, Gen
for (int i = 0; i < redirectGenericsTypes.length; i++) {
GenericsType redirectType = redirectGenericsTypes[i];
if (redirectType.isPlaceholder()) {
GenericsTypeName name = new GenericsTypeName(redirectType.getName());
GenericsType.GenericsTypeName name = new GenericsType.GenericsTypeName(redirectType.getName());
if (!map.containsKey(name)) {
GenericsType value = parameterized[i];
map.put(name, value);
Expand Down Expand Up @@ -941,7 +940,7 @@ private static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTyp

private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclaringAndActualGenericsTypeMap(ClassNode declaringClass, ClassNode actualReceiver, boolean tryToFindExactType) {
ClassNode parameterizedType = findParameterizedTypeFromCache(declaringClass, actualReceiver, tryToFindExactType);

/* GRECLIPSE edit -- GROOVY-10166
if (parameterizedType == null) {
return new Tuple2<>(Collections.<GenericsType,GenericsType>emptyMap(), parameterizedType);
}
Expand All @@ -953,6 +952,22 @@ private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclarin
result = connectGenericsTypes(result);
return new Tuple2<>(result, parameterizedType);
*/
if (parameterizedType != null && parameterizedType.isRedirectNode() && !parameterizedType.isGenericsPlaceHolder()) {
// declaringClass may be "List<T> -> List<E>" and parameterizedType may be "List<String> -> List<E>"
GenericsType[] targetGenericsTypes = parameterizedType.redirect().getGenericsTypes();
if (targetGenericsTypes != null) {
GenericsType[] sourceGenericsTypes = parameterizedType.getGenericsTypes();
if (sourceGenericsTypes == null) sourceGenericsTypes = EMPTY_GENERICS_ARRAY;
Map<GenericsType, GenericsType> map = new LinkedHashMap<>();
for (int i = 0, m = sourceGenericsTypes.length, n = targetGenericsTypes.length; i < n; i += 1) {
map.put(targetGenericsTypes[i], i < m ? sourceGenericsTypes[i] : targetGenericsTypes[i]);
}
return new Tuple2<>(map, parameterizedType);
}
}
return new Tuple2<>(Collections.emptyMap(), parameterizedType);
// GRECLIPSE end
}

private static Map<GenericsType, GenericsType> connectGenericsTypes(Map<GenericsType, GenericsType> genericsTypeMap) {
Expand Down Expand Up @@ -999,6 +1014,7 @@ private static boolean checkPlaceHolders(final ClassNode parameterizedType, fina
return false;
}

/* GRECLIPSE edit
private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTypeMap(ClassNode declaringClass) {
if (declaringClass == null) {
return Collections.emptyMap();
Expand All @@ -1016,6 +1032,7 @@ private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTy
}
return result;
}
*/

/**
* Get the actual type according to the placeholder name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,7 @@ private static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTyp

private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
ClassNode parameterizedType = findParameterizedTypeFromCache(declaringClass, actualReceiver, tryToFindExactType);
/* GRECLIPSE edit -- GROOVY-10166
if (parameterizedType == null) {
return tuple(Collections.emptyMap(), parameterizedType);
}
Expand All @@ -877,8 +878,25 @@ private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclarin
result = connectGenericsTypes(result);
return tuple(result, parameterizedType);
*/
if (parameterizedType != null && parameterizedType.isRedirectNode() && !parameterizedType.isGenericsPlaceHolder()) {
// declaringClass may be "List<T> -> List<E>" and parameterizedType may be "List<String> -> List<E>"
GenericsType[] targetGenericsTypes = parameterizedType.redirect().getGenericsTypes();
if (targetGenericsTypes != null) {
GenericsType[] sourceGenericsTypes = parameterizedType.getGenericsTypes();
if (sourceGenericsTypes == null) sourceGenericsTypes = EMPTY_GENERICS_ARRAY;
Map<GenericsType, GenericsType> map = new LinkedHashMap<>();
for (int i = 0, m = sourceGenericsTypes.length, n = targetGenericsTypes.length; i < n; i += 1) {
map.put(targetGenericsTypes[i], i < m ? sourceGenericsTypes[i] : targetGenericsTypes[i]);
}
return tuple(map, parameterizedType);
}
}
return tuple(Collections.emptyMap(), parameterizedType);
// GRECLIPSE end
}

/* GRECLIPSE edit
private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTypeMap(final ClassNode declaringClass) {
if (null == declaringClass) {
return Collections.emptyMap();
Expand All @@ -898,6 +916,7 @@ private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTy
return result;
}
*/

private static Map<GenericsType, GenericsType> connectGenericsTypes(final Map<GenericsType, GenericsType> genericsTypeMap) {
Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -865,19 +865,36 @@ private static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTyp

private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
ClassNode parameterizedType = findParameterizedTypeFromCache(declaringClass, actualReceiver, tryToFindExactType);
/* GRECLIPSE edit -- GROOVY-10166
if (parameterizedType == null) {
return tuple(Collections.emptyMap(), parameterizedType);
}

Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
result.putAll(makePlaceholderAndParameterizedTypeMap(declaringClass));
result.putAll(makePlaceholderAndParameterizedTypeMap(parameterizedType));
result = connectGenericsTypes(result);
return tuple(result, parameterizedType);
*/
if (parameterizedType != null && parameterizedType.isRedirectNode() && !parameterizedType.isGenericsPlaceHolder()) {
// declaringClass may be "List<T> -> List<E>" and parameterizedType may be "List<String> -> List<E>"
GenericsType[] targetGenericsTypes = parameterizedType.redirect().getGenericsTypes();
if (targetGenericsTypes != null) {
GenericsType[] sourceGenericsTypes = parameterizedType.getGenericsTypes();
if (sourceGenericsTypes == null) sourceGenericsTypes = EMPTY_GENERICS_ARRAY;
Map<GenericsType, GenericsType> map = new LinkedHashMap<>();
for (int i = 0, m = sourceGenericsTypes.length, n = targetGenericsTypes.length; i < n; i += 1) {
map.put(targetGenericsTypes[i], i < m ? sourceGenericsTypes[i] : targetGenericsTypes[i]);
}
return tuple(map, parameterizedType);
}
}
return tuple(Collections.emptyMap(), parameterizedType);
// GRECLIPSE end
}

/* GRECLIPSE edit
private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTypeMap(final ClassNode declaringClass) {
if (null == declaringClass) {
return Collections.emptyMap();
Expand All @@ -897,6 +914,7 @@ private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTy
return result;
}
*/

private static Map<GenericsType, GenericsType> connectGenericsTypes(final Map<GenericsType, GenericsType> genericsTypeMap) {
Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
Expand Down Expand Up @@ -1010,7 +1028,8 @@ public static Tuple2<ClassNode[], ClassNode> parameterizeSAM(final ClassNode sam
Map<GenericsType, GenericsType> generics = makeDeclaringAndActualGenericsTypeMapOfExactType(abstractMethod.getDeclaringClass(), samType);
Function<ClassNode, ClassNode> resolver = t -> {
if (t.isGenericsPlaceHolder()) {
return findActualTypeByGenericsPlaceholderName(t.getUnresolvedName(), generics);
ClassNode type = findActualTypeByGenericsPlaceholderName(t.getUnresolvedName(), generics);
return type;
}
return t;
};
Expand Down

0 comments on commit 23a8af4

Please sign in to comment.