This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 5baa8c8  GROOVY-10322: STC: remove hidden generics when checking 
method arguments
5baa8c8 is described below

commit 5baa8c8e17fb414d6fbad37835da87a93ede2900
Author: Eric Milles <[email protected]>
AuthorDate: Wed Nov 3 19:35:36 2021 -0500

    GROOVY-10322: STC: remove hidden generics when checking method arguments
---
 .../transform/stc/StaticTypeCheckingSupport.java   |  88 ++---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 145 ++++----
 .../stc/ArraysAndCollectionsSTCTest.groovy         |   6 +-
 .../stc/DefaultGroovyMethodsSTCTest.groovy         |   4 +-
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 410 +++++++++++----------
 5 files changed, 338 insertions(+), 315 deletions(-)

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 19e961b..7095e54 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -59,6 +59,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -1060,14 +1061,28 @@ public abstract class StaticTypeCheckingSupport {
                 Person p = foo(b)
             */
 
-            ClassNode declaringClassForDistance = 
candidate.getDeclaringClass();
-            ClassNode actualReceiverForDistance = receiver != null ? receiver 
: declaringClassForDistance;
-            Map<GenericsType, GenericsType> declaringAndActualGenericsTypeMap 
= 
GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType(declaringClassForDistance,
 actualReceiverForDistance);
+            ClassNode declaringClass = candidate.getDeclaringClass();
+            ClassNode actualReceiver = receiver != null ? receiver : 
declaringClass;
 
-            Parameter[] params = makeRawTypes(safeNode.getParameters(), 
declaringAndActualGenericsTypeMap);
+            Map<GenericsType, GenericsType> spec;
+            if (candidate.isStatic()) {
+                spec = Collections.emptyMap(); // none visible
+            } else {
+                spec = 
GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType(declaringClass, 
actualReceiver);
+                GenericsType[] methodGenerics = candidate.getGenericsTypes();
+                if (methodGenerics != null) { // GROOVY-10322: remove hidden 
type parameters
+                    for (int i = 0, n = methodGenerics.length; i < n && 
!spec.isEmpty(); i += 1) {
+                        for (Iterator<GenericsType> it = 
spec.keySet().iterator(); it.hasNext(); ) {
+                            if 
(it.next().getName().equals(methodGenerics[i].getName())) it.remove();
+                        }
+                    }
+                }
+            }
+
+            Parameter[] params = makeRawTypes(safeNode.getParameters(), spec);
             int dist = measureParametersAndArgumentsDistance(params, safeArgs);
             if (dist >= 0) {
-                dist += getClassDistance(declaringClassForDistance, 
actualReceiverForDistance);
+                dist += getClassDistance(declaringClass, actualReceiver);
                 dist += getExtensionDistance(isExtensionMethod);
                 if (dist < bestDist) {
                     bestDist = dist;
@@ -1387,16 +1402,6 @@ public abstract class StaticTypeCheckingSupport {
         return true;
     }
 
-    static void addMethodLevelDeclaredGenerics(final MethodNode method, final 
Map<GenericsTypeName, GenericsType> placeholders) {
-        GenericsType[] generics = method.getGenericsTypes();
-        if (!method.isStatic() && !placeholders.isEmpty()) {
-            // GROOVY-8034: non-static method may use class generics
-            generics = applyGenericsContext(placeholders, generics);
-        }
-        ClassNode dummy = GenericsUtils.makeClassSafe0(OBJECT_TYPE, generics);
-        GenericsUtils.extractPlaceholders(dummy, placeholders);
-    }
-
     protected static boolean typeCheckMethodsWithGenerics(final ClassNode 
receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod) {
         if (candidateMethod instanceof ExtensionMethodNode) {
             ClassNode[] realTypes = new ClassNode[argumentTypes.length + 1];
@@ -1417,46 +1422,46 @@ public abstract class StaticTypeCheckingSupport {
 
     private static boolean typeCheckMethodsWithGenerics(final ClassNode 
receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod, 
final boolean isExtensionMethod) {
         Parameter[] parameters = candidateMethod.getParameters();
-        if (parameters.length > argumentTypes.length || parameters.length == 
0) {
-            // this is a limitation that must be removed in a future version
-            // we cannot check generic type arguments if there are default 
parameters!
+        if (parameters.length == 0 || parameters.length > 
argumentTypes.length) {
+            // this is a limitation that must be removed in a future version; 
we
+            // cannot check generic type arguments if there is default 
argument!
             return true;
         }
 
         boolean failure = false;
         Set<GenericsTypeName> fixedPlaceHolders = Collections.emptySet();
-        Map<GenericsTypeName, GenericsType> resolvedMethodGenerics = new 
HashMap<>();
+        Map<GenericsTypeName, GenericsType> candidateGenerics = new 
HashMap<>();
         // correct receiver for inner class
         // we assume the receiver is an instance of the declaring class of the
-        // candidate method, but findMethod returns also outer class methods
-        // for that receiver. For now we skip receiver based checks in that 
case
-        // TODO: correct generics for when receiver is to be skipped
+        // candidate method, but findMethod() returns also outer class methods
+        // for that receiver; for now we skip receiver-based checks in that 
case
         boolean skipBecauseOfInnerClassNotReceiver = 
!implementsInterfaceOrIsSubclassOf(receiver, 
candidateMethod.getDeclaringClass());
         if (!skipBecauseOfInnerClassNotReceiver) {
             if (candidateMethod instanceof ConstructorNode) {
-                resolvedMethodGenerics = 
GenericsUtils.extractPlaceholders(receiver);
-                fixedPlaceHolders = new 
HashSet<>(resolvedMethodGenerics.keySet());
+                candidateGenerics = 
GenericsUtils.extractPlaceholders(receiver);
+                fixedPlaceHolders = new HashSet<>(candidateGenerics.keySet());
             } else {
-                // we have here different generics contexts we have to deal 
with.
-                // 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.
-                addMethodLevelDeclaredGenerics(candidateMethod, 
resolvedMethodGenerics);
-                if (!resolvedMethodGenerics.isEmpty()) {
-                    // first remove hidden generics
-                    Map<GenericsTypeName, GenericsType> receiverGenerics = 
GenericsUtils.extractPlaceholders(receiver);
-                    
receiverGenerics.keySet().removeAll(resolvedMethodGenerics.keySet());
-                    // then use the remaining information to refine the method 
generics
-                    applyGenericsConnections(receiverGenerics, 
resolvedMethodGenerics);
+                failure = inferenceCheck(fixedPlaceHolders, candidateGenerics, 
candidateMethod.getDeclaringClass(), receiver, false);
+
+                GenericsType[] gts = candidateMethod.getGenericsTypes();
+                if (candidateMethod.isStatic()) {
+                    candidateGenerics.clear(); // not in scope
+                } else if (gts != null) {
+                    // first remove hidden params
+                    for (GenericsType gt : gts) {
+                        candidateGenerics.remove(new 
GenericsTypeName(gt.getName()));
+                    }
+                    // GROOVY-8034: non-static method may use class generics
+                    gts = applyGenericsContext(candidateGenerics, gts);
                 }
-                // and then start our checks with the receiver
-                failure = inferenceCheck(fixedPlaceHolders, 
resolvedMethodGenerics, candidateMethod.getDeclaringClass(), receiver, false);
+                GenericsUtils.extractPlaceholders(makeClassSafe0(OBJECT_TYPE, 
gts), candidateGenerics);
+
                 // the outside context parts till now define placeholder we 
are not allowed to
                 // generalize, thus we save that for later use...
                 // 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.
-                fixedPlaceHolders = 
extractResolvedPlaceHolders(resolvedMethodGenerics);
+                fixedPlaceHolders = 
extractResolvedPlaceHolders(candidateGenerics);
             }
         }
 
@@ -1464,11 +1469,10 @@ public abstract class StaticTypeCheckingSupport {
         for (int i = 0, n = argumentTypes.length; i < n; i += 1) {
             ClassNode parameterType = parameters[Math.min(i, 
lastParamIndex)].getOriginType();
             ClassNode argumentType = 
StaticTypeCheckingVisitor.wrapTypeIfNecessary(argumentTypes[i]);
-            failure |= inferenceCheck(fixedPlaceHolders, 
resolvedMethodGenerics, parameterType, argumentType, i >= lastParamIndex);
+            failure |= inferenceCheck(fixedPlaceHolders, candidateGenerics, 
parameterType, argumentType, i >= lastParamIndex);
 
-            if (i == 0 && isExtensionMethod) {
-                // set real fixed type parameters for extension method
-                fixedPlaceHolders = 
extractResolvedPlaceHolders(resolvedMethodGenerics);
+            if (i == 0 && isExtensionMethod) { // re-load fixed names for 
extension
+                fixedPlaceHolders = 
extractResolvedPlaceHolders(candidateGenerics);
             }
         }
         return !failure;
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 a2db17e..35c696b 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -260,7 +260,6 @@ import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Linked
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Matcher_TYPE;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.NUMBER_OPS;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.UNKNOWN_PARAMETER_TYPE;
-import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.addMethodLevelDeclaredGenerics;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.allParametersAndArgumentsMatchWithDefaultParams;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsConnections;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext;
@@ -1008,8 +1007,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         Function<MethodNode, ClassNode> setterType = setter -> {
             ClassNode type = setter.getParameters()[0].getOriginType();
             if (!setter.isStatic() && !(setter instanceof ExtensionMethodNode) 
&& GenericsUtils.hasUnresolvedGenerics(type)) {
-                Map<GenericsTypeName, GenericsType> spec = 
extractPlaceHolders(null, setterInfo.receiverType, setter.getDeclaringClass());
-                type = applyGenericsContext(spec, type);
+                type = 
applyGenericsContext(extractPlaceHolders(setterInfo.receiverType, 
setter.getDeclaringClass()), type);
             }
             return type;
         };
@@ -1867,8 +1865,8 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
     }
 
     private void storeWithResolve(ClassNode type, final ClassNode receiver, 
final ClassNode declaringClass, final boolean isStatic, final Expression 
expressionToStoreOn) {
-        if (GenericsUtils.hasUnresolvedGenerics(type)) {
-            type = 
resolveGenericsWithContext(resolvePlaceHoldersFromDeclaration(receiver, 
declaringClass, null, isStatic), type);
+        if (!isStatic && GenericsUtils.hasUnresolvedGenerics(type)) {
+            type = resolveGenericsWithContext(extractPlaceHolders(receiver, 
declaringClass), type);
         }
         if (expressionToStoreOn instanceof PropertyExpression) {
             storeInferredTypeForPropertyExpression((PropertyExpression) 
expressionToStoreOn, type);
@@ -2906,7 +2904,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                 }
             }
         } else if (isSAMType(target.getOriginType())) { // SAM-type coercion
-            Map<GenericsTypeName, GenericsType> context = method.isStatic() ? 
new HashMap<>() : extractPlaceHolders(null, receiver, getDeclaringClass(method, 
arguments));
+            Map<GenericsTypeName, GenericsType> context = 
extractPlaceHoldersVisibleToDeclaration(receiver, method, arguments);
             GenericsType[] typeParameters = method instanceof ConstructorNode 
? method.getDeclaringClass().getGenericsTypes() : applyGenericsContext(context, 
method.getGenericsTypes());
 
             if (typeParameters != null) {
@@ -3516,8 +3514,8 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                         // GROOVY-7106, GROOVY-7274, GROOVY-8909, GROOVY-8961, 
GROOVY-9734, GROOVY-9844, GROOVY-9915, et al.
                         Parameter[] parameters = 
directMethodCallCandidate.getParameters();
                         if (chosenReceiver.getType().getGenericsTypes() != 
null && !directMethodCallCandidate.isStatic() && !(directMethodCallCandidate 
instanceof ExtensionMethodNode)) {
-                            Map<GenericsTypeName, GenericsType> context = 
extractPlaceHolders(null, chosenReceiver.getType(), 
getDeclaringClass(directMethodCallCandidate, argumentList));
-                            parameters = Arrays.stream(parameters).map(param 
-> new Parameter(applyGenericsContext(context, param.getType()), 
param.getName())).toArray(Parameter[]::new);
+                            Map<GenericsTypeName, GenericsType> context = 
extractPlaceHoldersVisibleToDeclaration(chosenReceiver.getType(), 
directMethodCallCandidate, argumentList);
+                            parameters = Arrays.stream(parameters).map(p -> 
new Parameter(applyGenericsContext(context, p.getType()), 
p.getName())).toArray(Parameter[]::new);
                         }
                         resolvePlaceholdersFromImplicitTypeHints(args, 
argumentList, parameters);
 
@@ -4986,13 +4984,11 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
             if (vexp.isSuperExpression()) return makeSuper();
             Variable variable = vexp.getAccessedVariable();
             if (variable instanceof FieldNode) {
-                ClassNode fieldType = variable.getOriginType();
-                if (isUsingGenericsOrIsArrayUsingGenerics(fieldType)) {
-                    boolean isStatic = (variable.getModifiers() & 
Opcodes.ACC_STATIC) != 0;
-                    ClassNode thisType = 
typeCheckingContext.getEnclosingClassNode(), declType = ((FieldNode) 
variable).getDeclaringClass();
-                    Map<GenericsTypeName, GenericsType> placeholders = 
resolvePlaceHoldersFromDeclaration(thisType, declType, null, isStatic);
-
-                    fieldType = resolveGenericsWithContext(placeholders, 
fieldType);
+                FieldNode fieldNode = (FieldNode) variable;
+                ClassNode fieldType = fieldNode.getOriginType();
+                if (!fieldNode.isStatic() && 
GenericsUtils.hasUnresolvedGenerics(fieldType)) {
+                    ClassNode declType = fieldNode.getDeclaringClass(), 
thisType = typeCheckingContext.getEnclosingClassNode();
+                    fieldType = 
resolveGenericsWithContext(extractPlaceHolders(thisType, declType), fieldType);
                 }
                 return fieldType;
             }
@@ -5278,9 +5274,8 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
             return inferReturnTypeGenerics(receiver, extension, args, 
explicitTypeHints);
         }
 
-        // TODO: remove name conflicts from context before applying to method 
generics or parameters
         Map<GenericsTypeName, GenericsType> context = method.isStatic() || 
method instanceof ConstructorNode
-                                            ? null : extractPlaceHolders(null, 
receiver, getDeclaringClass(method, arguments));
+                                            ? null : 
extractPlaceHoldersVisibleToDeclaration(receiver, method, arguments);
         GenericsType[] methodGenericTypes = method instanceof ConstructorNode 
? method.getDeclaringClass().getGenericsTypes() : applyGenericsContext(context, 
method.getGenericsTypes());
 
         // 1) resolve type parameters of method
@@ -5590,21 +5585,6 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         return getInferredTypeFromTempInfo(expression, declaredOrInferred);
     }
 
-    private static ClassNode getDeclaringClass(final MethodNode method, final 
Expression arguments) {
-        ClassNode declaringClass = method.getDeclaringClass();
-
-        // correcting declaring class for extension methods:
-        if (arguments instanceof ArgumentListExpression) {
-            ArgumentListExpression al = (ArgumentListExpression) arguments;
-            List<Expression> list = al.getExpressions();
-            if (list.isEmpty()) return declaringClass;
-            Expression exp = list.get(0);
-            ClassNode cn = 
exp.getNodeMetaData(ExtensionMethodDeclaringClass.class);
-            if (cn != null) return cn;
-        }
-        return declaringClass;
-    }
-
     private static class ExtensionMethodDeclaringClass {
     }
 
@@ -5629,64 +5609,45 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         return cn.isGenericsPlaceHolder();
     }
 
-    private static Map<GenericsTypeName, GenericsType> 
resolvePlaceHoldersFromDeclaration(final ClassNode receiver, final ClassNode 
declaration, final MethodNode method, final boolean isStaticTarget) {
-        Map<GenericsTypeName, GenericsType> resolvedPlaceholders;
-        if (isStaticTarget
-                && isClassType(receiver)
-                && receiver.getGenericsTypes() != null
-                && receiver.getGenericsTypes().length > 0
-                && !isObjectType(receiver.getGenericsTypes()[0].getType())) {
-            return 
resolvePlaceHoldersFromDeclaration(receiver.getGenericsTypes()[0].getType(), 
declaration, method, isStaticTarget);
-        } else {
-            resolvedPlaceholders = extractPlaceHolders(method, receiver, 
declaration);
-        }
-        return resolvedPlaceholders;
-    }
-
-    private static Map<GenericsTypeName, GenericsType> 
extractPlaceHolders(final MethodNode method, ClassNode receiver, final 
ClassNode declaringClass) {
-        Map<GenericsTypeName, GenericsType> resolvedPlaceHolders = null;
-        if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
-            receiver = getWrapper(receiver);
-        }
+    private static Map<GenericsTypeName, GenericsType> 
extractPlaceHolders(final ClassNode receiver, final ClassNode declaringClass) {
+        Map<GenericsTypeName, GenericsType> result = null;
         ClassNode[] todo;
         if (receiver instanceof UnionTypeClassNode) {
             todo = ((UnionTypeClassNode) receiver).getDelegates();
         } else {
-            todo = new ClassNode[] {receiver};
+            todo = new ClassNode[] {!isPrimitiveType(declaringClass) ? 
wrapTypeIfNecessary(receiver) : receiver};
         }
         for (ClassNode type : todo) {
             ClassNode current = type;
             while (current != null) {
-                Map<GenericsTypeName, GenericsType> currentPlaceHolders = new 
HashMap<>();
+                Map<GenericsTypeName, GenericsType> placeHolders = new 
HashMap<>();
                 // GROOVY-10055: handle diamond or raw
                 if (current.getGenericsTypes() != null
                         ? current.getGenericsTypes().length == 0
                         : current.redirect().getGenericsTypes() != null) {
                     for (GenericsType gt : 
current.redirect().getGenericsTypes()) {
                         ClassNode cn = gt.getUpperBounds() != null ? 
gt.getUpperBounds()[0] : gt.getType().redirect();
-                        currentPlaceHolders.put(new 
GenericsTypeName(gt.getName()), cn.getPlainNodeReference().asGenericsType());
+                        placeHolders.put(new GenericsTypeName(gt.getName()), 
cn.getPlainNodeReference().asGenericsType());
                     }
                 }
 
                 boolean currentIsDeclaring = current.equals(declaringClass) || 
isGenericsPlaceHolderOrArrayOf(declaringClass);
                 if (currentIsDeclaring) {
-                    extractGenericsConnections(currentPlaceHolders, current, 
declaringClass);
-                    if (method != null)
-                        addMethodLevelDeclaredGenerics(method, 
currentPlaceHolders);
+                    extractGenericsConnections(placeHolders, current, 
declaringClass);
                 } else {
-                    GenericsUtils.extractPlaceholders(current, 
currentPlaceHolders);
+                    GenericsUtils.extractPlaceholders(current, placeHolders);
                 }
 
-                if (resolvedPlaceHolders != null) { // merge maps
-                    for (Map.Entry<GenericsTypeName, GenericsType> entry : 
currentPlaceHolders.entrySet()) {
+                if (result != null) { // merge maps
+                    for (Map.Entry<GenericsTypeName, GenericsType> entry : 
placeHolders.entrySet()) {
                         GenericsType gt = entry.getValue();
                         if (!gt.isPlaceholder()) continue;
-                        GenericsType referenced = resolvedPlaceHolders.get(new 
GenericsTypeName(gt.getName()));
+                        GenericsType referenced = result.get(new 
GenericsTypeName(gt.getName()));
                         if (referenced == null) continue;
                         entry.setValue(referenced);
                     }
                 }
-                resolvedPlaceHolders = currentPlaceHolders;
+                result = placeHolders;
 
                 // we are done if we are now in the declaring class
                 if (currentIsDeclaring) break;
@@ -5697,42 +5658,68 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                     // the actual receiver is Foo and declaringClass is Class
                     current = declaringClass;
                 } else {
-                    current = applyGenericsContext(currentPlaceHolders, 
current);
+                    current = applyGenericsContext(placeHolders, current);
                 }
             }
         }
-        if (resolvedPlaceHolders == null) {
-            throw new GroovyBugError("Declaring class for method call to '" + 
(method != null ? method.getTypeDescriptor() : "<>") +
-                    "' declared in " + declaringClass.getName() + " was not 
matched with found receiver " + receiver.getName() + ". This should not have 
happened!");
+        if (result == null) {
+            throw new GroovyBugError("Declaring class " + 
prettyPrintTypeName(declaringClass) + " was not matched with receiver " + 
prettyPrintTypeName(receiver) + ". This should not have happened!");
         }
-        return resolvedPlaceHolders;
+        return result;
+    }
+
+    private static Map<GenericsTypeName, GenericsType> 
extractPlaceHoldersVisibleToDeclaration(final ClassNode receiver, final 
MethodNode method, final Expression argument) {
+        Map<GenericsTypeName, GenericsType> result;
+        if (method.isStatic()) {
+            result = new HashMap<>();
+        } else {
+            ClassNode declaring = method.getDeclaringClass();
+            if (argument instanceof ArgumentListExpression) { // resolve 
extension method class
+                List<Expression> arguments = ((ArgumentListExpression) 
argument).getExpressions();
+                if (!arguments.isEmpty()) {
+                    ClassNode cn = 
arguments.get(0).getNodeMetaData(ExtensionMethodDeclaringClass.class);
+                    if (cn != null)
+                        declaring = cn;
+                }
+            }
+            result = extractPlaceHolders(receiver, declaring);
+            if (!result.isEmpty()) 
Optional.ofNullable(method.getGenericsTypes()).ifPresent(methodGenerics ->
+                Arrays.stream(methodGenerics).map(gt -> new 
GenericsTypeName(gt.getName())).forEach(result::remove)); // GROOVY-10322
+        }
+        return result;
     }
 
     protected boolean typeCheckMethodsWithGenericsOrFail(final ClassNode 
receiver, final ClassNode[] arguments, final MethodNode candidateMethod, final 
Expression location) {
         if (!typeCheckMethodsWithGenerics(receiver, arguments, 
candidateMethod)) {
-            Map<GenericsTypeName, GenericsType> generics = 
GenericsUtils.extractPlaceholders(receiver);
-            
applyGenericsConnections(extractGenericsParameterMapOfThis(typeCheckingContext),
 generics);
-            addMethodLevelDeclaredGenerics(candidateMethod, generics);
-            Parameter[] parameters = candidateMethod.getParameters();
+            ClassNode r = receiver, at[] = arguments; MethodNode m = 
candidateMethod;
+            if (candidateMethod instanceof ExtensionMethodNode) {
+                m = ((ExtensionMethodNode) 
candidateMethod).getExtensionMethodNode();
+                r = m.getDeclaringClass();
+                at = new ClassNode[arguments.length + 1];
+                at[0] = receiver; // object expression is first argument
+                System.arraycopy(arguments, 0, at, 1, arguments.length);
+            }
+            Map<GenericsTypeName, GenericsType> spec = 
extractPlaceHoldersVisibleToDeclaration(r, m, null);
+            GenericsType[] gt = applyGenericsContext(spec, 
m.getGenericsTypes()); // class params in bounds
+            GenericsUtils.extractPlaceholders(makeClassSafe0(OBJECT_TYPE, gt), 
spec);
+
+            Parameter[] parameters = m.getParameters();
             ClassNode[] paramTypes = new ClassNode[parameters.length];
             for (int i = 0, n = parameters.length; i < n; i += 1) {
-                paramTypes[i] = fullyResolveType(parameters[i].getType(), 
generics);
+                paramTypes[i] = fullyResolveType(parameters[i].getType(), 
spec);
                 // GROOVY-10010: check for List<String> parameter and 
["foo","$bar"] argument
-                if (i < arguments.length && 
hasGStringStringError(paramTypes[i], arguments[i], location)) {
+                if (i < at.length && hasGStringStringError(paramTypes[i], 
at[i], location)) {
                     return false;
                 }
             }
-            addStaticTypeError("Cannot call " + 
toMethodGenericTypesString(candidateMethod) + prettyPrintTypeName(receiver) + 
"#" +
-                    toMethodParametersString(candidateMethod.getName(), 
paramTypes) + " with arguments " + formatArgumentList(arguments), location);
+
+            addStaticTypeError("Cannot call " + 
Optional.ofNullable(gt).map(GenericsUtils::toGenericTypesString).orElse("") +
+                    prettyPrintTypeName(r) + "#" + 
toMethodParametersString(m.getName(), paramTypes) + " with arguments " + 
formatArgumentList(at), location);
             return false;
         }
         return true;
     }
 
-    private static String toMethodGenericTypesString(final MethodNode node) {
-        return 
Optional.ofNullable(node.getGenericsTypes()).map(GenericsUtils::toGenericTypesString).orElse("");
-    }
-
     protected static String formatArgumentList(final ClassNode[] nodes) {
         if (nodes == null || nodes.length == 0) return "[]";
 
diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy 
b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index f375092..8de032e 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -583,7 +583,8 @@ class ArraysAndCollectionsSTCTest extends 
StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             String[] arr = ['abc']
             arr.putAt(0, new Object())
-        ''', 'Cannot call <T,U extends T> java.lang.String[]#putAt(int, U) 
with arguments [int, java.lang.Object]'
+        ''',
+        '#putAt(T[], int, U) with arguments [java.lang.String[], int, 
java.lang.Object]'
     }
 
     void testStringArrayPutWithSubType() {
@@ -604,7 +605,8 @@ class ArraysAndCollectionsSTCTest extends 
StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             Serializable[] arr = ['abc']
             arr.putAt(0, new groovy.xml.XmlSlurper())
-        ''', 'Cannot call <T,U extends T> java.io.Serializable[]#putAt(int, U) 
with arguments [int, groovy.xml.XmlSlurper]'
+        ''',
+        '#putAt(T[], int, U) with arguments [java.io.Serializable[], int, 
groovy.xml.XmlSlurper]'
     }
 
     void testArrayGetOnPrimitiveArray() {
diff --git a/src/test/groovy/transform/stc/DefaultGroovyMethodsSTCTest.groovy 
b/src/test/groovy/transform/stc/DefaultGroovyMethodsSTCTest.groovy
index 6192bba..5b2a702 100644
--- a/src/test/groovy/transform/stc/DefaultGroovyMethodsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/DefaultGroovyMethodsSTCTest.groovy
@@ -114,8 +114,8 @@ class DefaultGroovyMethodsSTCTest extends 
StaticTypeCheckingTestCase {
             numbers.sequence
             numbers.string
         ''',
-        'Cannot call <CS extends java.lang.CharSequence> 
java.util.ArrayList#getSequence() with arguments []',
-        'Cannot call java.util.ArrayList#getString() with arguments []',
+        '#getSequence(java.util.List<CS extends java.lang.CharSequence>) with 
arguments [java.util.ArrayList<java.lang.Number>]',
+        '#getString(java.util.List<java.lang.String>) with arguments 
[java.util.ArrayList<java.lang.Number>]',
         'No such property: sequence for class: java.util.ArrayList',
         'No such property: string for class: java.util.ArrayList'
     }
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy 
b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 0669a23..1a8d7fd 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -41,21 +41,24 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     void testDeclaration3() {
         shouldFailWithMessages '''
             Map<String,String> obj = new HashMap<String,Integer>()
-        ''', 'Incompatible generic argument types. Cannot assign 
java.util.HashMap<java.lang.String, java.lang.Integer> to: 
java.util.Map<java.lang.String, java.lang.String>'
+        ''',
+        'Incompatible generic argument types. Cannot assign 
java.util.HashMap<java.lang.String, java.lang.Integer> to: 
java.util.Map<java.lang.String, java.lang.String>'
     }
 
     void testDeclaration4() {
         // no generics checked after first wildcard
         shouldFailWithMessages '''
             Map<? extends CharSequence,String> obj = new 
HashMap<String,Integer>()
-        ''', 'Incompatible generic argument types. Cannot assign 
java.util.HashMap<java.lang.String, java.lang.Integer> to: java.util.Map<? 
extends java.lang.CharSequence, java.lang.String>'
+        ''',
+        'Incompatible generic argument types. Cannot assign 
java.util.HashMap<java.lang.String, java.lang.Integer> to: java.util.Map<? 
extends java.lang.CharSequence, java.lang.String>'
     }
 
     void testAddOnList() {
         shouldFailWithMessages '''
             List<String> list = []
             list.add(1)
-        ''', "[Static type checking] - Cannot find matching method 
java.util.ArrayList#add(int)"
+        ''',
+        'Cannot find matching method java.util.ArrayList#add(int)'
     }
 
     void testAddOnList2() {
@@ -81,7 +84,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             List<String> list = []
             list << 1
-        ''', 'Cannot call <T> java.util.ArrayList#leftShift(T) with arguments 
[int]'
+        ''',
+        'Cannot call <T> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#leftShift(java.util.List<T>, 
T) with arguments [java.util.ArrayList<java.lang.String>, int]'
     }
 
     void testAddOnList2UsingLeftShift() {
@@ -129,14 +133,16 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             List<Integer> list = new LinkedList<>()
             list.add 'Hello'
-        ''', 'Cannot find matching method 
java.util.LinkedList#add(java.lang.String). Please check if the declared type 
is correct and if the method exists.'
+        ''',
+        'Cannot find matching method 
java.util.LinkedList#add(java.lang.String). Please check if the declared type 
is correct and if the method exists.'
     }
 
     void testAddOnListWithDiamondAndWrongTypeUsingLeftShift() {
         shouldFailWithMessages '''
             List<Integer> list = new LinkedList<>()
             list << 'Hello'
-        ''', 'Cannot call <T> java.util.LinkedList#leftShift(T) with arguments 
[java.lang.String]'
+        ''',
+        'Cannot call <T> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#leftShift(java.util.List<T>, 
T) with arguments [java.util.LinkedList<java.lang.Integer>, java.lang.String]'
     }
 
     void testAddOnListWithDiamondAndNullUsingLeftShift() {
@@ -234,7 +240,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             Number number = Optional.of(42).orElse(Double.NaN)
             assert number.intValue() == 42
-        ''', '[Static type checking] - Cannot find matching method 
java.util.Optional#orElse(double).'
+        ''',
+        'Cannot find matching method java.util.Optional#orElse(double).'
     }
 
     void testReturnTypeInferenceWithMethodGenerics5() {
@@ -249,7 +256,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
             Number number = Optional.ofNullable((Integer) null).orElse(42d)
             assert number.intValue() == 42
-        ''', '[Static type checking] - Cannot find matching method 
java.util.Optional#orElse(double).'
+        ''',
+        'Cannot find matching method java.util.Optional#orElse(double).'
     }
 
     void testReturnTypeInferenceWithMethodGenerics7() {
@@ -267,7 +275,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
               x.add(new Object())
               return x // List<E>
             }
-        ''', 'Incompatible generic argument types.' // Cannot assign 
java.util.List<java.lang.Object> to: java.util.List<java.lang.String>
+        ''',
+        'Incompatible generic argument types.' // Cannot assign 
java.util.List<java.lang.Object> to: java.util.List<java.lang.String>
 
         assertScript '''
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -738,11 +747,13 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             class D implements I { }
 
             A<String> ax = new C<>(new D())
-        ''', 'Incompatible generic argument types. Cannot assign C<D> to: 
A<java.lang.String>'
+        ''',
+        'Incompatible generic argument types. Cannot assign C<D> to: 
A<java.lang.String>'
 
         shouldFailWithMessages '''
             Set<List<String>> strings = new HashSet<>([new 
ArrayList<Number>()])
-        ''', 'Incompatible generic argument types. Cannot assign 
java.util.HashSet<java.util.ArrayList<java.lang.Number>> to: 
java.util.Set<java.util.List<java.lang.String>>'
+        ''',
+        'Incompatible generic argument types. Cannot assign 
java.util.HashSet<java.util.ArrayList<java.lang.Number>> to: 
java.util.Set<java.util.List<java.lang.String>>'
     }
 
     // GROOVY-9972
@@ -831,7 +842,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             def foo = { flag, C<D> cd = (flag ? new C<>(new D()) : new C<>(new 
Object())) ->
                 cd.p.f.toLowerCase()
             }
-        ''', 'Incompatible generic argument types. Cannot assign C<? extends 
java.lang.Object> to: C<D>'
+        ''',
+        'Incompatible generic argument types. Cannot assign C<? extends 
java.lang.Object> to: C<D>'
     }
 
     // GROOVY-9963
@@ -1102,7 +1114,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     void testLinkedListWithListArgumentAndWrongElementTypes() {
         shouldFailWithMessages '''
             List<String> list = new LinkedList<String>([1,2,3])
-        ''', 'Cannot call java.util.LinkedList#<init>(java.util.Collection<? 
extends java.lang.String>) with arguments [java.util.List<java.lang.Integer>]'
+        ''',
+        'Cannot call java.util.LinkedList#<init>(java.util.Collection<? 
extends java.lang.String>) with arguments [java.util.List<java.lang.Integer>]'
     }
 
     void testGenericAssignmentWithSubClass() {
@@ -1114,7 +1127,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     void testGenericAssignmentWithSubClassAndWrongGenericType() {
         shouldFailWithMessages '''
             List<Integer> list = new 
groovy.transform.stc.GenericsSTCTest.MyList()
-        ''', 'Incompatible generic argument types'
+        ''',
+        'Incompatible generic argument types'
     }
 
     void testAddShouldBeAllowedOnUncheckedGenerics() {
@@ -1130,7 +1144,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     void testAssignmentShouldFailBecauseOfLowerBound() {
         shouldFailWithMessages '''
             List<? super Number> list = ['string']
-        ''', 'Number'
+        ''',
+        'Cannot assign java.util.ArrayList<java.lang.String> to: 
java.util.List<? super java.lang.Number>'
     }
 
     // GROOVY-9914, GROOVY-10036
@@ -1292,7 +1307,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             class FooBound {
             }
             new Foo()
-        ''', 'Cannot find matching method 
FooWithGenerics#say(java.lang.Object)'
+        ''',
+        'Cannot find matching method FooWithGenerics#say(java.lang.Object)'
     }
 
     // GROOVY-5237
@@ -1414,7 +1430,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
 
             A<String, Integer> a = new B()
             a.test()
-        ''', 'Cannot call A#<init>(java.lang.Class<java.lang.String>, 
java.lang.Class<java.lang.Integer>) with arguments 
[java.lang.Class<java.lang.Integer>, java.lang.Class<java.lang.String>]'
+        ''',
+        'Cannot call A#<init>(java.lang.Class<java.lang.String>, 
java.lang.Class<java.lang.Integer>) with arguments 
[java.lang.Class<java.lang.Integer>, java.lang.Class<java.lang.String>]'
     }
 
     // GROOVY-9460
@@ -1486,7 +1503,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             def map = new HashMap<String, Integer>()
             map['hello'] = new Object()
         ''',
-        'Cannot call <K,V> java.util.HashMap#putAt(java.lang.String, 
java.lang.Integer) with arguments [java.lang.String, java.lang.Object]'
+        'Cannot call <K,V> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, 
V) with arguments [java.util.HashMap<java.lang.String, java.lang.Integer>, 
java.lang.String, java.lang.Object]'
     }
 
     // GROOVY-9069
@@ -1496,15 +1513,14 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             }
             void test(Map<String, Map<String, List<String>>> maps) {
                 maps.each { String key, Map<String, List<String>> map ->
-                    Map<String, List<ConfigAttribute>> value = [:] // Why 
"List<ConfigAttribute>"?
-                    // populate value
-                    maps[key] = value
+                    Map<String, List<ConfigAttribute>> value = [:]
                     maps.put(key, value)
+                    maps[key] = value
                 }
             }
         ''',
-        'Cannot call <K,V> java.util.Map#putAt(java.lang.String, 
java.util.Map<java.lang.String, java.util.List<java.lang.String>>) with 
arguments [java.lang.String, java.util.LinkedHashMap<java.lang.String, 
java.util.List<ConfigAttribute>>]',
-        'Cannot find matching method java.util.Map#put(java.lang.String, 
java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>). 
Please check if the declared type is correct and if the method exists.'
+        'Cannot find matching method java.util.Map#put(java.lang.String, 
java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>). 
Please check if the declared type is correct and if the method exists.',
+        'Cannot call <K,V> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, 
V) with arguments [java.util.Map<java.lang.String, 
java.util.Map<java.lang.String, java.util.List<java.lang.String>>>, 
java.lang.String, java.util.LinkedHashMap<java.lang.String, 
java.util.List<ConfigAttribute>>]'
     }
 
     void testPutAtMethodWithWrongValueType3() {
@@ -1521,7 +1537,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     }
 
     void testShouldComplainAboutToInteger() {
-        String code = '''
+        shouldFailWithMessages '''
             class Test {
                 static test2() {
                     if (new Random().nextBoolean()) {
@@ -1542,11 +1558,9 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
                 }
             }
             new Test()
-        '''
-
-        shouldFailWithMessages code,
-                'Cannot find matching method java.lang.Object#getAt(int)',
-                'Cannot find matching method java.lang.Object#toInteger()'
+        ''',
+        'Cannot find matching method java.lang.Object#getAt(int)',
+        'Cannot find matching method java.lang.Object#toInteger()'
     }
 
     void testAssignmentOfNewInstance() {
@@ -1586,7 +1600,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             }
         }
         new ClassB()
-        ''', 'Cannot call <X> 
groovy.transform.stc.GenericsSTCTest$ClassA#bar(java.lang.Class<java.lang.Long>)
 with arguments [java.lang.Class<? extends java.lang.Object>]'
+        ''',
+        'Cannot call <X> 
groovy.transform.stc.GenericsSTCTest$ClassA#bar(java.lang.Class<java.lang.Long>)
 with arguments [java.lang.Class<? extends java.lang.Object>]'
     }
 
     // GROOVY-8961, GROOVY-9915
@@ -1623,7 +1638,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 void test() {
                     x = Collections.<Integer>emptyList()
                 }
-            """, 'Incompatible generic argument types. Cannot assign 
java.util.List<java.lang.Integer> to: java.util.List<java.lang.String>'
+            """,
+            'Incompatible generic argument types. Cannot assign 
java.util.List<java.lang.Integer> to: java.util.List<java.lang.String>'
         }
     }
 
@@ -1893,7 +1909,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             List<String> list = ['a','b','c']
             Collection<Integer> numbers = (Collection<Integer>) [1,2,3]
             boolean r = list.addAll(numbers)
-        ''', 'Cannot call java.util.ArrayList#addAll(java.util.Collection<? 
extends java.lang.String>) with arguments 
[java.util.Collection<java.lang.Integer>]'
+        ''',
+        'Cannot call java.util.ArrayList#addAll(java.util.Collection<? extends 
java.lang.String>) with arguments [java.util.Collection<java.lang.Integer>]'
     }
 
     // GROOVY-5528
