You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/08/13 08:08:28 UTC
[groovy] branch master updated: GROOVY-9031: correct trait property
generics before writing stub methods
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 d321754 GROOVY-9031: correct trait property generics before writing stub methods
d321754 is described below
commit d321754e8cf7054c5bcf89c56c2eadfc0c01916e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Aug 12 14:43:57 2019 -0500
GROOVY-9031: correct trait property generics before writing stub methods
---
.../groovy/tools/javac/JavaStubGenerator.java | 32 +++++++++-
src/test/groovy/bugs/Groovy9031.groovy | 72 ++++++++++++++++++++++
2 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
index 71049ec..879064f 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
@@ -67,13 +67,19 @@ import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
+
public class JavaStubGenerator {
private final boolean java5;
private final String encoding;
@@ -171,17 +177,37 @@ public class JavaStubGenerator {
try {
Verifier verifier = new Verifier() {
@Override
- public void visitClass(final ClassNode node) {
- List<Statement> savedStatements = new ArrayList<Statement>(node.getObjectInitializerStatements());
+ public void visitClass(ClassNode node) {
+ List<Statement> savedStatements = new ArrayList<>(node.getObjectInitializerStatements());
super.visitClass(node);
node.getObjectInitializerStatements().addAll(savedStatements);
- for (ClassNode trait : Traits.findTraits(node)) {
+
+ for (ClassNode trait : findTraits(node)) {
+ // GROOVY-9031: replace property type placeholder with resolved type from trait generics
+ Map<String, ClassNode> generics = trait.isUsingGenerics() ? createGenericsSpec(trait) : null;
for (PropertyNode traitProperty : trait.getProperties()) {
+ ClassNode traitPropertyType = traitProperty.getType();
+ traitProperty.setType(correctToGenericsSpec(generics, traitPropertyType));
super.visitProperty(traitProperty);
+ traitProperty.setType(traitPropertyType);
}
}
}
+ private Iterable<ClassNode> findTraits(ClassNode node) {
+ Set<ClassNode> traits = new LinkedHashSet<>();
+
+ LinkedList<ClassNode> todo = new LinkedList<>();
+ Collections.addAll(todo, node.getInterfaces());
+ while (!todo.isEmpty()) {
+ ClassNode next = todo.removeLast();
+ if (Traits.isTrait(next)) traits.add(next);
+ Collections.addAll(todo, next.getInterfaces());
+ }
+
+ return traits;
+ }
+
@Override
public void visitConstructor(ConstructorNode node) {
Statement stmt = node.getCode();
diff --git a/src/test/groovy/bugs/Groovy9031.groovy b/src/test/groovy/bugs/Groovy9031.groovy
new file mode 100644
index 0000000..6af7740
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9031.groovy
@@ -0,0 +1,72 @@
+/*
+ * 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.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+import org.junit.Test
+
+final class Groovy9031 {
+
+ @Test
+ void testGenerics() {
+ def config = new CompilerConfiguration(
+ targetDirectory: File.createTempDir(),
+ jointCompilationOptions: [stubDir: File.createTempDir()]
+ )
+
+ def parentDir = File.createTempDir()
+ try {
+ def a = new File(parentDir, 'Trait.groovy')
+ a.write '''
+ trait Trait<V> {
+ V value
+ }
+ '''
+ def b = new File(parentDir, 'TraitImpl.groovy')
+ b.write '''
+ class TraitImpl implements Trait<String> {
+ }
+ '''
+ def c = new File(parentDir, 'Whatever.java')
+ c.write '''
+ class Whatever {
+ void meth() {
+ new TraitImpl().getValue();
+ }
+ }
+ '''
+
+ def loader = new GroovyClassLoader(this.class.classLoader)
+ def cu = new JavaAwareCompilationUnit(config, loader)
+ cu.addSources(a, b, c)
+ cu.compile()
+
+ def stub = new File(config.jointCompilationOptions.stubDir, 'TraitImpl.java')
+ def text = stub.text
+
+ assert text.contains('java.lang.String getValue()')
+ assert text.contains('void setValue(java.lang.String value)')
+ } finally {
+ parentDir.deleteDir()
+ config.targetDirectory.deleteDir()
+ config.jointCompilationOptions.stubDir.deleteDir()
+ }
+ }
+}