1 package org.robolectric.internal.bytecode; 2 3 import com.google.common.collect.ImmutableSet; 4 import java.lang.annotation.Annotation; 5 import java.util.ArrayList; 6 import java.util.List; 7 import org.objectweb.asm.Opcodes; 8 import org.objectweb.asm.Type; 9 import org.objectweb.asm.tree.AnnotationNode; 10 import org.objectweb.asm.tree.ClassNode; 11 import org.objectweb.asm.tree.FieldNode; 12 import org.objectweb.asm.tree.MethodNode; 13 14 public class MutableClass { 15 public final ClassNode classNode; 16 final InstrumentationConfiguration config; 17 final ClassNodeProvider classNodeProvider; 18 final boolean containsStubs; 19 20 final String internalClassName; 21 private final String className; 22 final Type classType; 23 final ImmutableSet<String> foundMethods; 24 MutableClass(ClassNode classNode, InstrumentationConfiguration config, ClassNodeProvider classNodeProvider)25 MutableClass(ClassNode classNode, InstrumentationConfiguration config, 26 ClassNodeProvider classNodeProvider) { 27 this.classNode = classNode; 28 this.config = config; 29 this.classNodeProvider = classNodeProvider; 30 this.internalClassName = classNode.name; 31 this.className = classNode.name.replace('/', '.'); 32 this.classType = Type.getObjectType(internalClassName); 33 this.containsStubs = config.containsStubs(className); 34 35 List<String> foundMethods = new ArrayList<>(classNode.methods.size()); 36 for (MethodNode methodNode : getMethods()) { 37 foundMethods.add(methodNode.name + methodNode.desc); 38 } 39 this.foundMethods = ImmutableSet.copyOf(foundMethods); 40 } 41 isInterface()42 public boolean isInterface() { 43 return (classNode.access & Opcodes.ACC_INTERFACE) != 0; 44 } 45 isAnnotation()46 public boolean isAnnotation() { 47 return (classNode.access & Opcodes.ACC_ANNOTATION) != 0; 48 } 49 hasAnnotation(Class<? extends Annotation> annotationClass)50 public boolean hasAnnotation(Class<? extends Annotation> annotationClass) { 51 String internalName = "L" + annotationClass.getName().replace('.', '/') + ";"; 52 if (classNode.visibleAnnotations == null) { 53 return false; 54 } 55 56 for (Object visibleAnnotation : classNode.visibleAnnotations) { 57 AnnotationNode annotationNode = (AnnotationNode) visibleAnnotation; 58 if (annotationNode.desc.equals(internalName)) { 59 return true; 60 } 61 } 62 return false; 63 } 64 getName()65 public String getName() { 66 return className; 67 } 68 getMethods()69 public Iterable<? extends MethodNode> getMethods() { 70 return new ArrayList<>(classNode.methods); 71 } 72 addMethod(MethodNode methodNode)73 public void addMethod(MethodNode methodNode) { 74 classNode.methods.add(methodNode); 75 } 76 getFields()77 public List<FieldNode> getFields() { 78 return classNode.fields; 79 } 80 addField(int index, FieldNode fieldNode)81 public void addField(int index, FieldNode fieldNode) { 82 classNode.fields.add(index, fieldNode); 83 } 84 addInterface(String internalName)85 public void addInterface(String internalName) { 86 classNode.interfaces.add(internalName); 87 } 88 } 89