You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/04/12 04:00:57 UTC

[groovy] branch master updated (1b5381b -> 4244569)

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

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


    from 1b5381b  Change doc URL from beta to non-beta (closes #908)
     new dbe9d2d  add some javadoc
     new 4244569  GROOVY-9079: STC: NPE in StaticTypeCheckingVisitor.inferSAMTypeGenericsInAssignment

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:
 .../groovy/ast/expr/ClosureExpression.java         |    6 +
 .../codehaus/groovy/ast/tools/ClosureUtils.java    |   15 +
 .../codehaus/groovy/control/ResolveVisitor.java    |   18 +-
 .../groovy/control/StaticImportVisitor.java        | 1155 ++++++++++----------
 .../transform/AutoFinalASTTransformation.java      |    3 +-
 .../transform/CategoryASTTransformation.java       |   19 +-
 .../transformers/ClosureExpressionTransformer.java |   11 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |   35 +-
 .../groovy/transform/stc/ClosuresSTCTest.groovy    |   16 +
 .../AutoFinalTransformBlackBoxTest.groovy          |   16 +
 10 files changed, 671 insertions(+), 623 deletions(-)


[groovy] 01/02: add some javadoc

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

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

commit dbe9d2d25c3c926f52d3c8b988893987148a63b4
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Apr 12 11:50:48 2019 +1000

    add some javadoc
---
 src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
index 62ba789..e2b2aee 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
@@ -74,10 +74,16 @@ public class ClosureExpression extends Expression {
         this.code = code;
     }
 
+    /**
+     * @return an array of zero (for implicit it) or more (when explicit args given) parameters or null otherwise (representing explicit no args)
+     */
     public Parameter[] getParameters() {
         return parameters;
     }
 
+    /**
+     * @return true if one or more explicit parameters are supplied
+     */
     public boolean isParameterSpecified() {
         return parameters != null && parameters.length > 0;
     }


[groovy] 02/02: GROOVY-9079: STC: NPE in StaticTypeCheckingVisitor.inferSAMTypeGenericsInAssignment

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

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

commit 4244569bb17d841d7df3828af4321a6e5dcc505a
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Apr 12 14:00:44 2019 +1000

    GROOVY-9079: STC: NPE in StaticTypeCheckingVisitor.inferSAMTypeGenericsInAssignment
    
    Includes some minor refactoring and fix for @AutoFinal
---
 .../codehaus/groovy/ast/tools/ClosureUtils.java    |   15 +
 .../codehaus/groovy/control/ResolveVisitor.java    |   18 +-
 .../groovy/control/StaticImportVisitor.java        | 1155 ++++++++++----------
 .../transform/AutoFinalASTTransformation.java      |    3 +-
 .../transform/CategoryASTTransformation.java       |   19 +-
 .../transformers/ClosureExpressionTransformer.java |   11 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |   35 +-
 .../groovy/transform/stc/ClosuresSTCTest.groovy    |   16 +
 .../AutoFinalTransformBlackBoxTest.groovy          |   16 +
 9 files changed, 665 insertions(+), 623 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/ClosureUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/ClosureUtils.java
index 06d4995..da07990 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/ClosureUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/ClosureUtils.java
@@ -19,6 +19,7 @@
 package org.codehaus.groovy.ast.tools;
 
 import groovy.lang.Closure;
+import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.control.io.ReaderSource;
 /**
@@ -66,4 +67,18 @@ public class ClosureUtils {
         return typeName.equals("java.lang.String");
     }
 
+    /**
+     * @return true if the ClosureExpression has an implicit 'it' parameter
+     */
+    public static boolean hasImplicitParameter(ClosureExpression ce) {
+        return ce.getParameters() != null && ce.getParameters().length == 0;
+    }
+
+    /**
+     * @return the parameters for the ClosureExpression
+     */
+    public static Parameter[] getParametersSafe(ClosureExpression ce) {
+        return ce.getParameters() != null ? ce.getParameters() : Parameter.EMPTY_ARRAY;
+    }
+
 }
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index ae2e133..aeca559 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -81,6 +81,7 @@ import java.util.Set;
 
 import static org.codehaus.groovy.ast.CompileUnit.ConstructedOuterNestedClassNode;
 import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
 
