|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package jdk.internal.org.objectweb.asm.tree; |
|
|
|
import java.util.ArrayList; |
|
import java.util.List; |
|
import jdk.internal.org.objectweb.asm.AnnotationVisitor; |
|
import jdk.internal.org.objectweb.asm.Attribute; |
|
import jdk.internal.org.objectweb.asm.ClassVisitor; |
|
import jdk.internal.org.objectweb.asm.FieldVisitor; |
|
import jdk.internal.org.objectweb.asm.MethodVisitor; |
|
import jdk.internal.org.objectweb.asm.ModuleVisitor; |
|
import jdk.internal.org.objectweb.asm.Opcodes; |
|
import jdk.internal.org.objectweb.asm.RecordComponentVisitor; |
|
import jdk.internal.org.objectweb.asm.TypePath; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class ClassNode extends ClassVisitor { |
|
|
|
|
|
|
|
|
|
*/ |
|
public int version; |
|
|
|
|
|
|
|
|
|
*/ |
|
public int access; |
|
|
|
|
|
public String name; |
|
|
|
|
|
public String signature; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String superName; |
|
|
|
|
|
|
|
|
|
*/ |
|
public List<String> interfaces; |
|
|
|
|
|
public String sourceFile; |
|
|
|
|
|
|
|
*/ |
|
public String sourceDebug; |
|
|
|
|
|
public ModuleNode module; |
|
|
|
|
|
public String outerClass; |
|
|
|
|
|
|
|
|
|
*/ |
|
public String outerMethod; |
|
|
|
|
|
|
|
|
|
*/ |
|
public String outerMethodDesc; |
|
|
|
|
|
public List<AnnotationNode> visibleAnnotations; |
|
|
|
|
|
public List<AnnotationNode> invisibleAnnotations; |
|
|
|
|
|
public List<TypeAnnotationNode> visibleTypeAnnotations; |
|
|
|
|
|
public List<TypeAnnotationNode> invisibleTypeAnnotations; |
|
|
|
|
|
public List<Attribute> attrs; |
|
|
|
|
|
public List<InnerClassNode> innerClasses; |
|
|
|
|
|
public String nestHostClass; |
|
|
|
|
|
public List<String> nestMembers; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Deprecated public List<String> permittedSubclassesExperimental; |
|
|
|
|
|
public List<RecordComponentNode> recordComponents; |
|
|
|
|
|
public List<FieldNode> fields; |
|
|
|
|
|
public List<MethodNode> methods; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassNode() { |
|
this(Opcodes.ASM8); |
|
if (getClass() != ClassNode.class) { |
|
throw new IllegalStateException(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassNode(final int api) { |
|
super(api); |
|
this.interfaces = new ArrayList<>(); |
|
this.innerClasses = new ArrayList<>(); |
|
this.fields = new ArrayList<>(); |
|
this.methods = new ArrayList<>(); |
|
} |
|
|
|
// ----------------------------------------------------------------------------------------------- |
|
// Implementation of the ClassVisitor abstract class |
|
// ----------------------------------------------------------------------------------------------- |
|
|
|
@Override |
|
public void visit( |
|
final int version, |
|
final int access, |
|
final String name, |
|
final String signature, |
|
final String superName, |
|
final String[] interfaces) { |
|
this.version = version; |
|
this.access = access; |
|
this.name = name; |
|
this.signature = signature; |
|
this.superName = superName; |
|
this.interfaces = Util.asArrayList(interfaces); |
|
} |
|
|
|
@Override |
|
public void visitSource(final String file, final String debug) { |
|
sourceFile = file; |
|
sourceDebug = debug; |
|
} |
|
|
|
@Override |
|
public ModuleVisitor visitModule(final String name, final int access, final String version) { |
|
module = new ModuleNode(name, access, version); |
|
return module; |
|
} |
|
|
|
@Override |
|
public void visitNestHost(final String nestHost) { |
|
this.nestHostClass = nestHost; |
|
} |
|
|
|
@Override |
|
public void visitOuterClass(final String owner, final String name, final String descriptor) { |
|
outerClass = owner; |
|
outerMethod = name; |
|
outerMethodDesc = descriptor; |
|
} |
|
|
|
@Override |
|
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { |
|
AnnotationNode annotation = new AnnotationNode(descriptor); |
|
if (visible) { |
|
visibleAnnotations = Util.add(visibleAnnotations, annotation); |
|
} else { |
|
invisibleAnnotations = Util.add(invisibleAnnotations, annotation); |
|
} |
|
return annotation; |
|
} |
|
|
|
@Override |
|
public AnnotationVisitor visitTypeAnnotation( |
|
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
|
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor); |
|
if (visible) { |
|
visibleTypeAnnotations = Util.add(visibleTypeAnnotations, typeAnnotation); |
|
} else { |
|
invisibleTypeAnnotations = Util.add(invisibleTypeAnnotations, typeAnnotation); |
|
} |
|
return typeAnnotation; |
|
} |
|
|
|
@Override |
|
public void visitAttribute(final Attribute attribute) { |
|
attrs = Util.add(attrs, attribute); |
|
} |
|
|
|
@Override |
|
public void visitNestMember(final String nestMember) { |
|
nestMembers = Util.add(nestMembers, nestMember); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
@Deprecated |
|
public void visitPermittedSubclassExperimental(final String permittedSubclass) { |
|
permittedSubclassesExperimental = Util.add(permittedSubclassesExperimental, permittedSubclass); |
|
} |
|
|
|
@Override |
|
public void visitInnerClass( |
|
final String name, final String outerName, final String innerName, final int access) { |
|
InnerClassNode innerClass = new InnerClassNode(name, outerName, innerName, access); |
|
innerClasses.add(innerClass); |
|
} |
|
|
|
@Override |
|
public RecordComponentVisitor visitRecordComponent( |
|
final String name, final String descriptor, final String signature) { |
|
RecordComponentNode recordComponent = new RecordComponentNode(name, descriptor, signature); |
|
recordComponents = Util.add(recordComponents, recordComponent); |
|
return recordComponent; |
|
} |
|
|
|
@Override |
|
public FieldVisitor visitField( |
|
final int access, |
|
final String name, |
|
final String descriptor, |
|
final String signature, |
|
final Object value) { |
|
FieldNode field = new FieldNode(access, name, descriptor, signature, value); |
|
fields.add(field); |
|
return field; |
|
} |
|
|
|
@Override |
|
public MethodVisitor visitMethod( |
|
final int access, |
|
final String name, |
|
final String descriptor, |
|
final String signature, |
|
final String[] exceptions) { |
|
MethodNode method = new MethodNode(access, name, descriptor, signature, exceptions); |
|
methods.add(method); |
|
return method; |
|
} |
|
|
|
@Override |
|
public void visitEnd() { |
|
// Nothing to do. |
|
} |
|
|
|
// ----------------------------------------------------------------------------------------------- |
|
// Accept method |
|
// ----------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("deprecation") |
|
public void check(final int api) { |
|
if (api != Opcodes.ASM9_EXPERIMENTAL && permittedSubclassesExperimental != null) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
if (api < Opcodes.ASM8 && ((access & Opcodes.ACC_RECORD) != 0 || recordComponents != null)) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
if (api < Opcodes.ASM7 && (nestHostClass != null || nestMembers != null)) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
if (api < Opcodes.ASM6 && module != null) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
if (api < Opcodes.ASM5) { |
|
if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) { |
|
throw new UnsupportedClassVersionException(); |
|
} |
|
} |
|
|
|
if (visibleAnnotations != null) { |
|
for (int i = visibleAnnotations.size() - 1; i >= 0; --i) { |
|
visibleAnnotations.get(i).check(api); |
|
} |
|
} |
|
if (invisibleAnnotations != null) { |
|
for (int i = invisibleAnnotations.size() - 1; i >= 0; --i) { |
|
invisibleAnnotations.get(i).check(api); |
|
} |
|
} |
|
if (visibleTypeAnnotations != null) { |
|
for (int i = visibleTypeAnnotations.size() - 1; i >= 0; --i) { |
|
visibleTypeAnnotations.get(i).check(api); |
|
} |
|
} |
|
if (invisibleTypeAnnotations != null) { |
|
for (int i = invisibleTypeAnnotations.size() - 1; i >= 0; --i) { |
|
invisibleTypeAnnotations.get(i).check(api); |
|
} |
|
} |
|
if (recordComponents != null) { |
|
for (int i = recordComponents.size() - 1; i >= 0; --i) { |
|
recordComponents.get(i).check(api); |
|
} |
|
} |
|
for (int i = fields.size() - 1; i >= 0; --i) { |
|
fields.get(i).check(api); |
|
} |
|
for (int i = methods.size() - 1; i >= 0; --i) { |
|
methods.get(i).check(api); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("deprecation") |
|
public void accept(final ClassVisitor classVisitor) { |
|
|
|
String[] interfacesArray = new String[this.interfaces.size()]; |
|
this.interfaces.toArray(interfacesArray); |
|
classVisitor.visit(version, access, name, signature, superName, interfacesArray); |
|
|
|
if (sourceFile != null || sourceDebug != null) { |
|
classVisitor.visitSource(sourceFile, sourceDebug); |
|
} |
|
|
|
if (module != null) { |
|
module.accept(classVisitor); |
|
} |
|
|
|
if (nestHostClass != null) { |
|
classVisitor.visitNestHost(nestHostClass); |
|
} |
|
|
|
if (outerClass != null) { |
|
classVisitor.visitOuterClass(outerClass, outerMethod, outerMethodDesc); |
|
} |
|
|
|
if (visibleAnnotations != null) { |
|
for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) { |
|
AnnotationNode annotation = visibleAnnotations.get(i); |
|
annotation.accept(classVisitor.visitAnnotation(annotation.desc, true)); |
|
} |
|
} |
|
if (invisibleAnnotations != null) { |
|
for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) { |
|
AnnotationNode annotation = invisibleAnnotations.get(i); |
|
annotation.accept(classVisitor.visitAnnotation(annotation.desc, false)); |
|
} |
|
} |
|
if (visibleTypeAnnotations != null) { |
|
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) { |
|
TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i); |
|
typeAnnotation.accept( |
|
classVisitor.visitTypeAnnotation( |
|
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true)); |
|
} |
|
} |
|
if (invisibleTypeAnnotations != null) { |
|
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) { |
|
TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i); |
|
typeAnnotation.accept( |
|
classVisitor.visitTypeAnnotation( |
|
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false)); |
|
} |
|
} |
|
|
|
if (attrs != null) { |
|
for (int i = 0, n = attrs.size(); i < n; ++i) { |
|
classVisitor.visitAttribute(attrs.get(i)); |
|
} |
|
} |
|
|
|
if (nestMembers != null) { |
|
for (int i = 0, n = nestMembers.size(); i < n; ++i) { |
|
classVisitor.visitNestMember(nestMembers.get(i)); |
|
} |
|
} |
|
|
|
if (permittedSubclassesExperimental != null) { |
|
for (int i = 0, n = permittedSubclassesExperimental.size(); i < n; ++i) { |
|
classVisitor.visitPermittedSubclassExperimental(permittedSubclassesExperimental.get(i)); |
|
} |
|
} |
|
|
|
for (int i = 0, n = innerClasses.size(); i < n; ++i) { |
|
innerClasses.get(i).accept(classVisitor); |
|
} |
|
|
|
if (recordComponents != null) { |
|
for (int i = 0, n = recordComponents.size(); i < n; ++i) { |
|
recordComponents.get(i).accept(classVisitor); |
|
} |
|
} |
|
|
|
for (int i = 0, n = fields.size(); i < n; ++i) { |
|
fields.get(i).accept(classVisitor); |
|
} |
|
|
|
for (int i = 0, n = methods.size(); i < n; ++i) { |
|
methods.get(i).accept(classVisitor); |
|
} |
|
classVisitor.visitEnd(); |
|
} |
|
} |