Repository: groovy
Updated Branches:
refs/heads/GROOVY_2_5_X 9ce3e1aa9 -> dbb665df2
GenericType name should use custom type rather than `String`(prepare to fix
GROOVY-8409)
e.g. The content of resolvedPlaceholders is:
{R=T, T=java.util.Date, U=java.net.URL}
the `T` of `R=T` is defined by user,
but the `T` of `T=java.util.Date` is defined in `BiFunction`.
As a result, R -> T -> Date
See the comment of GROOVY-8409, which is not resolved yet.
(cherry picked from commit f8d4f1bec1dc8cd079e3db97bb2297ae448950af)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/dbb665df
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/dbb665df
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/dbb665df
Branch: refs/heads/GROOVY_2_5_X
Commit: dbb665df29e7e6298925e04dad8383f1f9b6cbf1
Parents: 9ce3e1a
Author: Daniel Sun <[email protected]>
Authored: Sat Aug 18 23:15:49 2018 +0800
Committer: Daniel Sun <[email protected]>
Committed: Sun Aug 19 00:01:37 2018 +0800
----------------------------------------------------------------------
.../org/codehaus/groovy/ast/GenericsType.java | 55 +++++++--
.../groovy/ast/tools/GenericsUtils.java | 9 +-
.../groovy/ast/tools/WideningCategories.java | 8 +-
.../codehaus/groovy/control/ResolveVisitor.java | 30 ++---
.../stc/StaticTypeCheckingSupport.java | 111 ++++++++++---------
.../stc/StaticTypeCheckingVisitor.java | 71 ++++++------
.../codehaus/groovy/ast/GenericsTypeTest.groovy | 16 +--
7 files changed, 170 insertions(+), 130 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/ast/GenericsType.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
index 57d4919..5041fb1 100644
--- a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
+++ b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
@@ -24,6 +24,7 @@ import org.codehaus.groovy.ast.tools.WideningCategories;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import static org.codehaus.groovy.ast.ClassHelper.GROOVY_OBJECT_TYPE;
@@ -371,18 +372,18 @@ public class GenericsType extends ASTNode {
return true;
}
GenericsType[] redirectBoundGenericTypes =
bound.redirect().getGenericsTypes();
- Map<String, GenericsType> classNodePlaceholders =
GenericsUtils.extractPlaceholders(classNode);
- Map<String, GenericsType> boundPlaceHolders =
GenericsUtils.extractPlaceholders(bound);
+ Map<GenericsType.GenericsTypeName, GenericsType>
classNodePlaceholders = GenericsUtils.extractPlaceholders(classNode);
+ Map<GenericsType.GenericsTypeName, GenericsType> boundPlaceHolders
= GenericsUtils.extractPlaceholders(bound);
boolean match = true;
for (int i = 0; redirectBoundGenericTypes!=null && i <
redirectBoundGenericTypes.length && match; i++) {
GenericsType redirectBoundType = redirectBoundGenericTypes[i];
GenericsType classNodeType = cnTypes[i];
if (classNodeType.isPlaceholder()) {
- String name = classNodeType.getName();
+ GenericsTypeName name = new
GenericsTypeName(classNodeType.getName());
if (redirectBoundType.isPlaceholder()) {
- match = name.equals(redirectBoundType.getName());
+ match = name.equals(new
GenericsTypeName(redirectBoundType.getName()));
if (!match) {
- GenericsType genericsType =
boundPlaceHolders.get(redirectBoundType.getName());
+ GenericsType genericsType =
boundPlaceHolders.get(new GenericsTypeName(redirectBoundType.getName()));
match = false;
if (genericsType!=null) {
if (genericsType.isPlaceholder()) {
@@ -408,7 +409,7 @@ public class GenericsType extends ASTNode {
if (classNodeType.isPlaceholder()) {
match =
classNodeType.getName().equals(redirectBoundType.getName());
} else {
- String name = redirectBoundType.getName();
+ GenericsTypeName name = new
GenericsTypeName(redirectBoundType.getName());
if (boundPlaceHolders.containsKey(name)) {
redirectBoundType =
boundPlaceHolders.get(name);
boolean wildcard =
redirectBoundType.isWildcard();
@@ -423,8 +424,8 @@ public class GenericsType extends ASTNode {
if (gt.isPlaceholder()) {
// check for recursive generic
typedef, like in
// <T extends Comparable<?
super T>>
- if
(classNodePlaceholders.containsKey(gt.getName())) {
- gt =
classNodePlaceholders.get(gt.getName());
+ if
(classNodePlaceholders.containsKey(new GenericsTypeName(gt.getName()))) {
+ gt =
classNodePlaceholders.get(new GenericsTypeName(gt.getName()));
}
}
match =
implementsInterfaceOrIsSubclassOf(gt.getType(), classNodeType.getType());
@@ -435,8 +436,8 @@ public class GenericsType extends ASTNode {
if (gt.isPlaceholder()) {
// check for recursive
generic typedef, like in
// <T extends Comparable<?
super T>>
- if
(classNodePlaceholders.containsKey(gt.getName())) {
- gt =
classNodePlaceholders.get(gt.getName());
+ if
(classNodePlaceholders.containsKey(new GenericsTypeName(gt.getName()))) {
+ gt =
classNodePlaceholders.get(new GenericsTypeName(gt.getName()));
}
}
match =
implementsInterfaceOrIsSubclassOf(classNodeType.getType(), gt.getType())
@@ -497,4 +498,38 @@ public class GenericsType extends ASTNode {
}
return superClass;
}
+
+ /**
+ * Represents GenericsType name
+ * TODO In order to distinguish GenericsType with same name(See
GROOVY-8409), we should add a property to keep the declaring class full name.
+ */
+ public static class GenericsTypeName {
+ private String name;
+
+ public GenericsTypeName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ GenericsTypeName that = (GenericsTypeName) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 879d217..375d1ef 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -54,6 +54,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
@@ -140,8 +141,8 @@ public class GenericsUtils {
return gt;
}
- public static Map<String, GenericsType> extractPlaceholders(ClassNode cn) {
- Map<String, GenericsType> ret = new HashMap<String, GenericsType>();
+ public static Map<GenericsTypeName, GenericsType>
extractPlaceholders(ClassNode cn) {
+ Map<GenericsTypeName, GenericsType> ret = new
HashMap<GenericsTypeName, GenericsType>();
extractPlaceholders(cn, ret);
return ret;
}
@@ -153,7 +154,7 @@ public class GenericsUtils {
* @param node the class node to check
* @param map the generics type information collector
*/
- public static void extractPlaceholders(ClassNode node, Map<String,
GenericsType> map) {
+ public static void extractPlaceholders(ClassNode node,
Map<GenericsTypeName, GenericsType> map) {
if (node == null) return;
if (node.isArray()) {
@@ -179,7 +180,7 @@ public class GenericsUtils {
for (int i = 0; i < redirectGenericsTypes.length; i++) {
GenericsType redirectType = redirectGenericsTypes[i];
if (redirectType.isPlaceholder()) {
- String name = redirectType.getName();
+ GenericsTypeName name = new
GenericsTypeName(redirectType.getName());
if (!map.containsKey(name)) {
GenericsType value = parameterized[i];
map.put(name, value);
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
----------------------------------------------------------------------
diff --git
a/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
b/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
index 3f6efbb..68b67b3 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
@@ -52,7 +52,7 @@ import static
org.codehaus.groovy.ast.ClassHelper.isNumberType;
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
-
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
/**
* This class provides helper methods to determine the type from a widening
* operation for example for a plus operation.
@@ -303,14 +303,14 @@ public class WideningCategories {
ClassNode superClass = source.getUnresolvedSuperClass();
// copy generic type information if available
if (superClass!=null && superClass.isUsingGenerics()) {
- Map<String, GenericsType> genericsTypeMap =
GenericsUtils.extractPlaceholders(source);
+ Map<GenericsTypeName, GenericsType> genericsTypeMap =
GenericsUtils.extractPlaceholders(source);
GenericsType[] genericsTypes = superClass.getGenericsTypes();
if (genericsTypes!=null) {
GenericsType[] copyTypes = new
GenericsType[genericsTypes.length];
for (int i = 0; i < genericsTypes.length; i++) {
GenericsType genericsType = genericsTypes[i];
- if (genericsType.isPlaceholder() &&
genericsTypeMap.containsKey(genericsType.getName())) {
- copyTypes[i] =
genericsTypeMap.get(genericsType.getName());
+ if (genericsType.isPlaceholder() &&
genericsTypeMap.containsKey(new GenericsTypeName(genericsType.getName()))) {
+ copyTypes[i] = genericsTypeMap.get(new
GenericsTypeName(genericsType.getName()));
} else {
copyTypes[i] = genericsType;
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 20adb0f..5b02b57 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -77,9 +77,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
-
/**
* Visitor to resolve Types and convert VariableExpression to
* ClassExpressions if needed. The ResolveVisitor will try to
@@ -106,7 +106,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
private boolean inPropertyExpression = false;
private boolean inClosure = false;
- private Map<String, GenericsType> genericParameterNames = new
HashMap<String, GenericsType>();
+ private Map<GenericsTypeName, GenericsType> genericParameterNames = new
HashMap<GenericsTypeName, GenericsType>();
private final Set<FieldNode> fieldTypesChecked = new HashSet<FieldNode>();
private boolean checkingVariableTypeInDeclaration = false;
private ImportNode currImportNode = null;
@@ -228,10 +228,10 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
protected void visitConstructorOrMethod(MethodNode node, boolean
isConstructor) {
VariableScope oldScope = currentScope;
currentScope = node.getVariableScope();
- Map<String, GenericsType> oldPNames = genericParameterNames;
+ Map<GenericsTypeName, GenericsType> oldPNames = genericParameterNames;
genericParameterNames = node.isStatic()
- ? new HashMap<String, GenericsType>()
- : new HashMap<String, GenericsType>(genericParameterNames);
+ ? new HashMap<GenericsTypeName, GenericsType>()
+ : new HashMap<GenericsTypeName,
GenericsType>(genericParameterNames);
resolveGenericsHeader(node.getGenericsTypes());
@@ -265,9 +265,9 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
}
public void visitProperty(PropertyNode node) {
- Map<String, GenericsType> oldPNames = genericParameterNames;
+ Map<GenericsTypeName, GenericsType> oldPNames = genericParameterNames;
if (node.isStatic()) {
- genericParameterNames = new HashMap<String, GenericsType>();
+ genericParameterNames = new HashMap<GenericsTypeName,
GenericsType>();
}
ClassNode t = node.getType();
@@ -372,7 +372,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
String typeName = type.getName();
- GenericsType genericsType = genericParameterNames.get(typeName);
+ GenericsType genericsType = genericParameterNames.get(new
GenericsTypeName(typeName));
if (genericsType != null) {
type.setRedirect(genericsType.getType());
type.setGenericsTypes(new GenericsType[]{ genericsType });
@@ -1337,7 +1337,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
if (node instanceof InnerClassNode) {
if (Modifier.isStatic(node.getModifiers())) {
- genericParameterNames = new HashMap<String, GenericsType>();
+ genericParameterNames = new HashMap<GenericsTypeName,
GenericsType>();
}
InnerClassNode innerClassNode = (InnerClassNode) node;
@@ -1348,7 +1348,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
}
}
} else {
- genericParameterNames = new HashMap<String, GenericsType>();
+ genericParameterNames = new HashMap<GenericsTypeName,
GenericsType>();
}
resolveGenericsHeader(node.getGenericsTypes());
@@ -1493,7 +1493,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
String name = type.getName();
ClassNode[] bounds = type.getUpperBounds();
boolean isWild = QUESTION_MARK.equals(name);
- boolean toDealWithGenerics = 0 == level || (level > 0 && null !=
genericParameterNames.get(name));
+ boolean toDealWithGenerics = 0 == level || (level > 0 && null !=
genericParameterNames.get(new GenericsTypeName(name)));
if (bounds != null) {
boolean nameAdded = false;
@@ -1501,7 +1501,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
if (!isWild) {
if (!nameAdded && upperBound != null ||
!resolve(classNode)) {
if (toDealWithGenerics) {
- genericParameterNames.put(name, type);
+ genericParameterNames.put(new
GenericsTypeName(name), type);
type.setPlaceholder(true);
classNode.setRedirect(upperBound);
nameAdded = true;
@@ -1518,8 +1518,8 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
} else {
if (!isWild) {
if (toDealWithGenerics) {
- GenericsType originalGt =
genericParameterNames.get(name);
- genericParameterNames.put(name, type);
+ GenericsType originalGt =
genericParameterNames.get(new GenericsTypeName(name));
+ genericParameterNames.put(new GenericsTypeName(name),
type);
type.setPlaceholder(true);
if (null == originalGt) {
@@ -1550,7 +1550,7 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
currentClass.setUsingGenerics(true);
ClassNode type = genericsType.getType();
// save name before redirect
- String name = type.getName();
+ GenericsTypeName name = new GenericsTypeName(type.getName());
ClassNode[] bounds = genericsType.getUpperBounds();
if (!genericParameterNames.containsKey(name)) {
if (bounds != null) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
----------------------------------------------------------------------
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index dac508b..5a6cfa8 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
package org.codehaus.groovy.transform.stc;
import org.codehaus.groovy.GroovyBugError;
@@ -107,6 +108,7 @@ import static org.codehaus.groovy.ast.ClassHelper.make;
import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
import static org.codehaus.groovy.ast.tools.GenericsUtils.getSuperClass;
import static org.codehaus.groovy.syntax.Types.ASSIGN;
import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
@@ -152,7 +154,6 @@ import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_EQUAL;
import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED_EQUAL;
-
/**
* Static support methods for {@link StaticTypeCheckingVisitor}.
*/
@@ -1295,8 +1296,8 @@ public abstract class StaticTypeCheckingSupport {
* @return the parameterized arguments
*/
public static Parameter[] parameterizeArguments(final ClassNode receiver,
final MethodNode m) {
- Map<String, GenericsType> genericFromReceiver =
GenericsUtils.extractPlaceholders(receiver);
- Map<String, GenericsType> contextPlaceholders =
extractGenericsParameterMapOfThis(m);
+ Map<GenericsTypeName, GenericsType> genericFromReceiver =
GenericsUtils.extractPlaceholders(receiver);
+ Map<GenericsTypeName, GenericsType> contextPlaceholders =
extractGenericsParameterMapOfThis(m);
Parameter[] methodParameters = m.getParameters();
Parameter[] params = new Parameter[methodParameters.length];
for (int i = 0; i < methodParameters.length; i++) {
@@ -1316,7 +1317,7 @@ public abstract class StaticTypeCheckingSupport {
* @param paramType the (unresolved) type of the method
parameter
* @return a new parameter with the same name and type as the original
one, but with resolved generic types
*/
- private static Parameter buildParameter(final Map<String, GenericsType>
genericFromReceiver, final Map<String, GenericsType> placeholdersFromContext,
final Parameter methodParameter, final ClassNode paramType) {
+ private static Parameter buildParameter(final Map<GenericsTypeName,
GenericsType> genericFromReceiver, final Map<GenericsTypeName, GenericsType>
placeholdersFromContext, final Parameter methodParameter, final ClassNode
paramType) {
if (genericFromReceiver.isEmpty() && (placeholdersFromContext == null
|| placeholdersFromContext.isEmpty())) {
return methodParameter;
}
@@ -1349,8 +1350,8 @@ public abstract class StaticTypeCheckingSupport {
* Given a generics type representing SomeClass<T,V> and a resolved
placeholder map, returns a new generics type
* for which placeholders are resolved recursively.
*/
- protected static GenericsType fullyResolve(GenericsType gt, Map<String,
GenericsType> placeholders) {
- GenericsType fromMap = placeholders.get(gt.getName());
+ protected static GenericsType fullyResolve(GenericsType gt,
Map<GenericsTypeName, GenericsType> placeholders) {
+ GenericsType fromMap = placeholders.get(new
GenericsTypeName(gt.getName()));
if (gt.isPlaceholder() && fromMap != null) {
gt = fromMap;
}
@@ -1372,15 +1373,15 @@ public abstract class StaticTypeCheckingSupport {
return genericsType;
}
- protected static ClassNode fullyResolveType(final ClassNode type, final
Map<String, GenericsType> placeholders) {
+ protected static ClassNode fullyResolveType(final ClassNode type, final
Map<GenericsTypeName, GenericsType> placeholders) {
if (type.isUsingGenerics() && !type.isGenericsPlaceHolder()) {
GenericsType[] gts = type.getGenericsTypes();
if (gts != null) {
GenericsType[] copy = new GenericsType[gts.length];
for (int i = 0; i < gts.length; i++) {
GenericsType genericsType = gts[i];
- if (genericsType.isPlaceholder() &&
placeholders.containsKey(genericsType.getName())) {
- copy[i] = placeholders.get(genericsType.getName());
+ if (genericsType.isPlaceholder() &&
placeholders.containsKey(new GenericsTypeName(genericsType.getName()))) {
+ copy[i] = placeholders.get(new
GenericsTypeName(genericsType.getName()));
} else {
copy[i] = fullyResolve(genericsType, placeholders);
}
@@ -1392,7 +1393,7 @@ public abstract class StaticTypeCheckingSupport {
return result;
} else if (type.isUsingGenerics() && OBJECT_TYPE.equals(type) &&
type.getGenericsTypes() != null) {
// Object<T>
- GenericsType genericsType =
placeholders.get(type.getGenericsTypes()[0].getName());
+ GenericsType genericsType = placeholders.get(new
GenericsTypeName(type.getGenericsTypes()[0].getName()));
if (genericsType != null) {
return genericsType.getType();
}
@@ -1444,7 +1445,7 @@ public abstract class StaticTypeCheckingSupport {
return true;
}
- static void addMethodLevelDeclaredGenerics(MethodNode method, Map<String,
GenericsType> resolvedPlaceholders) {
+ static void addMethodLevelDeclaredGenerics(MethodNode method,
Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
ClassNode dummy = OBJECT_TYPE.getPlainNodeReference();
dummy.setGenericsTypes(method.getGenericsTypes());
GenericsUtils.extractPlaceholders(dummy, resolvedPlaceholders);
@@ -1486,7 +1487,7 @@ public abstract class StaticTypeCheckingSupport {
boolean skipBecauseOfInnerClassNotReceiver = isOuterClassOf(receiver,
candidateMethod.getDeclaringClass());
Parameter[] parameters = candidateMethod.getParameters();
- Map<String, GenericsType> classGTs;
+ Map<GenericsTypeName, GenericsType> classGTs;
if (skipBecauseOfInnerClassNotReceiver) {
classGTs = Collections.EMPTY_MAP;
} else {
@@ -1502,12 +1503,12 @@ public abstract class StaticTypeCheckingSupport {
// There is firstly the context given through the class, and the
method.
// The method context may hide generics given through the class, but
use
// the non-hidden ones.
- Map<String, GenericsType> resolvedMethodGenerics = new HashMap<String,
GenericsType>();
+ Map<GenericsTypeName, GenericsType> resolvedMethodGenerics = new
HashMap<GenericsTypeName, GenericsType>();
if (!skipBecauseOfInnerClassNotReceiver) {
addMethodLevelDeclaredGenerics(candidateMethod,
resolvedMethodGenerics);
}
// so first we remove hidden generics
- for (String key : resolvedMethodGenerics.keySet())
classGTs.remove(key);
+ for (GenericsTypeName key : resolvedMethodGenerics.keySet())
classGTs.remove(key);
// then we use the remaining information to refine the given generics
applyGenericsConnections(classGTs, resolvedMethodGenerics);
// and then start our checks with the receiver
@@ -1519,7 +1520,7 @@ public abstract class StaticTypeCheckingSupport {
// extension methods are special, since they set the receiver as
// first parameter. While we normally allow generalization for the
first
// parameter, in case of an extension method we must not.
- Set<String> fixedGenericsPlaceHolders =
extractResolvedPlaceHolders(resolvedMethodGenerics);
+ Set<GenericsTypeName> fixedGenericsPlaceHolders =
extractResolvedPlaceHolders(resolvedMethodGenerics);
for (int i = 0; i < arguments.length; i++) {
int pindex = min(i, parameters.length - 1);
@@ -1540,10 +1541,10 @@ public abstract class StaticTypeCheckingSupport {
return true;
}
- private static Set<String> extractResolvedPlaceHolders(Map<String,
GenericsType> resolvedMethodGenerics) {
+ private static Set<GenericsTypeName>
extractResolvedPlaceHolders(Map<GenericsTypeName, GenericsType>
resolvedMethodGenerics) {
if (resolvedMethodGenerics.isEmpty()) return Collections.EMPTY_SET;
- Set<String> result = new HashSet<String>();
- for (Map.Entry<String, GenericsType> entry :
resolvedMethodGenerics.entrySet()) {
+ Set<GenericsTypeName> result = new HashSet<GenericsTypeName>();
+ for (Entry<GenericsTypeName, GenericsType> entry :
resolvedMethodGenerics.entrySet()) {
GenericsType value = entry.getValue();
if (value.isPlaceholder()) continue;
result.add(entry.getKey());
@@ -1551,8 +1552,8 @@ public abstract class StaticTypeCheckingSupport {
return result;
}
- private static boolean inferenceCheck(Set<String>
fixedGenericsPlaceHolders, Map<String, GenericsType> resolvedMethodGenerics,
ClassNode type, ClassNode wrappedArgument, boolean lastArg) {
- Map<String, GenericsType> connections = new HashMap<String,
GenericsType>();
+ private static boolean inferenceCheck(Set<GenericsTypeName>
fixedGenericsPlaceHolders, Map<GenericsTypeName, GenericsType>
resolvedMethodGenerics, ClassNode type, ClassNode wrappedArgument, boolean
lastArg) {
+ Map<GenericsTypeName, GenericsType> connections = new
HashMap<GenericsTypeName, GenericsType>();
if (isPrimitiveType(wrappedArgument)) wrappedArgument =
getWrapper(wrappedArgument);
// the context we compare with in the end is the one of the callsite
// so far we specified the context of the method declaration only
@@ -1587,8 +1588,8 @@ public abstract class StaticTypeCheckingSupport {
return gt;
}
- private static boolean compatibleConnections(Map<String, GenericsType>
connections, Map<String, GenericsType> resolvedMethodGenerics, Set<String>
fixedGenericsPlaceHolders) {
- for (Map.Entry<String, GenericsType> entry : connections.entrySet()) {
+ private static boolean compatibleConnections(Map<GenericsTypeName,
GenericsType> connections, Map<GenericsTypeName, GenericsType>
resolvedMethodGenerics, Set<GenericsTypeName> fixedGenericsPlaceHolders) {
+ for (Entry<GenericsTypeName, GenericsType> entry :
connections.entrySet()) {
GenericsType resolved = resolvedMethodGenerics.get(entry.getKey());
if (resolved == null) continue;
GenericsType connection = entry.getValue();
@@ -1634,8 +1635,8 @@ public abstract class StaticTypeCheckingSupport {
return gt.isCompatibleWith(compareNode);
}
- private static void addMissingEntries(Map<String, GenericsType>
connections, Map<String, GenericsType> resolved) {
- for (Entry<String, GenericsType> entry : connections.entrySet()) {
+ private static void addMissingEntries(Map<GenericsTypeName, GenericsType>
connections, Map<GenericsTypeName, GenericsType> resolved) {
+ for (Entry<GenericsTypeName, GenericsType> entry :
connections.entrySet()) {
if (resolved.containsKey(entry.getKey())) continue;
GenericsType gt = entry.getValue();
ClassNode cn = gt.getType();
@@ -1644,12 +1645,12 @@ public abstract class StaticTypeCheckingSupport {
}
}
- public static ClassNode resolveClassNodeGenerics(Map<String, GenericsType>
resolvedPlaceholders, final Map<String, GenericsType> placeholdersFromContext,
ClassNode currentType) {
+ public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName,
GenericsType> resolvedPlaceholders, final Map<GenericsTypeName, GenericsType>
placeholdersFromContext, ClassNode currentType) {
ClassNode target = currentType.redirect();
- resolvedPlaceholders = new HashMap<String,
GenericsType>(resolvedPlaceholders);
+ resolvedPlaceholders = new HashMap<GenericsTypeName,
GenericsType>(resolvedPlaceholders);
applyContextGenerics(resolvedPlaceholders, placeholdersFromContext);
- Map<String, GenericsType> connections = new HashMap<String,
GenericsType>();
+ Map<GenericsTypeName, GenericsType> connections = new
HashMap<GenericsTypeName, GenericsType>();
extractGenericsConnections(connections, currentType, target);
applyGenericsConnections(connections, resolvedPlaceholders);
currentType = applyGenericsContext(resolvedPlaceholders, currentType);
@@ -1657,16 +1658,16 @@ public abstract class StaticTypeCheckingSupport {
}
static void applyGenericsConnections(
- Map<String, GenericsType> connections,
- Map<String, GenericsType> resolvedPlaceholders
+ Map<GenericsTypeName, GenericsType> connections,
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders
) {
if (connections == null) return;
int count = 0;
while (count < 10000) {
count++;
boolean checkForMorePlaceHolders = false;
- for (Map.Entry<String, GenericsType> entry :
resolvedPlaceholders.entrySet()) {
- String name = entry.getKey();
+ for (Entry<GenericsTypeName, GenericsType> entry :
resolvedPlaceholders.entrySet()) {
+ GenericsTypeName name = entry.getKey();
GenericsType replacement = connections.get(name);
if (replacement == null) {
GenericsType value = entry.getValue();
@@ -1681,7 +1682,7 @@ public abstract class StaticTypeCheckingSupport {
}
boolean placeholderReplacement = replacement.isPlaceholder();
if (placeholderReplacement) {
- GenericsType connectedType =
resolvedPlaceholders.get(replacement.getName());
+ GenericsType connectedType = resolvedPlaceholders.get(new
GenericsTypeName(replacement.getName()));
if (replacement == connectedType) continue;
}
// GROOVY-6787: Don't override the original if the replacement
placeholder doesn't respect the bounds,
@@ -1771,7 +1772,7 @@ public abstract class StaticTypeCheckingSupport {
* to get E=Integer, since IntRange is an AbstractList<Integer>)
* Should the target not have any generics this method does nothing.
*/
- static void extractGenericsConnections(Map<String, GenericsType>
connections, ClassNode type, ClassNode target) {
+ static void extractGenericsConnections(Map<GenericsTypeName, GenericsType>
connections, ClassNode type, ClassNode target) {
if (target == null || type == target ||
!isUsingGenericsOrIsArrayUsingGenerics(target)) return;
if (type == null || type == UNKNOWN_PARAMETER_TYPE) return;
if (type.isArray() && target.isArray()) {
@@ -1779,7 +1780,7 @@ public abstract class StaticTypeCheckingSupport {
} else if (target.isGenericsPlaceHolder() || type.equals(target) ||
!implementsInterfaceOrIsSubclassOf(type, target)) {
// structural match route
if (target.isGenericsPlaceHolder()) {
- connections.put(target.getGenericsTypes()[0].getName(), new
GenericsType(type));
+ connections.put(new
GenericsTypeName(target.getGenericsTypes()[0].getName()), new
GenericsType(type));
} else {
extractGenericsConnections(connections,
type.getGenericsTypes(), target.getGenericsTypes());
}
@@ -1807,7 +1808,7 @@ public abstract class StaticTypeCheckingSupport {
return corrected;
}
- private static void extractGenericsConnections(Map<String, GenericsType>
connections, GenericsType[] usage, GenericsType[] declaration) {
+ private static void extractGenericsConnections(Map<GenericsTypeName,
GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
// if declaration does not provide generics, there is no connection to
make
if (usage == null || declaration == null || declaration.length == 0)
return;
if (usage.length != declaration.length) return;
@@ -1817,7 +1818,7 @@ public abstract class StaticTypeCheckingSupport {
GenericsType ui = usage[i];
GenericsType di = declaration[i];
if (di.isPlaceholder()) {
- connections.put(di.getName(), ui);
+ connections.put(new GenericsTypeName(di.getName()), ui);
} else if (di.isWildcard()) {
if (ui.isWildcard()) {
extractGenericsConnections(connections,
ui.getLowerBound(), di.getLowerBound());
@@ -1838,7 +1839,7 @@ public abstract class StaticTypeCheckingSupport {
}
}
- private static void extractGenericsConnections(Map<String, GenericsType>
connections, ClassNode[] usage, ClassNode[] declaration) {
+ private static void extractGenericsConnections(Map<GenericsTypeName,
GenericsType> connections, ClassNode[] usage, ClassNode[] declaration) {
if (usage == null || declaration == null || declaration.length == 0)
return;
// both have generics
for (int i = 0; i < usage.length; i++) {
@@ -1847,7 +1848,7 @@ public abstract class StaticTypeCheckingSupport {
if (di.isGenericsPlaceHolder()) {
GenericsType gt = new GenericsType(di);
gt.setPlaceholder(di.isGenericsPlaceHolder());
- connections.put(di.getGenericsTypes()[0].getName(), gt);
+ connections.put(new
GenericsTypeName(di.getGenericsTypes()[0].getName()), gt);
} else if (di.isUsingGenerics()) {
extractGenericsConnections(connections, ui.getGenericsTypes(),
di.getGenericsTypes());
}
@@ -1859,8 +1860,8 @@ public abstract class StaticTypeCheckingSupport {
return type.getGenericsTypes();
}
- static Map<String, GenericsType> applyGenericsContextToParameterClass(
- Map<String, GenericsType> spec, ClassNode parameterUsage
+ static Map<GenericsTypeName, GenericsType>
applyGenericsContextToParameterClass(
+ Map<GenericsTypeName, GenericsType> spec, ClassNode parameterUsage
) {
GenericsType[] gts = parameterUsage.getGenericsTypes();
if (gts == null) return Collections.EMPTY_MAP;
@@ -1872,7 +1873,7 @@ public abstract class StaticTypeCheckingSupport {
}
private static GenericsType[] applyGenericsContext(
- Map<String, GenericsType> spec, GenericsType[] gts
+ Map<GenericsTypeName, GenericsType> spec, GenericsType[] gts
) {
if (gts == null) return null;
GenericsType[] newGTs = new GenericsType[gts.length];
@@ -1883,9 +1884,9 @@ public abstract class StaticTypeCheckingSupport {
return newGTs;
}
- private static GenericsType applyGenericsContext(Map<String, GenericsType>
spec, GenericsType gt) {
+ private static GenericsType applyGenericsContext(Map<GenericsTypeName,
GenericsType> spec, GenericsType gt) {
if (gt.isPlaceholder()) {
- String name = gt.getName();
+ GenericsTypeName name = new GenericsTypeName(gt.getName());
GenericsType specType = spec.get(name);
if (specType != null) return specType;
if (hasNonTrivialBounds(gt)) {
@@ -1918,7 +1919,7 @@ public abstract class StaticTypeCheckingSupport {
}
private static ClassNode[] applyGenericsContext(
- Map<String, GenericsType> spec, ClassNode[] bounds
+ Map<GenericsTypeName, GenericsType> spec, ClassNode[] bounds
) {
if (bounds == null) return null;
ClassNode[] newBounds = new ClassNode[bounds.length];
@@ -1929,7 +1930,7 @@ public abstract class StaticTypeCheckingSupport {
}
static ClassNode applyGenericsContext(
- Map<String, GenericsType> spec, ClassNode bound
+ Map<GenericsTypeName, GenericsType> spec, ClassNode bound
) {
if (bound == null) return null;
if (bound.isArray()) {
@@ -1966,12 +1967,12 @@ public abstract class StaticTypeCheckingSupport {
return genericsType.getType();
}
- private static void applyContextGenerics(Map<String, GenericsType>
resolvedPlaceholders, Map<String, GenericsType> placeholdersFromContext) {
+ private static void applyContextGenerics(Map<GenericsTypeName,
GenericsType> resolvedPlaceholders, Map<GenericsTypeName, GenericsType>
placeholdersFromContext) {
if (placeholdersFromContext == null) return;
- for (Map.Entry<String, GenericsType> entry :
resolvedPlaceholders.entrySet()) {
+ for (Entry<GenericsTypeName, GenericsType> entry :
resolvedPlaceholders.entrySet()) {
GenericsType gt = entry.getValue();
if (gt.isPlaceholder()) {
- String name = gt.getName();
+ GenericsTypeName name = new GenericsTypeName(gt.getName());
GenericsType outer = placeholdersFromContext.get(name);
if (outer == null) continue;
entry.setValue(outer);
@@ -1979,9 +1980,9 @@ public abstract class StaticTypeCheckingSupport {
}
}
- private static Map<String, GenericsType>
getGenericsParameterMapOfThis(ClassNode cn) {
+ private static Map<GenericsTypeName, GenericsType>
getGenericsParameterMapOfThis(ClassNode cn) {
if (cn == null) return null;
- Map<String, GenericsType> map = null;
+ Map<GenericsTypeName, GenericsType> map = null;
if (cn.getEnclosingMethod() != null) {
map = extractGenericsParameterMapOfThis(cn.getEnclosingMethod());
} else if (cn.getOuterClass() != null) {
@@ -2039,10 +2040,10 @@ public abstract class StaticTypeCheckingSupport {
return false;
}
- static Map<String, GenericsType>
extractGenericsParameterMapOfThis(MethodNode mn) {
+ static Map<GenericsTypeName, GenericsType>
extractGenericsParameterMapOfThis(MethodNode mn) {
if (mn == null) return null;
- Map<String, GenericsType> map;
+ Map<GenericsTypeName, GenericsType> map;
if (mn.isStatic()) {
map = new HashMap<>();
} else {
@@ -2052,12 +2053,12 @@ public abstract class StaticTypeCheckingSupport {
return mergeGenerics(map, mn.getGenericsTypes());
}
- private static Map<String, GenericsType> mergeGenerics(Map<String,
GenericsType> current, GenericsType[] newGenerics) {
+ private static Map<GenericsTypeName, GenericsType>
mergeGenerics(Map<GenericsTypeName, GenericsType> current, GenericsType[]
newGenerics) {
if (newGenerics == null || newGenerics.length == 0) return current;
- if (current == null) current = new HashMap<String, GenericsType>();
+ if (current == null) current = new HashMap<GenericsTypeName,
GenericsType>();
for (GenericsType gt : newGenerics) {
if (!gt.isPlaceholder()) continue;
- String name = gt.getName();
+ GenericsTypeName name = new GenericsTypeName(gt.getName());
if (!current.containsKey(name)) current.put(name, gt);
}
return current;
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 98ab3e5..56dc529 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -62,6 +62,7 @@ import org.codehaus.groovy.ast.expr.MapEntryExpression;
import org.codehaus.groovy.ast.expr.MapExpression;
import org.codehaus.groovy.ast.expr.MethodCall;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.NotExpression;
import org.codehaus.groovy.ast.expr.PostfixExpression;
import org.codehaus.groovy.ast.expr.PrefixExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
@@ -73,7 +74,6 @@ import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.UnaryMinusExpression;
import org.codehaus.groovy.ast.expr.UnaryPlusExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
-import org.codehaus.groovy.ast.expr.NotExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.CaseStatement;
import org.codehaus.groovy.ast.stmt.CatchStatement;
@@ -166,6 +166,7 @@ import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.make;
import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
@@ -1697,7 +1698,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
private void storeWithResolve(ClassNode typeToResolve, ClassNode receiver,
ClassNode declaringClass, boolean isStatic, PropertyExpression
expressionToStoreOn) {
ClassNode type = typeToResolve;
if (getGenericsWithoutArray(type) != null) {
- Map<String, GenericsType> resolvedPlaceholders =
resolvePlaceHoldersFromDeclaration(receiver, declaringClass, null, isStatic);
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders =
resolvePlaceHoldersFromDeclaration(receiver, declaringClass, null, isStatic);
type = resolveGenericsWithContext(resolvedPlaceholders, type);
}
storeInferredTypeForPropertyExpression(expressionToStoreOn, type);
@@ -2635,18 +2636,18 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
private void inferSAMType(Parameter param, ClassNode receiver, MethodNode
methodWithSAMParameter, ArgumentListExpression originalMethodCallArguments,
ClosureExpression openBlock) {
// In a method call with SAM coercion the inference is to be
// understood as a two phase process. We have the normal method call
- // to the target method with the closure argument and we have the
- // SAM method that will be called inside the normal target method.
+ // to the target method with the closure argument and we have the
+ // SAM method that will be called inside the normal target method.
// To infer correctly we have to "simulate" this process. We know the
// call to the closure will be done through the SAM type, so the SAM
// type generics deliver information about the Closure. At the same
- // time the SAM class is used in the target method parameter,
+ // time the SAM class is used in the target method parameter,
// providing a connection from the SAM type and the target method
// declaration class.
// First we try to get as much information about the declaration
// class through the receiver
- Map<String, GenericsType> targetMethodDeclarationClassConnections =
new HashMap<String, GenericsType>();
+ Map<GenericsTypeName, GenericsType>
targetMethodDeclarationClassConnections = new HashMap<GenericsTypeName,
GenericsType>();
extractGenericsConnections(targetMethodDeclarationClassConnections,
receiver, receiver.redirect());
// then we use the method with the SAM parameter to get more
information about the declaration
Parameter[] parametersOfMethodContainingSAM =
methodWithSAMParameter.getParameters();
@@ -2667,7 +2668,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
// to replace the generics in the SAM type parameter of the target
// method and than that to make the connections to the SAM type
generics
ClassNode paramTypeWithReceiverInformation =
applyGenericsContext(targetMethodDeclarationClassConnections,
param.getOriginType());
- Map<String, GenericsType> SAMTypeConnections = new HashMap<String,
GenericsType>();
+ Map<GenericsTypeName, GenericsType> SAMTypeConnections = new
HashMap<GenericsTypeName, GenericsType>();
ClassNode classForSAM = paramTypeWithReceiverInformation.redirect();
extractGenericsConnections(SAMTypeConnections,
paramTypeWithReceiverInformation, classForSAM);
@@ -2699,7 +2700,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
extractGenericsConnections(SAMTypeConnections,
blockParameterTypes[i], typeOrNull(parameterTypesForSAM, i));
}
- // and finally we apply the generics information to the parameters and
+ // and finally we apply the generics information to the parameters and
// store the type of parameter and block type as meta information
for (int i = 0; i < blockParameterTypes.length; i++) {
ClassNode resolvedParameter =
@@ -4099,17 +4100,17 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
private ClassNode inferSAMTypeGenericsInAssignment(ClassNode samUsage,
MethodNode sam, ClassNode closureType, ClosureExpression closureExpression) {
- // if the sam type or closure type do not provide generics
information,
+ // if the sam type or closure type do not provide generics information,
// we cannot infer anything, thus we simply return the provided
samUsage
GenericsType[] samGt = samUsage.getGenericsTypes();
GenericsType[] closureGt = closureType.getGenericsTypes();
if (samGt == null || closureGt == null) return samUsage;
// extract the generics from the return type
- Map<String, GenericsType> connections = new HashMap<String,
GenericsType>();
+ Map<GenericsTypeName, GenericsType> connections = new
HashMap<GenericsTypeName, GenericsType>();
extractGenericsConnections(connections,
getInferredReturnType(closureExpression), sam.getReturnType());
- // next we get the block parameter types and set the generics
+ // next we get the block parameter types and set the generics
// information just like before
// TODO: add vargs handling
Parameter[] closureParams = closureExpression.getParameters();
@@ -4690,7 +4691,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
*/
private ClassNode getGenericsResolvedTypeOfFieldOrProperty(AnnotatedNode
an, ClassNode type) {
if (!type.isUsingGenerics()) return type;
- Map<String, GenericsType> connections = new HashMap<String,
GenericsType>();
+ Map<GenericsTypeName, GenericsType> connections = new
HashMap<GenericsTypeName, GenericsType>();
//TODO: inner classes mean a different this-type. This is ignored here!
extractGenericsConnections(connections,
typeCheckingContext.getEnclosingClassNode(), an.getDeclaringClass());
type = applyGenericsContext(connections, type);
@@ -4875,7 +4876,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
if (!isUsingGenericsOrIsArrayUsingGenerics(returnType)) return
returnType;
if (getGenericsWithoutArray(returnType) == null) return returnType;
- Map<String, GenericsType> resolvedPlaceholders =
resolvePlaceHoldersFromDeclaration(receiver, getDeclaringClass(method,
arguments), method, method.isStatic());
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders =
resolvePlaceHoldersFromDeclaration(receiver, getDeclaringClass(method,
arguments), method, method.isStatic());
if (!receiver.isGenericsPlaceHolder()) {
GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
}
@@ -4883,7 +4884,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (resolvedPlaceholders.isEmpty()) {
return boundUnboundedWildcards(returnType);
}
- Map<String, GenericsType> placeholdersFromContext =
extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+ Map<GenericsTypeName, GenericsType> placeholdersFromContext =
extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
applyGenericsConnections(placeholdersFromContext,
resolvedPlaceholders);
// then resolve receivers from method arguments
@@ -4905,7 +4906,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (implementsInterfaceOrIsSubclassOf(actualType,
CLOSURE_TYPE) &&
isSAMType(type)) {
// implicit closure coercion in action!
- Map<String, GenericsType> pholders =
applyGenericsContextToParameterClass(resolvedPlaceholders, type);
+ Map<GenericsTypeName, GenericsType> pholders =
applyGenericsContextToParameterClass(resolvedPlaceholders, type);
actualType =
convertClosureTypeToSAMType(expressions.get(i), actualType, type, pholders);
}
if (isVargs && lastArg && actualType.isArray()) {
@@ -4916,7 +4917,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
actualType = wrapTypeIfNecessary(actualType);
- Map<String, GenericsType> connections = new
HashMap<String, GenericsType>();
+ Map<GenericsTypeName, GenericsType> connections = new
HashMap<GenericsTypeName, GenericsType>();
extractGenericsConnections(connections, actualType, type);
extractGenericsConnectionsForSuperClassAndInterfaces(resolvedPlaceholders,
connections);
applyGenericsConnections(connections,
resolvedPlaceholders);
@@ -4927,20 +4928,20 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return applyGenericsContext(resolvedPlaceholders, returnType);
}
- private static void resolvePlaceholdersFromExplicitTypeHints(final
MethodNode method, final GenericsType[] explicitTypeHints, final Map<String,
GenericsType> resolvedPlaceholders) {
+ private static void resolvePlaceholdersFromExplicitTypeHints(final
MethodNode method, final GenericsType[] explicitTypeHints, final
Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
if (explicitTypeHints != null) {
GenericsType[] methodGenericTypes = method.getGenericsTypes();
if (methodGenericTypes != null && methodGenericTypes.length ==
explicitTypeHints.length) {
for (int i = 0; i < explicitTypeHints.length; i++) {
GenericsType methodGenericType = methodGenericTypes[i];
GenericsType explicitTypeHint = explicitTypeHints[i];
- resolvedPlaceholders.put(methodGenericType.getName(),
explicitTypeHint);
+ resolvedPlaceholders.put(new
GenericsTypeName(methodGenericType.getName()), explicitTypeHint);
}
}
}
}
- private static void
extractGenericsConnectionsForSuperClassAndInterfaces(final Map<String,
GenericsType> resolvedPlaceholders, final Map<String, GenericsType>
connections) {
+ private static void
extractGenericsConnectionsForSuperClassAndInterfaces(final
Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final
Map<GenericsTypeName, GenericsType> connections) {
for (GenericsType value : new
HashSet<GenericsType>(connections.values())) {
if (!value.isPlaceholder() && !value.isWildcard()) {
ClassNode valueType = value.getType();
@@ -4988,7 +4989,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
* @param samType the type into which the closure is coerced into
* @return same SAM type, but completed with information from the closure
node
*/
- private static ClassNode convertClosureTypeToSAMType(final Expression
expression, final ClassNode closureType, final ClassNode samType, final
Map<String, GenericsType> placeholders) {
+ private static ClassNode convertClosureTypeToSAMType(final Expression
expression, final ClassNode closureType, final ClassNode samType, final
Map<GenericsTypeName, GenericsType> placeholders) {
if (!samType.isUsingGenerics()) return samType;
// use the generics information from the Closure to further specify
the type
@@ -5004,7 +5005,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
ClassNode unwrapped =
closureReturnType.getGenericsTypes()[0].getType();
extractGenericsConnections(placeholders, unwrapped,
samReturnType);
} else if (samReturnType.isGenericsPlaceHolder()) {
-
placeholders.put(samReturnType.getGenericsTypes()[0].getName(),
closureType.getGenericsTypes()[0]);
+ placeholders.put(new
GenericsTypeName(samReturnType.getGenericsTypes()[0].getName()),
closureType.getGenericsTypes()[0]);
}
// now repeat the same for each parameter given in the
ClosureExpression
@@ -5035,7 +5036,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
generifiedType = generifiedType.getComponentType();
}
if (expected.isGenericsPlaceHolder()) {
-
placeholders.put(expected.getGenericsTypes()[0].getName(), new
GenericsType(generifiedType));
+ placeholders.put(new
GenericsTypeName(expected.getGenericsTypes()[0].getName()), new
GenericsType(generifiedType));
} else {
GenericsType[] expectedGenericsTypes =
expected.getGenericsTypes();
GenericsType[] foundGenericsTypes =
generifiedType.getGenericsTypes();
@@ -5044,7 +5045,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
final GenericsType type = expectedGenericsTypes[i];
if (type.isPlaceholder()) {
String name = type.getName();
- placeholders.put(name, foundGenericsTypes[i]);
+ placeholders.put(new GenericsTypeName(name),
foundGenericsTypes[i]);
}
}
}
@@ -5055,8 +5056,8 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return result;
}
- private ClassNode resolveGenericsWithContext(Map<String, GenericsType>
resolvedPlaceholders, ClassNode currentType) {
- Map<String, GenericsType> placeholdersFromContext =
extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+ private ClassNode resolveGenericsWithContext(Map<GenericsTypeName,
GenericsType> resolvedPlaceholders, ClassNode currentType) {
+ Map<GenericsTypeName, GenericsType> placeholdersFromContext =
extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
return resolveClassNodeGenerics(resolvedPlaceholders,
placeholdersFromContext, currentType);
}
@@ -5075,8 +5076,8 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return declaringClass;
}
- private Map<String, GenericsType>
resolvePlaceHoldersFromDeclaration(ClassNode receiver, ClassNode declaration,
MethodNode method, boolean isStaticTarget) {
- Map<String, GenericsType> resolvedPlaceholders;
+ private Map<GenericsTypeName, GenericsType>
resolvePlaceHoldersFromDeclaration(ClassNode receiver, ClassNode declaration,
MethodNode method, boolean isStaticTarget) {
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders;
if (isStaticTarget && CLASS_Type.equals(receiver) &&
receiver.isUsingGenerics() &&
receiver.getGenericsTypes().length > 0 &&
@@ -5094,14 +5095,14 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
- private static Map<String, GenericsType> extractPlaceHolders(MethodNode
method, ClassNode receiver, ClassNode declaringClass) {
+ private static Map<GenericsTypeName, GenericsType>
extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode
declaringClass) {
if (declaringClass.equals(OBJECT_TYPE)) {
- Map<String, GenericsType> resolvedPlaceholders = new
HashMap<String, GenericsType>();
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders = new
HashMap<GenericsTypeName, GenericsType>();
if (method != null) addMethodLevelDeclaredGenerics(method,
resolvedPlaceholders);
return resolvedPlaceholders;
}
- Map<String, GenericsType> resolvedPlaceholders = null;
+ Map<GenericsTypeName, GenericsType> resolvedPlaceholders = null;
if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
receiver = getWrapper(receiver);
}
@@ -5116,7 +5117,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
while (current != null) {
boolean continueLoop = true;
//extract the place holders
- Map<String, GenericsType> currentPlaceHolders = new
HashMap<String, GenericsType>();
+ Map<GenericsTypeName, GenericsType> currentPlaceHolders = new
HashMap<GenericsTypeName, GenericsType>();
if (isGenericsPlaceHolderOrArrayOf(declaringClass) ||
declaringClass.equals(current)) {
extractGenericsConnections(currentPlaceHolders, current,
declaringClass);
if (method != null) addMethodLevelDeclaredGenerics(method,
currentPlaceHolders);
@@ -5127,11 +5128,11 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (resolvedPlaceholders != null) {
// merge maps
- Set<Map.Entry<String, GenericsType>> entries =
currentPlaceHolders.entrySet();
- for (Map.Entry<String, GenericsType> entry : entries) {
+ Set<Map.Entry<GenericsTypeName, GenericsType>> entries =
currentPlaceHolders.entrySet();
+ for (Map.Entry<GenericsTypeName, GenericsType> entry :
entries) {
GenericsType gt = entry.getValue();
if (!gt.isPlaceholder()) continue;
- GenericsType referenced =
resolvedPlaceholders.get(gt.getName());
+ GenericsType referenced = resolvedPlaceholders.get(new
GenericsTypeName(gt.getName()));
if (referenced == null) continue;
entry.setValue(referenced);
}
@@ -5163,7 +5164,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
protected boolean typeCheckMethodsWithGenericsOrFail(ClassNode receiver,
ClassNode[] arguments, MethodNode candidateMethod, Expression location) {
if (!typeCheckMethodsWithGenerics(receiver, arguments,
candidateMethod)) {
- Map<String, GenericsType> classGTs =
GenericsUtils.extractPlaceholders(receiver);
+ Map<GenericsTypeName, GenericsType> classGTs =
GenericsUtils.extractPlaceholders(receiver);
ClassNode[] ptypes = new
ClassNode[candidateMethod.getParameters().length];
final Parameter[] parameters = candidateMethod.getParameters();
for (int i = 0; i < parameters.length; i++) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/dbb665df/src/test/org/codehaus/groovy/ast/GenericsTypeTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/ast/GenericsTypeTest.groovy
b/src/test/org/codehaus/groovy/ast/GenericsTypeTest.groovy
index 7a72d66..858cdff 100644
--- a/src/test/org/codehaus/groovy/ast/GenericsTypeTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/GenericsTypeTest.groovy
@@ -20,6 +20,8 @@ package org.codehaus.groovy.ast
import org.codehaus.groovy.ast.tools.GenericsUtils
+import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName
+
/**
* Various tests aimed at testing the {@link GenericsType} class.
*/
@@ -135,23 +137,23 @@ public class GenericsTypeTest extends GenericsTestCase {
void testPlaceholderExtract() {
def type = extractTypesFromCode("List<String> type").type
def placeholders = GenericsUtils.extractPlaceholders(type)
- assert placeholders.E?.type == ClassHelper.STRING_TYPE
+ assert placeholders[new GenericsTypeName('E')]?.type ==
ClassHelper.STRING_TYPE
}
void testPlaceholderExtract2() {
def type = extractTypesFromCode("Map<String,Integer> type").type
def placeholders = GenericsUtils.extractPlaceholders(type)
- assert placeholders.K?.type == ClassHelper.STRING_TYPE
- assert placeholders.V?.type == ClassHelper.Integer_TYPE
+ assert placeholders[new GenericsTypeName('K')]?.type ==
ClassHelper.STRING_TYPE
+ assert placeholders[new GenericsTypeName('V')]?.type ==
ClassHelper.Integer_TYPE
}
void testPlaceholderExtract3() {
def type = extractTypesFromCode("List<Map<String,Integer>> type").type
def placeholders = GenericsUtils.extractPlaceholders(type)
- assert placeholders.E?.type == ClassHelper.MAP_TYPE
- placeholders = GenericsUtils.extractPlaceholders(placeholders.E.type)
- assert placeholders.K?.type == ClassHelper.STRING_TYPE
- assert placeholders.V?.type == ClassHelper.Integer_TYPE
+ assert placeholders[new GenericsTypeName('E')]?.type ==
ClassHelper.MAP_TYPE
+ placeholders = GenericsUtils.extractPlaceholders(placeholders[new
GenericsTypeName('E')].type)
+ assert placeholders[new GenericsTypeName('K')]?.type ==
ClassHelper.STRING_TYPE
+ assert placeholders[new GenericsTypeName('V')]?.type ==
ClassHelper.Integer_TYPE
}
// ------------------ Support methods -------------------------