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 2020/05/29 16:31:38 UTC

[groovy] branch GROOVY-9577 created (now 294ad6f)

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

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


      at 294ad6f  GROOVY-9577: maintain insertion order of imports and retain duplicates

This branch includes the following new commits:

     new 294ad6f  GROOVY-9577: maintain insertion order of imports and retain duplicates

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-9577: maintain insertion order of imports and retain duplicates

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

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

commit 294ad6f0465622329dd9fc3d1e11b0b9b52a52d1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri May 29 11:28:04 2020 -0500

    GROOVY-9577: maintain insertion order of imports and retain duplicates
    
    - lazily create name to node map
---
 .../java/org/codehaus/groovy/ast/ModuleNode.java   | 13 +++---
 .../groovy/control/io/AbstractReaderSource.java    | 12 ++----
 .../org/codehaus/groovy/ast/ModuleNodeTest.java    | 46 +++++++++++++++-------
 .../groovy/syntax/parser/TestParserSupport.java    | 38 ------------------
 4 files changed, 44 insertions(+), 65 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
index 7fcdfc6..4cc6870 100644
--- a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
@@ -32,12 +32,12 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
@@ -57,7 +57,7 @@ public class ModuleNode extends ASTNode implements Opcodes {
 
     private List<ClassNode> classes = new LinkedList<>();
     private final List<MethodNode> methods = new ArrayList<>();
-    private final Map<String, ImportNode> imports = new HashMap<>();
+    private final List<ImportNode> imports = new ArrayList<>();
     private final List<ImportNode> starImports = new ArrayList<>();
     private final Map<String, ImportNode> staticImports = new LinkedHashMap<>();
     private final Map<String, ImportNode> staticStarImports = new LinkedHashMap<>();
@@ -96,7 +96,7 @@ public class ModuleNode extends ASTNode implements Opcodes {
     }
 
     public List<ImportNode> getImports() {
-        return new ArrayList<>(imports.values());
+        return Collections.unmodifiableList(imports);
     }
 
     public List<ImportNode> getStarImports() {
@@ -125,7 +125,9 @@ public class ModuleNode extends ASTNode implements Opcodes {
      * @return the import node for the given alias or null if none is available
      */
     public ImportNode getImport(final String alias) {
-        return imports.get(alias);
+        Map<String, ImportNode> aliases = getNodeMetaData("import.aliases", x ->
+            imports.stream().collect(Collectors.toMap(ImportNode::getAlias, n -> n, (n, m) -> m)));
+        return aliases.get(alias);
     }
 
     public void addImport(final String alias, final ClassNode type) {
@@ -135,8 +137,9 @@ public class ModuleNode extends ASTNode implements Opcodes {
     public void addImport(final String alias, final ClassNode type, final List<AnnotationNode> annotations) {
         ImportNode importNode = new ImportNode(type, alias);
         importNode.addAnnotations(annotations);
-        imports.put(alias, importNode);
+        imports.add(importNode);
 
+        removeNodeMetaData("import.aliases");
         storeLastAddedImportNode(importNode);
     }
 
diff --git a/src/main/java/org/codehaus/groovy/control/io/AbstractReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/AbstractReaderSource.java
index c3a9d59..d31dd7b 100644
--- a/src/main/java/org/codehaus/groovy/control/io/AbstractReaderSource.java
+++ b/src/main/java/org/codehaus/groovy/control/io/AbstractReaderSource.java
@@ -29,15 +29,11 @@ import java.io.IOException;
  * provides common functionality.
  */
 public abstract class AbstractReaderSource implements ReaderSource {
-    protected CompilerConfiguration configuration;   // Configuration data
 
-    public AbstractReaderSource(CompilerConfiguration configuration) {
-        if (configuration == null) {
-            throw new IllegalArgumentException("Compiler configuration must not be null!");
-            // ... or more relaxed?
-            // configuration = CompilerConfiguration.DEFAULT;
-        }
-        this.configuration = configuration;
+    protected CompilerConfiguration configuration;
+
+    public AbstractReaderSource(final CompilerConfiguration configuration) {
+        this.configuration = configuration != null ? configuration : CompilerConfiguration.DEFAULT;
     }
 
     /**
diff --git a/src/test/org/codehaus/groovy/ast/ModuleNodeTest.java b/src/test/org/codehaus/groovy/ast/ModuleNodeTest.java
index e38a0c6..67d155f 100644
--- a/src/test/org/codehaus/groovy/ast/ModuleNodeTest.java
+++ b/src/test/org/codehaus/groovy/ast/ModuleNodeTest.java
@@ -18,31 +18,49 @@
  */
 package org.codehaus.groovy.ast;
 
-import org.codehaus.groovy.syntax.parser.TestParserSupport;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.junit.Test;
 
-import java.util.List;
+import static org.codehaus.groovy.control.ParserPlugin.buildAST;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
- * Tests the ClassNode
+ * Tests for {@link ModuleNode}.
  */
-public class ModuleNodeTest extends TestParserSupport {
+public final class ModuleNodeTest {
 
+    @Test
     public void testStatementClass() {
-        ModuleNode module = parse("x = [1, 2, 3]; println(x)", "Cheese.groovy");
-        assertFalse("Should have statements", module.getStatementBlock().isEmpty());
+        ModuleNode mn = buildAST("x = [1, 2, 3]; println(x)", null, null, null);
 
-        List<ClassNode> classes = module.getClasses();
-        assertEquals("Number of classes", 1, classes.size());
-
-        ClassNode classNode = (ClassNode) classes.get(0);
-        assertEquals("Class name", "Cheese", classNode.getName());
+        assertEquals(1, mn.getClasses().size());
+        assertTrue(mn.getClasses().get(0).getName().startsWith("Script"));
+        assertFalse("Should have statements", mn.getStatementBlock().isEmpty());
     }
 
-    // GROOVY-9194
+    @Test // GROOVY-9194
     public void testScriptStartingWithHash() {
         ModuleNode mn = new ModuleNode((CompileUnit) null);
         mn.setDescription("#script.groovy");
-        ClassNode cn = mn.getScriptClassDummy();
-        assertEquals("Dummy class name should not be empty", "#script", cn.getName());
+
+        assertEquals("Dummy class name should not be empty", "#script", mn.getScriptClassDummy().getName());
+    }
+
+    @Test // GROOVY-9577
+    public void testDuplicateImports() {
+        //@formatter:off
+        String source =
+            "import java.lang.Object\n" +
+            "import java.lang.Object\n" +
+            "import java.lang.Object as X\n";
+        //@formatter:on
+        ModuleNode mn = buildAST(source, null, null, null);
+
+        assertEquals(3, mn.getImports().size());
+        assertEquals(3, mn.getImport("X").getLineNumber());
+        assertEquals(2, mn.getImport("Object").getLineNumber());
+        assertEquals("X", DefaultGroovyMethods.last(mn.getImports()).getAlias());
     }
 }
diff --git a/src/test/org/codehaus/groovy/syntax/parser/TestParserSupport.java b/src/test/org/codehaus/groovy/syntax/parser/TestParserSupport.java
deleted file mode 100644
index c1fa1f7..0000000
--- a/src/test/org/codehaus/groovy/syntax/parser/TestParserSupport.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  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 org.codehaus.groovy.syntax.parser;
-
-import groovy.test.GroovyTestCase;
-import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.control.SourceUnit;
-
-/**
- * An abstract base class useful for AST parser related test cases
- */
-public abstract class TestParserSupport extends GroovyTestCase {
-    public ModuleNode parse(String text, String description) {
-        SourceUnit unit = SourceUnit.create(description, text);
-        CompilationUnit compUnit = new CompilationUnit();
-        compUnit.addSource(unit);
-        compUnit.compile(Phases.CONVERSION);
-        return unit.getAST();
-    }
-}