@@ -1924,7 +1941,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 assert 
node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
             })
             List<String> list = ["foo", "$bar"]
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
 
         shouldFailWithMessages base + '''
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -1932,12 +1950,14 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
                 assert 
node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type == GSTRING_TYPE // 
single element means no LUB
             })
             List<String> list = ["$bar"]
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
 
         shouldFailWithMessages base + '''
             void m(List<String> list) {}
             m(["foo", "$bar"])
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
     }
 
     // GROOVY-5559, GROOVY-10010
@@ -1946,17 +1966,20 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
 
         shouldFailWithMessages base + '''
             Map<String,String> map = [x:"foo", y:"$bar"]
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
 
         shouldFailWithMessages base + '''
             void m(Map<?,String> map) {}
             m([x:"foo", y:"$bar"])
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
 
         shouldFailWithMessages base + '''
             void m(Map<?,String> map) {}
             m(x:"foo", y:"$bar")
-        ''', 'You are trying to use a GString in place of a String'
+        ''',
+        'You are trying to use a GString in place of a String'
     }
 
     // GROOVY-5559: related behaviour
@@ -2068,7 +2091,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     void testInferDiamondUsingAIC() {
         shouldFailWithMessages '''
             Map<String,Date> map = new HashMap<>() {}
-        ''', 'Cannot use diamond <> with anonymous inner classes'
+        ''',
+        'Cannot use diamond <> with anonymous inner classes'
     }
 
     // GROOVY-5614
