Skip to content

Commit 607112d

Browse files
committed
GROOVY-3945, GROOVY-7490, GROOVY-8389, GROOVY-10329
1 parent bd6db52 commit 607112d

File tree

4 files changed

+173
-77
lines changed

4 files changed

+173
-77
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/StaticCompilationTests.java

+82-20
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,67 @@ public void testCompileStatic7363() {
12801280
runConformTest(sources, "42");
12811281
}
12821282

1283+
@Test
1284+
public void testCompileStatic7490() {
1285+
for (String imports : new String[] {"import static Pogo.callable_property; import static Pogo.closure_property", "import static Pogo.*"}) {
1286+
//@formatter:off
1287+
String[] sources = {
1288+
"Main.groovy",
1289+
imports + "\n" +
1290+
"@groovy.transform.CompileStatic\n" +
1291+
"void test() {\n" +
1292+
" print callable_property('hello')\n" +
1293+
" print closure_property(' world')\n" +
1294+
"}\n" +
1295+
"test()\n",
1296+
1297+
"Pogo.groovy",
1298+
"class Pogo {\n" +
1299+
" static final WithCall callable_property = new WithCall()\n" +
1300+
" static final Closure closure_property = { return it }\n" +
1301+
"}\n",
1302+
1303+
"WithCall.groovy",
1304+
"class WithCall {\n" +
1305+
" String call(String input) {\n" +
1306+
" return input\n" +
1307+
" }\n" +
1308+
"}\n",
1309+
};
1310+
//@formatter:on
1311+
1312+
runConformTest(sources, "hello world");
1313+
}
1314+
}
1315+
1316+
@Test
1317+
public void testCompileStatic7490a() {
1318+
//@formatter:off
1319+
String[] sources = {
1320+
"Main.groovy",
1321+
"@groovy.transform.CompileStatic\n" +
1322+
"void test() {\n" +
1323+
" print Pogo.callable_property.call('works')\n" + // TODO:5881,6324
1324+
"}\n" +
1325+
"test()\n",
1326+
1327+
"Pogo.groovy",
1328+
"class Pogo {\n" +
1329+
" static final WithCall callable_property = new WithCall()\n" +
1330+
"}\n",
1331+
1332+
"WithCall.groovy",
1333+
"class WithCall {\n" +
1334+
" String call(String input) {\n" +
1335+
" return input\n" +
1336+
" }\n" +
1337+
"}\n",
1338+
};
1339+
//@formatter:on
1340+
1341+
runConformTest(sources, "works");
1342+
}
1343+
12831344
@Test
12841345
public void testCompileStatic7526() {
12851346
//@formatter:off
@@ -2047,27 +2108,28 @@ public void testCompileStatic8389() {
20472108

20482109
@Test
20492110
public void testCompileStatic8389a() {
2050-
//@formatter:off
2051-
String[] sources = {
2052-
"Main.groovy",
2053-
"import static Foo.bar\n" +
2054-
"import static Foo.baz\n" +
2055-
"class Foo {\n" +
2056-
" static Closure<String> bar = { -> 'property' }\n" +
2057-
" static Closure<String> baz = { -> 'property' }\n" +
2058-
"}\n" +
2059-
"String bar() {\n" +
2060-
" 'method'\n" +
2061-
"}\n" +
2062-
"@groovy.transform.CompileStatic\n" +
2063-
"def test() {\n" +
2064-
" bar() + ':' + baz.call()\n" + // TODO: Should this work without ".call"?
2065-
"}\n" +
2066-
"print test()\n",
2067-
};
2068-
//@formatter:on
2111+
for (String imports : new String[] {"import static Foo.bar; import static Foo.baz", "import static Foo.*"}) {
2112+
//@formatter:off
2113+
String[] sources = {
2114+
"Main.groovy",
2115+
imports + "\n" +
2116+
"class Foo {\n" +
2117+
" static Closure<String> bar = { -> 'property' }\n" +
2118+
" static Closure<String> baz = { -> 'property' }\n" +
2119+
"}\n" +
2120+
"String bar() {\n" +
2121+
" 'method'\n" +
2122+
"}\n" +
2123+
"@groovy.transform.CompileStatic\n" +
2124+
"def test() {\n" +
2125+
" bar() + ':' + baz()\n" +
2126+
"}\n" +
2127+
"print test()\n",
2128+
};
2129+
//@formatter:on
20692130

2070-
runConformTest(sources, "method:property");
2131+
runConformTest(sources, "method:property");
2132+
}
20712133
}
20722134

20732135
@Test

base/org.codehaus.groovy25/src/org/codehaus/groovy/control/StaticImportVisitor.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,11 @@ private Expression findStaticMethodImportFromModule(Expression method, Expressio
480480
ImportNode importNode = importNodes.get(name);
481481
expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
482482
if (expression != null) return expression;
483+
// GRECLIPSE add -- GROOVY-8389
484+
if (isValidAccessorName(name)){
485+
// GRECLIPSE end
483486
expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
484-
if (expression != null) {
487+
if (expression != null)
485488
return newStaticMethodCallX(importNode.getType(), importNode.getFieldName(), args);
486489
}
487490
}
@@ -514,8 +517,11 @@ private Expression findStaticMethodImportFromModule(Expression method, Expressio
514517
starImportType = importNode == null ? null : importNode.getType();
515518
expression = findStaticMethod(starImportType, name, args);
516519
if (expression != null) return expression;
520+
// GRECLIPSE add -- GROOVY-8389
521+
if (isValidAccessorName(name)){
522+
// GRECLIPSE end
517523
expression = findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
518-
if (expression != null) {
524+
if (expression != null)
519525
return newStaticMethodCallX(starImportType, name, args);
520526
}
521527
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/control/StaticImportVisitor.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,11 @@ private Expression findStaticMethodImportFromModule(Expression method, Expressio
497497
ImportNode importNode = importNodes.get(name);
498498
expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
499499
if (expression != null) return expression;
500+
// GRECLIPSE add -- GROOVY-8389
501+
if (isValidAccessorName(name)){
502+
// GRECLIPSE end
500503
expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
501-
if (expression != null) {
504+
if (expression != null)
502505
return newStaticMethodCallX(importNode.getType(), importNode.getFieldName(), args);
503506
}
504507
}
@@ -531,8 +534,11 @@ private Expression findStaticMethodImportFromModule(Expression method, Expressio
531534
starImportType = importNode == null ? null : importNode.getType();
532535
expression = findStaticMethod(starImportType, name, args);
533536
if (expression != null) return expression;
537+
// GRECLIPSE add -- GROOVY-8389
538+
if (isValidAccessorName(name)){
539+
// GRECLIPSE end
534540
expression = findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
535-
if (expression != null) {
541+
if (expression != null)
536542
return newStaticMethodCallX(starImportType, name, args);
537543
}
538544
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/control/StaticImportVisitor.java

+75-53
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,7 @@ protected Expression transformBinaryExpression(BinaryExpression be) {
205205
if (left instanceof StaticMethodCallExpression) {
206206
StaticMethodCallExpression smce = (StaticMethodCallExpression) left;
207207
StaticMethodCallExpression result = new StaticMethodCallExpression(smce.getOwnerType(), smce.getMethod(), right);
208-
// GRECLIPSE add
209208
result.copyNodeMetaData(smce);
210-
// GRECLIPSE end
211209
setSourcePosition(result, be);
212210
return result;
213211
}
@@ -263,14 +261,6 @@ protected Expression transformMethodCallExpression(MethodCallExpression mce) {
263261
setSourcePosition(result, mce);
264262
return result;
265263
}
266-
if (name != null && !inLeftExpression) { // maybe a closure field
267-
result = findStaticFieldOrPropertyAccessorImportFromModule(name);
268-
if (result != null) {
269-
result = new MethodCallExpression(result, "call", args);
270-
result.setSourcePosition(mce);
271-
return result;
272-
}
273-
}
274264
}
275265
} else if (currentMethod != null && currentMethod.isStatic() && isSuperExpression(object)) {
276266
Expression result = new MethodCallExpression(new ClassExpression(currentClass.getSuperClass()), method, args);
@@ -446,59 +436,91 @@ private Expression findStaticFieldOrPropertyAccessorImportFromModule(String name
446436
}
447437

448438
private Expression findStaticMethodImportFromModule(Expression method, Expression args) {
449-
ModuleNode module = currentClass.getModule();
450-
if (module == null || !(method instanceof ConstantExpression)) return null;
451-
Map<String, ImportNode> importNodes = module.getStaticImports();
452-
ConstantExpression ce = (ConstantExpression) method;
439+
if (currentClass.getModule() == null) return null;
440+
if (!(method instanceof ConstantExpression)) return null;
441+
if (!(((ConstantExpression) method).getValue() instanceof String)) return null;
442+
453443
Expression expression;
454-
Object value = ce.getValue();
455-
// skip non-Strings, e.g. Integer
456-
if (!(value instanceof String)) return null;
457-
final String name = (String) value;
444+
String name = method.getText();
445+
Map<String, ImportNode> staticImports = currentClass.getModule().getStaticImports();
458446
// look for one of these:
459-
// import static SomeClass.method [as otherName]
460-
// when resolving methodCall() or getProp() or setProp()
461-
if (importNodes.containsKey(name)) {
462-
ImportNode importNode = importNodes.get(name);
447+
// import static MyClass.field [as alias]
448+
// import static MyClass.method [as alias]
449+
// import static MyClass.property [as alias]
450+
// when resolving implicit-this call name(args)
451+
if (staticImports.containsKey(name)) {
452+
ImportNode importNode = staticImports.get(name);
463453
expression = findStaticMethod(importNode.getType(), importNode.getFieldName(), args);
464-
if (expression != null) return expression;
465-
expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), getPropNameForAccessor(importNode.getFieldName()), args);
466454
if (expression != null) {
467-
return newStaticMethodCallX(importNode.getType(), importNode.getFieldName(), args);
455+
return expression;
456+
}
457+
if (!inClosure && !inLeftExpression) {
458+
expression = findStaticPropertyOrField(importNode.getType(), importNode.getFieldName());
459+
if (expression != null) { // assume name refers to a callable static field/property
460+
MethodCallExpression call = new MethodCallExpression(expression, "call", args);
461+
call.setImplicitThis(false);
462+
return call;
463+
}
468464
}
469465
}
470466
// look for one of these:
471-
// import static SomeClass.someProp [as otherName]
472-
// when resolving getProp() or setProp()
473-
if (isValidAccessorName(name)) {
474-
String propName = getPropNameForAccessor(name);
475-
if (importNodes.containsKey(propName)) {
476-
ImportNode importNode = importNodes.get(propName);
477-
ClassNode importClass = importNode.getType();
467+
// import static MyClass.property [as alias]
468+
// import static MyClass.isProperty [as alias]
469+
// import static MyClass.getProperty [as alias]
470+
// import static MyClass.setProperty [as alias]
471+
// when resolving isName(), getName() or setName(args)
472+
boolean accessor = isValidAccessorName(name);
473+
if (accessor) {
474+
ImportNode importNode = staticImports.get(name);
475+
if (importNode != null) {
476+
String propName = getPropNameForAccessor(importNode.getFieldName());
477+
expression = findStaticPropertyAccessorGivenArgs(importNode.getType(), propName, args);
478+
if (expression != null) { // expression may refer to getter or setter, so make new call
479+
return newStaticMethodCallX(importNode.getType(), importNode.getFieldName(), args);
480+
}
481+
}
482+
importNode = staticImports.get(getPropNameForAccessor(name));
483+
if (importNode != null) {
484+
ClassNode importType = importNode.getType();
478485
String importMember = importNode.getFieldName();
479-
expression = findStaticMethod(importClass, prefix(name) + capitalize(importMember), args);
486+
expression = findStaticMethod(importType, prefix(name) + capitalize(importMember), args);
480487
if (expression != null) return expression;
481-
expression = findStaticPropertyAccessorGivenArgs(importClass, importMember, args);
488+
expression = findStaticPropertyAccessorGivenArgs(importType, importMember, args);
482489
if (expression != null) {
483-
return newStaticMethodCallX(importClass, prefix(name) + capitalize(importMember), args);
490+
return newStaticMethodCallX(importType, prefix(name) + capitalize(importMember), args);
484491
}
485492
}
486493
}
487-
Map<String, ImportNode> starImports = module.getStaticStarImports();
488-
ClassNode starImportType;
489-
if (currentClass.isEnum() && starImports.containsKey(currentClass.getName())) {
490-
ImportNode importNode = starImports.get(currentClass.getName());
491-
starImportType = importNode == null ? null : importNode.getType();
492-
expression = findStaticMethod(starImportType, name, args);
494+
495+
Map<String, ImportNode> staticStarImports = currentClass.getModule().getStaticStarImports();
496+
if (currentClass.isEnum() && staticStarImports.containsKey(currentClass.getName())) {
497+
ImportNode importNode = staticStarImports.get(currentClass.getName());
498+
expression = findStaticMethod(importNode.getType(), name, args);
493499
return expression;
494-
} else {
495-
for (ImportNode importNode : starImports.values()) {
496-
starImportType = importNode == null ? null : importNode.getType();
497-
expression = findStaticMethod(starImportType, name, args);
498-
if (expression != null) return expression;
499-
expression = findStaticPropertyAccessorGivenArgs(starImportType, getPropNameForAccessor(name), args);
500-
if (expression != null) {
501-
return newStaticMethodCallX(starImportType, name, args);
500+
}
501+
// look for one of these:
502+
// import static MyClass.*
503+
// when resolving name(args), getName(), etc.
504+
for (ImportNode importNode : staticStarImports.values()) {
505+
ClassNode importType = importNode.getType();
506+
expression = findStaticMethod(importType, name, args);
507+
if (expression != null) return expression;
508+
if (!inClosure && !inLeftExpression) { // GROOVY-10329
509+
expression = findStaticPropertyOrField(importType, name);
510+
if (expression != null) { // assume name refers to a callable static field/property
511+
MethodCallExpression call = new MethodCallExpression(expression, "call", args);
512+
call.setImplicitThis(false);
513+
// GRECLIPSE add
514+
expression.setSourcePosition(method);
515+
// GRECLIPSE end
516+
return call;
517+
}
518+
}
519+
if (accessor) {
520+
String propName = getPropNameForAccessor(name);
521+
expression = findStaticPropertyAccessorGivenArgs(importType, propName, args);
522+
if (expression != null) { // expression may refer to getter or setter, so ...
523+
return newStaticMethodCallX(importType, name, args);
502524
}
503525
}
504526
}
@@ -591,14 +613,14 @@ private static Expression findStaticMethod(ClassNode staticImportType, String me
591613
return null;
592614
}
593615

594-
private static PropertyExpression newStaticPropertyX(ClassNode type, String name) {
595-
return new PropertyExpression(new ClassExpression(type.getPlainNodeReference()), name);
596-
}
597-
598616
private static StaticMethodCallExpression newStaticMethodCallX(ClassNode type, String name, Expression args) {
599617
return new StaticMethodCallExpression(type.getPlainNodeReference(), name, args);
600618
}
601619

620+
private static PropertyExpression newStaticPropertyX(ClassNode type, String name) {
621+
return new PropertyExpression(new ClassExpression(type.getPlainNodeReference()), name);
622+
}
623+
602624
@Override
603625
protected SourceUnit getSourceUnit() {
604626
return sourceUnit;

0 commit comments

Comments
 (0)