1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.tools.layoutlib.create; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.AnnotationVisitor; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Attribute; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.ClassReader; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.ClassVisitor; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Label; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.MethodVisitor; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Opcodes; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Type; 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.ArrayList; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This method adapter generates delegate methods. 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods: 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <ul> 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}. 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The content is the original method as-is from the reader. 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This step is omitted if the method is native, since it has no Java implementation. 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * non-existing method named {@code SomeClass_Delegate.MethodName()}. 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The implementation of this 'delegate' method is done in layoutlib_brigde. 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * </ul> 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * A method visitor is generally constructed to generate a single method; however 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * here we might want to generate one or two depending on the context. To achieve 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * that, the visitor here generates the 'original' method and acts as a no-op if 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * no such method exists (e.g. when the original is a native method). 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The delegate method is generated after the {@code visitEnd} of the original method 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()} 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * for native methods. 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * When generating the 'delegate', the implementation generates a call to a class 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * class named <code><className>_Delegate</code> with static methods matching 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * the methods to be overridden here. The methods have the same return type. 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The argument type list is the same except the "this" reference is passed first 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * for non-static methods. 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * A new annotation is added to these 'delegate' methods so that we can easily find them 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * for automated testing. 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class isn't intended to be generic or reusable. 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * the two method writers for the original and the delegate class, as needed, with their 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * expected names. 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a native and use the visitor pattern for non-natives. 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Note that native methods have, by definition, no code so there's nothing a visitor 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * can visit. 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Instances of this class are not re-usable. 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The class adapter creates a new instance for each method. 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 74c5a58437e62698f34abde93ec785c4cbe36aec2dDeepanshu Guptaclass DelegateMethodAdapter extends MethodVisitor { 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Suffix added to delegate classes. */ 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String DELEGATE_SUFFIX = "_Delegate"; 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** The parent method writer to copy of the original method. 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Null when dealing with a native original method. */ 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private MethodVisitor mOrgWriter; 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** The parent method writer to generate the delegating method. Never null. */ 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private MethodVisitor mDelWriter; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** The original method descriptor (return type + argument types.) */ 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private String mDesc; 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** True if the original method is static. */ 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final boolean mIsStatic; 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */ 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final String mClassName; 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** The method name. */ 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final String mMethodName; 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Logger object. */ 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final Log mLog; 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Array used to capture the first line number information from the original method 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * and duplicate it in the delegate. */ 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private Object[] mDelegateLineNumber; 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 100c5a58437e62698f34abde93ec785c4cbe36aec2dDeepanshu Gupta * Creates a new {@link DelegateMethodAdapter} that will transform this method 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * into a delegate call. 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 103c5a58437e62698f34abde93ec785c4cbe36aec2dDeepanshu Gupta * See {@link DelegateMethodAdapter} for more details. 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param log The logger object. Must not be null. 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param mvOriginal The parent method writer to copy of the original method. 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Must be {@code null} when dealing with a native original method. 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param mvDelegate The parent method writer to generate the delegating method. 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Must never be null. 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param className The internal class name of the class to visit, 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * e.g. <code>com/android/SomeClass$InnerClass</code>. 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param methodName The simple name of the method. 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} + 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * {@link Type#getArgumentTypes(String)}) 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param isStatic True if the method is declared static. 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 117c5a58437e62698f34abde93ec785c4cbe36aec2dDeepanshu Gupta public DelegateMethodAdapter(Log log, 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MethodVisitor mvOriginal, 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MethodVisitor mvDelegate, 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String className, 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String methodName, 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String desc, 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean isStatic) { 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski super(Opcodes.ASM4); 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mLog = log; 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter = mvOriginal; 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter = mvDelegate; 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mClassName = className; 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mMethodName = methodName; 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDesc = desc; 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mIsStatic = isStatic; 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Generates the new code for the method. 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * For native methods, this must be invoked directly by {@link DelegateClassAdapter} 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * (since they have no code to visit). 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to 141c5a58437e62698f34abde93ec785c4cbe36aec2dDeepanshu Gupta * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * this method will be invoked from {@link MethodVisitor#visitEnd()}. 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void generateDelegateCode() { 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The goal is to generate a call to a static delegate method. 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * If this method is non-static, the first parameter will be 'this'. 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * All the parameters must be passed and then the eventual return type returned. 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Example, let's say we have a method such as 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * public void myMethod(int a, Object b, ArrayList<String> c) { ... } 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * We'll want to create a body that calls a delegate method like this: 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * TheClass_Delegate.myMethod(this, a, b, c); 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * If the method is non-static and the class name is an inner class (e.g. has $ in its 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * last segment), we want to push the 'this' of the outer class first: 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * OuterClass_InnerClass_Delegate.myMethod( 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * OuterClass.this, 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * OuterClass$InnerClass.this, 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a, b, c); 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Only one level of inner class is supported right now, for simplicity and because 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * we don't need more. 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The generated class name is the current class name with "_Delegate" appended to it. 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * One thing to realize is that we don't care about generics -- since generic types 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * are erased at build time, they have no influence on the method name being called. 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add our annotation 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AnnotationVisitor aw = mDelWriter.visitAnnotation( 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski true); // visible at runtime 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (aw != null) { 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski aw.visitEnd(); 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitCode(); 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mDelegateLineNumber != null) { 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Object[] p = mDelegateLineNumber; 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]); 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ArrayList<Type> paramTypes = new ArrayList<Type>(); 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String delegateClassName = mClassName + DELEGATE_SUFFIX; 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean pushedArg0 = false; 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int maxStack = 0; 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Check if the last segment of the class name has inner an class. 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Right now we only support one level of inner classes. 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Type outerType = null; 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int slash = mClassName.lastIndexOf('/'); 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dol = mClassName.lastIndexOf('$'); 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) { 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String outerClass = mClassName.substring(0, dol); 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outerType = Type.getObjectType(outerClass); 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Change a delegate class name to "com/foo/Outer_Inner_Delegate" 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delegateClassName = delegateClassName.replace('$', '_'); 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For an instance method (e.g. non-static), push the 'this' preceded 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // by the 'this' of any outer class, if any. 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!mIsStatic) { 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outerType != null) { 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // The first-level inner class has a package-protected member called 'this$0' 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // that points to the outer class. 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Push this.getField("this$0") on the call stack. 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitFieldInsn(Opcodes.GETFIELD, 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mClassName, // class where the field is defined 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "this$0", // field name 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outerType.getDescriptor()); // type of the field 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski maxStack++; 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski paramTypes.add(outerType); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Push "this" for the instance method, which is always ALOAD 0 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski maxStack++; 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pushedArg0 = true; 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski paramTypes.add(Type.getObjectType(mClassName)); 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Push all other arguments. Start at arg 1 if we already pushed 'this' above. 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Type[] argTypes = Type.getArgumentTypes(mDesc); 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int maxLocals = pushedArg0 ? 1 : 0; 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (Type t : argTypes) { 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int size = t.getSize(); 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals); 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski maxLocals += size; 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski maxStack += size; 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski paramTypes.add(t); 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Construct the descriptor of the delegate based on the parameters 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we pushed on the call stack. The return type remains unchanged. 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String desc = Type.getMethodDescriptor( 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Type.getReturnType(mDesc), 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski paramTypes.toArray(new Type[paramTypes.size()])); 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Invoke the static delegate 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC, 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delegateClassName, 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mMethodName, 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski desc); 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Type returnType = Type.getReturnType(mDesc); 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitMaxs(maxStack, maxLocals); 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelWriter.visitEnd(); 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For debugging now. Maybe we should collect these and store them in 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // a text file for helping create the delegates. We could also compare 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the text file to a golden and break the build on unsupported changes 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // or regressions. Even better we could fancy-print something that looks 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // like the expected Java method declaration. 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc); 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* Pass down to visitor writer. In this implementation, either do nothing. */ 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitCode() { 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitCode(); 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * visitMaxs is called just before visitEnd if there was any code to rewrite. 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitMaxs(int maxStack, int maxLocals) { 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitMaxs(maxStack, maxLocals); 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** End of visiting. Generate the delegating code. */ 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitEnd() { 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitEnd(); 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski generateDelegateCode(); 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* Writes all annotation from the original method. */ 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mOrgWriter.visitAnnotation(desc, visible); 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* Writes all annotation default values from the original method. */ 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public AnnotationVisitor visitAnnotationDefault() { 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mOrgWriter.visitAnnotationDefault(); 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean visible) { 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mOrgWriter.visitParameterAnnotation(parameter, desc, visible); 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* Writes all attributes from the original method. */ 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitAttribute(Attribute attr) { 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitAttribute(attr); 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Only writes the first line number present in the original code so that source 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * viewers can direct to the correct method, even if the content doesn't match. 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitLineNumber(int line, Label start) { 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Capture the first line values for the new delegate method 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mDelegateLineNumber == null) { 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mDelegateLineNumber = new Object[] { line, start }; 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitLineNumber(line, start); 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitInsn(int opcode) { 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitInsn(opcode); 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitLabel(Label label) { 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitLabel(label); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitTryCatchBlock(start, end, handler, type); 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitMethodInsn(int opcode, String owner, String name, String desc) { 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitMethodInsn(opcode, owner, name, desc); 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitFieldInsn(int opcode, String owner, String name, String desc) { 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitFieldInsn(opcode, owner, name, desc); 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitFrame(type, nLocal, local, nStack, stack); 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitIincInsn(int var, int increment) { 392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitIincInsn(var, increment); 394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitIntInsn(int opcode, int operand) { 399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitIntInsn(opcode, operand); 401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitJumpInsn(int opcode, Label label) { 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitJumpInsn(opcode, label); 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitLdcInsn(Object cst) { 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitLdcInsn(cst); 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitLocalVariable(String name, String desc, String signature, 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Label start, Label end, int index) { 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index); 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels); 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitMultiANewArrayInsn(String desc, int dims) { 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitMultiANewArrayInsn(desc, dims); 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels); 444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitTypeInsn(int opcode, String type) { 449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitTypeInsn(opcode, type); 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void visitVarInsn(int opcode, int var) { 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrgWriter != null) { 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrgWriter.visitVarInsn(opcode, var); 458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 462