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

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


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new bf30d25e12 GROOVY-7490, GROOVY-8389, GROOVY-10329: import static 
callable property
bf30d25e12 is described below

commit bf30d25e12f85f6ee871844bfd3887d97fefde5c
Author: Eric Milles <[email protected]>
AuthorDate: Mon Mar 6 11:25:21 2023 -0600

    GROOVY-7490, GROOVY-8389, GROOVY-10329: import static callable property
    
    2_5_X backport
---
 .../org/codehaus/groovy/classgen/Verifier.java     |  48 ++--
 .../groovy/control/StaticImportVisitor.java        | 241 +++++++++++----------
 src/test/Outer3.groovy                             |  22 --
 src/test/Outer4.groovy                             |  22 --
 src/test/groovy/StaticImportTest.groovy            |  44 ++++
 src/test/groovy/bugs/Groovy4145.groovy             |  25 ---
 6 files changed, 197 insertions(+), 205 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java 
b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index ed40d7731c..c9b3763df1 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.classgen;
 
 import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyObject;
 import groovy.lang.GroovyRuntimeException;
 import groovy.lang.MetaClass;
 import groovy.transform.Generated;
@@ -359,6 +358,7 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
         FieldNode staticMetaClassField = 
node.addField(staticMetaClassFieldName, ACC_PRIVATE | ACC_STATIC | 
ACC_SYNTHETIC, ClassHelper.make(ClassInfo.class, false), null);
         staticMetaClassField.setSynthetic(true);
 
+        final ClassNode classNode = this.classNode;
         node.addSyntheticMethod(
                 "$getStaticMetaClass",
                 ACC_PROTECTED,
@@ -1281,31 +1281,33 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
         return MetaClassHelper.capitalize(name);
     }
 
