This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 21b252a GROOVY-10329: StaticImportVisitor: import static star:
callable property
21b252a is described below
commit 21b252adbaa2a28810a4aa440936962b7e71edda
Author: Eric Milles <[email protected]>
AuthorDate: Mon Oct 25 16:44:21 2021 -0500
GROOVY-10329: StaticImportVisitor: import static star: callable property
---
.../groovy/control/StaticImportVisitor.java | 20 +-
src/test/Outer3.groovy | 22 --
src/test/Outer4.groovy | 22 --
src/test/groovy/StaticImportTest.groovy | 291 ++++++++++++---------
src/test/groovy/bugs/Groovy4145.groovy | 25 --
5 files changed, 183 insertions(+), 197 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
index 4c257f9..fc4838c 100644
--- a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
@@ -439,9 +439,9 @@ public class StaticImportVisitor extends
ClassCodeExpressionTransformer {
if (expression != null) {
return expression;
}
- if (!inClosure) {
+ if (!inClosure && !inLeftExpression) {
expression = findStaticPropertyOrField(importNode.getType(),
importNode.getFieldName());
- if (expression != null) { // assume name refers to a callable
static field or property
+ if (expression != null) { // assume name refers to a callable
static field/property
MethodCallExpression call = new
MethodCallExpression(expression, "call", args);
call.setImplicitThis(false);
return call;
@@ -490,6 +490,14 @@ public class StaticImportVisitor extends
ClassCodeExpressionTransformer {
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);
@@ -584,14 +592,14 @@ public class StaticImportVisitor extends
ClassCodeExpressionTransformer {
return null;
}
- 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 ee2ffa6..0000000
--- 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 52385db..0000000
--- 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 465bc9a..6603772 100644
--- a/src/test/groovy/StaticImportTest.groovy
+++ b/src/test/groovy/StaticImportTest.groovy
@@ -35,10 +35,8 @@ import static groovy.Outer2.Inner2
import static groovy.Outer2.Inner2 as InnerAlias2
import static java.util.jar.Attributes.*
import static java.util.jar.Attributes.Name as AttrName
-// TODO GROOVY-4287: reinstate next two imports
-//import static Outer3.*
-//import static Outer4.Inner4
import static groovy.Container5087.*
+import static Foo4964.*
import org.codehaus.groovy.runtime.DefaultGroovyMethods as DGM
final class StaticImportTest extends groovy.test.GroovyTestCase {
@@ -69,15 +67,16 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
void testFieldAsArgumentList() {
- assert ("" + PI.toString()).contains('3.14')
+ assert ('' + PI.toString()).contains('3.14')
}
void testFieldAliasing() {
assert MEDIUM == M
}
+ // GROOVY-1809
void testMethodAliasing() {
- // GROOVY-1809 making this not possible on one line?
+ // making this not possible on one line?
def now = now().time
assert now.class == Date
}
@@ -89,7 +88,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
private format(a, b, c, ignored) { format(a, b, c) }
void testMethodDefCanUseStaticallyImportedMethodWithSameNameButDiffArgs() {
- assert format("different", "abc", "aBc", 3) == 'different
expected:<abc> but was:<aBc>'
+ assert format('different', 'abc', 'aBc', 3) == 'different
expected:<abc> but was:<aBc>'
}
void testAssertEqualsFromJUnit() {
@@ -101,15 +100,15 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
void testStaticImportFromGroovy() {
- def nonstaticval = new StaticImportTarget().y("he", 3)
- def staticval = x("he", 3)
+ def nonstaticval = new StaticImportTarget().y('he', 3)
+ def staticval = x('he', 3)
assert nonstaticval == staticval
}
void testStaticImportWithVarArgs() {
- assert noArrayMethod("one", 1) == 'noArrayMethod(one, 1)'
- assert API.arrayMethod("two", 1, 2, 3) == 'arrayMethod(two, 1, 2, 3)'
- assert arrayMethod("three", 1, 2, 3) == 'arrayMethod(three, 1, 2, 3)'
+ assert noArrayMethod('one', 1) == 'noArrayMethod(one, 1)'
+ assert API.arrayMethod('two', 1, 2, 3) == 'arrayMethod(two, 1, 2, 3)'
+ assert arrayMethod('three', 1, 2, 3) == 'arrayMethod(three, 1, 2, 3)'
}
void testStaticImportFromParentClass() {
@@ -126,7 +125,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
class Bar {
static void bar() {
- assert foo(10,1000) == 1010
+ assert foo(10,1000) == 1010
assert foo(10) == 110
}
}
@@ -140,9 +139,8 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
void testStaticImportProperty() {
- for (imports in ['import static Foo.*', 'import static Foo.getX;
import static Foo.setX']) {
- assertScript """
- $imports
+ for (imports in ['import static Foo.getX; import static Foo.setX',
'import static Foo.*']) {
+ assertScript """$imports
class Foo {
static x = 'foo'
}
@@ -152,8 +150,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
setX('baz')
assert 'baz' == x
"""
- assertScript """
- $imports
+ assertScript """$imports
class Foo {
static x = 'foo'
static getX() { x + '_get' }
@@ -164,8 +161,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
setX('baz')
assert 'baz_get' == x
"""
- assertScript """
- $imports
+ assertScript """$imports
class Foo {
static x = 'foo'
static void setX(newx) { x = newx + '_set' }
@@ -176,8 +172,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
setX('baz')
assert 'baz_set' == x
"""
- assertScript """
- $imports
+ assertScript """$imports
class Foo {
static x = 'foo'
static getX() { x + '_get' }
@@ -193,9 +188,8 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
void testStaticImportPropertyBooleanAlternative() {
- for (imports in ['import static Foo.*', 'import static Foo.x', 'import
static Foo.isX; import static Foo.setX']) {
- assertScript """
- $imports
+ for (imports in ['import static Foo.isX; import static Foo.setX',
'import static Foo.x', 'import static Foo.*']) {
+ assertScript """$imports
class Foo {
static x
static boolean isX() { !!x }
@@ -206,8 +200,7 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
setX(false)
assert !x
"""
- assertScript """
- $imports
+ assertScript """$imports
class Foo {
static x
static boolean isX() { !!x }
@@ -223,50 +216,105 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
void testStaticImportPropertyWithPublicField() {
- def sources = [
- "class Foo { public static x = 'foo'" + " }",
- "class Foo { public static x = 'foo'" + "; static getX() { x +
'_get' } }",
- "class Foo { public static x = 'foo'" + ";
static void setX(newx) { x = newx + '_set' } }",
- "class Foo { public static x = 'foo'" + "; static getX() { x +
'_get' }; static void setX(newx) { x = newx + '_set' } }"
- ]
- def imports = [
- "import static Foo.*",
- "import static Foo.x"
- ]
- def results = [
- "assert x == 'foo'; x = 'bar'; assert x == 'bar';
x = 'baz' ; assert 'baz' == x",
- "assert x == 'foo_get'; x = 'bar'; assert getX() == 'bar_get';
x = 'baz' ; assert 'baz_get' == x",
- "assert x == 'foo'; x = 'bar'; assert x == 'bar_set';
setX('baz'); assert 'baz_set' == x",
- "assert x == 'foo_get'; x = 'bar'; assert getX() == 'bar_set_get';
setX('baz'); assert 'baz_set_get' == x"
- ]
- [0..<sources.size(), 0..<imports.size()].combinations().each { i, j ->
- assertScript sources[i] + "\n" + imports[j] + "\n" + results[i]
+ for (imports in ['import static Foo.x', 'import static Foo.*']) {
+ assertScript """$imports
+ class Foo {
+ public static x = 'foo'
+ }
+ assert x == 'foo'
+ x = 'bar'
+ assert x == 'bar'
+ x = 'baz'
+ assert x == 'baz'
+ """
+ assertScript """$imports
+ class Foo {
+ public static x = 'foo'
+ static getX() { x + '_get' }
+ }
+ assert x == 'foo_get'
+ x = 'bar'
+ assert getX() == 'bar_get'
+ x = 'baz'
+ assert x == 'baz_get'
+ """
+ assertScript """$imports
+ class Foo {
+ public static x = 'foo'
+ static void setX(newx) { x = newx + '_set' }
+ }
+ assert x == 'foo'
+ x = 'bar'
+ assert x == 'bar_set'
+ setX('baz')
+ assert x == 'baz_set'
+ """
+ assertScript """$imports
+ class Foo {
+ public static x = 'foo'
+ static getX() { x + '_get' }
+ static void setX(newx) { x = newx + '_set' }
+ }
+ assert x == 'foo_get'
+ x = 'bar'
+ assert getX() == 'bar_set_get'
+ setX('baz')
+ assert x == 'baz_set_get'
+ """
}
- assertScript sources[3] + """
+ assertScript '''
import static Foo.getX; import static Foo.setX
+ class Foo { public static x = 'foo'; static getX() { x + '_get' };
static void setX(newx) { x = newx + '_set' } }
assert getX() == 'foo_get'; setX('bar'); assert getX() ==
'bar_set_get'; setX('baz'); assert 'baz_set_get' == getX()
- """
+ '''
}
void testStaticImportPropertyWithAliases() {
- def sources = [
- "class Foo { static x = 'foo'" + " }",
- "class Foo { static x = 'foo'" + "; static getX() { x + '_get' }
}",
- "class Foo { static x = 'foo'" + ";
static void setX(newx) { x = newx + '_set' } }",
- "class Foo { static x = 'foo'" + "; static getX() { x + '_get' };
static void setX(newx) { x = newx + '_set' } }"
- ]
- def imports = [
- "import static Foo.x as z",
- "import static Foo.getX as getZ; import static Foo.setX as setZ"
- ]
- def results = [
- "assert z == 'foo'; z = 'bar'; assert getZ() == 'bar';
setZ('baz'); assert 'baz' == z",
- "assert z == 'foo_get'; z = 'bar'; assert getZ() == 'bar_get';
setZ('baz'); assert 'baz_get' == z",
- "assert z == 'foo'; z = 'bar'; assert getZ() == 'bar_set';
setZ('baz'); assert 'baz_set' == z",
- "assert z == 'foo_get'; z = 'bar'; assert getZ() == 'bar_set_get';
setZ('baz'); assert 'baz_set_get' == z"
- ]
- [0..<sources.size(), 0..<imports.size()].combinations().each { i, j ->
- assertScript sources[i] + "\n" + imports[j] + "\n" + results[i]
+ for (imports in ['import static Foo.getX as getZ; import static
Foo.setX as setZ', 'import static Foo.x as z']) {
+ assertScript """$imports
+ class Foo {
+ static x = 'foo'
+ }
+ assert z == 'foo'
+ z = 'bar'
+ assert getZ() == 'bar'
+ setZ('baz')
+ assert z == 'baz'
+ """
+ assertScript """$imports
+ class Foo {
+ static x = 'foo'
+ static getX() { x + '_get' }
+ }
+ assert z == 'foo_get'
+ z = 'bar'
+ assert getZ() == 'bar_get'
+ setZ('baz')
+ assert z == 'baz_get'
+ """
+ assertScript """$imports
+ class Foo {
+ static x = 'foo'
+ static void setX(newx) { x = newx + '_set' }
+ }
+ assert z == 'foo'
+ z = 'bar'
+ assert getZ() == 'bar_set'
+ setZ('baz')
+ assert z == 'baz_set'
+ """
+ assertScript """$imports
+ class Foo {
+ static x = 'foo'
+ static getX() { x + '_get' }
+ static void setX(newx) { x = newx + '_set' }
+ }
+ assert z == 'foo_get'
+ z = 'bar'
+ assert getZ() == 'bar_set_get'
+ setZ('baz')
+ assert z == 'baz_set_get'
+ """
}
}
@@ -299,25 +347,25 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
assert err =~ /No such property: y for class/
}
- // GROOVY-8389
+ // GROOVY-8389, GROOVY-10329
void testStaticImportPropertyWithClosure() {
- assertScript '''
- import static Foo.bar
- import static Foo.baz
- 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'
- '''
+ 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
@@ -415,47 +463,54 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
} catch (MissingMethodException expected) {}
}
- // GROOVY-3945
+ // GROOVY-3945, GROOVY-10329
void testStaticImportOfClosureProperty() {
- assertScript '''
- import static groovy.StaticImportTarget.cl
- String result = cl()
- assert result == 'StaticImportTarget#static closure called'
- '''
+ for (imports in ['import static groovy.StaticImportTarget.cl', 'import
static groovy.StaticImportTarget.*']) {
+ assertScript """$imports
+ String result = cl()
+ assert result == 'StaticImportTarget#static closure called'
+ """
+ }
}
- // GROOVY-7490
+ // GROOVY-7490, GROOVY-10329
void testStaticImportOfCallableProperty() {
- assertScript '''
- class WithCall {
- String call(String input) {
- return input
+ 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()
}
- }
- class Pogo {
- static final WithCall callable_property = new WithCall()
- }
-
- import static Pogo.callable_property
- @groovy.transform.CompileStatic
- def usage() {
- callable_property('works')
- }
- String result = usage()
- assert result == 'works'
- '''
+ @groovy.transform.CompileStatic
+ def usage() {
+ callable_property('works')
+ }
+ String result = usage()
+ assert result == 'works'
+ """
+ }
}
// GROOVY-4145
void testStaticPropertyImportedImplementedAsGetter() {
assertScript '''
- import static groovy.bugs.Groovy4145.foo4145
+ import static Groovy4145.foo4145
+ class Groovy4145 {
+ static getFoo4145() {
+ return 3
+ }
+ }
assert foo4145 == 3
'''
}
- void
testMethodCallExpressionInStaticContextWithInstanceVariableShouldFail() {
//GROOVY-4228
+ // GROOVY-4228
+ void
testMethodCallExpressionInStaticContextWithInstanceVariableShouldFail() {
def err = shouldFail '''
class B {
def c = new Object()
@@ -491,15 +546,6 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
Bar4964.run()
}
- // TODO GROOVY-4287: reinstate next two tests
-// void testStaticStarImportOfStaticInnerClassExternalClass() {
-// assert Inner3.class.name == 'Outer3$Inner3'
-// }
-//
-// void testStaticImportOfStaticInnerClassExternalClass() {
-// assert Inner4.class.name == 'Outer4$Inner4'
-// }
-
void testMapIndexInLeftExpressionOfEquals() {
holder = 'foo'
def map = [:]
@@ -527,6 +573,8 @@ final class StaticImportTest extends
groovy.test.GroovyTestCase {
}
}
+//------------------------------------------------------------------------------
+
class API {
static noArrayMethod(String s, int value) {
"noArrayMethod(${s}, ${value})"
@@ -538,13 +586,13 @@ class API {
}
class StaticImportParent {
- static pfield = 42
- static pmethod() { 'hello from parent' }
+ static pfield = 42
+ static pmethod() { 'hello from parent' }
}
class StaticImportChild extends StaticImportParent {
- static cfield = 21
- static cmethod() { 'hello from child' }
+ static cfield = 21
+ static cmethod() { 'hello from child' }
}
class Outer1 {
@@ -559,7 +607,6 @@ class Foo4964 {
static doIt() { [k: 'foo'] }
}
-import static Foo4964.*
class Bar4964 {
static doIt() { [k: 'bar'] }
diff --git a/src/test/groovy/bugs/Groovy4145.groovy
b/src/test/groovy/bugs/Groovy4145.groovy
deleted file mode 100644
index d453490..0000000
--- 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