This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch GROOVY_3_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1145e9d8bbed5d69c2a5eaafd63d0edbb8be07a3 Author: Eric Milles <[email protected]> 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 f42e862..d348a77 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); } @@ -1471,10 +1476,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 1d4c1ad..65377eb 100644 --- a/src/test/gls/innerClass/InnerClassTest.groovy +++ b/src/test/gls/innerClass/InnerClassTest.groovy @@ -1236,6 +1236,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 '''
