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 2019/11/21 17:49:00 UTC

[groovy] branch GROOVY-8399 created (now 9da0c81)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY-8399
in repository https://gitbox.apache.org/repos/asf/groovy.git.


      at 9da0c81  GROOVY-8399: apply import customizations only once per module

This branch includes the following new commits:

     new 9da0c81  GROOVY-8399: apply import customizations only once per module

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[groovy] 01/01: GROOVY-8399: apply import customizations only once per module

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-8399
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 9da0c81c4657687331ef8307c72034e950d422bb
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 21 11:48:44 2019 -0600

    GROOVY-8399: apply import customizations only once per module
---
 .../control/customizers/ImportCustomizer.java      |  65 +++++-----
 .../customizers/ImportCustomizerTest.groovy        | 132 +++++++++++++++------
 2 files changed, 131 insertions(+), 66 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java b/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
index ebd16f5..d1bf9d0 100644
--- a/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
+++ b/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
@@ -22,7 +22,6 @@ import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.classgen.GeneratorContext;
-import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilePhase;
 import org.codehaus.groovy.control.SourceUnit;
 
@@ -30,27 +29,31 @@ import java.util.LinkedList;
 import java.util.List;
 
 /**
- * This compilation customizer allows addiing various types of imports to the compilation unit. Supports adding :
+ * This compilation customizer allows addiing various types of imports to the compilation unit. Supports adding:
  * <ul>
- *     <li>standard imports thanks to {@link #addImport(String)}, {@link #addImport(String, String)} or {@link #addImports(String...)}</li>
- *     <li>star imports thanks to {@link #addStarImport(String)} or {@link #addStarImports(String...)}</li>
- *     <li>static imports thanks to {@link #addStaticImport(String, String)} or {@link #addStaticImport(String, String, String)}</li>
- *     <li>static star imports thanks to {@link #addStaticStar(String)} or {@link #addStaticStars(String...)}</li>
+ *     <li>standard imports via {@link #addImports(String...)} or {@link #addImport(String, String)}</li>
+ *     <li>star imports via {@link #addStarImports(String...)}</li>
+ *     <li>static imports via {@link #addStaticImport(String, String)} or {@link #addStaticImport(String, String, String)}</li>
+ *     <li>static star imports via {@link #addStaticStars(String...)}</li>
  * </ul>
  *
  * @since 1.8.0
  */
 public class ImportCustomizer extends CompilationCustomizer {
 
-    private final List<Import> imports = new LinkedList<Import>();
+    private final List<Import> imports = new LinkedList<>();
 
     public ImportCustomizer() {
         super(CompilePhase.CONVERSION);
     }
 
     @Override
-    public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
-        final ModuleNode ast = source.getAST();
+    public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) {
+        ModuleNode ast = source.getAST();
+
+        // GROOVY-8399: apply import customizations only once per module
+        if (!classNode.getName().equals(ast.getMainClassName())) return;
+
         for (Import anImport : imports) {
             switch (anImport.type) {
                 case regular:
@@ -75,15 +78,7 @@ public class ImportCustomizer extends CompilationCustomizer {
     }
 
     public ImportCustomizer addStaticImport(final String className, final String fieldName) {
-        final ClassNode node = ClassHelper.make(className);
-        imports.add(new Import(ImportType.staticImport, fieldName, node, fieldName));
-        return this;
-    }
-
-    public ImportCustomizer addStaticStars(final String... classNames) {
-        for (String className : classNames) {
-            addStaticStar(className);
-        }
+        imports.add(new Import(ImportType.staticImport, fieldName, ClassHelper.make(className), fieldName));
         return this;
     }
 
@@ -92,32 +87,40 @@ public class ImportCustomizer extends CompilationCustomizer {
         return this;
     }
 
-    public ImportCustomizer addImports(final String... imports) {
-            for (String anImport : imports) {
-                addImport(anImport);
-            }
+    public ImportCustomizer addImports(final String... classNames) {
+        for (String className : classNames) {
+            addImport(className);
+        }
         return this;
     }
 
     public ImportCustomizer addStarImports(final String... packageNames) {
-            for (String packageName : packageNames) {
-                addStarImport(packageName);
-            }
+        for (String packageName : packageNames) {
+            addStarImport(packageName);
+        }
         return this;
     }
 
+    public ImportCustomizer addStaticStars(final String... classNames) {
+        for (String className : classNames) {
+            addStaticStar(className);
+        }
+        return this;
+    }
+
+    //
+
     private void addImport(final String className) {
-        final ClassNode node = ClassHelper.make(className);
+        ClassNode node = ClassHelper.make(className);
         imports.add(new Import(ImportType.regular, node.getNameWithoutPackage(), node));
     }
 
-    private void addStaticStar(final String className) {
-        imports.add(new Import(ImportCustomizer.ImportType.staticStar, className, ClassHelper.make(className)));
+    private void addStarImport(final String packageName) {
+        imports.add(new Import(ImportType.star, packageName.endsWith(".") ? packageName : packageName + "."));
     }
 
-    private void addStarImport(final String packagename) {
-        final String packageNameEndingWithDot = packagename.endsWith(".")?packagename:packagename+'.';
-        imports.add(new Import(ImportType.star,packageNameEndingWithDot));
+    private void addStaticStar(final String className) {
+        imports.add(new Import(ImportCustomizer.ImportType.staticStar, className, ClassHelper.make(className)));
     }
 
     // -------------------- Helper classes -------------------------
diff --git a/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy b/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
index 733c24d..adcd0c4 100644
--- a/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
+++ b/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
@@ -18,99 +18,161 @@
  */
 package org.codehaus.groovy.control.customizers
 
-import groovy.test.GroovyTestCase
 import org.codehaus.groovy.control.CompilerConfiguration
+import org.junit.Before
+import org.junit.Test
 
 /**
- * Tests the import customizer.
+ * Tests for {@link ImportCustomizer}.
  */
-class ImportCustomizerTest extends GroovyTestCase {
-    CompilerConfiguration configuration
-    ImportCustomizer importCustomizer
+final class ImportCustomizerTest {
 
+    private final CompilerConfiguration configuration = new CompilerConfiguration()
+    private final ImportCustomizer importCustomizer = new ImportCustomizer()
+
+    @Before
     void setUp() {
-        configuration = new CompilerConfiguration()
-        importCustomizer = new ImportCustomizer()
         configuration.addCompilationCustomizers(importCustomizer)
     }
 
+    @Test
     void testAddImport() {
-        importCustomizer.addImports("java.util.concurrent.atomic.AtomicInteger")
+        importCustomizer.addImports('java.util.concurrent.atomic.AtomicInteger')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AtomicInteger(0)")
+        shell.evaluate('new AtomicInteger(0)')
         // no exception means success
     }
 
+    @Test
     void testAddImportWithAlias() {
-        importCustomizer.addImport("AI","java.util.concurrent.atomic.AtomicInteger")
+        importCustomizer.addImport('AI', 'java.util.concurrent.atomic.AtomicInteger')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AI(0)")
+        shell.evaluate('new AI(0)')
         // no exception means success
     }
 
+    @Test
     void testAddInnerClassImport() {
-        importCustomizer.addImports("org.codehaus.groovy.control.customizers.ImportCustomizerTest.Inner")
+        importCustomizer.addImports('org.codehaus.groovy.control.customizers.ImportCustomizerTest.Inner')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new Inner()")
+        shell.evaluate('new Inner()')
         // no exception means success
     }
 
+    @Test
     void testAddInnerClassImport2() {
-        importCustomizer.addImports("org.codehaus.groovy.control.customizers.ImportCustomizerTest")
+        importCustomizer.addImports('org.codehaus.groovy.control.customizers.ImportCustomizerTest')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new ImportCustomizerTest.Inner()")
+        shell.evaluate('new ImportCustomizerTest.Inner()')
         // no exception means success
     }
 
+    @Test
     void testAddStaticImport() {
-        importCustomizer.addStaticImport("java.lang.Math", "PI")
+        importCustomizer.addStaticImport('java.lang.Math', 'PI')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("PI")
+        shell.evaluate('PI')
         // no exception means success
     }
 
+    @Test
     void testAddStaticImportWithAlias() {
-        importCustomizer.addStaticImport("pi","java.lang.Math", "PI")
+        importCustomizer.addStaticImport('pi', 'java.lang.Math', 'PI')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("pi")
+        shell.evaluate('pi')
         // no exception means success
     }
 
+    @Test
     void testAddStaticStarImport() {
-        importCustomizer.addStaticStars("java.lang.Math")
+        importCustomizer.addStaticStars('java.lang.Math')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("PI")
+        shell.evaluate('PI')
         // no exception means success
     }
 
+    @Test
     void testAddStarImport() {
-        importCustomizer.addStarImports("java.util.concurrent.atomic")
+        importCustomizer.addStarImports('java.util.concurrent.atomic')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AtomicInteger(0)")
+        shell.evaluate('new AtomicInteger(0)')
         // no exception means success
     }
 
+    @Test
     void testAddImports() {
-        importCustomizer.addImports("java.util.concurrent.atomic.AtomicInteger","java.util.concurrent.atomic.AtomicLong")
+        importCustomizer.addImports('java.util.concurrent.atomic.AtomicInteger', 'java.util.concurrent.atomic.AtomicLong')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("""new AtomicInteger(0)
-        new AtomicLong(0)""")
+        shell.evaluate('''
+            new AtomicInteger(0)
+            new AtomicLong(0)
+        ''')
         // no exception means success
     }
 
+    @Test
     void testAddImportsOnScriptEngine() {
-        File script = File.createTempFile('test', '.groovy')
-            script.deleteOnExit()
-            script.write """
+        importCustomizer.addImports('java.text.SimpleDateFormat')
+
+        def script = File.createTempFile('test', '.groovy')
+        script.deleteOnExit()
+        script.write '''
             println new SimpleDateFormat()
-        """
+        '''
+        // run script with script engine; this will not work if import customizer is not used
+        def scriptEngine = new GroovyScriptEngine(script.parent)
+        scriptEngine.config = configuration
+        scriptEngine.run(script.name, new Binding())
+    }
 
-        importCustomizer.addImports 'java.text.SimpleDateFormat'
+    @Test // GROOVY-8399
+    void testAddImportsOnModuleWithMultipleClasses() {
+        importCustomizer.addImports('java.text.SimpleDateFormat')
+        def shell = new GroovyShell(configuration)
+        shell.evaluate('''\
+            @groovy.transform.ASTTest({
+                def imports = node.module.imports*.text
+                assert imports == ['import java.text.SimpleDateFormat as SimpleDateFormat']
+            })
+            class A {
+                static class AA {
+                }
+            }
+            class B {
+                static class BB {
+                }
+            }
+            class C {
+                static class CC {
+                }
+            }
+            println new SimpleDateFormat()
+        ''')
+    }
 
-        // Run script with script engine: this will not work, import customizer is not used
-        GroovyScriptEngine scriptEngine = new GroovyScriptEngine(script.parent)
-        scriptEngine.setConfig configuration
-        scriptEngine.run script.name, new Binding()
+    @Test // GROOVY-8399
+    void testAddStarImportsOnModuleWithMultipleClasses() {
+        importCustomizer.addStarImports('java.text', 'groovy.transform')
+        def shell = new GroovyShell(configuration)
+        shell.evaluate('''\
+            @groovy.transform.ASTTest({
+                def imports = node.module.starImports*.text
+                assert imports == ['import java.text.*', 'import groovy.transform.*']
+            })
+            class A {
+                static class AA {
+                }
+            }
+            class B {
+                static class BB {
+                }
+            }
+            class C {
+                static class CC {
+                }
+            }
+            println new SimpleDateFormat()
+        ''')
     }
 
     protected static class Inner {}