@@ -2155,7 +2179,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             })
             Map<Date, Date> map = new HashMap<>()
             map.put('foo', new Date())
-        ''', '[Static type checking] - Cannot find matching method 
java.util.HashMap#put(java.lang.String, java.util.Date). Please check if the 
declared type is correct and if the method exists.'
+        ''',
+        'Cannot find matching method java.util.HashMap#put(java.lang.String, 
java.util.Date). Please check if the declared type is correct and if the method 
exists.'
     }
     void 
testInferDiamondForAssignmentWithDatesAndIllegalKeyUsingSquareBracket() {
         shouldFailWithMessages '''
@@ -2174,7 +2199,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             })
             Map<Date, Date> map = new HashMap<>()
             map['foo'] = new Date()
-        ''', 'Cannot call <K,V> java.util.HashMap#putAt(java.util.Date, 
java.util.Date) with arguments [java.lang.String, java.util.Date]'
+        ''',
+        'Cannot call <K,V> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, 
V) with arguments [java.util.HashMap<java.util.Date, java.util.Date>, 
java.lang.String, java.util.Date]'
     }
     void testInferDiamondForAssignmentWithDatesAndIllegalValueUsingPut() {
         shouldFailWithMessages '''
@@ -2193,7 +2219,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             })
             Map<Date, Date> map = new HashMap<>()
             map.put(new Date(), 'foo')
