FileDocCategorySizeDatePackage
StubMethodAdapter.javaAPI DocAndroid 5.1 API12610Thu Mar 12 22:22:44 GMT 2015com.android.tools.layoutlib.create

StubMethodAdapter

public class StubMethodAdapter extends org.objectweb.asm.MethodVisitor
This method adapter rewrites a method by discarding the original code and generating a stub depending on the return type. Original annotations are passed along unchanged.

Fields Summary
private static final String
CONSTRUCTOR
private static final String
CLASS_INIT
private org.objectweb.asm.MethodVisitor
mParentVisitor
The parent method writer
private org.objectweb.asm.Type
mReturnType
The method return type. Can be null.
private String
mInvokeSignature
Message to be printed by stub methods.
private boolean
mOutputFirstLineNumber
Flag to output the first line number.
private boolean
mIsInitMethod
Flag that is true when implementing a constructor, to accept all original code calling the original super constructor.
private boolean
mMessageGenerated
private final boolean
mIsStatic
private final boolean
mIsNative
Constructors Summary
public StubMethodAdapter(org.objectweb.asm.MethodVisitor mv, String methodName, org.objectweb.asm.Type returnType, String invokeSignature, boolean isStatic, boolean isNative)


          
                  
        super(Opcodes.ASM4);
        mParentVisitor = mv;
        mReturnType = returnType;
        mInvokeSignature = invokeSignature;
        mIsStatic = isStatic;
        mIsNative = isNative;

        if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
            mIsInitMethod = true;
        }
    
Methods Summary
private voidgenerateInvoke()

        /* Generates the code:
         *  OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
         */
        mParentVisitor.visitLdcInsn(mInvokeSignature);
        // push true or false
        mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
        // push null or this
        if (mIsStatic) {
            mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
        } else {
            mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        }

        int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
        switch(sort) {
        case Type.VOID:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeV",
                    "(Ljava/lang/String;ZLjava/lang/Object;)V");
            mParentVisitor.visitInsn(Opcodes.RETURN);
            break;
        case Type.BOOLEAN:
        case Type.CHAR:
        case Type.BYTE:
        case Type.SHORT:
        case Type.INT:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeI",
                    "(Ljava/lang/String;ZLjava/lang/Object;)I");
            switch(sort) {
            case Type.BOOLEAN:
                Label l1 = new Label();
                mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
                mParentVisitor.visitInsn(Opcodes.ICONST_1);
                mParentVisitor.visitInsn(Opcodes.IRETURN);
                mParentVisitor.visitLabel(l1);
                mParentVisitor.visitInsn(Opcodes.ICONST_0);
                break;
            case Type.CHAR:
                mParentVisitor.visitInsn(Opcodes.I2C);
                break;
            case Type.BYTE:
                mParentVisitor.visitInsn(Opcodes.I2B);
                break;
            case Type.SHORT:
                mParentVisitor.visitInsn(Opcodes.I2S);
                break;
            }
            mParentVisitor.visitInsn(Opcodes.IRETURN);
            break;
        case Type.LONG:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeL",
                    "(Ljava/lang/String;ZLjava/lang/Object;)J");
            mParentVisitor.visitInsn(Opcodes.LRETURN);
            break;
        case Type.FLOAT:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeF",
                    "(Ljava/lang/String;ZLjava/lang/Object;)F");
            mParentVisitor.visitInsn(Opcodes.FRETURN);
            break;
        case Type.DOUBLE:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeD",
                    "(Ljava/lang/String;ZLjava/lang/Object;)D");
            mParentVisitor.visitInsn(Opcodes.DRETURN);
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                    "com/android/tools/layoutlib/create/OverrideMethod",
                    "invokeA",
                    "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;");
            mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
            mParentVisitor.visitInsn(Opcodes.ARETURN);
            break;
        }

    
private voidgeneratePop()

        /* Pops the stack, depending on the return type.
         */
        switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
        case Type.VOID:
            break;
        case Type.BOOLEAN:
        case Type.CHAR:
        case Type.BYTE:
        case Type.SHORT:
        case Type.INT:
        case Type.FLOAT:
        case Type.ARRAY:
        case Type.OBJECT:
            mParentVisitor.visitInsn(Opcodes.POP);
            break;
        case Type.LONG:
        case Type.DOUBLE:
            mParentVisitor.visitInsn(Opcodes.POP2);
            break;
        }
    
public org.objectweb.asm.AnnotationVisitorvisitAnnotation(java.lang.String desc, boolean visible)

        return mParentVisitor.visitAnnotation(desc, visible);
    
public org.objectweb.asm.AnnotationVisitorvisitAnnotationDefault()

        return mParentVisitor.visitAnnotationDefault();
    
public voidvisitAttribute(org.objectweb.asm.Attribute attr)

        mParentVisitor.visitAttribute(attr);
    
