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 2022/11/19 19:58:56 UTC
[groovy] branch master updated: GROOVY-10797: stubgen: deal with class/method type parameters separately
This is an automated email from the ASF dual-hosted git repository.
emilles 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 39153104c3 GROOVY-10797: stubgen: deal with class/method type parameters separately
39153104c3 is described below
commit 39153104c318c0ee50ce315c7dd0ea85369ccacf
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 19 13:54:55 2022 -0600
GROOVY-10797: stubgen: deal with class/method type parameters separately
---
.../groovy/tools/javac/JavaStubGenerator.java | 104 ++++++++++++---------
.../{Groovy7306.groovy => Groovy10797.groovy} | 29 +++---
.../groovy/tools/stubgenerator/Groovy7306.groovy | 2 +-
.../groovy/tools/stubgenerator/StubTestCase.groovy | 10 +-
.../TraitAbstractGetterStubTest.groovy | 43 +++------
5 files changed, 94 insertions(+), 94 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 add86edd02..a12526305e 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
@@ -78,6 +78,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
@@ -105,7 +106,7 @@ import static org.codehaus.groovy.ast.tools.WideningCategories.isFloatingCategor
import static org.codehaus.groovy.ast.tools.WideningCategories.isLongCategory;
public class JavaStubGenerator {
- private final boolean java5;
+
private final String encoding;
private final boolean requireSuperResolved;
private final File outputPath;
@@ -118,40 +119,34 @@ public class JavaStubGenerator {
this(outputPath, false, Charset.defaultCharset().name());
}
- public JavaStubGenerator(final File outputPath, final boolean requireSuperResolved, String encoding) {
- this(outputPath, requireSuperResolved, true, encoding);
- }
-
- @Deprecated
- public JavaStubGenerator(final File outputPath, final boolean requireSuperResolved, final boolean java5, String encoding) {
- this.outputPath = outputPath;
+ public JavaStubGenerator(final File outputPath, final boolean requireSuperResolved, final String encoding) {
this.requireSuperResolved = requireSuperResolved;
- this.java5 = java5;
+ this.outputPath = outputPath;
this.encoding = encoding;
- if (null != outputPath) outputPath.mkdirs(); // when outputPath is null, we generate stubs in memory
+
+ // when outputPath is null, generate stubs in memory
+ if (outputPath != null) outputPath.mkdirs();
}
- private static void mkdirs(File parent, String relativeFile) {
+ private static void mkdirs(final File parent, final String relativeFile) {
int index = relativeFile.lastIndexOf('/');
if (index == -1) return;
File dir = new File(parent, relativeFile.substring(0, index));
dir.mkdirs();
}
- public void generateClass(ClassNode classNode) throws FileNotFoundException {
- // Only attempt to render our self if our super-class is resolved, else wait for it
+ public void generateClass(final ClassNode classNode) throws FileNotFoundException {
+ // only attempt to render if super-class is resolved; else wait for it
if (requireSuperResolved && !classNode.getSuperClass().isResolved()) {
return;
}
-
- // owner should take care for us
- if (classNode instanceof InnerClassNode)
+ // skip private class; they are not visible outside the file
+ if ((classNode.getModifiers() & Opcodes.ACC_PRIVATE) != 0) {
return;
-
- // don't generate stubs for private classes, as they are only visible in the same file
- if ((classNode.getModifiers() & Opcodes.ACC_PRIVATE) != 0) return;
-
-
+ }
+ if (classNode instanceof InnerClassNode) {
+ return;
+ }
if (outputPath == null) {
generateMemStub(classNode);
} else {
@@ -357,7 +352,7 @@ public class JavaStubGenerator {
if (classNode instanceof InnerClassNode)
className = className.substring(className.lastIndexOf('$') + 1);
out.println(className);
- printGenericsBounds(out, classNode, true);
+ printTypeParameters(out, classNode.getGenericsTypes());
ClassNode superClass = classNode.getUnresolvedSuperClass(false);
@@ -730,7 +725,7 @@ public class JavaStubGenerator {
printModifiers(out, modifiers & ~(clazz.isEnum() ? Opcodes.ACC_ABSTRACT : 0));
}
- printGenericsBounds(out, methodNode.getGenericsTypes());
+ printTypeParameters(out, methodNode.getGenericsTypes());
out.print(" ");
printType(out, methodNode.getReturnType());
out.print(" ");
@@ -871,18 +866,29 @@ public class JavaStubGenerator {
}
}
- private void printType(PrintWriter out, ClassNode type) {
+ private void printType(final PrintWriter out, final ClassNode type) {
if (type.isArray()) {
printType(out, type.getComponentType());
out.print("[]");
- } else if (java5 && type.isGenericsPlaceHolder()) {
+ } else if (type.isGenericsPlaceHolder()) {
out.print(type.getUnresolvedName());
} else {
- printGenericsBounds(out, type, false);
+ printTypeName(out, type);
+ if (!isCachedType(type)) {
+ printGenericsBounds(out, type.getGenericsTypes());
+ }
}
}
- private void printTypeName(PrintWriter out, ClassNode type) {
+ private String getTypeName(final ClassNode type) {
+ String name = type.getName();
+ // check for an alias
+ ClassNode alias = currentModule.getImportType(name);
+ if (alias != null) name = alias.getName();
+ return name.replace('$', '.');
+ }
+
+ private void printTypeName(final PrintWriter out, final ClassNode type) {
if (isPrimitiveType(type)) {
if (isPrimitiveBoolean(type)) {
out.print("boolean");
@@ -904,32 +910,43 @@ public class JavaStubGenerator {
out.print("void");
}
} else {
- String name = type.getName();
- // check for an alias
- ClassNode alias = currentModule.getImportType(name);
- if (alias != null) name = alias.getName();
- out.print(name.replace('$', '.'));
+ out.print(getTypeName(type));
}
}
- private void printGenericsBounds(PrintWriter out, ClassNode type, boolean skipName) {
- if (!skipName) printTypeName(out, type);
- if (java5 && !isCachedType(type)) {
- printGenericsBounds(out, type.getGenericsTypes());
+ private void printTypeParameters(final PrintWriter out, final GenericsType[] typeParams) {
+ if (typeParams == null || typeParams.length == 0) return;
+ StringJoiner sj = new StringJoiner(", ", "<", ">");
+ for (GenericsType tp : typeParams) {
+ ClassNode[] bounds = tp.getUpperBounds();
+ if (bounds == null || bounds.length == 0) {
+ sj.add(tp.getName());
+ } else {
+ sj.add(tp.getName() + " extends " + Arrays.stream(bounds).map(cn -> {
+ GenericsType[] typeArguments = cn.getGenericsTypes();
+ if (typeArguments == null) return getTypeName(cn);
+
+ StringJoiner parameterized = new StringJoiner(", ", getTypeName(cn) + "<", ">");
+ for (GenericsType ta : typeArguments) {
+ parameterized.add(ta.toString().replace('$', '.'));
+ }
+ return parameterized.toString();
+ }).collect(Collectors.joining(" & ")));
+ }
}
+ out.print(sj.toString());
}
- private static void printGenericsBounds(PrintWriter out, GenericsType[] genericsTypes) {
+ private static void printGenericsBounds(final PrintWriter out, final GenericsType[] genericsTypes) {
if (genericsTypes == null || genericsTypes.length == 0) return;
- out.print('<');
- for (int i = 0; i < genericsTypes.length; i++) {
- if (i != 0) out.print(", ");
- out.print(genericsTypes[i].toString().replace("$","."));
+ StringJoiner sj = new StringJoiner(", ", "<", ">");
+ for (GenericsType gt : genericsTypes) {
+ sj.add(gt.toString().replace('$', '.'));
}
- out.print('>');
+ out.print(sj.toString());
}
- private void printParams(PrintWriter out, MethodNode methodNode) {
+ private void printParams(final PrintWriter out, final MethodNode methodNode) {
out.print("(");
Parameter[] parameters = methodNode.getParameters();
if (parameters != null && parameters.length != 0) {
@@ -954,7 +971,6 @@ public class JavaStubGenerator {
}
private void printAnnotations(final PrintWriter out, final AnnotatedNode annotated) {
- if (!java5) return;
for (AnnotationNode annotation : annotated.getAnnotations()) {
printAnnotation(out, annotation);
}
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10797.groovy
similarity index 63%
copy from src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
copy to src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10797.groovy
index fec232a30d..05b4d43df6 100644
--- a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10797.groovy
@@ -18,30 +18,29 @@
*/
package org.codehaus.groovy.tools.stubgenerator
-final class Groovy7306 extends StringSourcesStubTestCase {
+final class Groovy10797 extends StringSourcesStubTestCase {
@Override
Map<String, String> provideSources() {
[
- 'A7306.groovy': '''
- abstract class A7306<T extends Number> {
- final T value
- A7306(T value) {
- this.value = value
- }
+ 'A.java': '''
+ public class A<T> {
+ }
+ ''',
+ 'B.java': '''
+ public class B<T extends A<?>> {
}
''',
- 'C7306.groovy': '''
- class C7306 extends A7306<Integer> {
- C7306(Integer value) {
- super(value)
+ 'C.groovy': '''
+ class C {
+ static <T extends A<?>> B<T> test() {
}
}
''',
'Main.java': '''
public class Main {
public static void main(String[] args) {
- new C7306();
+ C.test();
}
}
''',
@@ -50,9 +49,7 @@ final class Groovy7306 extends StringSourcesStubTestCase {
@Override
void verifyStubs() {
- compile([new File(stubDir,'A7306.java'), new File(stubDir,'C7306.java')])
-
- def specialCtorCall = (stubJavaSourceFor('C7306') =~ /super\s*\((.+?)\);/)
- assert specialCtorCall.find() && specialCtorCall.group(1) == '(java.lang.Integer)null'
+ String stub = stubJavaSourceFor('C')
+ assert stub.contains('public static <T extends A<?>> B<T> test() { return (B<T>)null;}');
}
}
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
index fec232a30d..6b49936d5b 100644
--- a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
@@ -41,7 +41,7 @@ final class Groovy7306 extends StringSourcesStubTestCase {
'Main.java': '''
public class Main {
public static void main(String[] args) {
- new C7306();
+ new C7306(1234);
}
}
''',
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/StubTestCase.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/StubTestCase.groovy
index 441abafa84..02e9c4dab7 100644
--- a/src/test/org/codehaus/groovy/tools/stubgenerator/StubTestCase.groovy
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/StubTestCase.groovy
@@ -182,25 +182,25 @@ abstract class StubTestCase extends GroovyTestCase {
println "Verifying the stubs"
}
- } catch(Throwable t) {
+ } catch (Throwable t) {
compileError = t
} finally {
try {
use (QDoxCategory) {
verifyStubs()
}
- } catch(ex) {
+ } catch (AssertionError | RuntimeException e) {
if (compileError) {
- println "Unable to verify stubs: $ex.message\nPerhaps due to earlier error?"
+ println "Unable to verify stubs: $e.message\nPerhaps due to earlier error?"
throw compileError
}
- throw ex
+ throw e
}
if (sourceRootPath.getAbsolutePath() =~ 'stubgentests') {
sourceRootPath.deleteDir()
}
}
-
+ if (compileError) throw compileError
}
/**
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/TraitAbstractGetterStubTest.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/TraitAbstractGetterStubTest.groovy
index d2df4c5a69..4b5d228bc7 100644
--- a/src/test/org/codehaus/groovy/tools/stubgenerator/TraitAbstractGetterStubTest.groovy
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/TraitAbstractGetterStubTest.groovy
@@ -21,48 +21,35 @@ package org.codehaus.groovy.tools.stubgenerator
/**
* GROOVY-8895: Checks that a trait with an abstract getter isn't included in stub by mistake
*/
-class TraitAbstractGetterStubTest extends StringSourcesStubTestCase {
+final class TraitAbstractGetterStubTest extends StringSourcesStubTestCase {
@Override
Map<String, String> provideSources() {
[
- 'Foo8895.java': '''
- public class Foo8895 { }
- ''',
-
- 'GetFoo.groovy': '''
- trait GetFoo {
- abstract Foo8895 getFoo()
+ 'Pogo.java': '''
+ public class Pogo {
}
''',
-
- 'BaseFooSpec.groovy': '''
- class BaseFooSpec {
- Foo8895 foo = new Foo8895()
+ 'GetPogo.groovy': '''
+ trait GetPogo {
+ abstract Pogo getPogo()
}
''',
-
- 'FooSpec.groovy': '''
- class FooSpec extends BaseFooSpec implements GetFoo { }
+ 'BaseSpec.groovy': '''
+ class BaseSpec {
+ Pogo pogo = new Pogo()
+ }
''',
-
- 'Control.groovy': '''
- class Control implements GetFoo { }
+ 'PogoSpec.groovy': '''
+ class PogoSpec extends BaseSpec implements GetPogo {
+ }
''',
]
}
-// protected void init() {
-// debug = true
-// delete = false
-// }
-
@Override
void verifyStubs() {
- String stubSource = stubJavaSourceFor('FooSpec')
- assert !stubSource.contains('Foo8895 getFoo()')
- stubSource = stubJavaSourceFor('Control')
- assert !stubSource.contains('Foo8895 getFoo()')
+ String stub = stubJavaSourceFor('PogoSpec')
+ assert !stub.contains('Pogo getPogo()')
}
-
}