-        ''', '[Static type checking] - Cannot find matching method 
java.util.HashMap#put(java.util.Date, java.lang.String). Please check if the 
declared type is correct and if the method exists.'
+        ''',
+        'Cannot find matching method java.util.HashMap#put(java.util.Date, 
java.lang.String). Please check if the declared type is correct and if the 
method exists.'
     }
     void 
testInferDiamondForAssignmentWithDatesAndIllegalValueUsingSquareBracket() {
         shouldFailWithMessages '''
@@ -2212,21 +2239,22 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             })
             Map<Date, Date> map = new HashMap<>()
             map[new Date()] = 'foo'
-        ''', 'Cannot call <K,V> java.util.HashMap#putAt(java.util.Date, 
java.util.Date) with arguments [java.util.Date, java.lang.String]'
+        ''',
+        'Cannot call <K,V> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, 
V) with arguments [java.util.HashMap<java.util.Date, java.util.Date>, 
java.util.Date, java.lang.String]'
     }
 
     void testCallMethodWithParameterizedArrayList() {
         assertScript '''
-        class MyUtility {
-            def methodOne() {
-                def someFiles = new ArrayList<File>()
-                def someString = ''
-                methodTwo someString, someFiles
-            }
+            class MyUtility {
+                def methodOne() {
+                    def someFiles = new ArrayList<File>()
+                    def someString = ''
+                    methodTwo someString, someFiles
+                }
 
-            def methodTwo(String s, List<File> files) {}
-        }
-        new MyUtility()
+                def methodTwo(String s, List<File> files) {}
+            }
+            new MyUtility()
         '''
     }
 
@@ -2240,35 +2268,35 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-5617
     void testIntermediateListAssignmentOfGStrings() {
         assertScript '''
