GROOVY-8715: check array in ResolveVisitor.resolveToInner
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index f42e862..d348a77 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -322,24 +322,14 @@
genericParameterNames = oldPNames;
}
- 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)) {
- return true;
- }
- }
+ private void resolveOrFailPlus(final ClassNode type, final ASTNode node) {
+ resolveGenericsTypes(type.getGenericsTypes());
+ if (resolveAliasFromModule(type)) return;
+ resolveOrFail(type, node);
+ }
- type.setName(saved);
- return false;
+ private void resolveOrFail(final ClassNode type, final ASTNode node) {
+ resolveOrFail(type, "", node);
}
private void resolveOrFail(final ClassNode type, final String msg, final ASTNode node) {
@@ -350,6 +340,31 @@
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;
+
+ // 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;
+ }
+ }
+ t.setName(name);
+ return false;
+ }
+
// 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 @@
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);
}
@@ -1471,10 +1476,10 @@
}
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 1d4c1ad..65377eb 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1236,6 +1236,74 @@
'''
}
+ @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 '''