package rtt.annotation.test.rtt; import java.io.InputStream; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import rtt.annotation.editor.data.asm.ASMAnnotationConverter; import rtt.annotation.editor.data.asm.ASMClassModelManager; import rtt.annotation.editor.model.ClassElement; import rtt.annotation.editor.model.ClassElement.ClassType; import rtt.annotation.editor.model.annotation.Annotation; import rtt.annotation.editor.model.ClassElementReference; import rtt.annotation.editor.model.ClassModelFactory; import rtt.annotation.editor.model.FieldElement; import rtt.annotation.editor.model.MethodElement; public final class ImportClassElementVisitor extends ClassVisitor { private ClassModelFactory factory; private ClassElement element; public ImportClassElementVisitor(ClassElement element, ClassModelFactory factory) { super(Opcodes.ASM5, null); this.factory = factory; this.element = element; } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { String completeName = name.replace("/", "."); String className = ASMClassModelManager.RESOLVER.computeClassName(completeName); String packageName = ASMClassModelManager.RESOLVER.computePackageName(completeName); element.setName(className); element.setPackageName(packageName); if (checkAccess(access, Opcodes.ACC_ABSTRACT)) { element.setType(ClassType.ABSTRACT); } if (checkAccess(access, Opcodes.ACC_INTERFACE)) { element.setType(ClassType.INTERFACE); } if (checkAccess(access, Opcodes.ACC_ENUM)) { element.setType(ClassType.ENUMERATION); } if (superName != null && !superName.equals("java/lang/Object")) { element.setSuperClass(ClassElementReference.create(superName.replace("/", "."))); } if (interfaces != null) { String[] changedInterfaces = interfaces.clone(); for (int i = 0; i < changedInterfaces.length; i++) { changedInterfaces[i] = changedInterfaces[i].replace("/", "."); } element.setInterfaces(ClassElementReference.create(changedInterfaces)); } super.visit(version, access, name, signature, superName, interfaces); } private boolean checkAccess(int access, int code) { return (access & code) == code; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { Annotation annotation = ASMAnnotationConverter.getAnnotation(desc); if (annotation != null) { // element.setAnnotation(annotation); } return super.visitAnnotation(desc, visible); } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { if (!isSynthetic(access)) { FieldElement field = factory.createFieldElement(element, name); field.setType(Type.getType(desc).getClassName()); FieldVisitor fv = super.visitField(access, name, desc, signature, value); FieldVisitor importVisitor = new ImportFieldElementVisitor(field, fv); element.addValuableField(field); return importVisitor; } return super.visitField(access, name, desc, signature, value); } private boolean isSynthetic(int access) { return (access & Opcodes.ACC_SYNTHETIC) == Opcodes.ACC_SYNTHETIC; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { Type methodType = Type.getType(desc); final MethodElement method = factory.createMethodElement(element, name); method.setType(methodType.getReturnType().getClassName()); MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); MethodVisitor importVisitor = new ImportMethodElementVisitor(method, mv); if (isValuableMethod(methodType)) { element.addValuableMethod(method); return importVisitor; } else if (isInitializableMethod(methodType)) { element.addInitializableMethod(method); return importVisitor; } return mv; } private boolean isValuableMethod(Type methodType) { return hasNonVoidReturnType(methodType) && methodType.getArgumentTypes().length == 0; } private boolean isInitializableMethod(Type methodType) { if (hasNonVoidReturnType(methodType)) { return false; } int argumentCount = methodType.getArgumentTypes().length; if (argumentCount < 1 || argumentCount > 2) { return false; } Type firstArgument = methodType.getArgumentTypes()[0]; if (!firstArgument.equals(Type.getType(InputStream.class))) { return false; } if (argumentCount == 2) { Type secondArgument = methodType.getArgumentTypes()[1]; if (!secondArgument.equals(Type.getType(String[].class))) { return false; } } return true; } private boolean hasNonVoidReturnType(Type methodType) { return !methodType.getReturnType().equals(Type.VOID_TYPE); } }