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:01 UTC

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

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 {}