@@ -1232,17 +1233,14 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
     protected Expression transformClosureExpression(ClosureExpression ce) {
         boolean oldInClosure = inClosure;
         inClosure = true;
-        Parameter[] paras = ce.getParameters();
-        if (paras != null) {
-            for (Parameter para : paras) {
-                ClassNode t = para.getType();
-                resolveOrFail(t, ce);
-                visitAnnotations(para);
-                if (para.hasInitialExpression()) {
-                    para.setInitialExpression(transform(para.getInitialExpression()));
-                }
-                visitAnnotations(para);
+        for (Parameter para : getParametersSafe(ce)) {
+            ClassNode t = para.getType();
+            resolveOrFail(t, ce);
+            visitAnnotations(para);
+            if (para.hasInitialExpression()) {
+                para.setInitialExpression(transform(para.getInitialExpression()));
             }
+            visitAnnotations(para);
         }
 
         Statement code = ce.getCode();
diff --git a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
index 3283d2b..b1a1e56 100644
--- a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
@@ -1,578 +1,577 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.codehaus.groovy.control;
-
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.DynamicVariable;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.ImportNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.Variable;
-import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
-import org.codehaus.groovy.ast.expr.EmptyExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MapEntryExpression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.NamedArgumentListExpression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
-import org.codehaus.groovy.ast.expr.TupleExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
-import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.syntax.Types;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.groovy.ast.tools.ClassNodeUtils.getPropNameForAccessor;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.hasPossibleStaticMethod;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.hasPossibleStaticProperty;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.hasStaticProperty;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.isInnerClass;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.isValidAccessorName;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.getField;
-import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
-import static org.apache.groovy.util.BeanUtils.capitalize;
-
-/**
- * Visitor to resolve constants and method calls from static Imports
- */
-public class StaticImportVisitor extends ClassCodeExpressionTransformer {
-    private ClassNode currentClass;
-    private MethodNode currentMethod;
-    private SourceUnit source;
-    private boolean inSpecialConstructorCall;
-    private boolean inClosure;
-    private boolean inPropertyExpression;
-    private Expression foundConstant;
-    private Expression foundArgs;
-    private boolean inAnnotation;
-    private boolean inLeftExpression;
-
-    public void visitClass(ClassNode node, SourceUnit source) {
-        this.currentClass = node;
-        this.source = source;
-        super.visitClass(node);
-    }
-
-    @Override
-    protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
-        this.currentMethod = node;
-        super.visitConstructorOrMethod(node, isConstructor);
-        this.currentMethod = null;
-    }
-
-    @Override
-    public void visitAnnotations(AnnotatedNode node) {
-        boolean oldInAnnotation = inAnnotation;
-        inAnnotation = true;
-        super.visitAnnotations(node);
-        inAnnotation = oldInAnnotation;
-    }
-
-    public Expression transform(Expression exp) {
-        if (exp == null) return null;
-        if (exp.getClass() == VariableExpression.class) {
-            return transformVariableExpression((VariableExpression) exp);
-        }
-        if (exp.getClass() == BinaryExpression.class) {
-            return transformBinaryExpression((BinaryExpression) exp);
-        }
-        if (exp.getClass() == PropertyExpression.class) {
-            return transformPropertyExpression((PropertyExpression) exp);
-        }
-        if (exp.getClass() == MethodCallExpression.class) {
-            return transformMethodCallExpression((MethodCallExpression) exp);
-        }
-        if (exp.getClass() == ClosureExpression.class) {
-            return transformClosureExpression((ClosureExpression) exp);
-        }
-        if (exp.getClass() == ConstructorCallExpression.class) {
-            return transformConstructorCallExpression((ConstructorCallExpression) exp);
-        }
-        if (exp.getClass() == ArgumentListExpression.class) {
-            Expression result = exp.transformExpression(this);
-            if (inPropertyExpression) {
-                foundArgs = result;
-            }
-            return result;
-        }
-        if (exp instanceof ConstantExpression) {
-            Expression result = exp.transformExpression(this);
-            if (inPropertyExpression) {
-                foundConstant = result;
-            }
-            if (inAnnotation && exp instanceof AnnotationConstantExpression) {
-                ConstantExpression ce = (ConstantExpression) result;
-                if (ce.getValue() instanceof AnnotationNode) {
-                    // replicate a little bit of AnnotationVisitor here
-                    // because we can't wait until later to do this
-                    AnnotationNode an = (AnnotationNode) ce.getValue();
-                    Map<String, Expression> attributes = an.getMembers();
-                    for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
-                        Expression attrExpr = transform(entry.getValue());
-                        entry.setValue(attrExpr);
-                    }
-
-                }
-            }
-            return result;
-        }
-        return exp.transformExpression(this);
-    }
-
-    // if you have a Bar class with a static foo property, and this:
-    //   import static Bar.foo as baz
-    // then this constructor (not normal usage of statics):
-    //   new Bar(baz:1)
-    // will become:
-    //   new Bar(foo:1)
-
-    private Expression transformMapEntryExpression(MapEntryExpression me, ClassNode constructorCallType) {
-        Expression key = me.getKeyExpression();
-        Expression value = me.getValueExpression();
-        ModuleNode module = currentClass.getModule();
-        if (module != null && key instanceof ConstantExpression) {
-            Map<String, ImportNode> importNodes = module.getStaticImports();
-            if (importNodes.containsKey(key.getText())) {
-                ImportNode importNode = importNodes.get(key.getText());
-                if (importNode.getType().equals(constructorCallType)) {
-                    String newKey = importNode.getFieldName();
-                    return new MapEntryExpression(new ConstantExpression(newKey), value.transformExpression(this));
-                }
-            }
-        }
-        return me;
-    }
-
-    protected Expression transformBinaryExpression(BinaryExpression be) {
-        int type = be.getOperation().getType();
-        boolean oldInLeftExpression;
-        Expression right = transform(be.getRightExpression());
-        be.setRightExpression(right);
-        Expression left;
-        if (type == Types.EQUAL && be.getLeftExpression() instanceof VariableExpression) {
-            oldInLeftExpression = inLeftExpression;
-            inLeftExpression = true;
-            left = transform(be.getLeftExpression());
-            inLeftExpression = oldInLeftExpression;
-            if (left instanceof StaticMethodCallExpression) {
-                StaticMethodCallExpression smce = (StaticMethodCallExpression) left;
-                StaticMethodCallExpression result = new StaticMethodCallExpression(smce.getOwnerType(), smce.getMethod(), right);
-                setSourcePosition(result, be);
-                return result;
-            }
-        } else {
-            left = transform(be.getLeftExpression());
-        }
-        be.setLeftExpression(left);
-        return be;
-    }
-
-    protected Expression transformVariableExpression(VariableExpression ve) {
-        Variable v = ve.getAccessedVariable();
-        if (v instanceof DynamicVariable) {
-            Expression result = findStaticFieldOrPropAccessorImportFromModule(v.getName());
-            if (result != null) {
-                setSourcePosition(result, ve);
-                if (inAnnotation) {
-                    result = transformInlineConstants(result);
-                }
-                return result;
-            }
-        } else if (v instanceof FieldNode) {
-            if (inSpecialConstructorCall) { // GROOVY-8819
-                FieldNode fn = (FieldNode) v;
-                ClassNode declaringClass = fn.getDeclaringClass();
-                if (fn.isStatic() && currentClass.isDerivedFrom(declaringClass)) {
-                    Expression result = new PropertyExpression(new ClassExpression(declaringClass), v.getName());
-                    result.setSourcePosition(ve);
-
-                    return result;
-                }
-            }
-        }
-        return ve;
-    }
-
-    /**
-     * Set the source position of toSet including its property expression if it has one.
-     *
-     * @param toSet resulting node
-     * @param origNode original node
-     */
-    private static void setSourcePosition(Expression toSet, Expression origNode) {
-        toSet.setSourcePosition(origNode);
-        if (toSet instanceof PropertyExpression) {
-            ((PropertyExpression) toSet).getProperty().setSourcePosition(origNode);
-        }
-    }
-
-    protected Expression transformMethodCallExpression(MethodCallExpression mce) {
-        Expression args = transform(mce.getArguments());
-        Expression method = transform(mce.getMethod());
-        Expression object = transform(mce.getObjectExpression());
-        boolean isExplicitThisOrSuper = false;
-        boolean isExplicitSuper = false;
-        if (object instanceof VariableExpression) {
-            VariableExpression ve = (VariableExpression) object;
-            isExplicitThisOrSuper = !mce.isImplicitThis() && (ve.isThisExpression() || ve.isSuperExpression());
-            isExplicitSuper = ve.isSuperExpression();
-        }
-
-        if (mce.isImplicitThis() || isExplicitThisOrSuper) {
-            if (mce.isImplicitThis()) {
-                if (null == currentClass.tryFindPossibleMethod(mce.getMethodAsString(), args)) {
-
-                    Expression ret = findStaticMethodImportFromModule(method, args);
-                    if (ret != null) {
-                        setSourcePosition(ret, mce);
-                        return ret;
-                    }
-                    if (method instanceof ConstantExpression && !inLeftExpression) {
-                        // could be a closure field
-                        String methodName = (String) ((ConstantExpression) method).getValue();
-                        ret = findStaticFieldOrPropAccessorImportFromModule(methodName);
-                        if (ret != null) {
-                            ret = new MethodCallExpression(ret, "call", args);
-                            setSourcePosition(ret, mce);
-                            return ret;
-                        }
-                    }
-                }
-            } else if (currentMethod!=null && currentMethod.isStatic() && isExplicitSuper) {
-                MethodCallExpression ret = new MethodCallExpression(new ClassExpression(currentClass.getSuperClass()), method, args);
-                setSourcePosition(ret, mce);
-                return ret;
-            }
-
-            if (method instanceof ConstantExpression) {
-                ConstantExpression ce = (ConstantExpression) method;
-                Object value = ce.getValue();
-                if (value instanceof String) {
-                    boolean foundInstanceMethod = false;
-                    String methodName = (String) value;
-                    boolean inInnerClass = isInnerClass(currentClass);
-                    if (currentMethod != null && !currentMethod.isStatic()) {
-                        if (currentClass.hasPossibleMethod(methodName, args)) {
-                            foundInstanceMethod = true;
-                        }
-                    }
-                    boolean lookForPossibleStaticMethod = !methodName.equals("call");
-                    lookForPossibleStaticMethod &= !foundInstanceMethod;
-                    lookForPossibleStaticMethod |= inSpecialConstructorCall;
-                    lookForPossibleStaticMethod &= !inInnerClass;
-                    if (!inClosure && lookForPossibleStaticMethod &&
-                            (hasPossibleStaticMethod(currentClass, methodName, args, true))
-                            || hasPossibleStaticProperty(currentClass, methodName)) {
-                        StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass, methodName, args);
-                        setSourcePosition(smce, mce);
-                        return smce;
-                    }
-                    if (!inClosure && inInnerClass && inSpecialConstructorCall && mce.isImplicitThis() && !foundInstanceMethod) {
-                        if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
-                            object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
-                        } else if (hasPossibleStaticMethod(currentClass.getOuterClass(), methodName, args, true)
-                                || hasPossibleStaticProperty(currentClass.getOuterClass(), methodName)) {
-                            StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
-                            setSourcePosition(smce, mce);
-                            return smce;
-                        }
-                    }
-
-                    if (mce.isImplicitThis() && lookForPossibleStaticMethod && hasPossibleStaticMethod(currentClass, methodName, args, true)) {
-                        StaticMethodCallExpression result = new StaticMethodCallExpression(currentClass, methodName, args);
-                        result.setSourcePosition(mce);
-                        return result;
-                    }
-                }
-            }
-        }
-
-        MethodCallExpression result = new MethodCallExpression(object, method, args);
-        result.setSafe(mce.isSafe());
-        result.setImplicitThis(mce.isImplicitThis());
-        result.setSpreadSafe(mce.isSpreadSafe());
-        result.setMethodTarget(mce.getMethodTarget());
-        // GROOVY-6757
-        result.setGenericsTypes(mce.getGenericsTypes());
-        setSourcePosition(result, mce);
-        return result;
-    }
-
-    protected Expression transformConstructorCallExpression(ConstructorCallExpression cce) {
-        inSpecialConstructorCall = cce.isSpecialCall();
-        Expression expression = cce.getArguments();
-        if (expression instanceof TupleExpression) {
-            TupleExpression tuple = (TupleExpression) expression;
-            if (tuple.getExpressions().size() == 1) {
-                expression = tuple.getExpression(0);
-                if (expression instanceof NamedArgumentListExpression) {
-                    NamedArgumentListExpression namedArgs = (NamedArgumentListExpression) expression;
-                    List<MapEntryExpression> entryExpressions = namedArgs.getMapEntryExpressions();
-                    for (int i = 0; i < entryExpressions.size(); i++) {
-                        entryExpressions.set(i, (MapEntryExpression) transformMapEntryExpression(entryExpressions.get(i), cce.getType()));
-                    }
-                }
-            }
-        }
-        Expression ret = cce.transformExpression(this);
-        inSpecialConstructorCall = false;
-        return ret;
-    }
-
-    protected Expression transformClosureExpression(ClosureExpression ce) {
-        boolean oldInClosure = inClosure;
-        inClosure = true;
-        if (ce.getParameters() != null) {
-            for (Parameter p : ce.getParameters()) {
-                if (p.hasInitialExpression()) {
-                    p.setInitialExpression(transform(p.getInitialExpression()));
-                }
-            }
-        }
-        Statement code = ce.getCode();
-        if (code != null) code.visit(this);
-        inClosure = oldInClosure;
-        return ce;
-    }
-
-    protected Expression transformPropertyExpression(PropertyExpression pe) {
-        if (currentMethod!=null && currentMethod.isStatic()
-                && pe.getObjectExpression() instanceof VariableExpression
-                && ((VariableExpression) pe.getObjectExpression()).isSuperExpression()) {
-            PropertyExpression pexp = new PropertyExpression(
-                    new ClassExpression(currentClass.getSuperClass()),
-                    transform(pe.getProperty())
-            );
-            pexp.setSourcePosition(pe);
-            return pexp;
-        }
-        boolean oldInPropertyExpression = inPropertyExpression;
-        Expression oldFoundArgs = foundArgs;
-        Expression oldFoundConstant = foundConstant;
-        inPropertyExpression = true;
-        foundArgs = null;
-        foundConstant = null;
-        Expression objectExpression = transform(pe.getObjectExpression());
-        boolean candidate = false;
-        if (objectExpression instanceof MethodCallExpression) {
-            candidate = ((MethodCallExpression)objectExpression).isImplicitThis();
-        }
-
-        if (foundArgs != null && foundConstant != null && candidate) {
-            Expression result = findStaticMethodImportFromModule(foundConstant, foundArgs);
-            if (result != null) {
-                objectExpression = result;
-                objectExpression.setSourcePosition(pe);
-            }
-        }
-        inPropertyExpression = oldInPropertyExpression;
-        foundArgs = oldFoundArgs;
-        foundConstant = oldFoundConstant;
-        pe.setObjectExpression(objectExpression);
-        return pe;
-    }
-
-    private Expression findStaticFieldOrPropAccessorImportFromModule(String name) {
-        ModuleNode module = currentClass.getModule();
-        if (module == null) return null;
-        Map<String, ImportNode> importNodes = module.getStaticImports();
-        Expression expression;
-        String accessorName = getAccessorName(name);
-        // look for one of these:
-        //   import static MyClass.setProp [as setOtherProp]
-        //   import static MyClass.getProp [as getOtherProp]
-        // when resolving prop reference
-        if (importNodes.containsKey(accessorName)) {
-            expression = findStaticProperty(importNodes, accessorName);
-            if (expression != null) return expression;
-        }
-        if (accessorName.startsWith("get")) {
-            accessorName = "is" + accessorName.substring(3);
-            if (importNodes.containsKey(accessorName)) {
-                expression = findStaticProperty(importNodes, accessorName);
-                if (expression != null) return expression;
-            }
-        }
-
-        // look for one of these:
-        //   import static MyClass.prop [as otherProp]
-        // when resolving prop or field reference
-        if (importNodes.containsKey(name)) {
-            ImportNode importNode = importNodes.get(name);
-            expression = findStaticPropertyAccessor(importNode.getType(), importNode.getFieldName());
-            if (expression != null) return expression;
-            expression = findStaticField(importNode.getType(), importNode.getFieldName());
-            if (expression != null) return expression;
-        }
-        // look for one of these:
-        //   import static MyClass.*
-        // when resolving prop or field reference
-        for (ImportNode importNode : module.getStaticStarImports().values()) {
-            ClassNode node = importNode.getType();
-            expression = findStaticPropertyAccessor(node, name);
-            if (expression != null) return expression;
-            expression = findStaticField(node, name);
-            if (expression != null) return expression;
-        }
-        return null;
-    }
-
-    private Expression findStaticProperty(Map<String, ImportNode> importNodes, String accessorName) {
-        Expression result = null;
-        ImportNode importNode = importNodes.get(accessorName);
-        ClassNode importClass = importNode.getType();
-        String importMember = importNode.getFieldName();
-        result = findStaticPropertyAccessorByFullName(importClass, importMember);
-        if (result == null) {
-            result = findStaticPropertyAccessor(importClass, getPropNameForAccessor(importMember));
-        }
-        return result;
-    }
-
-    private Expression findStaticMethodImportFromModule(Expression method, Expression args) {
-        ModuleNode module = currentClass.getModule();
-        if (module == null || !(method instanceof ConstantExpression)) return null;
-        Map<String, ImportNode> importNodes = module.getStaticImports();
-        ConstantExpression ce = (ConstantExpression) method;
-        Expression expression;
-        Object value = ce.getValue();
-        // skip non-Strings, e.g. Integer
-        if (!(value instanceof String)) return null;
-        final String name = (String) value;
-        // look for one of these:
-        //   import static SomeClass.method [as otherName]
-        // when resolving methodCall() or getProp() or setProp()
-        if (importNodes.containsKey(name)) {
-            ImportNode importNode = importNodes.get(name);
-            expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
-            if (expression != null) return expression;
-            expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
-            if (expression != null) {
-                return new StaticMethodCallExpression(importNode.getType(), importNode.getFieldName(), args);
-            }
-        }
-        // look for one of these:
-        //   import static SomeClass.someProp [as otherName]
-        // when resolving getProp() or setProp()
-        if (isValidAccessorName(name)) {
-            String propName = getPropNameForAccessor(name);
-            if (importNodes.containsKey(propName)) {
-                ImportNode importNode = importNodes.get(propName);
-                ClassNode importClass = importNode.getType();
-                String importMember = importNode.getFieldName();
-                expression = findStaticMethod(importClass, prefix(name) + capitalize(importMember), args);
-                if (expression != null) return expression;
-                expression = findStaticPropertyAccessorGivenArgs(importClass, importMember, args);
-                if (expression != null) {
-                    return new StaticMethodCallExpression(importClass, prefix(name) + capitalize(importMember), args);
-                }
-            }
-        }
-        Map<String, ImportNode> starImports = module.getStaticStarImports();
-        ClassNode starImportType;
-        if (currentClass.isEnum() && starImports.containsKey(currentClass.getName())) {
-            ImportNode importNode = starImports.get(currentClass.getName());
-            starImportType = importNode == null ? null : importNode.getType();
-            expression = findStaticMethod(starImportType, name, args);
-            if (expression != null) return expression;
-        } else {
-            for (ImportNode importNode : starImports.values()) {
-                starImportType = importNode == null ? null : importNode.getType();
-                expression = findStaticMethod(starImportType, name, args);
-                if (expression != null) return expression;
-                expression = findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
-                if (expression != null) {
-                    return new StaticMethodCallExpression(starImportType, name, args);
-                }
-            }
-        }
-        return null;
-    }
-
-    private static String prefix(String name) {
-        return name.startsWith("is") ? "is" : name.substring(0, 3);
-    }
-
-    private String getAccessorName(String name) {
-        return (inLeftExpression ? "set" : "get") + capitalize(name);
-    }
-
-    private Expression findStaticPropertyAccessorGivenArgs(ClassNode staticImportType, String propName, Expression args) {
-        // TODO validate args?
-        return findStaticPropertyAccessor(staticImportType, propName);
-    }
-
-    private Expression findStaticPropertyAccessor(ClassNode staticImportType, String propName) {
-        String accessorName = getAccessorName(propName);
-        Expression accessor = findStaticPropertyAccessorByFullName(staticImportType, accessorName);
-        if (accessor == null && accessorName.startsWith("get")) {
-            accessor = findStaticPropertyAccessorByFullName(staticImportType, "is" + accessorName.substring(3));
-        }
-        if (accessor == null && hasStaticProperty(staticImportType, propName)) {
-            // args will be replaced
-            if (inLeftExpression)
-                accessor = new StaticMethodCallExpression(staticImportType, accessorName, ArgumentListExpression.EMPTY_ARGUMENTS);
-            else
-                accessor = new PropertyExpression(new ClassExpression(staticImportType), propName);
-        }
-        return accessor;
-    }
-
-    private Expression findStaticPropertyAccessorByFullName(ClassNode staticImportType, String accessorMethodName) {
-        // anything will do as we only check size == 1
-        ArgumentListExpression dummyArgs = new ArgumentListExpression();
-        dummyArgs.addExpression(EmptyExpression.INSTANCE);
-        return findStaticMethod(staticImportType, accessorMethodName, (inLeftExpression ? dummyArgs : ArgumentListExpression.EMPTY_ARGUMENTS));
-    }
-
-    private static Expression findStaticField(ClassNode staticImportType, String fieldName) {
-        if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
-            FieldNode field = getField(staticImportType, fieldName);
-            if (field != null && field.isStatic())
-                return new PropertyExpression(new ClassExpression(staticImportType), fieldName);
-        }
-        return null;
-    }
-
-    private static Expression findStaticMethod(ClassNode staticImportType, String methodName, Expression args) {
-        if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
-            if (staticImportType.hasPossibleStaticMethod(methodName, args)) {
-                return new StaticMethodCallExpression(staticImportType, methodName, args);
-            }
-        }
-        return null;
-    }
-
-    protected SourceUnit getSourceUnit() {
-        return source;
-    }
-}
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.control;
+
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.DynamicVariable;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.ImportNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.Variable;
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
+import org.codehaus.groovy.ast.expr.EmptyExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MapEntryExpression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.NamedArgumentListExpression;
+import org.codehaus.groovy.ast.expr.PropertyExpression;
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
+import org.codehaus.groovy.ast.expr.TupleExpression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.syntax.Types;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.groovy.ast.tools.ClassNodeUtils.getPropNameForAccessor;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.hasPossibleStaticMethod;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.hasPossibleStaticProperty;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.hasStaticProperty;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.isInnerClass;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.isValidAccessorName;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.getField;
+import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
+import static org.apache.groovy.util.BeanUtils.capitalize;
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
+
+/**
+ * Visitor to resolve constants and method calls from static Imports
+ */
+public class StaticImportVisitor extends ClassCodeExpressionTransformer {
+    private ClassNode currentClass;
+    private MethodNode currentMethod;
+    private SourceUnit source;
+    private boolean inSpecialConstructorCall;
+    private boolean inClosure;
+    private boolean inPropertyExpression;
+    private Expression foundConstant;
+    private Expression foundArgs;
+    private boolean inAnnotation;
+    private boolean inLeftExpression;
+
+    public void visitClass(ClassNode node, SourceUnit source) {
+        this.currentClass = node;
+        this.source = source;
+        super.visitClass(node);
+    }
+
+    @Override
+    protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
+        this.currentMethod = node;
+        super.visitConstructorOrMethod(node, isConstructor);
+        this.currentMethod = null;
+    }
+
+    @Override
+    public void visitAnnotations(AnnotatedNode node) {
+        boolean oldInAnnotation = inAnnotation;
+        inAnnotation = true;
+        super.visitAnnotations(node);
+        inAnnotation = oldInAnnotation;
+    }
+
+    public Expression transform(Expression exp) {
+        if (exp == null) return null;
+        if (exp.getClass() == VariableExpression.class) {
+            return transformVariableExpression((VariableExpression) exp);
+        }
+        if (exp.getClass() == BinaryExpression.class) {
+            return transformBinaryExpression((BinaryExpression) exp);
+        }
+        if (exp.getClass() == PropertyExpression.class) {
+            return transformPropertyExpression((PropertyExpression) exp);
+        }
+        if (exp.getClass() == MethodCallExpression.class) {
+            return transformMethodCallExpression((MethodCallExpression) exp);
+        }
+        if (exp.getClass() == ClosureExpression.class) {
+            return transformClosureExpression((ClosureExpression) exp);
+        }
+        if (exp.getClass() == ConstructorCallExpression.class) {
+            return transformConstructorCallExpression((ConstructorCallExpression) exp);
+        }
+        if (exp.getClass() == ArgumentListExpression.class) {
+            Expression result = exp.transformExpression(this);
+            if (inPropertyExpression) {
+                foundArgs = result;
+            }
+            return result;
+        }
+        if (exp instanceof ConstantExpression) {
+            Expression result = exp.transformExpression(this);
+            if (inPropertyExpression) {
+                foundConstant = result;
+            }
+            if (inAnnotation && exp instanceof AnnotationConstantExpression) {
+                ConstantExpression ce = (ConstantExpression) result;
+                if (ce.getValue() instanceof AnnotationNode) {
+                    // replicate a little bit of AnnotationVisitor here
+                    // because we can't wait until later to do this
+                    AnnotationNode an = (AnnotationNode) ce.getValue();
+                    Map<String, Expression> attributes = an.getMembers();
+                    for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
+                        Expression attrExpr = transform(entry.getValue());
+                        entry.setValue(attrExpr);
+                    }
+
+                }
+            }
+            return result;
+        }
+        return exp.transformExpression(this);
+    }
+
+    // if you have a Bar class with a static foo property, and this:
+    //   import static Bar.foo as baz
+    // then this constructor (not normal usage of statics):
+    //   new Bar(baz:1)
+    // will become:
+    //   new Bar(foo:1)
+
+    private Expression transformMapEntryExpression(MapEntryExpression me, ClassNode constructorCallType) {
+        Expression key = me.getKeyExpression();
+        Expression value = me.getValueExpression();
+        ModuleNode module = currentClass.getModule();
+        if (module != null && key instanceof ConstantExpression) {
+            Map<String, ImportNode> importNodes = module.getStaticImports();
+            if (importNodes.containsKey(key.getText())) {
+                ImportNode importNode = importNodes.get(key.getText());
+                if (importNode.getType().equals(constructorCallType)) {
+                    String newKey = importNode.getFieldName();
+                    return new MapEntryExpression(new ConstantExpression(newKey), value.transformExpression(this));
+                }
+            }
+        }
+        return me;
+    }
+
+    protected Expression transformBinaryExpression(BinaryExpression be) {
+        int type = be.getOperation().getType();
+        boolean oldInLeftExpression;
+        Expression right = transform(be.getRightExpression());
+        be.setRightExpression(right);
+        Expression left;
+        if (type == Types.EQUAL && be.getLeftExpression() instanceof VariableExpression) {
+            oldInLeftExpression = inLeftExpression;
+            inLeftExpression = true;
+            left = transform(be.getLeftExpression());
+            inLeftExpression = oldInLeftExpression;
+            if (left instanceof StaticMethodCallExpression) {
+                StaticMethodCallExpression smce = (StaticMethodCallExpression) left;
+                StaticMethodCallExpression result = new StaticMethodCallExpression(smce.getOwnerType(), smce.getMethod(), right);
+                setSourcePosition(result, be);
+                return result;
+            }
+        } else {
+            left = transform(be.getLeftExpression());
+        }
+        be.setLeftExpression(left);
+        return be;
+    }
+
+    protected Expression transformVariableExpression(VariableExpression ve) {
+        Variable v = ve.getAccessedVariable();
+        if (v instanceof DynamicVariable) {
+            Expression result = findStaticFieldOrPropAccessorImportFromModule(v.getName());
+            if (result != null) {
+                setSourcePosition(result, ve);
+                if (inAnnotation) {
+                    result = transformInlineConstants(result);
+                }
+                return result;
+            }
+        } else if (v instanceof FieldNode) {
+            if (inSpecialConstructorCall) { // GROOVY-8819
+                FieldNode fn = (FieldNode) v;
+                ClassNode declaringClass = fn.getDeclaringClass();
+                if (fn.isStatic() && currentClass.isDerivedFrom(declaringClass)) {
+                    Expression result = new PropertyExpression(new ClassExpression(declaringClass), v.getName());
+                    result.setSourcePosition(ve);
+
+                    return result;
+                }
+            }
+        }
+        return ve;
+    }
+
+    /**
+     * Set the source position of toSet including its property expression if it has one.
+     *
+     * @param toSet resulting node
+     * @param origNode original node
+     */
+    private static void setSourcePosition(Expression toSet, Expression origNode) {
+        toSet.setSourcePosition(origNode);
+        if (toSet instanceof PropertyExpression) {
+            ((PropertyExpression) toSet).getProperty().setSourcePosition(origNode);
+        }
+    }
+
+    protected Expression transformMethodCallExpression(MethodCallExpression mce) {
+        Expression args = transform(mce.getArguments());
+        Expression method = transform(mce.getMethod());
+        Expression object = transform(mce.getObjectExpression());
+        boolean isExplicitThisOrSuper = false;
+        boolean isExplicitSuper = false;
+        if (object instanceof VariableExpression) {
+            VariableExpression ve = (VariableExpression) object;
+            isExplicitThisOrSuper = !mce.isImplicitThis() && (ve.isThisExpression() || ve.isSuperExpression());
+            isExplicitSuper = ve.isSuperExpression();
+        }
+
+        if (mce.isImplicitThis() || isExplicitThisOrSuper) {
+            if (mce.isImplicitThis()) {
+                if (null == currentClass.tryFindPossibleMethod(mce.getMethodAsString(), args)) {
+
+                    Expression ret = findStaticMethodImportFromModule(method, args);
+                    if (ret != null) {
+                        setSourcePosition(ret, mce);
+                        return ret;
+                    }
+                    if (method instanceof ConstantExpression && !inLeftExpression) {
+                        // could be a closure field
+                        String methodName = (String) ((ConstantExpression) method).getValue();
+                        ret = findStaticFieldOrPropAccessorImportFromModule(methodName);
+                        if (ret != null) {
+                            ret = new MethodCallExpression(ret, "call", args);
+                            setSourcePosition(ret, mce);
+                            return ret;
+                        }
+                    }
+                }
+            } else if (currentMethod!=null && currentMethod.isStatic() && isExplicitSuper) {
+                MethodCallExpression ret = new MethodCallExpression(new ClassExpression(currentClass.getSuperClass()), method, args);
+                setSourcePosition(ret, mce);
+                return ret;
+            }
+
+            if (method instanceof ConstantExpression) {
+                ConstantExpression ce = (ConstantExpression) method;
+                Object value = ce.getValue();
+                if (value instanceof String) {
+                    boolean foundInstanceMethod = false;
+                    String methodName = (String) value;
+                    boolean inInnerClass = isInnerClass(currentClass);
+                    if (currentMethod != null && !currentMethod.isStatic()) {
+                        if (currentClass.hasPossibleMethod(methodName, args)) {
+                            foundInstanceMethod = true;
+                        }
+                    }
+                    boolean lookForPossibleStaticMethod = !methodName.equals("call");
+                    lookForPossibleStaticMethod &= !foundInstanceMethod;
+                    lookForPossibleStaticMethod |= inSpecialConstructorCall;
+                    lookForPossibleStaticMethod &= !inInnerClass;
+                    if (!inClosure && lookForPossibleStaticMethod &&
+                            (hasPossibleStaticMethod(currentClass, methodName, args, true))
+                            || hasPossibleStaticProperty(currentClass, methodName)) {
+                        StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass, methodName, args);
+                        setSourcePosition(smce, mce);
+                        return smce;
+                    }
+                    if (!inClosure && inInnerClass && inSpecialConstructorCall && mce.isImplicitThis() && !foundInstanceMethod) {
+                        if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
+                            object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
+                        } else if (hasPossibleStaticMethod(currentClass.getOuterClass(), methodName, args, true)
+                                || hasPossibleStaticProperty(currentClass.getOuterClass(), methodName)) {
+                            StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
+                            setSourcePosition(smce, mce);
+                            return smce;
+                        }
+                    }
+
+                    if (mce.isImplicitThis() && lookForPossibleStaticMethod && hasPossibleStaticMethod(currentClass, methodName, args, true)) {
+                        StaticMethodCallExpression result = new StaticMethodCallExpression(currentClass, methodName, args);
+                        result.setSourcePosition(mce);
+                        return result;
+                    }
+                }
+            }
+        }
+
+        MethodCallExpression result = new MethodCallExpression(object, method, args);
+        result.setSafe(mce.isSafe());
+        result.setImplicitThis(mce.isImplicitThis());
+        result.setSpreadSafe(mce.isSpreadSafe());
+        result.setMethodTarget(mce.getMethodTarget());
+        // GROOVY-6757
+        result.setGenericsTypes(mce.getGenericsTypes());
+        setSourcePosition(result, mce);
+        return result;
+    }
+
+    protected Expression transformConstructorCallExpression(ConstructorCallExpression cce) {
+        inSpecialConstructorCall = cce.isSpecialCall();
+        Expression expression = cce.getArguments();
+        if (expression instanceof TupleExpression) {
+            TupleExpression tuple = (TupleExpression) expression;
+            if (tuple.getExpressions().size() == 1) {
+                expression = tuple.getExpression(0);
+                if (expression instanceof NamedArgumentListExpression) {
+                    NamedArgumentListExpression namedArgs = (NamedArgumentListExpression) expression;
+                    List<MapEntryExpression> entryExpressions = namedArgs.getMapEntryExpressions();
+                    for (int i = 0; i < entryExpressions.size(); i++) {
+                        entryExpressions.set(i, (MapEntryExpression) transformMapEntryExpression(entryExpressions.get(i), cce.getType()));
+                    }
+                }
+            }
+        }
+        Expression ret = cce.transformExpression(this);
+        inSpecialConstructorCall = false;
+        return ret;
+    }
+
+    protected Expression transformClosureExpression(ClosureExpression ce) {
+        boolean oldInClosure = inClosure;
+        inClosure = true;
+        for (Parameter p : getParametersSafe(ce)) {
+            if (p.hasInitialExpression()) {
+                p.setInitialExpression(transform(p.getInitialExpression()));
+            }
+        }
+        Statement code = ce.getCode();
+        if (code != null) code.visit(this);
+        inClosure = oldInClosure;
+        return ce;
+    }
+
+    protected Expression transformPropertyExpression(PropertyExpression pe) {
+        if (currentMethod!=null && currentMethod.isStatic()
+                && pe.getObjectExpression() instanceof VariableExpression
+                && ((VariableExpression) pe.getObjectExpression()).isSuperExpression()) {
+            PropertyExpression pexp = new PropertyExpression(
+                    new ClassExpression(currentClass.getSuperClass()),
+                    transform(pe.getProperty())
+            );
+            pexp.setSourcePosition(pe);
+            return pexp;
+        }
+        boolean oldInPropertyExpression = inPropertyExpression;
+        Expression oldFoundArgs = foundArgs;
+        Expression oldFoundConstant = foundConstant;
+        inPropertyExpression = true;
+        foundArgs = null;
+        foundConstant = null;
+        Expression objectExpression = transform(pe.getObjectExpression());
+        boolean candidate = false;
+        if (objectExpression instanceof MethodCallExpression) {
+            candidate = ((MethodCallExpression)objectExpression).isImplicitThis();
+        }
+
+        if (foundArgs != null && foundConstant != null && candidate) {
+            Expression result = findStaticMethodImportFromModule(foundConstant, foundArgs);
+            if (result != null) {
+                objectExpression = result;
+                objectExpression.setSourcePosition(pe);
+            }
+        }
+        inPropertyExpression = oldInPropertyExpression;
+        foundArgs = oldFoundArgs;
+        foundConstant = oldFoundConstant;
+        pe.setObjectExpression(objectExpression);
+        return pe;
+    }
+
+    private Expression findStaticFieldOrPropAccessorImportFromModule(String name) {
+        ModuleNode module = currentClass.getModule();
+        if (module == null) return null;
+        Map<String, ImportNode> importNodes = module.getStaticImports();
+        Expression expression;
+        String accessorName = getAccessorName(name);
+        // look for one of these:
+        //   import static MyClass.setProp [as setOtherProp]
+        //   import static MyClass.getProp [as getOtherProp]
+        // when resolving prop reference
+        if (importNodes.containsKey(accessorName)) {
+            expression = findStaticProperty(importNodes, accessorName);
+            if (expression != null) return expression;
+        }
+        if (accessorName.startsWith("get")) {
+            accessorName = "is" + accessorName.substring(3);
+            if (importNodes.containsKey(accessorName)) {
+                expression = findStaticProperty(importNodes, accessorName);
+                if (expression != null) return expression;
+            }
+        }
+
+        // look for one of these:
+        //   import static MyClass.prop [as otherProp]
+        // when resolving prop or field reference
+        if (importNodes.containsKey(name)) {
+            ImportNode importNode = importNodes.get(name);
+            expression = findStaticPropertyAccessor(importNode.getType(), importNode.getFieldName());
+            if (expression != null) return expression;
+            expression = findStaticField(importNode.getType(), importNode.getFieldName());
+            if (expression != null) return expression;
+        }
+        // look for one of these:
+        //   import static MyClass.*
+        // when resolving prop or field reference
+        for (ImportNode importNode : module.getStaticStarImports().values()) {
+            ClassNode node = importNode.getType();
+            expression = findStaticPropertyAccessor(node, name);
+            if (expression != null) return expression;
+            expression = findStaticField(node, name);
+            if (expression != null) return expression;
+        }
+        return null;
+    }
+
+    private Expression findStaticProperty(Map<String, ImportNode> importNodes, String accessorName) {
+        Expression result = null;
+        ImportNode importNode = importNodes.get(accessorName);
+        ClassNode importClass = importNode.getType();
+        String importMember = importNode.getFieldName();
+        result = findStaticPropertyAccessorByFullName(importClass, importMember);
+        if (result == null) {
+            result = findStaticPropertyAccessor(importClass, getPropNameForAccessor(importMember));
+        }
+        return result;
+    }
+
+    private Expression findStaticMethodImportFromModule(Expression method, Expression args) {
+        ModuleNode module = currentClass.getModule();
+        if (module == null || !(method instanceof ConstantExpression)) return null;
+        Map<String, ImportNode> importNodes = module.getStaticImports();
+        ConstantExpression ce = (ConstantExpression) method;
+        Expression expression;
+        Object value = ce.getValue();
+        // skip non-Strings, e.g. Integer
+        if (!(value instanceof String)) return null;
+        final String name = (String) value;
+        // look for one of these:
+        //   import static SomeClass.method [as otherName]
+        // when resolving methodCall() or getProp() or setProp()
+        if (importNodes.containsKey(name)) {
+            ImportNode importNode = importNodes.get(name);
+            expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
+            if (expression != null) return expression;
+            expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
+            if (expression != null) {
+                return new StaticMethodCallExpression(importNode.getType(), importNode.getFieldName(), args);
+            }
+        }
+        // look for one of these:
+        //   import static SomeClass.someProp [as otherName]
+        // when resolving getProp() or setProp()
+        if (isValidAccessorName(name)) {
+            String propName = getPropNameForAccessor(name);
+            if (importNodes.containsKey(propName)) {
+                ImportNode importNode = importNodes.get(propName);
+                ClassNode importClass = importNode.getType();
+                String importMember = importNode.getFieldName();
+                expression = findStaticMethod(importClass, prefix(name) + capitalize(importMember), args);
+                if (expression != null) return expression;
+                expression = findStaticPropertyAccessorGivenArgs(importClass, importMember, args);
+                if (expression != null) {
+                    return new StaticMethodCallExpression(importClass, prefix(name) + capitalize(importMember), args);
+                }
+            }
+        }
+        Map<String, ImportNode> starImports = module.getStaticStarImports();
+        ClassNode starImportType;
+        if (currentClass.isEnum() && starImports.containsKey(currentClass.getName())) {
+            ImportNode importNode = starImports.get(currentClass.getName());
+            starImportType = importNode == null ? null : importNode.getType();
+            expression = findStaticMethod(starImportType, name, args);
+            if (expression != null) return expression;
+        } else {
+            for (ImportNode importNode : starImports.values()) {
+                starImportType = importNode == null ? null : importNode.getType();
+                expression = findStaticMethod(starImportType, name, args);
+                if (expression != null) return expression;
+                expression = findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
+                if (expression != null) {
+                    return new StaticMethodCallExpression(starImportType, name, args);
+                }
+            }
+        }
+        return null;
+    }
+
+    private static String prefix(String name) {
+        return name.startsWith("is") ? "is" : name.substring(0, 3);
+    }
+
+    private String getAccessorName(String name) {
+        return (inLeftExpression ? "set" : "get") + capitalize(name);
+    }
+
+    private Expression findStaticPropertyAccessorGivenArgs(ClassNode staticImportType, String propName, Expression args) {
+        // TODO validate args?
+        return findStaticPropertyAccessor(staticImportType, propName);
+    }
+
+    private Expression findStaticPropertyAccessor(ClassNode staticImportType, String propName) {
+        String accessorName = getAccessorName(propName);
+        Expression accessor = findStaticPropertyAccessorByFullName(staticImportType, accessorName);
+        if (accessor == null && accessorName.startsWith("get")) {
+            accessor = findStaticPropertyAccessorByFullName(staticImportType, "is" + accessorName.substring(3));
+        }
+        if (accessor == null && hasStaticProperty(staticImportType, propName)) {
+            // args will be replaced
+            if (inLeftExpression)
+                accessor = new StaticMethodCallExpression(staticImportType, accessorName, ArgumentListExpression.EMPTY_ARGUMENTS);
+            else
+                accessor = new PropertyExpression(new ClassExpression(staticImportType), propName);
+        }
+        return accessor;
+    }
+
+    private Expression findStaticPropertyAccessorByFullName(ClassNode staticImportType, String accessorMethodName) {
+        // anything will do as we only check size == 1
+        ArgumentListExpression dummyArgs = new ArgumentListExpression();
+        dummyArgs.addExpression(EmptyExpression.INSTANCE);
+        return findStaticMethod(staticImportType, accessorMethodName, (inLeftExpression ? dummyArgs : ArgumentListExpression.EMPTY_ARGUMENTS));
+    }
+
+    private static Expression findStaticField(ClassNode staticImportType, String fieldName) {
+        if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
+            FieldNode field = getField(staticImportType, fieldName);
+            if (field != null && field.isStatic())
+                return new PropertyExpression(new ClassExpression(staticImportType), fieldName);
+        }
+        return null;
+    }
+
+    private static Expression findStaticMethod(ClassNode staticImportType, String methodName, Expression args) {
+        if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
+            if (staticImportType.hasPossibleStaticMethod(methodName, args)) {
+                return new StaticMethodCallExpression(staticImportType, methodName, args);
+            }
+        }
+        return null;
+    }
+
+    protected SourceUnit getSourceUnit() {
+        return source;
+    }
+}
diff --git a/src/main/java/org/codehaus/groovy/transform/AutoFinalASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
index 3717d24..176b51e 100644
--- a/src/main/java/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
@@ -39,6 +39,7 @@ import java.util.Iterator;
 import java.util.List;
 
 import static org.codehaus.groovy.ast.ClassHelper.make;
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
 
 /**
  * Handles generation of code for the {@link AutoFinal} annotation.
@@ -65,7 +66,7 @@ public class AutoFinalASTTransformation extends AbstractASTTransformation {
                 if (expression.isSynthetic()) {
                     return;
                 }
-                Parameter[] origParams = expression.getParameters();
+                Parameter[] origParams = getParametersSafe(expression);
                 for (Parameter p : origParams) {
                     p.setModifiers(p.getModifiers() | Modifier.FINAL);
                 }
diff --git a/src/main/java/org/codehaus/groovy/transform/CategoryASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/CategoryASTTransformation.java
index c56a7b5..443db581 100644
--- a/src/main/java/org/codehaus/groovy/transform/CategoryASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/CategoryASTTransformation.java
@@ -51,6 +51,10 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
+import static org.codehaus.groovy.ast.tools.ClosureUtils.hasImplicitParameter;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
 
 /**
  * Handles generation of code for the @Category annotation.
@@ -140,7 +144,7 @@ public class CategoryASTTransformation implements ASTTransformation, Opcodes {
 
             @Override
             public void visitClosureExpression(ClosureExpression ce) {
-                addVariablesToStack(ce.getParameters());
+                addVariablesToStack(getParametersSafe(ce));
                 super.visitClosureExpression(ce);
                 varStack.removeLast();
             }
@@ -205,15 +209,10 @@ public class CategoryASTTransformation implements ASTTransformation, Opcodes {
                 } else if (exp instanceof ClosureExpression) {
                     ClosureExpression ce = (ClosureExpression) exp;
                     ce.getVariableScope().putReferencedLocalVariable((Parameter) parameter.get());
-                    Parameter[] params = ce.getParameters();
-                    if (params == null) {
-                        params = Parameter.EMPTY_ARRAY;
-                    } else if (params.length == 0) {
-                        params = new Parameter[]{
-                                new Parameter(ClassHelper.OBJECT_TYPE, "it")
-                        };
-                    }
-                    addVariablesToStack(params);
+                    addVariablesToStack(
+                            hasImplicitParameter(ce)
+                                    ? params(param(ClassHelper.OBJECT_TYPE, "it"))
+                                    : getParametersSafe(ce));
                     ce.getCode().visit(this);
                     varStack.removeLast();
                 }
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/ClosureExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/ClosureExpressionTransformer.java
index a5b33f8..8be6416 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/ClosureExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/ClosureExpressionTransformer.java
@@ -23,6 +23,8 @@ import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.stmt.Statement;
 
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
+
 public class ClosureExpressionTransformer {
     private final StaticCompilationTransformer transformer;
 
@@ -31,12 +33,9 @@ public class ClosureExpressionTransformer {
     }
 
     Expression transformClosureExpression(final ClosureExpression expr) {
-        Parameter[] parameters = expr.getParameters();        
-        if (parameters!=null) {
-            for (Parameter parameter : parameters) {
-                if (parameter.hasInitialExpression()) {
-                    parameter.setInitialExpression(transformer.transform(parameter.getInitialExpression()));
-                }
+        for (Parameter parameter : getParametersSafe(expr)) {
+            if (parameter.hasInitialExpression()) {
+                parameter.setInitialExpression(transformer.transform(parameter.getInitialExpression()));
             }
         }
         Statement code = expr.getCode();
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 2fe787a..0f2b3c3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -175,6 +175,7 @@ import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
 import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
+import static org.codehaus.groovy.ast.tools.ClosureUtils.getParametersSafe;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
@@ -831,14 +832,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
                 Expression constructedRightExpression = rightExpression;
 
-                boolean isMrExprRHS = rightExpression instanceof MethodReferenceExpression && ClassHelper.isFunctionalInterface(lType);
-                if (isMrExprRHS) {
+                boolean isMethodRefRHS = rightExpression instanceof MethodReferenceExpression && ClassHelper.isFunctionalInterface(lType);
+                if (isMethodRefRHS) {
                     constructedRightExpression = constructLambdaExpressionForMethodReference(lType);
                 }
 
                 inferParameterAndReturnTypesOfClosureOnRHS(lType, constructedRightExpression, op);
 
-                if (isMrExprRHS) {
+                if (isMethodRefRHS) {
                     LambdaExpression lambdaExpression = (LambdaExpression) constructedRightExpression;
                     ClassNode[] argumentTypes =
                             Arrays.stream(lambdaExpression.getParameters())
@@ -1002,7 +1003,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 Tuple2<ClassNode[], ClassNode> typeInfo = GenericsUtils.parameterizeSAM(lType);
                 ClassNode[] paramTypes = typeInfo.getV1();
                 ClosureExpression closureExpression = ((ClosureExpression) rightExpression);
-                Parameter[] closureParameters = closureExpression.getParameters();
+                Parameter[] closureParameters = getParametersSafe(closureExpression);
 
                 if (paramTypes.length == closureParameters.length) {
                     for (int i = 0, n = closureParameters.length; i < n; i++) {
@@ -2452,11 +2453,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // restore original metadata
         restoreVariableExpressionMetadata(typesBeforeVisit);
         typeCheckingContext.isInStaticContext = oldStaticContext;
-        Parameter[] parameters = expression.getParameters();
-        if (parameters != null) {
-            for (Parameter parameter : parameters) {
-                typeCheckingContext.controlStructureVariables.remove(parameter);
-            }
+        for (Parameter parameter : getParametersSafe(expression)) {
+            typeCheckingContext.controlStructureVariables.remove(parameter);
         }
     }
 
@@ -4520,15 +4518,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // next we get the block parameter types and set the generics
         // information just like before
         // TODO: add vargs handling
-        Parameter[] closureParams = closureExpression.getParameters();
-        Parameter[] methodParams = sam.getParameters();
-        for (int i = 0; i < closureParams.length; i++) {
-            ClassNode fromClosure = closureParams[i].getType();
-            ClassNode fromMethod = methodParams[i].getType();
-            extractGenericsConnections(connections, fromClosure, fromMethod);
-        }
-        ClassNode result = applyGenericsContext(connections, samUsage.redirect());
-        return result;
+        if (closureExpression.isParameterSpecified()) {
+            Parameter[] closureParams = closureExpression.getParameters();
+            Parameter[] methodParams = sam.getParameters();
+            for (int i = 0; i < closureParams.length; i++) {
+                ClassNode fromClosure = closureParams[i].getType();
+                ClassNode fromMethod = methodParams[i].getType();
+                extractGenericsConnections(connections, fromClosure, fromMethod);
+            }
+        }
+        return applyGenericsContext(connections, samUsage.redirect());
     }
 
     protected static ClassNode getGroupOperationResultType(ClassNode a, ClassNode b) {
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 102e1c5..108376d 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -32,6 +32,22 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testClosureWithoutArgumentsExplicit() {
+        // GROOVY-9079: no params to statically type check but shouldn't get NPE
+        assertScript '''
+            import groovy.transform.CompileStatic
+            import java.util.concurrent.Callable
+
+            @CompileStatic
+            String makeFoo() {
+                Callable<String> call = { -> 'foo' }
+                call()
+            }
+
+            assert makeFoo() == 'foo'
+        '''
+    }
+
     void testClosureWithArguments() {
         assertScript '''
             def printSum = { int a, int b -> print a+b }
diff --git a/src/test/org/codehaus/groovy/transform/AutoFinalTransformBlackBoxTest.groovy b/src/test/org/codehaus/groovy/transform/AutoFinalTransformBlackBoxTest.groovy
index b06e265..a1df9dc 100644
--- a/src/test/org/codehaus/groovy/transform/AutoFinalTransformBlackBoxTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/AutoFinalTransformBlackBoxTest.groovy
@@ -66,6 +66,22 @@ class AutoFinalTransformBlackBoxTest extends CompilableTestSupport {
         assertScript(script)
     }
 
+    @Test
+    void testNoargClosureSuccessfullyParsed() {
+        // GROOVY-9079: no params to make final but shouldn't get NPE
+        assertScript '''
+            import groovy.transform.AutoFinal
+            import java.util.concurrent.Callable
+
+            String makeFoo() {
+                @AutoFinal
+                Callable<String> call = { -> 'foo' }
+                call()
+            }
+
+            assert makeFoo() == 'foo'
+        '''
+    }
 
     void assertAutoFinalClassTestScript(final String paramName, final String classPart) {
         assertAutoFinalTestScriptWithAnnotation(paramName, classPart)