-    protected Statement createGetterBlock(PropertyNode propertyNode, final 
FieldNode field) {
+    protected Statement createGetterBlock(final PropertyNode propertyNode, 
final FieldNode field) {
+        final String owner = BytecodeHelper.getClassInternalName(classNode);
         return new BytecodeSequence(new BytecodeInstruction() {
             public void visit(MethodVisitor mv) {
                 if (field.isStatic()) {
-                    mv.visitFieldInsn(GETSTATIC, 
BytecodeHelper.getClassInternalName(classNode), field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
+                    mv.visitFieldInsn(GETSTATIC, owner, field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
                 } else {
                     mv.visitVarInsn(ALOAD, 0);
-                    mv.visitFieldInsn(GETFIELD, 
BytecodeHelper.getClassInternalName(classNode), field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
+                    mv.visitFieldInsn(GETFIELD, owner, field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
                 }
                 BytecodeHelper.doReturn(mv, field.getType());
             }
         });
     }
 
-    protected Statement createSetterBlock(PropertyNode propertyNode, final 
FieldNode field) {
+    protected Statement createSetterBlock(final PropertyNode propertyNode, 
final FieldNode field) {
+        final String owner = BytecodeHelper.getClassInternalName(classNode);
         return new BytecodeSequence(new BytecodeInstruction() {
             @Override
             public void visit(MethodVisitor mv) {
                 if (field.isStatic()) {
                     BytecodeHelper.load(mv, field.getType(), 0);
-                    mv.visitFieldInsn(PUTSTATIC, 
BytecodeHelper.getClassInternalName(classNode), field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
+                    mv.visitFieldInsn(PUTSTATIC, owner, field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
                 } else {
                     mv.visitVarInsn(ALOAD, 0);
                     BytecodeHelper.load(mv, field.getType(), 1);
-                    mv.visitFieldInsn(PUTFIELD, 
BytecodeHelper.getClassInternalName(classNode), field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
+                    mv.visitFieldInsn(PUTFIELD, owner, field.getName(), 
BytecodeHelper.getTypeDescription(field.getType()));
                 }
                 mv.visitInsn(RETURN);
             }
@@ -1496,48 +1498,42 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
             }
         }
 
-        // if we reach this point we have at least one parameter or return 
type, that
-        // is different in its specified form. That means we have to create a 
bridge method!
-        MethodNode newMethod = new MethodNode(
+        // if we reach this point there is least one parameter or return type
+        // that is different in its specified form, so create a bridge method
+        final String owner = BytecodeHelper.getClassInternalName(classNode);
+        return new MethodNode(
                 oldMethod.getName(),
                 overridingMethod.getModifiers() | ACC_SYNTHETIC | ACC_BRIDGE,
                 cleanType(oldMethod.getReturnType()),
                 cleanParameters(oldMethod.getParameters()),
                 oldMethod.getExceptions(),
-                null
-        );
-        List instructions = new ArrayList(1);
-        instructions.add(
-                new BytecodeInstruction() {
+                new BytecodeSequence(new BytecodeInstruction() {
                     @Override
                     public void visit(MethodVisitor mv) {
                         mv.visitVarInsn(ALOAD, 0);
                         Parameter[] para = oldMethod.getParameters();
                         Parameter[] goal = overridingMethod.getParameters();
                         int doubleSlotOffset = 0;
-                        for (int i = 0; i < para.length; i++) {
+                        for (int i = 0; i < para.length; ++i) {
                             ClassNode type = para[i].getType();
                             BytecodeHelper.load(mv, type, i + 1 + 
doubleSlotOffset);
-                            if (type.redirect() == ClassHelper.double_TYPE ||
-                                    type.redirect() == ClassHelper.long_TYPE) {
-                                doubleSlotOffset++;
+                            if (type.redirect() == ClassHelper.double_TYPE
+                                    || type.redirect() == 
ClassHelper.long_TYPE) {
+                                doubleSlotOffset += 1;
                             }
                             if (!type.equals(goal[i].getType())) {
                                 BytecodeHelper.doCast(mv, goal[i].getType());
                             }
                         }
-                        mv.visitMethodInsn(INVOKEVIRTUAL, 
BytecodeHelper.getClassInternalName(classNode), overridingMethod.getName(), 
BytecodeHelper.getMethodDescriptor(overridingMethod.getReturnType(), 
overridingMethod.getParameters()), false);
+                        mv.visitMethodInsn(INVOKEVIRTUAL, owner, 
overridingMethod.getName(), 
BytecodeHelper.getMethodDescriptor(overridingMethod.getReturnType(), 
overridingMethod.getParameters()), false);
 
                         BytecodeHelper.doReturn(mv, oldMethod.getReturnType());
                     }
-                }
-
+                })
         );
-        newMethod.setCode(new BytecodeSequence(instructions));
-        return newMethod;
     }
 
-    private boolean isAssignable(ClassNode node, ClassNode testNode) {
+    private static boolean isAssignable(ClassNode node, ClassNode testNode) {
         if (node.isArray() && testNode.isArray()) {
             return isArrayAssignable(node.getComponentType(), 
testNode.getComponentType());
         }
@@ -1547,7 +1543,7 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
         return node.isDerivedFrom(testNode);
     }
 
-    private boolean isArrayAssignable(ClassNode node, ClassNode testNode) {
+    private static boolean isArrayAssignable(ClassNode node, ClassNode 
testNode) {
         if (node.isArray() && testNode.isArray()) {
             return isArrayAssignable(node.getComponentType(), 
testNode.getComponentType());
         }
diff --git a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java 
b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
index 5ac4917d47..b86c2cf2c9 100644
--- a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
@@ -205,7 +205,7 @@ public class StaticImportVisitor extends 
ClassCodeExpressionTransformer {
     protected Expression transformVariableExpression(VariableExpression ve) {
         Variable v = ve.getAccessedVariable();
         if (v instanceof DynamicVariable) {
-            Expression result = 
findStaticFieldOrPropAccessorImportFromModule(v.getName());
+            Expression result = 
findStaticFieldOrPropertyAccessorImportFromModule(v.getName());
             if (result != null) {
                 setSourcePosition(result, ve);
                 if (inAnnotation) {
@@ -254,19 +254,9 @@ public class StaticImportVisitor extends 
ClassCodeExpressionTransformer {
             if (!thisOrSuperMethod && !hasPossibleOuterMethod(currentClass, 
name, args)) { // GROOVY-5239
                 Expression result = findStaticMethodImportFromModule(method, 
args);
                 if (result != null) {
-                    result.setSourcePosition(mce);
+                    setSourcePosition(result, mce);
                     return result;
                 }
-                if (name != null && !inLeftExpression) { // maybe a closure 
field
-                    result = 
findStaticFieldOrPropAccessorImportFromModule(name);
-                    if (result != null) {
-                        setSourcePosition(result, method);
-                        result = new MethodCallExpression(result, "call", 
args);
-                        ((MethodCallExpression) result).setImplicitThis(false);
-                        result.setSourcePosition(mce);
-                        return result;
-                    }
-                }
             }
         } else if (staticWrtCurrent && isSuperExpression(object)) {
             Expression result = new MethodCallExpression(new 
ClassExpression(currentClass.getSuperClass()), method, args);
@@ -383,117 +373,127 @@ public class StaticImportVisitor extends 
ClassCodeExpressionTransformer {
         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);
+    
//--------------------------------------------------------------------------
+
+    private Expression 
findStaticFieldOrPropertyAccessorImportFromModule(String name) {
+        ModuleNode module = currentClass.getModule(); if (module == null) 
return null;
+        Map<String, ImportNode> staticImports = module.getStaticImports();
+
         // 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);
+        //   import static MyClass.isProp [as isOtherProp]
+        // when resolving property reference
+        Expression expression;
+        expression = findStaticProperty(staticImports, getAccessorName(name));
+        if (expression != null) return expression;
+        if (!inLeftExpression) {
+            expression = findStaticProperty(staticImports, "is" + 
capitalize(name));
             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());
+        // when resolving property or field reference
+        if (staticImports.containsKey(name)) { ImportNode importNode = 
staticImports.get(name);
+            expression = findStaticPropertyOrField(importNode.getType(), 
importNode.getFieldName());
             if (expression != null) return expression;
         }
+
         // look for one of these:
         //   import static MyClass.*
-        // when resolving prop or field reference
+        // when resolving property 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);
+            expression = findStaticPropertyOrField(importNode.getType(), 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;
+        return null;
     }
 
     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;
+        if (currentClass.getModule() == null) return null;
+        if (!(method instanceof ConstantExpression)) return null;
+        if (!(((ConstantExpression) method).getValue() instanceof String)) 
return null;
+
         Expression expression;
-        Object value = ce.getValue();
-        // skip non-Strings, e.g. Integer
-        if (!(value instanceof String)) return null;
-        final String name = (String) value;
+        String name = method.getText();
+        Map<String, ImportNode> staticImports = 
currentClass.getModule().getStaticImports();
         // 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);
+        //   import static MyClass.field [as alias]
+        //   import static MyClass.method [as alias]
+        //   import static MyClass.property [as alias]
+        // when resolving implicit-this call name(args)
+        if (staticImports.containsKey(name)) {
+            ImportNode importNode = staticImports.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 newStaticMethodCallX(importNode.getType(), 
importNode.getFieldName(), args);
+                return expression;
+            }
+            if (!inClosure && !inLeftExpression) {
+                expression = findStaticPropertyOrField(importNode.getType(), 
importNode.getFieldName());
+                if (expression != null) { // assume name refers to a callable 
static field/property
+                    MethodCallExpression call = new 
MethodCallExpression(expression, "call", args);
+                    call.setImplicitThis(false);
+                    return call;
+                }
             }
         }
         // 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();
+        //   import static MyClass.property [as alias]
+        //   import static MyClass.setProperty [as alias]
+        //   import static MyClass.getProperty [as alias]
+        //   import static MyClass.isProperty  [as alias]
+        // when resolving isName(), getName() or setName(args)
+        boolean accessor = isValidAccessorName(name);
+        if (accessor) {
+            ImportNode importNode = staticImports.get(name);
+            if (importNode != null) {
+                String propName = 
getPropNameForAccessor(importNode.getFieldName());
+                expression = 
findStaticPropertyAccessorGivenArgs(importNode.getType(), propName, args);
+                if (expression != null) { // expression may refer to getter or 
setter, so make new call
+                    return newStaticMethodCallX(importNode.getType(), 
importNode.getFieldName(), args);
+                }
+            }
+            importNode = staticImports.get(getPropNameForAccessor(name));
+            if (importNode != null) {
+                ClassNode importType = importNode.getType();
                 String importMember = importNode.getFieldName();
-                expression = findStaticMethod(importClass, prefix(name) + 
capitalize(importMember), args);
+                expression = findStaticMethod(importType, prefix(name) + 
capitalize(importMember), args);
                 if (expression != null) return expression;
-                expression = findStaticPropertyAccessorGivenArgs(importClass, 
importMember, args);
+                expression = findStaticPropertyAccessorGivenArgs(importType, 
importMember, args);
                 if (expression != null) {
-                    return newStaticMethodCallX(importClass, prefix(name) + 
capitalize(importMember), args);
+                    return newStaticMethodCallX(importType, 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);
+
+        Map<String, ImportNode> staticStarImports = 
currentClass.getModule().getStaticStarImports();
+        if (currentClass.isEnum() && 
staticStarImports.containsKey(currentClass.getName())) {
+            ImportNode importNode = 
staticStarImports.get(currentClass.getName());
+            expression = findStaticMethod(importNode.getType(), name, args);
             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 newStaticMethodCallX(starImportType, name, args);
+        }
+        // look for one of these:
+        //   import static MyClass.*
+        // when resolving name(args), getName(), etc.
+        for (ImportNode importNode : staticStarImports.values()) {
+            ClassNode importType = importNode.getType();
+            expression = findStaticMethod(importType, name, args);
+            if (expression != null) return expression;
+            if (!inClosure && !inLeftExpression) { // GROOVY-10329
+                expression = findStaticPropertyOrField(importType, name);
+                if (expression != null) { // assume name refers to a callable 
static field/property
+                    MethodCallExpression call = new 
MethodCallExpression(expression, "call", args);
+                    call.setImplicitThis(false);
+                    return call;
+                }
+            }
+            if (accessor) {
+                String propName = getPropNameForAccessor(name);
+                expression = findStaticPropertyAccessorGivenArgs(importType, 
propName, args);
+                if (expression != null) { // expression may refer to getter or 
setter, so ...
+                    return newStaticMethodCallX(importType, name, args);
                 }
             }
         }
@@ -508,41 +508,62 @@ public class StaticImportVisitor extends 
ClassCodeExpressionTransformer {
         return (inLeftExpression ? "set" : "get") + capitalize(name);
     }
 
+    private Expression findStaticPropertyAccessorByFullName(ClassNode 
staticImportType, String accessorName) {
+        Expression argumentList = inLeftExpression ? new 
ArgumentListExpression(EmptyExpression.INSTANCE) : 
ArgumentListExpression.EMPTY_ARGUMENTS;
+        Expression accessorExpr = findStaticMethod(staticImportType, 
accessorName, argumentList);
+        // TODO: GROOVY-9382, GROOVY-10133
+        return accessorExpr;
+    }
+
     private Expression findStaticPropertyAccessorGivenArgs(ClassNode 
staticImportType, String propName, Expression args) {
-        // TODO validate args?
-        return findStaticPropertyAccessor(staticImportType, propName);
+        return findStaticPropertyAccessor(staticImportType, propName); // 
TODO: validate args?
     }
 
     private Expression findStaticPropertyAccessor(ClassNode staticImportType, 
String propName) {
         String accessorName = getAccessorName(propName);
         Expression accessor = 
findStaticPropertyAccessorByFullName(staticImportType, accessorName);
-        if (accessor == null && accessorName.startsWith("get")) {
+        if (accessor == null && !inLeftExpression) {
             accessor = findStaticPropertyAccessorByFullName(staticImportType, 
"is" + accessorName.substring(3));
         }
         if (accessor == null && hasStaticProperty(staticImportType, propName)) 
{
-            // args will be replaced
             if (inLeftExpression)
-                accessor = newStaticMethodCallX(staticImportType, 
accessorName, ArgumentListExpression.EMPTY_ARGUMENTS);
+                accessor = newStaticMethodCallX(staticImportType, 
accessorName, ArgumentListExpression.EMPTY_ARGUMENTS); // <-- will be replaced
             else
                 accessor = newStaticPropertyX(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 Expression findStaticPropertyOrField(ClassNode staticImportType, 
String variableName) {
+        Expression expression = findStaticPropertyAccessor(staticImportType, 
variableName);
+        if (expression == null) {
+            if (staticImportType.isPrimaryClassNode() || 
staticImportType.isResolved()) {
+                FieldNode field = getField(staticImportType, variableName);
+                if (field != null && field.isStatic())
+                    expression = newStaticPropertyX(staticImportType, 
variableName);
+            }
+        }
+        return expression;
     }
 
-    private static Expression findStaticField(ClassNode staticImportType, 
String fieldName) {
-        if (staticImportType.isPrimaryClassNode() || 
staticImportType.isResolved()) {
-            FieldNode field = getField(staticImportType, fieldName);
-            if (field != null && field.isStatic())
-                return newStaticPropertyX(staticImportType, fieldName);
+    private Expression findStaticProperty(Map<String, ImportNode> 
staticImports, String accessorName) {
+        Expression expression = null;
+        ImportNode importNode = staticImports.get(accessorName);
+        if (importNode != null) { ClassNode importType = importNode.getType();
+            expression = findStaticPropertyAccessorByFullName(importType, 
importNode.getFieldName());
+            if (expression == null) { // perhaps the property accessor will be 
generated
+                String propertyName = 
getPropNameForAccessor(importNode.getFieldName());
+                if (hasStaticProperty(importType, propertyName)) {
+                    if (inLeftExpression) {
+                        expression = newStaticMethodCallX(importType, 
importNode.getFieldName(),
+                                ArgumentListExpression.EMPTY_ARGUMENTS); // 
<-- will be replaced
+                    } else {
+                        expression = newStaticPropertyX(importType, 
propertyName);
+                    }
+                }
+            }
         }
-        return null;
+        return expression;
     }
 
     private static Expression findStaticMethod(ClassNode staticImportType, 
String methodName, Expression args) {
@@ -575,14 +596,14 @@ public class StaticImportVisitor extends 
ClassCodeExpressionTransformer {
         return false;
     }
 
-    private static PropertyExpression newStaticPropertyX(ClassNode type, 
String name) {
-        return new PropertyExpression(new 
ClassExpression(type.getPlainNodeReference()), name);
-    }
-
     private static StaticMethodCallExpression newStaticMethodCallX(ClassNode 
type, String name, Expression args) {
         return new StaticMethodCallExpression(type.getPlainNodeReference(), 
name, args);
     }
 
+    private static PropertyExpression newStaticPropertyX(ClassNode type, 
String name) {
+        return new PropertyExpression(new 
ClassExpression(type.getPlainNodeReference()), name);
+    }
+
     @Override
     protected SourceUnit getSourceUnit() {
         return sourceUnit;
diff --git a/src/test/Outer3.groovy b/src/test/Outer3.groovy
deleted file mode 100644
index ee2ffa6ccf..0000000000
--- a/src/test/Outer3.groovy
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  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.
- */
-class Outer3 {
-    // test class with no package and having a static inner class
-    static class Inner3 {}
-}
diff --git a/src/test/Outer4.groovy b/src/test/Outer4.groovy
deleted file mode 100644
index 52385dbdc3..0000000000
--- a/src/test/Outer4.groovy
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  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.
- */
-class Outer4 {
-    // test class with no package and having a static inner class
-    static class Inner4 {}
-}
diff --git a/src/test/groovy/StaticImportTest.groovy 
b/src/test/groovy/StaticImportTest.groovy
index 4f2f35dc3a..347aa8f67e 100644
--- a/src/test/groovy/StaticImportTest.groovy
+++ b/src/test/groovy/StaticImportTest.groovy
@@ -318,6 +318,27 @@ final class StaticImportTest extends 
gls.CompilableTestSupport {
         }
     }
 
+    // GROOVY-8389, GROOVY-10329
+    void testStaticImportPropertyWithClosure() {
+        for (imports in ['import static Foo.bar; import static Foo.baz', 
'import static Foo.*']) {
+            assertScript """$imports
+                class Foo {
+                    static Closure<String> bar = { -> 'property' }
+                    static Closure<String> baz = { -> 'property' }
+                }
+                String bar() {
+                    'method'
+                }
+                @groovy.transform.CompileStatic
+                def test() {
+                    bar() + ':' + baz()
+                }
+                String result = test()
+                assert result == 'method:property'
+            """
+        }
+    }
+
     // GROOVY-8389
     void testStaticImportMethodVsLocalMethod() {
         assertScript '''
@@ -423,6 +444,29 @@ final class StaticImportTest extends 
gls.CompilableTestSupport {
         }
     }
 
+    // GROOVY-7490, GROOVY-10329
+    void testStaticImportOfCallableProperty() {
+        for (imports in ['import static Pogo.callable_property', 'import 
static Pogo.*']) {
+            assertScript """$imports
+                class WithCall {
+                    String call(String input) {
+                        return input
+                    }
+                }
+                class Pogo {
+                    static final WithCall callable_property = new WithCall()
+                }
+
+                @groovy.transform.CompileStatic
+                def usage() {
+                    callable_property('works')
+                }
+                String result = usage()
+                assert result == 'works'
+            """
+        }
+    }
+
     // GROOVY-4145
     void testStaticPropertyImportedImplementedAsGetter() {
         assertScript '''
diff --git a/src/test/groovy/bugs/Groovy4145.groovy 
b/src/test/groovy/bugs/Groovy4145.groovy
deleted file mode 100644
index d45349055d..0000000000
--- a/src/test/groovy/bugs/Groovy4145.groovy
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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 groovy.bugs
-
-class Groovy4145 {
-    static getFoo4145() {
-        return 3
-    } 
-}
\ No newline at end of file

Reply via email to