-        def test() {
-            @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def type = node.getNodeMetaData(INFERRED_TYPE)
-                assert type.implementsInterface(LIST_TYPE)
-                assert type.genericsTypes.length == 1
-                assert type.genericsTypes[0].type == GSTRING_TYPE
-            })
-            List<GString> dates = ["${new Date()-1}", "${new Date()}", "${new 
Date()+1}"]
-            dates*.toUpperCase()
-            @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def type = node.getNodeMetaData(INFERRED_TYPE)
-                assert type.implementsInterface(LIST_TYPE)
-                assert type.genericsTypes.length == 1
-                assert type.genericsTypes[0].type == GSTRING_TYPE
-            })
-            List<GString> copied = []
-            copied.addAll(dates)
-            List<String> upper = copied*.toUpperCase()
-        }
-        test()
+            def test() {
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                    def type = node.getNodeMetaData(INFERRED_TYPE)
+                    assert type.implementsInterface(LIST_TYPE)
+                    assert type.genericsTypes.length == 1
+                    assert type.genericsTypes[0].type == GSTRING_TYPE
+                })
+                List<GString> dates = ["${new Date()-1}", "${new Date()}", 
"${new Date()+1}"]
+                dates*.toUpperCase()
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                    def type = node.getNodeMetaData(INFERRED_TYPE)
+                    assert type.implementsInterface(LIST_TYPE)
+                    assert type.genericsTypes.length == 1
+                    assert type.genericsTypes[0].type == GSTRING_TYPE
+                })
+                List<GString> copied = []
+                copied.addAll(dates)
+                List<String> upper = copied*.toUpperCase()
+            }
+            test()
         '''
     }
 
     // GROOVY-5650
     void testRegressionInGenericsTypeInference() {
         assertScript '''import 
