You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/07/17 19:25:49 UTC
[groovy] 01/01: GROOVY-8715: check array in
ResolveVisitor.resolveToInner
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-8715
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 9c49a89e46ced56c34b48e6f6929aafe2c4932bb
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 17 14:18:12 2020 -0500
GROOVY-8715: check array in ResolveVisitor.resolveToInner
---
.../codehaus/groovy/control/ResolveVisitor.java | 61 ++++++++++---------
src/test/gls/innerClass/InnerClassTest.groovy | 68 ++++++++++++++++++++++
2 files changed, 101 insertions(+), 28 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 4395dc8..bc526fc 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -322,34 +322,49 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
genericParameterNames = oldPNames;
}
+ private void resolveOrFailPlus(final ClassNode type, final ASTNode node) {
+ resolveGenericsTypes(type.getGenericsTypes());
+ if (resolveAliasFromModule(type)) return;
+ resolveOrFail(type, node);
+ }
+
+ private void resolveOrFail(final ClassNode type, final ASTNode node) {
+ resolveOrFail(type, "", node);
+ }
+
+ private void resolveOrFail(final ClassNode type, final String msg, final ASTNode node) {
+ if (resolve(type)) return;
+ if (resolveToInner(type)) return;
+ if (resolveToOuterNested(type)) return;
+
+ addError("unable to resolve class " + type.toString(false) + msg, node);
+ }
+
protected boolean resolveToInner(final ClassNode type) {
// we do not do our name mangling to find an inner class
// if the type is a ConstructedClassWithPackage, because in this case we
// are resolving the name at a different place already
if (type instanceof ConstructedClassWithPackage) return false;
if (type instanceof ConstructedNestedClass) return false;
- String name = type.getName();
- String saved = name;
- while (name.lastIndexOf('.') != -1) {
- name = replaceLastPointWithDollar(name);
- type.setName(name);
- if (resolve(type)) {
+
+ // GROOVY-8715
+ ClassNode t = type;
+ while (t.isArray()) {
+ t = t.getComponentType();
+ }
+
+ String name = t.getName(), temp = name;
+ while (temp.lastIndexOf('.') != -1) {
+ temp = replaceLastPointWithDollar(temp);
+ t.setName(temp);
+ if (resolve(t, true, false, false)) {
return true;
}
}
-
- type.setName(saved);
+ t.setName(name);
return false;
}
- private void resolveOrFail(final ClassNode type, final String msg, final ASTNode node) {
- if (resolve(type)) return;
- if (resolveToInner(type)) return;
- if (resolveToOuterNested(type)) return;
-
- addError("unable to resolve class " + type.toString(false) + msg, node);
- }
-
// GROOVY-7812(#1): Static inner classes cannot be accessed from other files when running by 'groovy' command
// if the type to resolve is an inner class and it is in an outer class which is not resolved,
// we set the resolved type to a placeholder class node, i.e. a ConstructedOuterNestedClass instance
@@ -447,16 +462,6 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
return constructedOuterNestedClassNode;
}
- private void resolveOrFail(final ClassNode type, final ASTNode node, final boolean prefereImports) {
- resolveGenericsTypes(type.getGenericsTypes());
- if (prefereImports && resolveAliasFromModule(type)) return;
- resolveOrFail(type, node);
- }
-
- private void resolveOrFail(final ClassNode type, final ASTNode node) {
- resolveOrFail(type, "", node);
- }
-
protected boolean resolve(final ClassNode type) {
return resolve(type, true, true, true);
}
@@ -1467,10 +1472,10 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
}
ClassNode sn = node.getUnresolvedSuperClass();
- if (sn != null) resolveOrFail(sn, node, true);
+ if (sn != null) resolveOrFailPlus(sn, node);
for (ClassNode anInterface : node.getInterfaces()) {
- resolveOrFail(anInterface, node, true);
+ resolveOrFailPlus(anInterface, node);
}
checkCyclicInheritance(node, node.getUnresolvedSuperClass(), node.getInterfaces());
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 81e51d9..f7a2bec 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1216,6 +1216,74 @@ final class InnerClassTest {
'''
}
+ @Test
+ void testResolveInnerOfSuperType9() {
+ assertScript '''
+ abstract class A {
+ static class B {}
+ }
+
+ def test(A.B[] bees) {
+ assert bees != null
+ }
+
+ test(new A.B[0])
+ '''
+ }
+
+ @Test
+ void testResolveInnerOfSuperType9a() {
+ assertScript '''
+ abstract class A {
+ static class B {}
+ }
+
+ def test(A.B... bees) {
+ assert bees != null
+ }
+
+ test()
+ '''
+ }
+
+ @CompileDynamic @Test // GROOVY-8715
+ void testResolveInnerOfSuperType9b() {
+ def config = new CompilerConfiguration(
+ targetDirectory: File.createTempDir(),
+ jointCompilationOptions: [memStub: true]
+ )
+ def parentDir = File.createTempDir()
+ try {
+ new File(parentDir, 'p').mkdir()
+
+ def a = new File(parentDir, 'p/A.Java')
+ a.write '''
+ package p;
+ public abstract class A {
+ public interface I {}
+ }
+ '''
+ def b = new File(parentDir, 'p/B.groovy')
+ b.write '''
+ package p
+ def test(A.I... eyes) {
+ assert eyes != null
+ }
+ test()
+ '''
+
+ def loader = new GroovyClassLoader(this.class.classLoader)
+ def cu = new JavaAwareCompilationUnit(config, loader)
+ cu.addSources(a, b)
+ cu.compile()
+
+ loader.loadClass('p.B').main()
+ } finally {
+ config.targetDirectory.deleteDir()
+ parentDir.deleteDir()
+ }
+ }
+
@Test // GROOVY-5679, GROOVY-5681
void testEnclosingMethodIsSet() {
assertScript '''