public voidvisitCode()

        mParentVisitor.visitCode();
    
public voidvisitEnd()
End of visiting. For non-constructor, generate the messaging code and the return statement if it hasn't been done before.

        if (!mIsInitMethod && !mMessageGenerated) {
            generateInvoke();
            mMessageGenerated = true;
            mParentVisitor.visitMaxs(1, 1);
        }
        mParentVisitor.visitEnd();
    
public voidvisitFieldInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)

        if (mIsInitMethod) {
            mParentVisitor.visitFieldInsn(opcode, owner, name, desc);
        }
    
public voidvisitFrame(int type, int nLocal, java.lang.Object[] local, int nStack, java.lang.Object[] stack)

        if (mIsInitMethod) {
            mParentVisitor.visitFrame(type, nLocal, local, nStack, stack);
        }
    
public voidvisitIincInsn(int var, int increment)

        if (mIsInitMethod) {
            mParentVisitor.visitIincInsn(var, increment);
        }
    
public voidvisitInsn(int opcode)
For non-constructor, rewrite existing "return" instructions to write the message.

        if (mIsInitMethod) {
            switch (opcode) {
            case Opcodes.RETURN:
            case Opcodes.ARETURN:
            case Opcodes.DRETURN:
            case Opcodes.FRETURN:
            case Opcodes.IRETURN:
            case Opcodes.LRETURN:
                // Pop the last word from the stack since invoke will generate its own return.
                generatePop();
                generateInvoke();
                mMessageGenerated = true;
                //$FALL-THROUGH$
            default:
                mParentVisitor.visitInsn(opcode);
            }
        }
    
public voidvisitIntInsn(int opcode, int operand)

        if (mIsInitMethod) {
            mParentVisitor.visitIntInsn(opcode, operand);
        }
    
public voidvisitJumpInsn(int opcode, org.objectweb.asm.Label label)

        if (mIsInitMethod) {
            mParentVisitor.visitJumpInsn(opcode, label);
        }
    
public voidvisitLabel(org.objectweb.asm.Label label)

        if (mIsInitMethod) {
            mParentVisitor.visitLabel(label);
        }
    
public voidvisitLdcInsn(java.lang.Object cst)

        if (mIsInitMethod) {
            mParentVisitor.visitLdcInsn(cst);
        }
    
public voidvisitLineNumber(int line, org.objectweb.asm.Label start)

        if (mIsInitMethod || mOutputFirstLineNumber) {
            mParentVisitor.visitLineNumber(line, start);
            mOutputFirstLineNumber = false;
        }
    
public voidvisitLocalVariable(java.lang.String name, java.lang.String desc, java.lang.String signature, org.objectweb.asm.Label start, org.objectweb.asm.Label end, int index)

        if (mIsInitMethod) {
            mParentVisitor.visitLocalVariable(name, desc, signature, start, end, index);
        }
    
public voidvisitLookupSwitchInsn(org.objectweb.asm.Label dflt, int[] keys, org.objectweb.asm.Label[] labels)

        if (mIsInitMethod) {
            mParentVisitor.visitLookupSwitchInsn(dflt, keys, labels);
        }
    
public voidvisitMaxs(int maxStack, int maxLocals)

        if (!mIsInitMethod && !mMessageGenerated) {
            generateInvoke();
            mMessageGenerated = true;
        }
        mParentVisitor.visitMaxs(maxStack, maxLocals);
    
public voidvisitMethodInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)

        if (mIsInitMethod) {
            mParentVisitor.visitMethodInsn(opcode, owner, name, desc);
        }
    
public voidvisitMultiANewArrayInsn(java.lang.String desc, int dims)

        if (mIsInitMethod) {
            mParentVisitor.visitMultiANewArrayInsn(desc, dims);
        }
    
public org.objectweb.asm.AnnotationVisitorvisitParameterAnnotation(int parameter, java.lang.String desc, boolean visible)

        return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
    
public voidvisitTableSwitchInsn(int min, int max, org.objectweb.asm.Label dflt, org.objectweb.asm.Label[] labels)

        if (mIsInitMethod) {
            mParentVisitor.visitTableSwitchInsn(min, max, dflt, labels);
        }
    
public voidvisitTryCatchBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, org.objectweb.asm.Label handler, java.lang.String type)

        if (mIsInitMethod) {
            mParentVisitor.visitTryCatchBlock(start, end, handler, type);
        }
    
public voidvisitTypeInsn(int opcode, java.lang.String type)

        if (mIsInitMethod) {
            mParentVisitor.visitTypeInsn(opcode, type);
        }
    
public voidvisitVarInsn(int opcode, int var)

        if (mIsInitMethod) {
            mParentVisitor.visitVarInsn(opcode, var);
        }