groovy.transform.stc.GenericsSTCTest.JavaClassSupport as JavaClass
-        List<JavaClass.StringContainer> containers = new ArrayList<>();
-        containers.add(new JavaClass.StringContainer());
-        List<String> strings = JavaClass.unwrap(containers);
+            List<JavaClass.StringContainer> containers = new ArrayList<>();
+            containers.add(new JavaClass.StringContainer());
+            List<String> strings = JavaClass.unwrap(containers);
         '''
     }
 
@@ -2544,14 +2572,14 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-5735
     void testCorrespondingParameterType() {
         assertScript '''
-        public <T> void someMethod (java.lang.Class<T> clazz, T object) {}
+            public <T> void someMethod (java.lang.Class<T> clazz, T object) {}
 
-        void method() {
-            List<String> list = null
-            someMethod(java.util.List.class, list)
-        }
+            void method() {
+                List<String> list = null
+                someMethod(java.util.List.class, list)
+            }
 
-        method()
+            method()
         '''
     }
 
@@ -2696,7 +2724,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 static <T extends List<? extends CharSequence>> void bar(T a) 
{}
             }
             Foo.bar([new Object()])
-        ''', 'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.Object>]'
+        ''',
+        'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.Object>]'
     }
 
     void testOutOfBoundsBySuperGenericParameterType() {
@@ -2705,7 +2734,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 static <T extends List<? super CharSequence>> void bar(T a) {}
             }
             Foo.bar(['abc'])
-        ''', 'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.String>]'
+        ''',
+        'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.String>]'
     }
 
     void testOutOfBoundsByExtendsPlaceholderParameterType() {
@@ -2716,7 +2746,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             def <U extends List<Object>> void baz(U list) {
                 Foo.bar(list)
             }
-        ''', 'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
+        ''',
+        'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
     }
 
     void testOutOfBoundsBySuperPlaceholderParameterType() {
@@ -2727,37 +2758,37 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             def <U extends List<String>> void baz(U list) {
                 Foo.bar(list)
             }
-        ''', 'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
+        ''',
+        'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
     }
 
     // GROOVY-5721
     void testExtractComponentTypeFromSubclass() {
         assertScript '''
