You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/09/16 02:47:46 UTC
[groovy] branch master updated: GROOVY-10233: Sealed classes should
generate native class information for JDK17+
This is an automated email from the ASF dual-hosted git repository.
paulk 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 7db88ea GROOVY-10233: Sealed classes should generate native class information for JDK17+
7db88ea is described below
commit 7db88ea2837e11527f8b2c7d1060a6ef1185a685
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Sep 14 22:24:58 2021 +1000
GROOVY-10233: Sealed classes should generate native class information for JDK17+
---
.../groovy/classgen/AsmClassGenerator.java | 9 ++++
.../groovy/control/CompilerConfiguration.java | 60 ++++++++++++++++++++++
.../core/SealedTypeDeclaration_01x.groovy | 1 -
.../groovy/transform/SealedTransformTest.groovy | 17 ++++++
4 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 39458bb..aaba8cc 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -19,6 +19,7 @@
package org.codehaus.groovy.classgen;
import groovy.lang.GroovyRuntimeException;
+import groovy.transform.Sealed;
import org.apache.groovy.ast.tools.ExpressionUtils;
import org.apache.groovy.io.StringBuilderWriter;
import org.codehaus.groovy.GroovyBugError;
@@ -110,6 +111,7 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference;
@@ -372,6 +374,12 @@ public class AsmClassGenerator extends ClassGenerator {
for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) {
makeInnerClassEntry(it.next());
}
+ if (controller.getBytecodeVersion() >= Opcodes.V17 &&
+ context.getCompileUnit().getConfig().isSealedNative()) {
+ for (ClassNode sub: classNode.getPermittedSubclasses()) {
+ classVisitor.visitPermittedSubclass(sub.getName());
+ }
+ }
classVisitor.visitEnd();
} catch (GroovyRuntimeException e) {
@@ -2065,6 +2073,7 @@ public class AsmClassGenerator extends ClassGenerator {
// skip built-in properties
if (an.isBuiltIn()) continue;
if (an.hasSourceRetention()) continue;
+ if (an.getClassNode().getName().equals(Sealed.class.getName()) && !context.getCompileUnit().getConfig().isSealedAnnotations()) continue;
AnnotationVisitor av = getAnnotationVisitor(targetNode, an, visitor);
visitAnnotationAttributes(an, av);
diff --git a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
index 4d0b789..e5fe194 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
@@ -385,6 +385,16 @@ public class CompilerConfiguration {
private boolean previewFeatures;
/**
+ * Whether Sealed class information is natively generated for target bytecode >= 17 (JEP 360/397/409)
+ */
+ private boolean sealedNative;
+
+ /**
+ * Whether Sealed annotations are generated
+ */
+ private boolean sealedAnnotations;
+
+ /**
* options for joint compilation (null by default == no joint compilation)
*/
private Map<String, Object> jointCompilationOptions;
@@ -418,6 +428,8 @@ public class CompilerConfiguration {
* <tr><td><code>groovy.target.directory</code></td><td>{@link #getTargetDirectory}</td></tr>
* <tr><td><code>groovy.parameters</code></td><td>{@link #getParameters()}</td></tr>
* <tr><td><code>groovy.preview.features</code></td><td>{@link #isPreviewFeatures}</td></tr>
+ * <tr><td><code>groovy.sealed.native.disable</code></td><td>{@link #isSealedNative}</td></tr>
+ * <tr><td><code>groovy.sealed.annotations.disable</code></td><td>{@link #isSealedAnnotations}</td></tr>
* <tr><td><code>groovy.default.scriptExtension</code></td><td>{@link #getDefaultScriptExtension}</td></tr>
* </table>
* </blockquote>
@@ -441,6 +453,8 @@ public class CompilerConfiguration {
warningLevel = WarningMessage.LIKELY_ERRORS;
parameters = getBooleanSafe("groovy.parameters");
previewFeatures = getBooleanSafe("groovy.preview.features");
+ sealedNative = !getBooleanSafe("groovy.sealed.native.disable");
+ sealedAnnotations = !getBooleanSafe("groovy.sealed.annotations.disable");
sourceEncoding = getSystemPropertySafe("groovy.source.encoding",
getSystemPropertySafe("file.encoding", DEFAULT_SOURCE_ENCODING));
setTargetDirectorySafe(getSystemPropertySafe("groovy.target.directory"));
@@ -487,6 +501,8 @@ public class CompilerConfiguration {
setMinimumRecompilationInterval(configuration.getMinimumRecompilationInterval());
setTargetBytecode(configuration.getTargetBytecode());
setPreviewFeatures(configuration.isPreviewFeatures());
+ setSealedNative(configuration.isSealedNative());
+ setSealedAnnotations(configuration.isSealedAnnotations());
setDefaultScriptExtension(configuration.getDefaultScriptExtension());
setSourceEncoding(configuration.getSourceEncoding());
Map<String, Object> jointCompilationOptions = configuration.getJointCompilationOptions();
@@ -540,6 +556,8 @@ public class CompilerConfiguration {
* <tr><td><code>groovy.target.bytecode</code></td><td>{@link #getTargetBytecode}</td></tr>
* <tr><td><code>groovy.parameters</code></td><td>{@link #getParameters()}</td></tr>
* <tr><td><code>groovy.preview.features</code></td><td>{@link #isPreviewFeatures}</td></tr>
+ * <tr><td><code>groovy.sealed.native.disable</code></td><td>{@link #isSealedNative}</td></tr>
+ * <tr><td><code>groovy.sealed.annotations.disable</code></td><td>{@link #isSealedAnnotations}</td></tr>
* <tr><td><code>groovy.classpath</code></td><td>{@link #getClasspath}</td></tr>
* <tr><td><code>groovy.output.verbose</code></td><td>{@link #getVerbose}</td></tr>
* <tr><td><code>groovy.output.debug</code></td><td>{@link #getDebug}</td></tr>
@@ -646,6 +664,12 @@ public class CompilerConfiguration {
text = configuration.getProperty("groovy.preview.features");
if (text != null) setPreviewFeatures(text.equalsIgnoreCase("true"));
+ text = configuration.getProperty("groovy.sealed.native.disable");
+ if (text != null) setSealedNative(!text.equalsIgnoreCase("false"));
+
+ text = configuration.getProperty("groovy.sealed.annotations.disable");
+ if (text != null) setSealedAnnotations(!text.equalsIgnoreCase("false"));
+
text = configuration.getProperty("groovy.classpath");
if (text != null) setClasspath(text);
@@ -974,6 +998,42 @@ public class CompilerConfiguration {
}
/**
+ * Whether Sealed class information is natively generated (JEP 360/397/409).
+ *
+ * @return sealedNative
+ */
+ public boolean isSealedNative() {
+ return sealedNative;
+ }
+
+ /**
+ * Sets whether Sealed class information is natively generated (JEP 360/397/409).
+ *
+ * @param sealedNative whether to generate permittedSubclass information in the class file for target bytecode >= 17
+ */
+ public void setSealedNative(final boolean sealedNative) {
+ this.sealedNative = sealedNative;
+ }
+
+ /**
+ * Whether Sealed annotations are generated.
+ *
+ * @return sealedAnnotations
+ */
+ public boolean isSealedAnnotations() {
+ return sealedAnnotations;
+ }
+
+ /**
+ * Sets whether Sealed annotations are generated.
+ *
+ * @param sealedAnnotations whether to generate {@code @Sealed} annotations for sealed types
+ */
+ public void setSealedAnnotations(final boolean sealedAnnotations) {
+ this.sealedAnnotations = sealedAnnotations;
+ }
+
+ /**
* Gets the joint compilation options for this configuration.
* @return the options
*/
diff --git a/src/test-resources/core/SealedTypeDeclaration_01x.groovy b/src/test-resources/core/SealedTypeDeclaration_01x.groovy
index eec62f4..c5374a0 100644
--- a/src/test-resources/core/SealedTypeDeclaration_01x.groovy
+++ b/src/test-resources/core/SealedTypeDeclaration_01x.groovy
@@ -1,4 +1,3 @@
-import groovy.transform.NonSealed
import groovy.transform.Sealed
/*
diff --git a/src/test/org/codehaus/groovy/transform/SealedTransformTest.groovy b/src/test/org/codehaus/groovy/transform/SealedTransformTest.groovy
index 19b9584..bdcc8d4 100644
--- a/src/test/org/codehaus/groovy/transform/SealedTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/SealedTransformTest.groovy
@@ -18,6 +18,8 @@
*/
package org.codehaus.groovy.transform
+import groovy.transform.Sealed
+import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.MultipleCompilationErrorsException
import org.junit.Test
@@ -203,4 +205,19 @@ class SealedTransformTest {
Shape.getAnnotation(Sealed).permittedSubclasses()*.name
''') == ['Shape$Triangle', 'Shape$Polygon']
}
+
+ @Test
+ void testInferredPermittedNestedClassesWithAnnosDisabled() {
+ def config = new CompilerConfiguration(sealedAnnotations: false)
+ def shapeClass = new GroovyShell(config).evaluate('''
+ import groovy.transform.Sealed
+
+ @Sealed class Shape {
+ final class Triangle extends Shape { }
+ final class Polygon extends Shape { }
+ }
+ Shape
+ ''')
+ assert shapeClass.getAnnotation(Sealed) == null
+ }
}