From commits-return-7941-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Fri Jan 25 17:43:58 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id C14AF180771 for ; Fri, 25 Jan 2019 17:43:57 +0100 (CET) Received: (qmail 98959 invoked by uid 500); 25 Jan 2019 16:43:56 -0000 Mailing-List: contact commits-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list commits@groovy.apache.org Received: (qmail 98941 invoked by uid 99); 25 Jan 2019 16:43:56 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 Jan 2019 16:43:56 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 458098556E; Fri, 25 Jan 2019 16:43:56 +0000 (UTC) Date: Fri, 25 Jan 2019 16:43:56 +0000 To: "commits@groovy.apache.org" Subject: [groovy] branch master updated: GROOVY-4287: CLONE - import of static nested classes in external groovy files is broken(closes #858) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <154843463598.30046.11628315944390004241@gitbox.apache.org> From: sunlan@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: groovy X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 0736035cb22182c3b8d252967ea1357ed2068e35 X-Git-Newrev: 9942c2b252845aa557f58850185b68c70fb7936e X-Git-Rev: 9942c2b252845aa557f58850185b68c70fb7936e X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. sunlan 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 9942c2b GROOVY-4287: CLONE - import of static nested classes in external groovy files is broken(closes #858) 9942c2b is described below commit 9942c2b252845aa557f58850185b68c70fb7936e Author: Daniel Sun AuthorDate: Sat Jan 26 00:43:46 2019 +0800 GROOVY-4287: CLONE - import of static nested classes in external groovy files is broken(closes #858) --- .../codehaus/groovy/control/ResolveVisitor.java | 56 +++++++++++++++++----- .../groovy/bugs/groovy4287/Main.groovy | 27 +++++++++++ .../groovy/bugs/groovy4287/Main2.groovy | 24 ++++++++++ .../groovy/bugs/groovy4287/Outer.groovy | 25 ++++++++++ .../groovy/bugs/groovy4287/Outer2.groovy | 25 ++++++++++ .../groovy/bugs/groovy4287/Outer3.groovy | 25 ++++++++++ src/test/groovy/bugs/Groovy4287Bug.groovy | 37 ++++++++++++++ 7 files changed, 208 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java index c6bd079..ff3f55f 100644 --- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java +++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java @@ -354,27 +354,61 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer { // when resolving the outer class later, we set the resolved type of ConstructedOuterNestedClass instance to the actual inner class node(SEE GROOVY-7812(#2)) private boolean resolveToOuterNested(ClassNode type) { CompileUnit compileUnit = currentClass.getCompileUnit(); - Map classesToCompile = compileUnit.getClassesToCompile(); + String typeName = type.getName(); + + ModuleNode module = currentClass.getModule(); + for (ImportNode importNode : module.getStaticImports().values()) { + String importFieldName = importNode.getFieldName(); + String importAlias = importNode.getAlias(); - for (Map.Entry entry : classesToCompile.entrySet()) { - String enclosingClassName = entry.getKey(); - ClassNode enclosingClassNode = entry.getValue(); + if (!typeName.equals(importAlias)) continue; - String outerNestedClassName = tryToConstructOuterNestedClassName(type, enclosingClassName); - if (null != outerNestedClassName) { - compileUnit.addClassNodeToResolve(new ConstructedOuterNestedClassNode(enclosingClassNode, outerNestedClassName)); + ConstructedOuterNestedClassNode constructedOuterNestedClassNode = tryToConstructOuterNestedClassNodeViaStaticImport(compileUnit, importNode, importFieldName); + if (null != constructedOuterNestedClassNode) { + compileUnit.addClassNodeToResolve(constructedOuterNestedClassNode); return true; } } - return false; + for (Map.Entry entry : compileUnit.getClassesToCompile().entrySet()) { + ClassNode outerClassNode = entry.getValue(); + ConstructedOuterNestedClassNode constructedOuterNestedClassNode = tryToConstructOuterNestedClassNode(type, outerClassNode); + if (null != constructedOuterNestedClassNode) { + compileUnit.addClassNodeToResolve(constructedOuterNestedClassNode); + return true; + } + } + + boolean toResolveFurther = false; + for (ImportNode importNode : module.getStaticStarImports().values()) { + ConstructedOuterNestedClassNode constructedOuterNestedClassNode = tryToConstructOuterNestedClassNodeViaStaticImport(compileUnit, importNode, typeName); + if (null != constructedOuterNestedClassNode) { + compileUnit.addClassNodeToResolve(constructedOuterNestedClassNode); + toResolveFurther = true; // do not return here and try all static star imports because currently we do not know which outer class the class to resolve is declared in + } + } + + return toResolveFurther; + } + + private ConstructedOuterNestedClassNode tryToConstructOuterNestedClassNodeViaStaticImport(CompileUnit compileUnit, ImportNode importNode, String typeName) { + String importClassName = importNode.getClassName(); + ClassNode outerClassNode = compileUnit.getClass(importClassName); + + if (null == outerClassNode) return null; + + String outerNestedClassName = importClassName + "$" + typeName.replace(".", "$"); + return new ConstructedOuterNestedClassNode(outerClassNode, outerNestedClassName); } - private String tryToConstructOuterNestedClassName(ClassNode type, String enclosingClassName) { + private ConstructedOuterNestedClassNode tryToConstructOuterNestedClassNode(ClassNode type, ClassNode outerClassNode) { + String outerClassName = outerClassNode.getName(); + for (String typeName = type.getName(), ident = typeName; ident.contains("."); ) { ident = ident.substring(0, ident.lastIndexOf(".")); - if (enclosingClassName.endsWith(ident)) { - return enclosingClassName + typeName.substring(ident.length()).replace(".", "$"); + if (outerClassName.endsWith(ident)) { + String outerNestedClassName = outerClassName + typeName.substring(ident.length()).replace(".", "$"); + return new ConstructedOuterNestedClassNode(outerClassNode, outerNestedClassName); } } diff --git a/src/test-resources/groovy/bugs/groovy4287/Main.groovy b/src/test-resources/groovy/bugs/groovy4287/Main.groovy new file mode 100644 index 0000000..a04077a --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4287/Main.groovy @@ -0,0 +1,27 @@ +/* + * 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.groovy4287 + +import static groovy.bugs.groovy4287.Outer.Inner +import static groovy.bugs.groovy4287.Outer3.* // the static star import is used to test resolving, don't remove it +import static groovy.bugs.groovy4287.Outer2.* + +assert "outer.inner" == new Inner().innerName +assert "outer2.inner2" == new Inner2().innerName +assert Inner2.class.name != null diff --git a/src/test-resources/groovy/bugs/groovy4287/Main2.groovy b/src/test-resources/groovy/bugs/groovy4287/Main2.groovy new file mode 100644 index 0000000..4f9feb8 --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4287/Main2.groovy @@ -0,0 +1,24 @@ +/* + * 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.groovy4287 + +import static groovy.bugs.groovy4287.Outer.Inner as OIC + +assert "outer.inner" == new OIC().innerName + diff --git a/src/test-resources/groovy/bugs/groovy4287/Outer.groovy b/src/test-resources/groovy/bugs/groovy4287/Outer.groovy new file mode 100644 index 0000000..6659f12 --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4287/Outer.groovy @@ -0,0 +1,25 @@ +/* + * 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.groovy4287 + +class Outer { + static class Inner { + def innerName = "outer.inner" + } +} diff --git a/src/test-resources/groovy/bugs/groovy4287/Outer2.groovy b/src/test-resources/groovy/bugs/groovy4287/Outer2.groovy new file mode 100644 index 0000000..0c0bf64 --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4287/Outer2.groovy @@ -0,0 +1,25 @@ +/* + * 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.groovy4287 + +class Outer2 { + static class Inner2 { + def innerName = "outer2.inner2" + } +} diff --git a/src/test-resources/groovy/bugs/groovy4287/Outer3.groovy b/src/test-resources/groovy/bugs/groovy4287/Outer3.groovy new file mode 100644 index 0000000..58732a3 --- /dev/null +++ b/src/test-resources/groovy/bugs/groovy4287/Outer3.groovy @@ -0,0 +1,25 @@ +/* + * 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.groovy4287 + +class Outer3 { + static class Inner3 { + def innerName = "outer3.inner3" + } +} diff --git a/src/test/groovy/bugs/Groovy4287Bug.groovy b/src/test/groovy/bugs/Groovy4287Bug.groovy new file mode 100644 index 0000000..9f3e79c --- /dev/null +++ b/src/test/groovy/bugs/Groovy4287Bug.groovy @@ -0,0 +1,37 @@ +/* + * 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 + +import org.codehaus.groovy.tools.GroovyStarter + +class Groovy4287Bug extends GroovyTestCase { + void testResolvingOuterStaticNestedClass() { + def mainScriptPath = new File(this.getClass().getResource('/groovy/bugs/groovy4287/Main.groovy').toURI()).absolutePath + runScript(mainScriptPath) + } + + void testResolvingOuterStaticNestedClassAlias() { + def mainScriptPath = new File(this.getClass().getResource('/groovy/bugs/groovy4287/Main2.groovy').toURI()).absolutePath + runScript(mainScriptPath) + } + + static void runScript(String path) { + GroovyStarter.main(new String[] { "--main", "groovy.ui.GroovyMain", path }) + } +}