-        class MyList extends ArrayList<Double> {}
+            class MyList extends ArrayList<Double> {}
 
-        List<Double> list1 = new ArrayList<Double>()
-        list1 << 0.0d
+            List<Double> list1 = new ArrayList<Double>()
+            list1 << 0.0d
 
-        // OK
-        Double d1 = list1.get(0)
+            // OK
+            Double d1 = list1.get(0)
 
-        //---------------------------
+            //---------------------------
 
-        List<Double> list2 = new MyList()
-        list2 << 0.0d
+            List<Double> list2 = new MyList()
+            list2 << 0.0d
 
-        //Groovyc: [Static type checking] - Cannot assign value of type 
java.lang.Object to variable of type java.lang.Double
-        Double d2 = list2.get(0)
+            //Groovyc: [Static type checking] - Cannot assign value of type 
java.lang.Object to variable of type java.lang.Double
+            Double d2 = list2.get(0)
 
-        //---------------------------
+            //---------------------------
 
-        MyList list3 = new MyList()
-        list3 << 0.0d
+            MyList list3 = new MyList()
+            list3 << 0.0d
 
-        //Groovyc: [Static type checking] - Cannot assign value of type 
java.lang.Object to variable of type java.lang.Double
-        Double d3 = list3.get(0)
+            //Groovyc: [Static type checking] - Cannot assign value of type 
java.lang.Object to variable of type java.lang.Double
+            Double d3 = list3.get(0)
         '''
-
     }
 
     // GROOVY-5724
@@ -2884,9 +2915,22 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
         '''
     }
 
-    // GROOVY-10337
+    // GROOVY-10322
     void testShouldFindMethodEvenWithRepeatNames4() {
         assertScript '''
+            class C<T> {
+                def <T> T m(T t) { // this T hides T from C<T>
+                    return t
+                }
+            }
+            int x = new C<String>().m(1) // no error, param and return types 
are `int` not `String`
+            assert x == 1
+        '''
+    }
+
+    // GROOVY-10337
+    void testShouldFindMethodEvenWithRepeatNames5() {
+        assertScript '''
             class C<X,Y> {
                 C(C<Y,? extends Y> that) {
                 }
@@ -3041,62 +3085,55 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-6051
     void testGenericsReturnTypeInferenceShouldNotThrowNPE() {
         assertScript '''
-        class Bar {
-          public static List<Date> bar(List<Date> dummy) {}
-        }
-        class Foo extends Bar {
-            static public Date genericItem() {
-                @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                    def inft = node.getNodeMetaData(INFERRED_TYPE)
-                    assert inft == make(List)
-                    assert inft.genericsTypes[0].type == make(Date)
-                })
-                def res = bar(null)
+            class Bar {
+              public static List<Date> bar(List<Date> dummy) {}
+            }
+            class Foo extends Bar {
+                static public Date genericItem() {
+                    @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                        def inft = node.getNodeMetaData(INFERRED_TYPE)
+                        assert inft == make(List)
+                        assert inft.genericsTypes[0].type == make(Date)
+                    })
+                    def res = bar(null)
 
-                res[0]
+                    res[0]
+                }
             }
