Skip to content

Commit c8cfeb7

Browse files
committed
GROOVY-10651 (pt.2)
1 parent 414c8ee commit c8cfeb7

File tree

6 files changed

+38
-15
lines changed

6 files changed

+38
-15
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/DGMInferencingTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,23 @@ public void testDGMClosure25() {
10121012
assertExprType(contents, "bar", "Bar"); // not "java.lang.Object"
10131013
}
10141014

1015+
@Test
1016+
public void testDGMClosure26() {
1017+
createJavaUnit("TreeNode",
1018+
"public abstract class TreeNode<TN extends TreeNode<?>>\n" +
1019+
" implements Appendable, Iterable<TN> {\n" +
1020+
"}\n");
1021+
1022+
//@formatter:off
1023+
String contents =
1024+
"void test(TreeNode node) {\n" +
1025+
" node.each { child ->\n" +
1026+
" }\n" +
1027+
"}\n";
1028+
//@formatter:on
1029+
assertExprType(contents, "child", "TreeNode");
1030+
}
1031+
10151032
@Test
10161033
public void testDGMDeclaring1() {
10171034
//@formatter:off

base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/InferencingTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1790,7 +1790,7 @@ public void testSuperInterfaceMethod3() {
17901790
if (!qual.startsWith("C")) {
17911791
assertUnknown(contents, "naturalOrder");
17921792
} else {
1793-
assertType(contents, "naturalOrder", "java.util.Comparator<java.lang." + (qual.endsWith(">") ? "String" : "Comparable<? super T>") + ">");
1793+
assertType(contents, "naturalOrder", "java.util.Comparator<java.lang." + (qual.endsWith(">") ? "String" : "Object") + ">");
17941794
}
17951795
}
17961796
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -5731,15 +5731,15 @@ public void testTypeChecked10651() {
57315731
String[] sources = {
57325732
"Main.groovy",
57335733
"@groovy.transform.TypeChecked\n" +
5734-
"void test(NodeType node) {\n" +
5734+
"void test(TreeNode node) {\n" +
57355735
" node.each { child ->\n" +
57365736
" test(child)\n" +
57375737
" }\n" +
57385738
"}\n" +
57395739
"test()\n",
57405740

5741-
"NodeType.java",
5742-
"public abstract class NodeType<T extends NodeType<?>> implements Iterable<T> {\n" +
5741+
"TreeNode.java",
5742+
"public abstract class TreeNode<TN extends TreeNode<?>> implements Iterable<TN> {\n" +
57435743
"}\n",
57445744
};
57455745
//@formatter:on

base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/GenericsMapper.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public static GenericsMapper gatherGenerics(final ClassNode resolvedType, final
110110
if (resolved == null) resolved = (n > 0 ? new TreeMap<>() : Collections.emptyMap());
111111
for (int i = 0; i < n; i += 1) {
112112
// now try to resolve the parameter in the context of the
113-
// most recently visited type. If it doesn't exist, then
113+
// most recently visited type; if it does not exist, then
114114
// default to the resovled type
115115
resolved.put(ugts[i].getName(), mapper.resolveParameter(rgts[i], 0));
116116
}
@@ -242,7 +242,7 @@ public static GenericsMapper gatherGenerics(final List<ClassNode> argumentTypes,
242242
return topGT.getType();
243243
}
244244

245-
ClassNode theType = findParameter(topGT.getName(), topGT.getType());
245+
ClassNode theType = allGenerics.getLast().getOrDefault(topGT.getName(), topGT.getType());
246246
// recur for type parameters of the type: class Enum<E extends Enum<E>>
247247
if (theType.redirect().isUsingGenerics()) {
248248
theType = VariableScope.clone(theType);
@@ -252,7 +252,7 @@ public static GenericsMapper gatherGenerics(final List<ClassNode> argumentTypes,
252252
if (genericsType.getName().equals(topGT.getName())) {
253253
continue; // avoid infinite loops -- not ideal but better than using a depth counter
254254
}
255-
genericsType.setType(findParameter(genericsType.getName(), resolveParameter(genericsType, depth + 1)));
255+
genericsType.setType(allGenerics.getLast().getOrDefault(genericsType.getName(), resolveParameter(genericsType, depth + 1)));
256256
genericsType.setName(genericsType.getType().getName());
257257
genericsType.setUpperBounds(null);
258258
genericsType.setLowerBound(null);
@@ -299,7 +299,7 @@ protected GenericsMapper fillPlaceholders(final GenericsType[] typeParameters) {
299299
* @param defaultType type to return if parameter name doesn't exist
300300
*/
301301
protected ClassNode findParameter(final String parameterName, final ClassNode defaultType) {
302-
if (hasGenerics()) {
302+
if (!allGenerics.isEmpty()) {
303303
ClassNode type = allGenerics.getLast().get(parameterName);
304304
if (type != null) {
305305
return type;
@@ -309,10 +309,11 @@ protected ClassNode findParameter(final String parameterName, final ClassNode de
309309
}
310310

311311
protected static Iterator<ClassNode> getTypeHierarchy(final ClassNode type, final boolean useResolved) {
312-
Set<ClassNode> hierarchy = new LinkedHashSet<>();
312+
Set<ClassNode> hierarchy = new LinkedHashSet<>(); // keeps order
313313
VariableScope.createTypeHierarchy(type, hierarchy, useResolved);
314-
hierarchy.remove(VariableScope.GROOVY_OBJECT_CLASS_NODE);
315314
hierarchy.remove(VariableScope.OBJECT_CLASS_NODE);
315+
hierarchy.removeIf(cn -> cn.isInterface() &&
316+
cn.redirect().getGenericsTypes() == null);
316317
return hierarchy.iterator();
317318
}
318319

base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -979,10 +979,8 @@ public void visitClosureExpression(final ClosureExpression node) {
979979
if (node.isParameterSpecified()) {
980980
Parameter[] parameters = node.getParameters();
981981
for (int i = 0, n = parameters.length; i < n; i += 1) {
982-
// only change the parameter's type if it's not declared explicitly
983-
if (parameters[i].isDynamicTyped() && inferredParamTypes[i] != null &&
984-
(!inferredParamTypes[i].equals(VariableScope.OBJECT_CLASS_NODE) || inferredParamTypes[i].isGenericsPlaceHolder())) {
985-
parameters[i].setType(inferredParamTypes[i]);
982+
if (parameters[i].isDynamicTyped() && isNotNullOrObject(inferredParamTypes[i])) {
983+
scope.addVariable(parameters[i].getName(), inferredParamTypes[i], null);
986984
}
987985
}
988986
handleParameters(parameters);
@@ -3249,6 +3247,10 @@ private static boolean isNotEmpty(final Stream<?> stream) {
32493247
return (stream != null && stream.anyMatch(x -> true));
32503248
}
32513249

3250+
private static boolean isNotNullOrObject(final ClassNode type) {
3251+
return (type != null && (!type.equals(VariableScope.OBJECT_CLASS_NODE) || type.isGenericsPlaceHolder()));
3252+
}
3253+
32523254
private static VariableExpression isNotNullTest(final Expression node) {
32533255
if (node instanceof CompareToNullExpression) {
32543256
CompareToNullExpression expr = (CompareToNullExpression) node;

base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeLookupResult.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -168,6 +168,9 @@ public TypeLookupResult resolveTypeParameterization(final ClassNode objExprType,
168168
}
169169
if (ClassHelper.isPrimitiveType(objectType)) {
170170
objectType = ClassHelper.getWrapper(objectType);
171+
} else if (objectType.equals(VariableScope.CLASS_CLASS_NODE) &&
172+
!declaringType.equals(VariableScope.CLASS_CLASS_NODE) && !isGroovy) {
173+
objectType = objectType.getGenericsTypes()[0].getType(); // peel Class<>
171174
}
172175

173176
if (!(declaration instanceof MethodNode)) {

0 commit comments

Comments
 (0)