I have extended the ASM ClassVisitor and want to know if the visited class in an anonymous class.
Since I do have the class file I figured that if the class file name ended with $[1-9][0-9]*.class it would be an anonymous class. But currency characters are valid in class names so for example a class named MyClass$1 would match (classfile is named MyClass$1.class) even though it is not an anonymous class. I know most people would probably not name things like this but it is allowed.
So I thought about overriding the visitOuterClass method to see if it had an outer class that would eliminate outer classes with names ending in $# but still you could have an inner non anonymous class name ending with, for example, $1.
So is there some way in ASM to know that it is visiting an anonymous class? Or a better trick than mine?
# means any number (regexp: [1-9][0-9]*)
The relevant criteria is whether the class’ InnerClasses
attribute declares the class to be an anonymous inner class. ASM report the contents by calling visitInnerClass
for each entry of the attribute, if present.
So you can check it like
public class CheckForInnerClass extends ClassVisitor {
public static void main(String[] args) throws IOException {
Class<?>[] test={ Object.class, Map.Entry.class, new Object(){}.getClass() };
for(Class<?> c: test) {
new ClassReader(c.getName())
.accept(new CheckForInnerClass(Opcodes.ASM5), ClassReader.SKIP_CODE);
}
}
private String actualName;
private Boolean anonymous;
public CheckForInnerClass(int api) {
super(Opcodes.ASM5);
}
@Override
public void visit(int version, int access,
String name, String signature, String superName, String[] interfaces) {
actualName=name;
}
@Override
public void visitInnerClass(String name, String outer, String innerName, int access) {
if(name.equals(actualName)) {
anonymous = innerName==null;
}
}
@Override
public void visitEnd() {
System.out.println(actualName+": is "
+ (anonymous==null? "not an": anonymous? "an anonymous": "a named")
+ " inner class");
}
}
which prints
java/lang/Object: is not an inner class
java/util/Map$Entry: is a named inner class
CheckForInnerClass$1: is an anonymous inner class