You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/12/20 17:58:14 UTC

[groovy] branch GROOVY_3_0_X updated (ca0fc53 -> f0862ff)

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

sunlan pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from ca0fc53  Move tests to fix weird exception occurred only on zulu JDK 11.0.5(ubuntu)
     new 4ad4713  minor edits
     new f0862ff  Improve back-compatibility further

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/codehaus/groovy/ast/Parameter.java    |   2 +-
 .../codehaus/groovy/control/CompilationUnit.java   |  14 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 647 ++++++++++-----------
 3 files changed, 313 insertions(+), 350 deletions(-)


[groovy] 01/02: minor edits

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4ad4713efb22acaa0a8e260e1f4a62772ef03d2b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Dec 20 11:22:16 2019 -0600

    minor edits
    
    (cherry picked from commit e921afa795e15c31a740f1e0933fbe99ccdd3691)
---
 .../java/org/codehaus/groovy/ast/Parameter.java    |   2 +-
 .../codehaus/groovy/control/CompilationUnit.java   |   9 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 647 ++++++++++-----------
 3 files changed, 308 insertions(+), 350 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/Parameter.java b/src/main/java/org/codehaus/groovy/ast/Parameter.java
index 36d4967..ce49781 100644
--- a/src/main/java/org/codehaus/groovy/ast/Parameter.java
+++ b/src/main/java/org/codehaus/groovy/ast/Parameter.java
@@ -65,7 +65,7 @@ public class Parameter extends AnnotatedNode implements Variable {
 
     public void setType(ClassNode type) {
         this.type = type;
-        dynamicTyped |= type==ClassHelper.DYNAMIC_TYPE;
+        dynamicTyped = (dynamicTyped || type == ClassHelper.DYNAMIC_TYPE);
     }
 
     public boolean hasInitialExpression() {
diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index eb75133..693baca 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -1058,10 +1058,6 @@ public class CompilationUnit extends ProcessingUnit {
     }
 
     //--------------------------------------------------------------------------
-    @Deprecated // IntelliJ IDEA depends on the API
-    public void applyToPrimaryClassNodes(final PrimaryClassNodeOperation op) throws CompilationFailedException {
-        op.doPhaseOperation(this);
-    }
 
     @Deprecated
     public void addPhaseOperation(final GroovyClassOperation op) {
@@ -1088,6 +1084,11 @@ public class CompilationUnit extends ProcessingUnit {
         addNewPhaseOperation((ISourceUnitOperation) op, phase);
     }
 
+    @Deprecated // IntelliJ IDEA depends on the API
+    public void applyToPrimaryClassNodes(final PrimaryClassNodeOperation op) throws CompilationFailedException {
+        op.doPhaseOperation(this);
+    }
+
     @Deprecated
     public abstract static class SourceUnitOperation implements ISourceUnitOperation {
     }
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 5c2823d..0184a83 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -152,9 +152,10 @@ 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}.
+ * Support methods for {@link StaticTypeCheckingVisitor}.
  */
 public abstract class StaticTypeCheckingSupport {
+
     protected static final ClassNode Matcher_TYPE = makeWithoutCaching(Matcher.class);
     protected static final ClassNode ArrayList_TYPE = makeWithoutCaching(ArrayList.class);
     protected static final ClassNode Collection_TYPE = makeWithoutCaching(Collection.class);
@@ -210,6 +211,7 @@ public abstract class StaticTypeCheckingSupport {
      * in an ambiguous method selection for similar methods.
      */
     protected static final Comparator<MethodNode> DGM_METHOD_NODE_COMPARATOR = new Comparator<MethodNode>() {
+        @Override
         public int compare(final MethodNode o1, final MethodNode o2) {
             if (o1.getName().equals(o2.getName())) {
                 Parameter[] o1ps = o1.getParameters();
@@ -243,7 +245,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param expression an expression
      * @return true for array access expressions
      */
-    protected static boolean isArrayAccessExpression(Expression expression) {
+    protected static boolean isArrayAccessExpression(final Expression expression) {
         return expression instanceof BinaryExpression && isArrayOp(((BinaryExpression) expression).getOperation().getType());
     }
 
@@ -251,18 +253,18 @@ public abstract class StaticTypeCheckingSupport {
      * Called on method call checks in order to determine if a method call corresponds to the
      * idiomatic o.with { ... } structure
      *
-     * @param name          name of the method called
-     * @param callArguments arguments of the method
+     * @param name      name of the method called
+     * @param arguments method call arguments
      * @return true if the name is "with" and arguments consist of a single closure
      */
-    public static boolean isWithCall(final String name, final Expression callArguments) {
-        boolean isWithCall = "with".equals(name) && callArguments instanceof ArgumentListExpression;
-        if (isWithCall) {
-            ArgumentListExpression argList = (ArgumentListExpression) callArguments;
-            List<Expression> expressions = argList.getExpressions();
-            isWithCall = expressions.size() == 1 && expressions.get(0) instanceof ClosureExpression;
+    public static boolean isWithCall(final String name, final Expression arguments) {
+        if ("with".equals(name) && arguments instanceof ArgumentListExpression) {
+            List<Expression> args = ((ArgumentListExpression) arguments).getExpressions();
+            if (args.size() == 1 && args.get(0) instanceof ClosureExpression) {
+                return true;
+            }
         }
-        return isWithCall;
+        return false;
     }
 
     /**
@@ -271,25 +273,26 @@ public abstract class StaticTypeCheckingSupport {
      * @param ve a variable expression
      * @return the target variable
      */
-    protected static Variable findTargetVariable(VariableExpression ve) {
-        final Variable accessedVariable = ve.getAccessedVariable() != null ? ve.getAccessedVariable() : ve;
-        if (accessedVariable != ve) {
-            if (accessedVariable instanceof VariableExpression)
+    protected static Variable findTargetVariable(final VariableExpression ve) {
+        Variable accessedVariable = ve.getAccessedVariable();
+        if (accessedVariable != null && accessedVariable != ve) {
+            if (accessedVariable instanceof VariableExpression) {
                 return findTargetVariable((VariableExpression) accessedVariable);
+            }
+            return accessedVariable;
         }
-        return accessedVariable;
+        return ve;
     }
 
-
     /**
      * @deprecated Use {@link #findDGMMethodsForClassNode(ClassLoader, ClassNode, String)} instead
      */
     @Deprecated
-    protected static Set<MethodNode> findDGMMethodsForClassNode(ClassNode clazz, String name) {
+    protected static Set<MethodNode> findDGMMethodsForClassNode(final ClassNode clazz, final String name) {
         return findDGMMethodsForClassNode(MetaClassRegistryImpl.class.getClassLoader(), clazz, name);
     }
 
-    public static Set<MethodNode> findDGMMethodsForClassNode(final ClassLoader loader, ClassNode clazz, String name) {
+    public static Set<MethodNode> findDGMMethodsForClassNode(final ClassLoader loader, final ClassNode clazz, final String name) {
         TreeSet<MethodNode> accumulator = new TreeSet<>(DGM_METHOD_NODE_COMPARATOR);
         findDGMMethodsForClassNode(loader, clazz, name, accumulator);
         return accumulator;
@@ -299,11 +302,11 @@ public abstract class StaticTypeCheckingSupport {
      * @deprecated Use {@link #findDGMMethodsForClassNode(ClassLoader, ClassNode, String, TreeSet)} instead
      */
     @Deprecated
-    protected static void findDGMMethodsForClassNode(ClassNode clazz, String name, TreeSet<MethodNode> accumulator) {
+    protected static void findDGMMethodsForClassNode(final ClassNode clazz, final String name, final TreeSet<MethodNode> accumulator) {
         findDGMMethodsForClassNode(MetaClassRegistryImpl.class.getClassLoader(), clazz, name, accumulator);
     }
 
-    protected static void findDGMMethodsForClassNode(final ClassLoader loader, ClassNode clazz, String name, TreeSet<MethodNode> accumulator) {
+    protected static void findDGMMethodsForClassNode(final ClassLoader loader, final ClassNode clazz, final String name, final TreeSet<MethodNode> accumulator) {
         List<MethodNode> fromDGM = EXTENSION_METHOD_CACHE.get(loader).get(clazz.getName());
         if (fromDGM != null) {
             for (MethodNode node : fromDGM) {
@@ -333,21 +336,19 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks that arguments and parameter types match.
      *
-     * @param params method parameters
-     * @param args   type arguments
      * @return -1 if arguments do not match, 0 if arguments are of the exact type and &gt; 0 when one or more argument is
      * not of the exact type but still match
      */
-    public static int allParametersAndArgumentsMatch(Parameter[] params, ClassNode[] args) {
-        if (params == null) {
-            params = Parameter.EMPTY_ARRAY;
+    public static int allParametersAndArgumentsMatch(Parameter[] parameters, final ClassNode[] argumentTypes) {
+        if (parameters == null) {
+            parameters = Parameter.EMPTY_ARRAY;
         }
         int dist = 0;
-        if (args.length < params.length) return -1;
+        if (argumentTypes.length < parameters.length) return -1;
         // we already know there are at least params.length elements in both arrays
-        for (int i = 0; i < params.length; i++) {
-            ClassNode paramType = params[i].getType();
-            ClassNode argType = args[i];
+        for (int i = 0; i < parameters.length; i++) {
+            ClassNode paramType = parameters[i].getType();
+            ClassNode argType = argumentTypes[i];
             if (!isAssignableTo(argType, paramType)) return -1;
             else {
                 if (!paramType.equals(argType)) dist += getDistance(argType, paramType);
@@ -360,19 +361,17 @@ public abstract class StaticTypeCheckingSupport {
      * Checks that arguments and parameter types match, expecting that the number of parameters is strictly greater
      * than the number of arguments, allowing possible inclusion of default parameters.
      *
-     * @param params method parameters
-     * @param args   type arguments
      * @return -1 if arguments do not match, 0 if arguments are of the exact type and >0 when one or more argument is
      * not of the exact type but still match
      */
-    static int allParametersAndArgumentsMatchWithDefaultParams(Parameter[] params, ClassNode[] args) {
+    static int allParametersAndArgumentsMatchWithDefaultParams(final Parameter[] parameters, final ClassNode[] argumentTypes) {
         int dist = 0;
         ClassNode ptype = null;
         // we already know the lengths are equal
-        for (int i = 0, j = 0; i < params.length; i++) {
-            Parameter param = params[i];
+        for (int i = 0, j = 0; i < parameters.length; i++) {
+            Parameter param = parameters[i];
             ClassNode paramType = param.getType();
-            ClassNode arg = j >= args.length ? null : args[j];
+            ClassNode arg = j >= argumentTypes.length ? null : argumentTypes[j];
             if (arg == null || !isAssignableTo(arg, paramType)) {
                 if (!param.hasInitialExpression() && (ptype == null || !ptype.equals(paramType))) {
                     return -1; // no default value
@@ -395,20 +394,18 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks that excess arguments match the vararg signature parameter.
      *
-     * @param params
-     * @param args
      * @return -1 if no match, 0 if all arguments matches the vararg type and >0 if one or more vararg argument is
      * assignable to the vararg type, but still not an exact match
      */
-    static int excessArgumentsMatchesVargsParameter(Parameter[] params, ClassNode[] args) {
+    static int excessArgumentsMatchesVargsParameter(final Parameter[] parameters, final ClassNode[] argumentTypes) {
         // we already know parameter length is bigger zero and last is a vargs
         // the excess arguments are all put in an array for the vargs call
         // so check against the component type
         int dist = 0;
-        ClassNode vargsBase = params[params.length - 1].getType().getComponentType();
-        for (int i = params.length; i < args.length; i++) {
-            if (!isAssignableTo(args[i], vargsBase)) return -1;
-            else dist += getClassDistance(vargsBase, args[i]);
+        ClassNode vargsBase = parameters[parameters.length - 1].getType().getComponentType();
+        for (int i = parameters.length; i < argumentTypes.length; i++) {
+            if (!isAssignableTo(argumentTypes[i], vargsBase)) return -1;
+            else dist += getClassDistance(vargsBase, argumentTypes[i]);
         }
         return dist;
     }
@@ -416,20 +413,18 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks if the last argument matches the vararg type.
      *
-     * @param params
-     * @param args
      * @return -1 if no match, 0 if the last argument is exactly the vararg type and 1 if of an assignable type
      */
-    static int lastArgMatchesVarg(Parameter[] params, ClassNode... args) {
-        if (!isVargs(params)) return -1;
+    static int lastArgMatchesVarg(final Parameter[] parameters, final ClassNode... argumentTypes) {
+        if (!isVargs(parameters)) return -1;
         // case length ==0 handled already
         // we have now two cases,
         // the argument is wrapped in the vargs array or
         // the argument is an array that can be used for the vargs part directly
         // we test only the wrapping part, since the non wrapping is done already
-        ClassNode lastParamType = params[params.length - 1].getType();
+        ClassNode lastParamType = parameters[parameters.length - 1].getType();
         ClassNode ptype = lastParamType.getComponentType();
-        ClassNode arg = args[args.length - 1];
+        ClassNode arg = argumentTypes[argumentTypes.length - 1];
         if (isNumberType(ptype) && isNumberType(arg) && !ptype.equals(arg)) return -1;
         return isAssignableTo(arg, ptype) ? min(getDistance(arg, lastParamType), getDistance(arg, ptype)) : -1;
     }
@@ -481,33 +476,40 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
-    static boolean isVargs(Parameter[] params) {
-        if (params.length == 0) return false;
-        if (params[params.length - 1].getType().isArray()) return true;
-        return false;
+    static boolean isVargs(final Parameter[] parameters) {
+        if (parameters == null || parameters.length == 0) return false;
+        return (parameters[parameters.length - 1].getType().isArray());
     }
 
-    public static boolean isCompareToBoolean(int op) {
-        return op == COMPARE_GREATER_THAN ||
-                op == COMPARE_GREATER_THAN_EQUAL ||
-                op == COMPARE_LESS_THAN ||
-                op == COMPARE_LESS_THAN_EQUAL;
+    public static boolean isCompareToBoolean(final int op) {
+        return op == COMPARE_LESS_THAN || op == COMPARE_LESS_THAN_EQUAL
+                || op == COMPARE_GREATER_THAN || op == COMPARE_GREATER_THAN_EQUAL;
     }
 
-    static boolean isArrayOp(int op) {
+    static boolean isArrayOp(final int op) {
         return op == LEFT_SQUARE_BRACKET;
     }
 
-    static boolean isBoolIntrinsicOp(int op) {
-        return op == LOGICAL_AND || op == LOGICAL_OR || op == COMPARE_NOT_IDENTICAL || op == COMPARE_IDENTICAL ||
-                op == MATCH_REGEX || op == KEYWORD_INSTANCEOF || op == COMPARE_NOT_INSTANCEOF;
+    static boolean isBoolIntrinsicOp(final int op) {
+        switch (op) {
+            case LOGICAL_AND:
+            case LOGICAL_OR:
+            case COMPARE_NOT_IDENTICAL:
+            case COMPARE_IDENTICAL:
+            case MATCH_REGEX:
+            case KEYWORD_INSTANCEOF:
+            case COMPARE_NOT_INSTANCEOF:
+                return true;
+            default:
+                return false;
+        }
     }
 
-    static boolean isPowerOperator(int op) {
+    static boolean isPowerOperator(final int op) {
         return op == POWER || op == POWER_EQUAL;
     }
 
-    static String getOperationName(int op) {
+    static String getOperationName(final int op) {
         switch (op) {
             case COMPARE_EQUAL:
             case COMPARE_NOT_EQUAL:
@@ -586,7 +588,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    static boolean isShiftOperation(String name) {
+    static boolean isShiftOperation(final String name) {
         return "leftShift".equals(name) || "rightShift".equals(name) || "rightShiftUnsigned".equals(name);
     }
 
@@ -595,7 +597,7 @@ public abstract class StaticTypeCheckingSupport {
      * operation "left op right" will have a result in the same type class In Groovy on numbers that is +,-,* as well as
      * their variants with equals.
      */
-    static boolean isOperationInGroup(int op) {
+    static boolean isOperationInGroup(final int op) {
         switch (op) {
             case PLUS:
             case PLUS_EQUAL:
@@ -609,7 +611,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    static boolean isBitOperator(int op) {
+    static boolean isBitOperator(final int op) {
         switch (op) {
             case BITWISE_OR_EQUAL:
             case BITWISE_OR:
@@ -623,7 +625,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    public static boolean isAssignment(int op) {
+    public static boolean isAssignment(final int op) {
         return Types.isAssignment(op);
     }
 
@@ -635,15 +637,15 @@ public abstract class StaticTypeCheckingSupport {
      * @param right the assignee class
      * @return false if types are incompatible
      */
-    public static boolean checkCompatibleAssignmentTypes(ClassNode left, ClassNode right) {
+    public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right) {
         return checkCompatibleAssignmentTypes(left, right, null);
     }
 
-    public static boolean checkCompatibleAssignmentTypes(ClassNode left, ClassNode right, Expression rightExpression) {
+    public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right, final Expression rightExpression) {
         return checkCompatibleAssignmentTypes(left, right, rightExpression, true);
     }
 
-    public static boolean checkCompatibleAssignmentTypes(ClassNode left, ClassNode right, Expression rightExpression, boolean allowConstructorCoercion) {
+    public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right, final Expression rightExpression, final boolean allowConstructorCoercion) {
         ClassNode leftRedirect = left.redirect();
         ClassNode rightRedirect = right.redirect();
         if (leftRedirect == rightRedirect) return true;
@@ -763,16 +765,16 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
-    public static boolean isBeingCompiled(ClassNode node) {
+    public static boolean isBeingCompiled(final ClassNode node) {
         return node.getCompileUnit() != null;
     }
 
     @Deprecated
-    static boolean checkPossibleLooseOfPrecision(ClassNode left, ClassNode right, Expression rightExpr) {
+    static boolean checkPossibleLooseOfPrecision(final ClassNode left, final ClassNode right, final Expression rightExpr) {
         return checkPossibleLossOfPrecision(left, right, rightExpr);
     }
 
-    static boolean checkPossibleLossOfPrecision(ClassNode left, ClassNode right, Expression rightExpr) {
+    static boolean checkPossibleLossOfPrecision(final ClassNode left, final ClassNode right, final Expression rightExpr) {
         if (left == right || left.equals(right)) return false; // identical types
         int leftIndex = NUMBER_TYPES.get(left);
         int rightIndex = NUMBER_TYPES.get(right);
@@ -840,7 +842,7 @@ public abstract class StaticTypeCheckingSupport {
         return true; // possible loss of precision
     }
 
-    static String toMethodParametersString(String methodName, ClassNode... parameters) {
+    static String toMethodParametersString(final String methodName, final ClassNode... parameters) {
         StringBuilder sb = new StringBuilder();
         sb.append(methodName).append("(");
         if (parameters != null) {
@@ -861,7 +863,7 @@ public abstract class StaticTypeCheckingSupport {
         return type.toString(false);
     }
 
-    public static boolean implementsInterfaceOrIsSubclassOf(ClassNode type, ClassNode superOrInterface) {
+    public static boolean implementsInterfaceOrIsSubclassOf(final ClassNode type, final ClassNode superOrInterface) {
         boolean result = type.equals(superOrInterface)
                 || type.isDerivedFrom(superOrInterface)
                 || type.implementsInterface(superOrInterface)
@@ -942,7 +944,7 @@ public abstract class StaticTypeCheckingSupport {
         return dist;
     }
 
-    private static int getMaximumInterfaceDistance(ClassNode c, ClassNode interfaceClass) {
+    private static int getMaximumInterfaceDistance(final ClassNode c, final ClassNode interfaceClass) {
         // -1 means a mismatch
         if (c == null) return -1;
         // 0 means a direct match
@@ -1003,7 +1005,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param node the node to test
      * @return true if it is using any placeholder in generics types
      */
-    public static boolean isUsingUncheckedGenerics(ClassNode node) {
+    public static boolean isUsingUncheckedGenerics(final ClassNode node) {
         if (node.isArray()) return isUsingUncheckedGenerics(node.getComponentType());
         if (node.isUsingGenerics()) {
             GenericsType[] genericsTypes = node.getGenericsTypes();
@@ -1029,15 +1031,15 @@ public abstract class StaticTypeCheckingSupport {
      *
      * @param receiver
      * @param methods  candidate methods
-     * @param args     argument types
+     * @param argumentTypes     argument types
      * @return the list of methods which best matches the argument types. It is still possible that multiple
      * methods match the argument types.
      */
-    public static List<MethodNode> chooseBestMethod(final ClassNode receiver, Collection<MethodNode> methods, ClassNode... args) {
+    public static List<MethodNode> chooseBestMethod(final ClassNode receiver, final Collection<MethodNode> methods, final ClassNode... argumentTypes) {
         if (methods.isEmpty()) return Collections.emptyList();
         if (isUsingUncheckedGenerics(receiver)) {
             ClassNode raw = makeRawType(receiver);
-            return chooseBestMethod(raw, methods, args);
+            return chooseBestMethod(raw, methods, argumentTypes);
         }
         List<MethodNode> bestChoices = new LinkedList<>();
         int bestDist = Integer.MAX_VALUE;
@@ -1046,11 +1048,11 @@ public abstract class StaticTypeCheckingSupport {
             ClassNode declaringClassForDistance = candidateNode.getDeclaringClass();
             ClassNode actualReceiverForDistance = receiver != null ? receiver : candidateNode.getDeclaringClass();
             MethodNode safeNode = candidateNode;
-            ClassNode[] safeArgs = args;
+            ClassNode[] safeArgs = argumentTypes;
             boolean isExtensionMethodNode = candidateNode instanceof ExtensionMethodNode;
             if (isExtensionMethodNode) {
-                safeArgs = new ClassNode[args.length + 1];
-                System.arraycopy(args, 0, safeArgs, 1, args.length);
+                safeArgs = new ClassNode[argumentTypes.length + 1];
+                System.arraycopy(argumentTypes, 0, safeArgs, 1, argumentTypes.length);
                 safeArgs[0] = receiver;
                 safeNode = ((ExtensionMethodNode) candidateNode).getExtensionMethodNode();
             }
@@ -1096,30 +1098,30 @@ public abstract class StaticTypeCheckingSupport {
         return bestChoices;
     }
 
-    private static int measureParametersAndArgumentsDistance(Parameter[] params, ClassNode[] args) {
+    private static int measureParametersAndArgumentsDistance(final Parameter[] parameters, final ClassNode[] argumentTypes) {
         int dist = -1;
-        if (params.length == args.length) {
-            int allPMatch = allParametersAndArgumentsMatch(params, args);
-            int firstParamDist = firstParametersAndArgumentsMatch(params, args);
-            int lastArgMatch = isVargs(params) && firstParamDist >= 0 ? lastArgMatchesVarg(params, args) : -1;
+        if (parameters.length == argumentTypes.length) {
+            int allPMatch = allParametersAndArgumentsMatch(parameters, argumentTypes);
+            int firstParamDist = firstParametersAndArgumentsMatch(parameters, argumentTypes);
+            int lastArgMatch = isVargs(parameters) && firstParamDist >= 0 ? lastArgMatchesVarg(parameters, argumentTypes) : -1;
             if (lastArgMatch >= 0) {
-                lastArgMatch += getVarargsDistance(params);
+                lastArgMatch += getVarargsDistance(parameters);
             }
             dist = allPMatch >= 0 ? Math.max(allPMatch, lastArgMatch) : lastArgMatch;
-        } else if (isVargs(params)) {
-            dist = firstParametersAndArgumentsMatch(params, args);
+        } else if (isVargs(parameters)) {
+            dist = firstParametersAndArgumentsMatch(parameters, argumentTypes);
             if (dist >= 0) {
                 // varargs methods must not be preferred to methods without varargs
                 // for example :
                 // int sum(int x) should be preferred to int sum(int x, int... y)
-                dist += getVarargsDistance(params);
+                dist += getVarargsDistance(parameters);
                 // there are three case for vargs
                 // (1) varg part is left out (there's one less argument than there are parameters)
                 // (2) last argument is put in the vargs array
                 //     that case is handled above already when params and args have the same length
-                if (params.length < args.length) {
+                if (parameters.length < argumentTypes.length) {
                     // (3) there is more than one argument for the vargs array
-                    int excessArgumentsDistance = excessArgumentsMatchesVargsParameter(params, args);
+                    int excessArgumentsDistance = excessArgumentsMatchesVargsParameter(parameters, argumentTypes);
                     if (excessArgumentsDistance < 0) {
                         dist = -1;
                     } else {
@@ -1131,34 +1133,34 @@ public abstract class StaticTypeCheckingSupport {
         return dist;
     }
 
-    private static int firstParametersAndArgumentsMatch(Parameter[] params, ClassNode[] safeArgs) {
+    private static int firstParametersAndArgumentsMatch(final Parameter[] parameters, final ClassNode[] safeArgumentTypes) {
         int dist = 0;
         // check first parameters
-        if (params.length > 0) {
-            Parameter[] firstParams = new Parameter[params.length - 1];
-            System.arraycopy(params, 0, firstParams, 0, firstParams.length);
-            dist = allParametersAndArgumentsMatch(firstParams, safeArgs);
+        if (parameters.length > 0) {
+            Parameter[] firstParams = new Parameter[parameters.length - 1];
+            System.arraycopy(parameters, 0, firstParams, 0, firstParams.length);
+            dist = allParametersAndArgumentsMatch(firstParams, safeArgumentTypes);
         }
         return dist;
     }
 
-    private static int getVarargsDistance(Parameter[] params) {
-        return 256 - params.length; // ensure exact matches are preferred over vargs
+    private static int getVarargsDistance(final Parameter[] parameters) {
+        return 256 - parameters.length; // ensure exact matches are preferred over vargs
     }
 
-    private static int getClassDistance(ClassNode declaringClassForDistance, ClassNode actualReceiverForDistance) {
+    private static int getClassDistance(final ClassNode declaringClassForDistance, final ClassNode actualReceiverForDistance) {
         if (actualReceiverForDistance.equals(declaringClassForDistance)) {
             return 0;
         }
         return getDistance(actualReceiverForDistance, declaringClassForDistance);
     }
 
-    private static int getExtensionDistance(boolean isExtensionMethodNode) {
+    private static int getExtensionDistance(final boolean isExtensionMethodNode) {
         return isExtensionMethodNode ? 0 : 1;
     }
 
-    private static Parameter[] makeRawTypes(Parameter[] params, Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
-        return Arrays.stream(params).map(param -> {
+    private static Parameter[] makeRawTypes(final Parameter[] parameters, final Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
+        return Arrays.stream(parameters).map(param -> {
             String name = param.getType().getUnresolvedName();
             Optional<GenericsType> value = genericsPlaceholderAndTypeMap.entrySet().stream()
                 .filter(e -> e.getKey().getName().equals(name)).findFirst().map(Map.Entry::getValue);
@@ -1178,7 +1180,7 @@ public abstract class StaticTypeCheckingSupport {
         return raw;
     }
 
-    private static Collection<MethodNode> removeCovariantsAndInterfaceEquivalents(Collection<MethodNode> collection) {
+    private static Collection<MethodNode> removeCovariantsAndInterfaceEquivalents(final Collection<MethodNode> collection) {
         if (collection.size() <= 1) return collection;
         List<MethodNode> toBeRemoved = new LinkedList<>();
         List<MethodNode> list = new LinkedList<>(new LinkedHashSet<>(collection));
@@ -1211,7 +1213,7 @@ public abstract class StaticTypeCheckingSupport {
         return result;
     }
 
-    private static void removeMethodInSuperInterface(List<MethodNode> toBeRemoved, MethodNode one, MethodNode two) {
+    private static void removeMethodInSuperInterface(final List<MethodNode> toBeRemoved, final MethodNode one, final MethodNode two) {
         ClassNode oneDC = one.getDeclaringClass();
         ClassNode twoDC = two.getDeclaringClass();
         if (oneDC.implementsInterface(twoDC)) {
@@ -1221,14 +1223,14 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static boolean areEquivalentInterfaceMethods(MethodNode one, MethodNode two) {
+    private static boolean areEquivalentInterfaceMethods(final MethodNode one, final MethodNode two) {
         return one.getName().equals(two.getName())
                 && one.getDeclaringClass().isInterface()
                 && two.getDeclaringClass().isInterface()
                 && ParameterUtils.parametersEqual(one.getParameters(), two.getParameters());
     }
 
-    private static void removeSyntheticMethodIfOne(List<MethodNode> toBeRemoved, MethodNode one, MethodNode two) {
+    private static void removeSyntheticMethodIfOne(final List<MethodNode> toBeRemoved, final MethodNode one, final MethodNode two) {
         if (one.isSynthetic() && !two.isSynthetic()) {
             toBeRemoved.add(one);
         } else if (two.isSynthetic() && !one.isSynthetic()) {
@@ -1236,7 +1238,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static void removeMethodWithSuperReturnType(List<MethodNode> toBeRemoved, MethodNode one, MethodNode two) {
+    private static void removeMethodWithSuperReturnType(final List<MethodNode> toBeRemoved, final MethodNode one, final MethodNode two) {
         ClassNode oneRT = one.getReturnType();
         ClassNode twoRT = two.getReturnType();
         if (isCovariant(oneRT, twoRT)) {
@@ -1246,14 +1248,14 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static boolean isCovariant(ClassNode left, ClassNode right) {
+    private static boolean isCovariant(final ClassNode left, final ClassNode right) {
         if (left.isArray() && right.isArray()) {
             return isCovariant(left.getComponentType(), right.getComponentType());
         }
         return left.isDerivedFrom(right) || left.implementsInterface(right);
     }
 
-    private static boolean areOverloadMethodsInSameClass(MethodNode one, MethodNode two) {
+    private static boolean areOverloadMethodsInSameClass(final MethodNode one, final MethodNode two) {
         return one.getName().equals(two.getName()) && one.getDeclaringClass() == two.getDeclaringClass();
     }
 
@@ -1309,7 +1311,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param cn a class node for which to check if it is using generics
      * @return true if the type (or component type) is using generics
      */
-    public static boolean isUsingGenericsOrIsArrayUsingGenerics(ClassNode cn) {
+    public static boolean isUsingGenericsOrIsArrayUsingGenerics(final ClassNode cn) {
         if (cn.isArray()) {
             return isUsingGenericsOrIsArrayUsingGenerics(cn.getComponentType());
         }
@@ -1320,7 +1322,7 @@ 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<GenericsTypeName, GenericsType> placeholders) {
+    protected static GenericsType fullyResolve(GenericsType gt, final Map<GenericsTypeName, GenericsType> placeholders) {
         GenericsType fromMap = placeholders.get(new GenericsTypeName(gt.getName()));
         if (gt.isPlaceholder() && fromMap != null) {
             gt = fromMap;
@@ -1379,7 +1381,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param parameterType the parameter type of a method
      * @param argumentType  the type of the argument passed to the method
      */
-    protected static boolean typeCheckMethodArgumentWithGenerics(ClassNode parameterType, ClassNode argumentType, boolean lastArg) {
+    protected static boolean typeCheckMethodArgumentWithGenerics(final ClassNode parameterType, final ClassNode argumentType, final boolean lastArg) {
         if (UNKNOWN_PARAMETER_TYPE == argumentType) {
             // called with null
             return !isPrimitiveType(parameterType);
@@ -1415,13 +1417,13 @@ public abstract class StaticTypeCheckingSupport {
         return true;
     }
 
-    static void addMethodLevelDeclaredGenerics(MethodNode method, Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
+    static void addMethodLevelDeclaredGenerics(final MethodNode method, final Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
         ClassNode dummy = OBJECT_TYPE.getPlainNodeReference();
         dummy.setGenericsTypes(method.getGenericsTypes());
         GenericsUtils.extractPlaceholders(dummy, resolvedPlaceholders);
     }
 
-    protected static boolean typeCheckMethodsWithGenerics(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod) {
+    protected static boolean typeCheckMethodsWithGenerics(final ClassNode receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod) {
         if (isUsingUncheckedGenerics(receiver)) {
             return true;
         }
@@ -1429,24 +1431,24 @@ public abstract class StaticTypeCheckingSupport {
                 && receiver.isUsingGenerics()
                 && !candidateMethod.getDeclaringClass().equals(receiver)
                 && !(candidateMethod instanceof ExtensionMethodNode)) {
-            return typeCheckMethodsWithGenerics(receiver.getGenericsTypes()[0].getType(), arguments, candidateMethod);
+            return typeCheckMethodsWithGenerics(receiver.getGenericsTypes()[0].getType(), argumentTypes, candidateMethod);
         }
         // both candidate method and receiver have generic information so a check is possible
         GenericsType[] genericsTypes = candidateMethod.getGenericsTypes();
         boolean methodUsesGenerics = (genericsTypes != null && genericsTypes.length > 0);
         boolean isExtensionMethod = candidateMethod instanceof ExtensionMethodNode;
         if (isExtensionMethod && methodUsesGenerics) {
-            ClassNode[] dgmArgs = new ClassNode[arguments.length + 1];
+            ClassNode[] dgmArgs = new ClassNode[argumentTypes.length + 1];
             dgmArgs[0] = receiver;
-            System.arraycopy(arguments, 0, dgmArgs, 1, arguments.length);
+            System.arraycopy(argumentTypes, 0, dgmArgs, 1, argumentTypes.length);
             MethodNode extensionMethodNode = ((ExtensionMethodNode) candidateMethod).getExtensionMethodNode();
             return typeCheckMethodsWithGenerics(extensionMethodNode.getDeclaringClass(), dgmArgs, extensionMethodNode, true);
         } else {
-            return typeCheckMethodsWithGenerics(receiver, arguments, candidateMethod, false);
+            return typeCheckMethodsWithGenerics(receiver, argumentTypes, candidateMethod, false);
         }
     }
 
-    private static boolean typeCheckMethodsWithGenerics(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod, boolean isExtensionMethod) {
+    private static boolean typeCheckMethodsWithGenerics(final ClassNode receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod, final boolean isExtensionMethod) {
         boolean failure = false;
 
         // correct receiver for inner class
@@ -1454,7 +1456,7 @@ public abstract class StaticTypeCheckingSupport {
         // 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
-        boolean skipBecauseOfInnerClassNotReceiver = isOuterClassOf(receiver, candidateMethod.getDeclaringClass());
+        boolean skipBecauseOfInnerClassNotReceiver = !implementsInterfaceOrIsSubclassOf(receiver, candidateMethod.getDeclaringClass());
 
         Parameter[] parameters = candidateMethod.getParameters();
         Map<GenericsTypeName, GenericsType> classGTs;
@@ -1463,7 +1465,7 @@ public abstract class StaticTypeCheckingSupport {
         } else {
             classGTs = GenericsUtils.extractPlaceholders(receiver);
         }
-        if (parameters.length > arguments.length || parameters.length == 0) {
+        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!
             return true;
@@ -1492,9 +1494,9 @@ public abstract class StaticTypeCheckingSupport {
         // parameter, in case of an extension method we must not.
         Set<GenericsTypeName> fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics);
 
-        for (int i = 0; i < arguments.length; i++) {
+        for (int i = 0; i < argumentTypes.length; i++) {
             int pindex = min(i, parameters.length - 1);
-            ClassNode wrappedArgument = arguments[i];
+            ClassNode wrappedArgument = argumentTypes[i];
             ClassNode type = parameters[pindex].getOriginType();
 
             failure |= inferenceCheck(fixedGenericsPlaceHolders, resolvedMethodGenerics, type, wrappedArgument, i >= parameters.length - 1);
@@ -1506,12 +1508,7 @@ public abstract class StaticTypeCheckingSupport {
         return !failure;
     }
 
-    private static boolean isOuterClassOf(ClassNode receiver, ClassNode type) {
-        if (implementsInterfaceOrIsSubclassOf(receiver, type)) return false;
-        return true;
-    }
-
-    private static Set<GenericsTypeName> extractResolvedPlaceHolders(Map<GenericsTypeName, GenericsType> resolvedMethodGenerics) {
+    private static Set<GenericsTypeName> extractResolvedPlaceHolders(final Map<GenericsTypeName, GenericsType> resolvedMethodGenerics) {
         if (resolvedMethodGenerics.isEmpty()) return Collections.emptySet();
         Set<GenericsTypeName> result = new HashSet<>();
         for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedMethodGenerics.entrySet()) {
@@ -1522,7 +1519,7 @@ public abstract class StaticTypeCheckingSupport {
         return result;
     }
 
-    private static boolean inferenceCheck(Set<GenericsTypeName> fixedGenericsPlaceHolders, Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, ClassNode type, ClassNode wrappedArgument, boolean lastArg) {
+    private static boolean inferenceCheck(final Set<GenericsTypeName> fixedGenericsPlaceHolders, final Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, ClassNode type, ClassNode wrappedArgument, final boolean lastArg) {
         Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         if (isPrimitiveType(wrappedArgument)) wrappedArgument = getWrapper(wrappedArgument);
 
@@ -1556,7 +1553,7 @@ public abstract class StaticTypeCheckingSupport {
         return failure;
     }
 
-    private static GenericsType buildWildcardType(GenericsType origin) {
+    private static GenericsType buildWildcardType(final GenericsType origin) {
         ClassNode lowerBound = origin.getType().getPlainNodeReference();
         if (hasNonTrivialBounds(origin)) {
             lowerBound.setGenericsTypes(new GenericsType[]{origin});
@@ -1567,7 +1564,7 @@ public abstract class StaticTypeCheckingSupport {
         return gt;
     }
 
-    private static boolean compatibleConnections(Map<GenericsTypeName, GenericsType> connections, Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, Set<GenericsTypeName> fixedGenericsPlaceHolders) {
+    private static boolean compatibleConnections(final Map<GenericsTypeName, GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, final Set<GenericsTypeName> fixedGenericsPlaceHolders) {
         for (Map.Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
             GenericsType resolved = resolvedMethodGenerics.get(entry.getKey());
             if (resolved == null) continue;
@@ -1592,7 +1589,7 @@ public abstract class StaticTypeCheckingSupport {
         return true;
     }
 
-    private static boolean compatibleConnection(GenericsType resolved, GenericsType connection) {
+    private static boolean compatibleConnection(final GenericsType resolved, final GenericsType connection) {
         GenericsType gt = connection;
         if (!connection.isWildcard()) gt = buildWildcardType(connection);
         if (resolved.isPlaceholder() && resolved.getUpperBounds() != null &&
@@ -1614,7 +1611,7 @@ public abstract class StaticTypeCheckingSupport {
         return gt.isCompatibleWith(compareNode);
     }
 
-    private static void addMissingEntries(Map<GenericsTypeName, GenericsType> connections, Map<GenericsTypeName, GenericsType> resolved) {
+    private static void addMissingEntries(final Map<GenericsTypeName, GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolved) {
         for (Map.Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
             if (resolved.containsKey(entry.getKey())) continue;
             GenericsType gt = entry.getValue();
@@ -1624,7 +1621,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final Map<GenericsTypeName, GenericsType> placeholdersFromContext, ClassNode currentType) {
+    public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final Map<GenericsTypeName, GenericsType> placeholdersFromContext, final ClassNode currentType) {
         ClassNode target = currentType.redirect();
         resolvedPlaceholders = new HashMap<>(resolvedPlaceholders);
         applyContextGenerics(resolvedPlaceholders, placeholdersFromContext);
@@ -1632,14 +1629,10 @@ public abstract class StaticTypeCheckingSupport {
         Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         extractGenericsConnections(connections, currentType, target);
         applyGenericsConnections(connections, resolvedPlaceholders);
-        currentType = applyGenericsContext(resolvedPlaceholders, currentType);
-        return currentType;
+        return applyGenericsContext(resolvedPlaceholders, currentType);
     }
 
-    static void applyGenericsConnections(
-            Map<GenericsTypeName, GenericsType> connections,
-            Map<GenericsTypeName, GenericsType> resolvedPlaceholders
-    ) {
+    static void applyGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
         if (connections == null) return;
         int count = 0;
         while (count < 10000) {
@@ -1681,7 +1674,7 @@ public abstract class StaticTypeCheckingSupport {
             throw new GroovyBugError("unable to handle generics in " + resolvedPlaceholders + " with connections " + connections);
     }
 
-    private static ClassNode extractType(GenericsType gt) {
+    private static ClassNode extractType(final GenericsType gt) {
         if (!gt.isPlaceholder()) {
             return gt.getType();
         }
@@ -1699,7 +1692,7 @@ public abstract class StaticTypeCheckingSupport {
         return replacementType;
     }
 
-    private static boolean equalIncludingGenerics(GenericsType orig, GenericsType copy) {
+    private static boolean equalIncludingGenerics(final GenericsType orig, final GenericsType copy) {
         if (orig == copy) return true;
         if (orig.isPlaceholder() != copy.isPlaceholder()) return false;
         if (orig.isWildcard() != copy.isWildcard()) return false;
@@ -1722,7 +1715,7 @@ public abstract class StaticTypeCheckingSupport {
         return true;
     }
 
-    private static boolean equalIncludingGenerics(ClassNode orig, ClassNode copy) {
+    private static boolean equalIncludingGenerics(final ClassNode orig, final ClassNode copy) {
         if (orig == copy) return true;
         if (orig.isGenericsPlaceHolder() != copy.isGenericsPlaceHolder()) return false;
         if (!orig.equals(copy)) return false;
@@ -1739,37 +1732,39 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     /**
-     * use supplied type to make a connection from usage to declaration
-     * The method operates in two modes.
-     * * For type !instanceof target a structural compare will be done
-     * (for example Dummy&lt;T&gt; and List&lt;R&gt; to get T=R)
-     * * If type equals target, a structural match is done as well
-     * (for example Collection&lt;U&gt; and Collection&lt;E&gt; to get U=E)
-     * * otherwise we climb the hierarchy to find a case of type equals target
-     * to then execute the structural match, while applying possibly existing
-     * generics contexts on the way (for example for IntRange and Collection&lt;E&gt;
-     * to get E=Integer, since IntRange is an AbstractList&lt;Integer&gt;)
+     * Uses supplied type to make a connection from usage to declaration.
+     * <p>
+     * The method operates in two modes:
+     * <ul>
+     * <li>For type !instanceof target a structural compare will be done
+     *     (for example Type&lt;T&gt; and List&lt;E&gt; to get E -> T)
+     * <li>If type equals target, a structural match is done as well
+     *     (for example Collection&lt;T&gt; and Collection&lt;E&gt; to get E -> T)
+     * <li>Otherwise we climb the hierarchy to find a case of type equals target
+     *     to then execute the structural match, while applying possibly existing
+     *     generics contexts on the way (for example for IntRange and Collection&lt;E&gt;
+     *     to get E -> Integer, since IntRange is an AbstractList&lt;Integer&gt;)
+     * </ul>
      * Should the target not have any generics this method does nothing.
      */
-    static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, ClassNode type, ClassNode target) {
+    static void extractGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final ClassNode type, final ClassNode target) {
         if (target == null || type == target || !isUsingGenericsOrIsArrayUsingGenerics(target)) return;
         if (type == null || type == UNKNOWN_PARAMETER_TYPE) return;
-        if (type.isArray() && target.isArray()) {
+
+        if (target.isGenericsPlaceHolder()) {
+            connections.put(new GenericsTypeName(target.getGenericsTypes()[0].getName()), new GenericsType(type));
+
+        } else if (type.isArray() && target.isArray()) {
             extractGenericsConnections(connections, type.getComponentType(), target.getComponentType());
-        } else if (target.isGenericsPlaceHolder() || type.equals(target) || !implementsInterfaceOrIsSubclassOf(type, target)) {
-            // structural match route
-            if (target.isGenericsPlaceHolder()) {
-                connections.put(new GenericsTypeName(target.getGenericsTypes()[0].getName()), new GenericsType(type));
-            } else {
-                extractGenericsConnections(connections, type.getGenericsTypes(), target.getGenericsTypes());
-            }
+
+        } else if (type.equals(target) || !implementsInterfaceOrIsSubclassOf(type, target)) {
+            extractGenericsConnections(connections, type.getGenericsTypes(), target.getGenericsTypes());
+
         } else {
-            // have first to find matching super class or interface
+            // first find matching super class or interface
             ClassNode superClass = getSuperClass(type, target);
-
             if (superClass != null) {
-                ClassNode corrected = getCorrectedClassNode(type, superClass, true);
-                extractGenericsConnections(connections, corrected, target);
+                extractGenericsConnections(connections, getCorrectedClassNode(type, superClass, true), target);
             } else {
                 // if we reach here, we have an unhandled case
                 throw new GroovyBugError("The type " + type + " seems not to normally extend " + target + ". Sorry, I cannot handle this.");
@@ -1777,17 +1772,12 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    public static ClassNode getCorrectedClassNode(ClassNode type, ClassNode superClass, boolean handlingGenerics) {
-        ClassNode corrected;
-        if (handlingGenerics && missesGenericsTypes(type)) {
-            corrected = superClass.getPlainNodeReference();
-        } else {
-            corrected = GenericsUtils.correctToGenericsSpecRecurse(GenericsUtils.createGenericsSpec(type), superClass);
-        }
-        return corrected;
+    public static ClassNode getCorrectedClassNode(final ClassNode type, final ClassNode superClass, final boolean handlingGenerics) {
+        if (handlingGenerics && missesGenericsTypes(type)) return superClass.getPlainNodeReference();
+        return GenericsUtils.correctToGenericsSpecRecurse(GenericsUtils.createGenericsSpec(type), superClass);
     }
 
-    private static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
+    private static void extractGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final GenericsType[] usage, final 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;
@@ -1818,7 +1808,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, ClassNode[] usage, ClassNode[] declaration) {
+    private static void extractGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final ClassNode[] usage, final ClassNode[] declaration) {
         if (usage == null || declaration == null || declaration.length == 0) return;
         // both have generics
         for (int i = 0; i < usage.length; i++) {
@@ -1834,14 +1824,12 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    static GenericsType[] getGenericsWithoutArray(ClassNode type) {
+    static GenericsType[] getGenericsWithoutArray(final ClassNode type) {
         if (type.isArray()) return getGenericsWithoutArray(type.getComponentType());
         return type.getGenericsTypes();
     }
 
-    static Map<GenericsTypeName, GenericsType> applyGenericsContextToParameterClass(
-            Map<GenericsTypeName, GenericsType> spec, ClassNode parameterUsage
-    ) {
+    static Map<GenericsTypeName, GenericsType> applyGenericsContextToParameterClass(final Map<GenericsTypeName, GenericsType> spec, final ClassNode parameterUsage) {
         GenericsType[] gts = parameterUsage.getGenericsTypes();
         if (gts == null) return Collections.emptyMap();
 
@@ -1851,9 +1839,7 @@ public abstract class StaticTypeCheckingSupport {
         return GenericsUtils.extractPlaceholders(newTarget);
     }
 
-    private static GenericsType[] applyGenericsContext(
-            Map<GenericsTypeName, GenericsType> spec, GenericsType[] gts
-    ) {
+    private static GenericsType[] applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final GenericsType[] gts) {
         if (gts == null) return null;
         GenericsType[] newGTs = new GenericsType[gts.length];
         for (int i = 0; i < gts.length; i++) {
@@ -1863,7 +1849,7 @@ public abstract class StaticTypeCheckingSupport {
         return newGTs;
     }
 
-    private static GenericsType applyGenericsContext(Map<GenericsTypeName, GenericsType> spec, GenericsType gt) {
+    private static GenericsType applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final GenericsType gt) {
         if (gt.isPlaceholder()) {
             GenericsTypeName name = new GenericsTypeName(gt.getName());
             GenericsType specType = spec.get(name);
@@ -1892,7 +1878,7 @@ public abstract class StaticTypeCheckingSupport {
         return new GenericsType(newType);
     }
 
-    private static boolean hasNonTrivialBounds(GenericsType gt) {
+    private static boolean hasNonTrivialBounds(final GenericsType gt) {
         ClassNode[] upperBounds = gt.getUpperBounds();
         return gt.getLowerBound() != null || gt.isWildcard() ||
                 (upperBounds != null && (
@@ -1901,9 +1887,7 @@ public abstract class StaticTypeCheckingSupport {
                                 || !OBJECT_TYPE.equals(upperBounds[0])));
     }
 
-    private static ClassNode[] applyGenericsContext(
-            Map<GenericsTypeName, GenericsType> spec, ClassNode[] bounds
-    ) {
+    private static ClassNode[] applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final ClassNode[] bounds) {
         if (bounds == null) return null;
         ClassNode[] newBounds = new ClassNode[bounds.length];
         for (int i = 0; i < bounds.length; i++) {
@@ -1912,9 +1896,7 @@ public abstract class StaticTypeCheckingSupport {
         return newBounds;
     }
 
-    static ClassNode applyGenericsContext(
-            Map<GenericsTypeName, GenericsType> spec, ClassNode bound
-    ) {
+    static ClassNode applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final ClassNode bound) {
         if (bound == null) return null;
         if (bound.isArray()) {
             return applyGenericsContext(spec, bound.getComponentType()).makeArray();
@@ -1939,7 +1921,7 @@ public abstract class StaticTypeCheckingSupport {
         return newBound;
     }
 
-    private static ClassNode getCombinedBoundType(GenericsType genericsType) {
+    private static ClassNode getCombinedBoundType(final GenericsType genericsType) {
         //TODO: this method should really return some kind of meta ClassNode
         // representing the combination of all bounds. The code here, just picks
         // something out to be able to proceed and is not actually correct
@@ -1950,7 +1932,7 @@ public abstract class StaticTypeCheckingSupport {
         return genericsType.getType();
     }
 
-    private static void applyContextGenerics(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, Map<GenericsTypeName, GenericsType> placeholdersFromContext) {
+    private static void applyContextGenerics(final Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final Map<GenericsTypeName, GenericsType> placeholdersFromContext) {
         if (placeholdersFromContext == null) return;
         for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedPlaceholders.entrySet()) {
             GenericsType gt = entry.getValue();
@@ -1963,7 +1945,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static Map<GenericsTypeName, GenericsType> getGenericsParameterMapOfThis(ClassNode cn) {
+    private static Map<GenericsTypeName, GenericsType> getGenericsParameterMapOfThis(final ClassNode cn) {
         if (cn == null) return null;
         Map<GenericsTypeName, GenericsType> map = null;
         if (cn.getEnclosingMethod() != null) {
@@ -1981,7 +1963,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param type A parameterized type
      * @return A parameterized type with more precise wildcards
      */
-    static ClassNode boundUnboundedWildcards(ClassNode type) {
+    static ClassNode boundUnboundedWildcards(final ClassNode type) {
         if (type.isArray()) {
             return boundUnboundedWildcards(type.getComponentType()).makeArray();
         }
@@ -1993,7 +1975,7 @@ public abstract class StaticTypeCheckingSupport {
         return newType;
     }
 
-    private static GenericsType[] boundUnboundedWildcards(GenericsType[] usage, GenericsType[] declaration) {
+    private static GenericsType[] boundUnboundedWildcards(final GenericsType[] usage, final GenericsType[] declaration) {
         GenericsType[] newGts = new GenericsType[usage.length];
         for (int i = 0; i < usage.length; i++) {
             newGts[i] = boundUnboundedWildcard(usage[i], declaration[i]);
@@ -2001,7 +1983,7 @@ public abstract class StaticTypeCheckingSupport {
         return newGts;
     }
 
-    private static GenericsType boundUnboundedWildcard(GenericsType gt, GenericsType spec) {
+    private static GenericsType boundUnboundedWildcard(final GenericsType gt, final GenericsType spec) {
         if (isUnboundedWildcard(gt)) {
             ClassNode base = makeWithoutCaching("?");
             // The bounds on the declared type are at least as good as the ones on an unbounded wildcard, since it has
@@ -2013,7 +1995,7 @@ public abstract class StaticTypeCheckingSupport {
         return gt;
     }
 
-    public static boolean isUnboundedWildcard(GenericsType gt) {
+    public static boolean isUnboundedWildcard(final GenericsType gt) {
         if (gt.isWildcard() && gt.getLowerBound() == null) {
             ClassNode[] upperBounds = gt.getUpperBounds();
             return upperBounds == null ||
@@ -2023,7 +2005,7 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
-    static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(MethodNode mn) {
+    static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(final MethodNode mn) {
         if (mn == null) return null;
 
         Map<GenericsTypeName, GenericsType> map;
@@ -2036,7 +2018,7 @@ public abstract class StaticTypeCheckingSupport {
         return mergeGenerics(map, mn.getGenericsTypes());
     }
 
-    private static Map<GenericsTypeName, GenericsType> mergeGenerics(Map<GenericsTypeName, GenericsType> current, GenericsType[] newGenerics) {
+    private static Map<GenericsTypeName, GenericsType> mergeGenerics(Map<GenericsTypeName, GenericsType> current, final GenericsType[] newGenerics) {
         if (newGenerics == null || newGenerics.length == 0) return current;
         if (current == null) current = new HashMap<>();
         for (GenericsType gt : newGenerics) {
@@ -2055,7 +2037,7 @@ public abstract class StaticTypeCheckingSupport {
      * @return filtered method nodes
      * @since 3.0.0
      */
-    public static List<MethodNode> filterMethodsByVisibility(List<MethodNode> methodNodeList, ClassNode enclosingClassNode) {
+    public static List<MethodNode> filterMethodsByVisibility(final List<MethodNode> methodNodeList, final ClassNode enclosingClassNode) {
         if (!asBoolean(methodNodeList)) {
             return StaticTypeCheckingVisitor.EMPTY_METHODNODE_LIST;
         }
@@ -2116,139 +2098,9 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     /**
-     * A DGM-like method which adds support for method calls which are handled
-     * specifically by the Groovy compiler.
-     */
-    public static class ObjectArrayStaticTypesHelper {
-        public static <T> T getAt(T[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static <T, U extends T> void putAt(T[] arr, int index, U object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class BooleanArrayStaticTypesHelper {
-        public static Boolean getAt(boolean[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(boolean[] arr, int index, boolean object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class CharArrayStaticTypesHelper {
-        public static Character getAt(char[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(char[] arr, int index, char object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class ByteArrayStaticTypesHelper {
-        public static Byte getAt(byte[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(byte[] arr, int index, byte object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class ShortArrayStaticTypesHelper {
-        public static Short getAt(short[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(short[] arr, int index, short object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class IntArrayStaticTypesHelper {
-        public static Integer getAt(int[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(int[] arr, int index, int object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class LongArrayStaticTypesHelper {
-        public static Long getAt(long[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(long[] arr, int index, long object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class FloatArrayStaticTypesHelper {
-        public static Float getAt(float[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(float[] arr, int index, float object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    public static class DoubleArrayStaticTypesHelper {
-        public static Double getAt(double[] arr, int index) {
-            return null == arr ? null : arr[index];
-        }
-
-        public static void putAt(double[] arr, int index, double object) {
-            if (null == arr) {
-                return;
-            }
-
-            arr[index] = object;
-        }
-    }
-
-    /**
      * @return true if the class node is either a GString or the LUB of String and GString.
      */
-    public static boolean isGStringOrGStringStringLUB(ClassNode node) {
+    public static boolean isGStringOrGStringStringLUB(final ClassNode node) {
         return GSTRING_TYPE.equals(node) || GSTRING_STRING_CLASSNODE.equals(node);
     }
 
@@ -2256,7 +2108,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param node the node to be tested
      * @return true if the node is using generics types and one of those types is a gstring or string/gstring lub
      */
-    public static boolean isParameterizedWithGStringOrGStringString(ClassNode node) {
+    public static boolean isParameterizedWithGStringOrGStringString(final ClassNode node) {
         if (node.isArray()) return isParameterizedWithGStringOrGStringString(node.getComponentType());
         if (node.isUsingGenerics()) {
             GenericsType[] genericsTypes = node.getGenericsTypes();
@@ -2273,7 +2125,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param node the node to be tested
      * @return true if the node is using generics types and one of those types is a string
      */
-    public static boolean isParameterizedWithString(ClassNode node) {
+    public static boolean isParameterizedWithString(final ClassNode node) {
         if (node.isArray()) return isParameterizedWithString(node.getComponentType());
         if (node.isUsingGenerics()) {
             GenericsType[] genericsTypes = node.getGenericsTypes();
@@ -2286,7 +2138,7 @@ public abstract class StaticTypeCheckingSupport {
         return node.getSuperClass() != null && isParameterizedWithString(node.getUnresolvedSuperClass());
     }
 
-    public static boolean missesGenericsTypes(ClassNode cn) {
+    public static boolean missesGenericsTypes(final ClassNode cn) {
         if (cn.isArray()) return missesGenericsTypes(cn.getComponentType());
         GenericsType[] cnTypes = cn.getGenericsTypes();
         GenericsType[] rnTypes = cn.redirect().getGenericsTypes();
@@ -2310,7 +2162,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param config the compiler configuration
      * @return the result of the expression
      */
-    public static Object evaluateExpression(Expression expr, CompilerConfiguration config) {
+    public static Object evaluateExpression(final Expression expr, final CompilerConfiguration config) {
         String className = "Expression$" + UUID.randomUUID().toString().replace('-', '$');
         ClassNode node = new ClassNode(className, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
         ReturnStatement code = new ReturnStatement(expr);
@@ -2335,7 +2187,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param node a class for which we want to retrieve all interfaces
      * @return a set of interfaces implemented by this class node
      */
-    public static Set<ClassNode> collectAllInterfaces(ClassNode node) {
+    public static Set<ClassNode> collectAllInterfaces(final ClassNode node) {
         Set<ClassNode> result = new HashSet<>();
         collectAllInterfaces(node, result);
         return result;
@@ -2364,7 +2216,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param classNode a class node to be tested
      * @return true if it is the class node for Class and its generic type is a real class
      */
-    public static boolean isClassClassNodeWrappingConcreteType(ClassNode classNode) {
+    public static boolean isClassClassNodeWrappingConcreteType(final ClassNode classNode) {
         GenericsType[] genericsTypes = classNode.getGenericsTypes();
         return CLASS_Type.equals(classNode)
                 && classNode.isUsingGenerics()
@@ -2373,7 +2225,7 @@ public abstract class StaticTypeCheckingSupport {
                 && !genericsTypes[0].isWildcard();
     }
 
-    public static List<MethodNode> findSetters(ClassNode cn, String setterName, boolean voidOnly) {
+    public static List<MethodNode> findSetters(final ClassNode cn, final String setterName, final boolean voidOnly) {
         List<MethodNode> result = null;
         for (MethodNode method : cn.getDeclaredMethods(setterName)) {
             if (setterName.equals(method.getName())
@@ -2395,7 +2247,7 @@ public abstract class StaticTypeCheckingSupport {
         return result;
     }
 
-    public static ClassNode isTraitSelf(VariableExpression vexp) {
+    public static ClassNode isTraitSelf(final VariableExpression vexp) {
         if (Traits.THIS_OBJECT.equals(vexp.getName())) {
             Variable accessedVariable = vexp.getAccessedVariable();
             ClassNode type = accessedVariable != null ? accessedVariable.getType() : null;
@@ -2406,4 +2258,109 @@ public abstract class StaticTypeCheckingSupport {
         }
         return null;
     }
+
+    //--------------------------------------------------------------------------
+
+    /**
+     * A DGM-like class which adds support for method calls which are handled
+     * specifically by the Groovy compiler.
+     */
+    public static class ObjectArrayStaticTypesHelper {
+        public static <T> T getAt(final T[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static <T, U extends T> void putAt(final T[] array, final int index, final U value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class BooleanArrayStaticTypesHelper {
+        public static Boolean getAt(final boolean[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final boolean[] array, final int index, final boolean value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class CharArrayStaticTypesHelper {
+        public static Character getAt(final char[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final char[] array, final int index, final char value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class ByteArrayStaticTypesHelper {
+        public static Byte getAt(final byte[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final byte[] array, final int index, final byte value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class ShortArrayStaticTypesHelper {
+        public static Short getAt(final short[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final short[] array, final int index, final short value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class IntArrayStaticTypesHelper {
+        public static Integer getAt(final int[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final int[] array, final int index, final int value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class LongArrayStaticTypesHelper {
+        public static Long getAt(final long[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final long[] array, final int index, final long value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class FloatArrayStaticTypesHelper {
+        public static Float getAt(final float[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final float[] array, final int index, final float value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
+
+    public static class DoubleArrayStaticTypesHelper {
+        public static Double getAt(final double[] array, final int index) {
+            return array != null ? array[index] : null;
+        }
+        public static void putAt(final double[] array, final int index, final double value) {
+            if (array != null) {
+                array[index] = value;
+            }
+        }
+    }
 }


[groovy] 02/02: Improve back-compatibility further

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f0862ffc888c3d043fb3dee37bd553a55ad8c8eb
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Dec 21 01:54:11 2019 +0800

    Improve back-compatibility further
    
    (cherry picked from commit a22b1b810d4d706a4aff525c34cc55e399d0f585)
---
 src/main/java/org/codehaus/groovy/control/CompilationUnit.java | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 693baca..053cad2 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -1090,6 +1090,11 @@ public class CompilationUnit extends ProcessingUnit {
     }
 
     @Deprecated
+    public void applyToSourceUnits(final SourceUnitOperation op) throws CompilationFailedException {
+        op.doPhaseOperation(this);
+    }
+
+    @Deprecated
     public abstract static class SourceUnitOperation implements ISourceUnitOperation {
     }