Skip to content
Permalink
Browse files
GROOVY-10434: ClassNode isSealed() refactoring: hide implementation d…
…etails about sealed native/annotation flags
  • Loading branch information
paulk-asert committed Jan 25, 2022
1 parent 3c37c58 commit 3eac9fbd98060810a60b41e8f6f5ac17b84c3b91
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
@@ -20,7 +20,6 @@

import groovy.lang.GroovyRuntimeException;
import groovy.transform.Sealed;
import groovy.transform.SealedMode;
import org.apache.groovy.ast.tools.ExpressionUtils;
import org.apache.groovy.io.StringBuilderWriter;
import org.codehaus.groovy.GroovyBugError;
@@ -155,7 +154,8 @@
import static org.codehaus.groovy.ast.tools.GeneralUtils.maybeFallsThrough;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
import static org.codehaus.groovy.transform.SealedASTTransformation.SEALED_ALWAYS_ANNOTATE;
import static org.codehaus.groovy.transform.SealedASTTransformation.sealedNative;
import static org.codehaus.groovy.transform.SealedASTTransformation.sealedSkipAnnotation;
import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PROPERTY_OWNER;
import static org.objectweb.asm.Opcodes.AASTORE;
import static org.objectweb.asm.Opcodes.ACC_ENUM;
@@ -378,7 +378,7 @@ public void visitClass(final ClassNode classNode) {
for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) {
makeInnerClassEntry(it.next());
}
if (classNode.getNodeMetaData(SealedMode.class) == SealedMode.NATIVE) {
if (sealedNative(classNode)) {
for (ClassNode sub: classNode.getPermittedSubclasses()) {
classVisitor.visitPermittedSubclass(sub.getName());
}
@@ -1985,7 +1985,7 @@ private void visitAnnotations(final AnnotatedNode targetNode, final AnnotatedNod
// skip built-in properties
if (an.isBuiltIn()) continue;
if (an.hasSourceRetention()) continue;
if (an.getClassNode().getName().equals(Sealed.class.getName()) && sourceNode.getNodeMetaData(SealedMode.class) == SealedMode.NATIVE && Boolean.FALSE.equals(sourceNode.getNodeMetaData(SEALED_ALWAYS_ANNOTATE))) continue;
if (an.getClassNode().getName().equals(Sealed.class.getName()) && sealedNative(sourceNode) && sealedSkipAnnotation(sourceNode)) continue;

AnnotationVisitor av = getAnnotationVisitor(targetNode, an, visitor);
visitAnnotationAttributes(an, av);
@@ -21,6 +21,7 @@
import groovy.transform.Sealed;
import groovy.transform.SealedMode;
import groovy.transform.SealedOptions;
import org.apache.groovy.lang.annotation.Incubating;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
@@ -46,7 +47,9 @@ public class SealedASTTransformation extends AbstractASTTransformation {
private static final String SEALED_NAME = "@" + SEALED_CLASS.getSimpleName();
private static final ClassNode SEALED_TYPE = make(SEALED_CLASS);
private static final ClassNode SEALED_OPTIONS_TYPE = make(SealedOptions.class);
public static final String SEALED_ALWAYS_ANNOTATE = "groovy.transform.SealedOptions.alwaysAnnotate";
private static final String SEALED_ALWAYS_ANNOTATE_KEY = "groovy.transform.SealedOptions.alwaysAnnotate";
@Deprecated
public static final String SEALED_ALWAYS_ANNOTATE = SEALED_ALWAYS_ANNOTATE_KEY;

@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
@@ -81,7 +84,7 @@ public void visit(ASTNode[] nodes, SourceUnit source) {

boolean isNative = isPostJDK17 && mode != SealedMode.EMULATE;
if (doNotAnnotate) {
cNode.putNodeMetaData(SEALED_ALWAYS_ANNOTATE, Boolean.FALSE);
cNode.putNodeMetaData(SEALED_ALWAYS_ANNOTATE_KEY, Boolean.FALSE);
}
if (isNative) {
cNode.putNodeMetaData(SealedMode.class, SealedMode.NATIVE);
@@ -100,6 +103,29 @@ public void visit(ASTNode[] nodes, SourceUnit source) {
}
}

/**
* Reports true if native sealed class information should be written into the bytecode.
* Will only ever return true after the SealedASTTransformation visit method has completed.
*
* @return true for a native sealed class
*/
@Incubating
public static boolean sealedNative(AnnotatedNode node) {
return node.getNodeMetaData(SealedMode.class) == SealedMode.NATIVE;
}

/**
* Reports true if the {@code Sealed} annotation should be included in the bytecode for
* a sealed or emulated-sealed class.
* Will only ever return true after the SealedASTTransformation visit method has completed.
*
* @return true if a {@code Sealed} annotation is not required for this node
*/
@Incubating
public static boolean sealedSkipAnnotation(AnnotatedNode node) {
return Boolean.FALSE.equals(node.getNodeMetaData(SEALED_ALWAYS_ANNOTATE_KEY));
}

private static SealedMode getMode(AnnotationNode node, String name) {
if (node != null) {
final Expression member = node.getMember(name);

0 comments on commit 3eac9fb

Please sign in to comment.