-        }
-        new Foo()
+            new Foo()
         '''
     }
 
     // GROOVY-6035
     void testReturnTypeInferenceWithClosure() {
         assertScript '''import org.codehaus.groovy.ast.expr.ClosureExpression
-        class CTypeTest {
-
-          public static void test1(String[] args) {
-
-            // Cannot assign value of type java.lang.Object to variable of 
type CTypeTest
-            @ASTTest(phase=INSTRUCTION_SELECTION,value={
-                def cl = node.rightExpression.arguments[0]
-                assert cl instanceof ClosureExpression
-                def type = cl.getNodeMetaData(INFERRED_TYPE)
-                assert type == make(Closure)
-                assert type.isUsingGenerics()
-                assert type.genericsTypes
-                assert type.genericsTypes[0].type.name == 'CTypeTest'
-
-                type = node.getNodeMetaData(INFERRED_TYPE)
-                assert type.name == 'CTypeTest'
-            })
-            def s1 = cache  {
-              return new CTypeTest();
-            }
-
-            CTypeTest s2 = cache {
-                new CTypeTest()
+            class CTypeTest {
+              public static void test1(String[] args) {
+                // Cannot assign value of type java.lang.Object to variable of 
type CTypeTest
+                @ASTTest(phase=INSTRUCTION_SELECTION,value={
+                    def cl = node.rightExpression.arguments[0]
+                    assert cl instanceof ClosureExpression
+                    def type = cl.getNodeMetaData(INFERRED_TYPE)
+                    assert type == make(Closure)
+                    assert type.isUsingGenerics()
+                    assert type.genericsTypes
+                    assert type.genericsTypes[0].type.name == 'CTypeTest'
+
+                    type = node.getNodeMetaData(INFERRED_TYPE)
+                    assert type.name == 'CTypeTest'
+                })
+                def s1 = cache  {
+                  return new CTypeTest();
+                }
+                CTypeTest s2 = cache {
+                    new CTypeTest()
+                }
+              }
+              static <T> T cache(Closure<T> closure) {
+                return closure.call();
+              }
             }
-
-          }
-
-
-          static <T> T cache(Closure<T> closure) {
-            return closure.call();
-          }
-
-        }
-        1
+            1
         '''
     }
 
@@ -3117,7 +3154,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 Foo<Map> f = new Foo<Map>("a",1)
             }
             bar()
-        ''', '[Static type checking] - Cannot find matching method 
Foo#<init>(java.lang.String, int)'
+        ''',
+        'Cannot find matching method Foo#<init>(java.lang.String, int)'
     }
 
     // GROOVY-5742
@@ -3318,67 +3356,56 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
 
     // GROOVY-5839
     void testMethodShadowGenerics() {
-        shouldFailWithMessages '''
-            public class GoodCodeRed<T> {
-                Collection<GoodCodeRed<T>> attached = []
-                public <T> void attach(GoodCodeRed<T> toAttach) {
-                    attached.add(toAttach)
-                }
-                static void foo() {
-                    def g1 = new GoodCodeRed<Long>()
-                    def g2 = new GoodCodeRed<Integer>()
-                    g1.attach(g2);
+        assertScript '''
+            class C<T> {
+                Collection<C<T>> attached = []
+                def <T> void attach(C<T> toAttach) {
+                    attached.add(toAttach) // TODO: GROOVY-7719
                 }
             }
-            GoodCodeRed.foo()
-        ''',
-        'Cannot call <T> GoodCodeRed#attach(GoodCodeRed<java.lang.Long>) with 
arguments [GoodCodeRed<java.lang.Integer>]'
+            def c1 = new C<Short>()
+            def c2 = new C<Long>()
+            c1.attach(c2)
+        '''
     }
 
-    void testHiddenGenerics() {
+    void testSuperClassGenerics() {
         // GROOVY-6237
         assertScript '''
-            class MyList extends LinkedList<Object> {}
+            class MyList extends LinkedList<Object> {
+            }
             List<Object> o = new MyList()
         '''
 
         shouldFailWithMessages '''
-            class Blah {}
-            class MyList extends LinkedList<Object> {}
-            List<Blah> o = new MyList()
-        ''','Incompatible generic argument types. Cannot assign MyList to: 
java.util.List<Blah>'
+            class MyList extends LinkedList<Object> {
+            }
+            List<String> o = new MyList()
+        ''',
+        'Incompatible generic argument types. Cannot assign MyList to: 
java.util.List<java.lang.String>'
 
         // GROOVY-5873
         assertScript '''
-            abstract class Parent<T> {
+            abstract class A<T> {
                 public T value
             }
-            class Impl extends Parent<Integer> {}
-            Impl impl = new Impl()
-            Integer i = impl.value
+            class C extends A<Integer> {
+            }
+            C c = new C()
+            Integer i = c.value
         '''
 
         // GROOVY-5920
         assertScript '''
             class Data<T> {
-              T value
+                T value
             }
-
             class StringDataIterator implements Iterator<Data<String>> {
-              boolean hasNext() { true }
-              void    remove()  {}
-              Data<String> next() {
-                new Data<String>( value: 'tim' )
-              }
-            }
-
-            class Runner {
-              static main( args ) {
-                Data<String> elem = new StringDataIterator().next()
-                assert elem.value.length() == 3
-              }
+                boolean hasNext() { true }
+                Data<String> next() { new Data<String>(value: 'tim') }
             }
-            Runner.main(null);
+            Data<String> elem = new StringDataIterator().next()
+            assert elem.value.length() == 3
         '''
     }
 
@@ -3488,6 +3515,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             }
             new C1().m1(null) // the call does not really matter
         '''
+
         assertScript '''
             class Test1 {
                 static <A, B> void pair1(A a, B b) {}
@@ -3873,13 +3901,15 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             List<String> test() {
                 return [1,2,3]
             }
-        ''', 'Cannot assign java.util.ArrayList<java.lang.Integer> to: 
java.util.List<java.lang.String>'
+        ''',
+        'Cannot assign java.util.ArrayList<java.lang.Integer> to: 
java.util.List<java.lang.String>'
 
         shouldFailWithMessages '''
             List<CharSequence> test() {
                 return [1,2,3]
             }
-        ''', 'Cannot assign java.util.ArrayList<java.lang.Integer> to: 
java.util.List<java.lang.CharSequence>'
+        ''',
+        'Cannot assign java.util.ArrayList<java.lang.Integer> to: 
java.util.List<java.lang.CharSequence>'
     }
 
     // GROOVY-10295

Reply via email to