Repository: groovy
Updated Branches:
  refs/heads/master 680317fc2 -> f8d4f1bec


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.


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/f8d4f1be
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/f8d4f1be
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/f8d4f1be

Branch: refs/heads/master
Commit: f8d4f1bec1dc8cd079e3db97bb2297ae448950af
Parents: 680317f
Author: Daniel Sun <[email protected]>
Authored: Sat Aug 18 20:31:02 2018 +0800
Committer: Daniel Sun <[email protected]>
Committed: Sat Aug 18 20:31:02 2018 +0800

----------------------------------------------------------------------
 .../org/codehaus/groovy/ast/GenericsType.java   |  46 ++++++--
 .../groovy/ast/tools/GenericsUtils.java         |   9 +-
 .../groovy/ast/tools/WideningCategories.java    |   8 +-
 .../codehaus/groovy/control/ResolveVisitor.java |  30 ++---
 .../stc/StaticTypeCheckingSupport.java          | 110 +++++++++----------
 .../stc/StaticTypeCheckingVisitor.java          |  58 +++++-----
 .../codehaus/groovy/ast/GenericsTypeTest.groovy |  16 +--
 7 files changed, 153 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/f8d4f1be/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..33d0b72 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,29 @@ public class GenericsType extends ASTNode {
         }
         return superClass;
     }
+
+    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);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/f8d4f1be/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 188ce59..06c8d84 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/f8d4f1be/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/f8d4f1be/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 3950745..b51aff3 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 });
@@ -1332,7 +1332,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;
@@ -1343,7 +1343,7 @@ public class ResolveVisitor extends 
ClassCodeExpressionTransformer {
                 }
             }
         } else {
-            genericParameterNames = new HashMap<String, GenericsType>();
+            genericParameterNames = new HashMap<GenericsTypeName, 
GenericsType>();
         }
 
         resolveGenericsHeader(node.getGenericsTypes());
@@ -1488,7 +1488,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;
@@ -1496,7 +1496,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;
@@ -1513,8 +1513,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) {
@@ -1545,7 +1545,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/f8d4f1be/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 a195ed7..56f64e3 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -108,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;
@@ -155,7 +156,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}.
  */
@@ -1301,8 +1301,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++) {
@@ -1322,7 +1322,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;
         }
@@ -1355,8 +1355,8 @@ public abstract class StaticTypeCheckingSupport {
      * Given a generics type representing SomeClass&lt;T,V&gt; 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;
         }
@@ -1378,15 +1378,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);
                     }
@@ -1398,7 +1398,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();
             }
@@ -1450,7 +1450,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);
@@ -1492,7 +1492,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 {
@@ -1508,12 +1508,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
@@ -1525,7 +1525,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);
@@ -1546,10 +1546,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 (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());
@@ -1557,8 +1557,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
@@ -1593,8 +1593,8 @@ public abstract class StaticTypeCheckingSupport {
         return gt;
     }
 
-    private static boolean compatibleConnections(Map<String, GenericsType> 
connections, Map<String, GenericsType> resolvedMethodGenerics, Set<String> 
fixedGenericsPlaceHolders) {
-        for (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();
@@ -1640,8 +1640,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();
@@ -1650,12 +1650,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);
@@ -1663,16 +1663,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 (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();
@@ -1687,7 +1687,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,
@@ -1777,7 +1777,7 @@ public abstract class StaticTypeCheckingSupport {
      * to get E=Integer, since IntRange is an AbstractList&lt;Integer&gt;)
      * 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()) {
@@ -1785,7 +1785,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());
             }
@@ -1813,7 +1813,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;
@@ -1823,7 +1823,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());
@@ -1844,7 +1844,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++) {
@@ -1853,7 +1853,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());
             }
@@ -1865,8 +1865,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;
@@ -1878,7 +1878,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];
@@ -1889,9 +1889,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)) {
@@ -1924,7 +1924,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];
@@ -1935,7 +1935,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()) {
@@ -1972,12 +1972,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 (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);
@@ -1985,9 +1985,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) {
@@ -2045,10 +2045,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 {
@@ -2058,12 +2058,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/f8d4f1be/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 6d1f21c..a80f27c 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -167,6 +167,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;
@@ -256,7 +257,6 @@ import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.resolv
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.toMethodParametersString;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCheckMethodArgumentWithGenerics;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCheckMethodsWithGenerics;
-
 //import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_INSTANCEOF;
 
 /**
@@ -1706,7 +1706,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);
@@ -2655,7 +2655,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
 
         // 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();
@@ -2676,7 +2676,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);
 
@@ -4155,7 +4155,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         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
@@ -4766,7 +4766,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);
@@ -4951,7 +4951,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);
         }
@@ -4959,7 +4959,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
@@ -4981,7 +4981,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()) {
@@ -4992,7 +4992,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);
@@ -5003,20 +5003,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();
@@ -5064,7 +5064,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
@@ -5080,7 +5080,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
@@ -5111,7 +5111,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();
@@ -5120,7 +5120,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]);
                             }
                         }
                     }
@@ -5131,8 +5131,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);
     }
 
@@ -5151,8 +5151,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 &&
@@ -5170,14 +5170,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);
         }
@@ -5192,7 +5192,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);
@@ -5203,11 +5203,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);
                     }
@@ -5239,7 +5239,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/f8d4f1be/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 -------------------------

Reply via email to