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:39 UTC
[groovy] 01/01: GROOVY-9577: maintain insertion order of imports
and retain duplicates
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();
- }
-}