14b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet/* 2865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Copyright (C) 2010 The Android Open Source Project 34b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 44b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 54b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * you may not use this file except in compliance with the License. 64b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * You may obtain a copy of the License at 74b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 84b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 94b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 114b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * See the License for the specific language governing permissions and 144b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * limitations under the License. 154b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetpackage com.android.tools.layoutlib.create; 184b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 194b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 214b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.AnnotationVisitor; 224b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.Attribute; 234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.ClassReader; 244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.ClassVisitor; 254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.Label; 264b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.MethodVisitor; 274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.Opcodes; 284b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.objectweb.asm.Type; 294b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 304b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport java.util.ArrayList; 314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet/** 33865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * This method adapter generates delegate methods. 344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 35865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods: 36865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * <ul> 37865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}. 38865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The content is the original method as-is from the reader. 39865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * This step is omitted if the method is native, since it has no Java implementation. 40865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a 41865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * non-existing method named {@code SomeClass_Delegate.MethodName()}. 42865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The implementation of this 'delegate' method is done in layoutlib_brigde. 43865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * </ul> 44865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * A method visitor is generally constructed to generate a single method; however 45865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * here we might want to generate one or two depending on the context. To achieve 46865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * that, the visitor here generates the 'original' method and acts as a no-op if 47865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * no such method exists (e.g. when the original is a native method). 48865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The delegate method is generated after the {@code visitEnd} of the original method 49865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()} 50865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * for native methods. 514b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 52865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * When generating the 'delegate', the implementation generates a call to a class 53865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * class named <code><className>_Delegate</code> with static methods matching 54865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * the methods to be overridden here. The methods have the same return type. 55865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The argument type list is the same except the "this" reference is passed first 56865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * for non-static methods. 574b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 58865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * A new annotation is added to these 'delegate' methods so that we can easily find them 59865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * for automated testing. 60865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * <p/> 61865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * This class isn't intended to be generic or reusable. 62865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing 63865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * the two method writers for the original and the delegate class, as needed, with their 64865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * expected names. 65865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * <p/> 66865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for 674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * a native and use the visitor pattern for non-natives. 68865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Note that native methods have, by definition, no code so there's nothing a visitor 69865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * can visit. 704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 71865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Instances of this class are not re-usable. 72865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * The class adapter creates a new instance for each method. 734b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 74f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbyeclass DelegateMethodAdapter2 extends MethodVisitor { 754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 76865c3bef54228a353fd449a093b0c8d155618296Raphael Moll /** Suffix added to delegate classes. */ 774b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public static final String DELEGATE_SUFFIX = "_Delegate"; 784b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 79865c3bef54228a353fd449a093b0c8d155618296Raphael Moll /** The parent method writer to copy of the original method. 80865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Null when dealing with a native original method. */ 81865c3bef54228a353fd449a093b0c8d155618296Raphael Moll private MethodVisitor mOrgWriter; 82865c3bef54228a353fd449a093b0c8d155618296Raphael Moll /** The parent method writer to generate the delegating method. Never null. */ 83865c3bef54228a353fd449a093b0c8d155618296Raphael Moll private MethodVisitor mDelWriter; 844b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** The original method descriptor (return type + argument types.) */ 854b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private String mDesc; 864b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** True if the original method is static. */ 874b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final boolean mIsStatic; 884b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */ 894b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final String mClassName; 904b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** The method name. */ 914b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final String mMethodName; 924b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** Logger object. */ 934b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final Log mLog; 94865c3bef54228a353fd449a093b0c8d155618296Raphael Moll 95865c3bef54228a353fd449a093b0c8d155618296Raphael Moll /** Array used to capture the first line number information from the original method 96865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * and duplicate it in the delegate. */ 97865c3bef54228a353fd449a093b0c8d155618296Raphael Moll private Object[] mDelegateLineNumber; 984b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 994b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** 100865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Creates a new {@link DelegateMethodAdapter2} that will transform this method 1014b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * into a delegate call. 1024b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 103865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * See {@link DelegateMethodAdapter2} for more details. 1044b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1054b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @param log The logger object. Must not be null. 106865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * @param mvOriginal The parent method writer to copy of the original method. 107865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Must be {@code null} when dealing with a native original method. 108865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * @param mvDelegate The parent method writer to generate the delegating method. 109865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * Must never be null. 1104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @param className The internal class name of the class to visit, 1114b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * e.g. <code>com/android/SomeClass$InnerClass</code>. 1124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @param methodName The simple name of the method. 1134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} + 1144b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * {@link Type#getArgumentTypes(String)}) 1154b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @param isStatic True if the method is declared static. 1164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 117865c3bef54228a353fd449a093b0c8d155618296Raphael Moll public DelegateMethodAdapter2(Log log, 118865c3bef54228a353fd449a093b0c8d155618296Raphael Moll MethodVisitor mvOriginal, 119865c3bef54228a353fd449a093b0c8d155618296Raphael Moll MethodVisitor mvDelegate, 1204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet String className, 1214b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet String methodName, 1224b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet String desc, 1234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet boolean isStatic) { 124f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye super(Opcodes.ASM4); 1254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mLog = log; 126865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter = mvOriginal; 127865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter = mvDelegate; 1284b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mClassName = className; 1294b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mMethodName = methodName; 1304b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mDesc = desc; 1314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mIsStatic = isStatic; 1324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1334b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** 1354b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Generates the new code for the method. 1364b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 1374b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * For native methods, this must be invoked directly by {@link DelegateClassAdapter} 1384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * (since they have no code to visit). 1394b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * <p/> 1404b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to 141865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern 1424b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then 1434b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * this method will be invoked from {@link MethodVisitor#visitEnd()}. 1444b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 145865c3bef54228a353fd449a093b0c8d155618296Raphael Moll public void generateDelegateCode() { 1464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* 1474b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * The goal is to generate a call to a static delegate method. 1484b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * If this method is non-static, the first parameter will be 'this'. 1494b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * All the parameters must be passed and then the eventual return type returned. 1504b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1514b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Example, let's say we have a method such as 152865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * public void myMethod(int a, Object b, ArrayList<String> c) { ... } 1534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1544b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * We'll want to create a body that calls a delegate method like this: 155865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * TheClass_Delegate.myMethod(this, a, b, c); 1564b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1574b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * If the method is non-static and the class name is an inner class (e.g. has $ in its 1584b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * last segment), we want to push the 'this' of the outer class first: 159865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * OuterClass_InnerClass_Delegate.myMethod( 1604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * OuterClass.this, 1614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * OuterClass$InnerClass.this, 1624b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * a, b, c); 1634b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1644b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Only one level of inner class is supported right now, for simplicity and because 1654b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * we don't need more. 1664b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 1674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * The generated class name is the current class name with "_Delegate" appended to it. 1684b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * One thing to realize is that we don't care about generics -- since generic types 169865c3bef54228a353fd449a093b0c8d155618296Raphael Moll * are erased at build time, they have no influence on the method name being called. 1704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 1714b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1724b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Add our annotation 173865c3bef54228a353fd449a093b0c8d155618296Raphael Moll AnnotationVisitor aw = mDelWriter.visitAnnotation( 1744b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), 1754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet true); // visible at runtime 176865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (aw != null) { 177865c3bef54228a353fd449a093b0c8d155618296Raphael Moll aw.visitEnd(); 178865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 179865c3bef54228a353fd449a093b0c8d155618296Raphael Moll 180865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitCode(); 1814b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 182865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mDelegateLineNumber != null) { 183865c3bef54228a353fd449a093b0c8d155618296Raphael Moll Object[] p = mDelegateLineNumber; 184865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]); 1854b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1864b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1874b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet ArrayList<Type> paramTypes = new ArrayList<Type>(); 1884b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet String delegateClassName = mClassName + DELEGATE_SUFFIX; 1894b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet boolean pushedArg0 = false; 1904b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet int maxStack = 0; 1914b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 192f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet // Check if the last segment of the class name has inner an class. 193f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet // Right now we only support one level of inner classes. 194f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet Type outerType = null; 195f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet int slash = mClassName.lastIndexOf('/'); 196f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet int dol = mClassName.lastIndexOf('$'); 197f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) { 198f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet String outerClass = mClassName.substring(0, dol); 199f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet outerType = Type.getObjectType(outerClass); 200f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet 201f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet // Change a delegate class name to "com/foo/Outer_Inner_Delegate" 202f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet delegateClassName = delegateClassName.replace('$', '_'); 203f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet } 204f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet 2054b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // For an instance method (e.g. non-static), push the 'this' preceded 2064b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // by the 'this' of any outer class, if any. 2074b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (!mIsStatic) { 2084b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 209f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet if (outerType != null) { 2104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // The first-level inner class has a package-protected member called 'this$0' 2114b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // that points to the outer class. 2124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Push this.getField("this$0") on the call stack. 214865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this 215865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitFieldInsn(Opcodes.GETFIELD, 2164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mClassName, // class where the field is defined 2174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet "this$0", // field name 2184b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet outerType.getDescriptor()); // type of the field 2194b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet maxStack++; 2204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet paramTypes.add(outerType); 221f1dee199a009fec5e3a5d1469f654098261f8b06Xavier Ducrohet 2224b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Push "this" for the instance method, which is always ALOAD 0 225865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); 2264b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet maxStack++; 2274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet pushedArg0 = true; 2284b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet paramTypes.add(Type.getObjectType(mClassName)); 2294b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2304b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Push all other arguments. Start at arg 1 if we already pushed 'this' above. 2324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Type[] argTypes = Type.getArgumentTypes(mDesc); 2334b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet int maxLocals = pushedArg0 ? 1 : 0; 2344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (Type t : argTypes) { 2354b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet int size = t.getSize(); 236865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals); 2374b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet maxLocals += size; 2384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet maxStack += size; 2394b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet paramTypes.add(t); 2404b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2414b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2424b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Construct the descriptor of the delegate based on the parameters 2434b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // we pushed on the call stack. The return type remains unchanged. 2444b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet String desc = Type.getMethodDescriptor( 2454b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Type.getReturnType(mDesc), 2464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet paramTypes.toArray(new Type[paramTypes.size()])); 2474b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2484b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // Invoke the static delegate 249865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC, 2504b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet delegateClassName, 2514b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mMethodName, 2524b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet desc); 2534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2544b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Type returnType = Type.getReturnType(mDesc); 255865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 2564b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 257865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitMaxs(maxStack, maxLocals); 258865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelWriter.visitEnd(); 2594b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // For debugging now. Maybe we should collect these and store them in 2614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // a text file for helping create the delegates. We could also compare 2624b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // the text file to a golden and break the build on unsupported changes 2634b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // or regressions. Even better we could fancy-print something that looks 2644b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet // like the expected Java method declaration. 2654b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc); 2664b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2684b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* Pass down to visitor writer. In this implementation, either do nothing. */ 269f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 2704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitCode() { 271865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 272865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitCode(); 273865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 2744b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2764b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* 2774b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * visitMaxs is called just before visitEnd if there was any code to rewrite. 2784b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 279f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 2804b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitMaxs(int maxStack, int maxLocals) { 281865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 282865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitMaxs(maxStack, maxLocals); 283865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 2844b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2854b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 286865c3bef54228a353fd449a093b0c8d155618296Raphael Moll /** End of visiting. Generate the delegating code. */ 287f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 2884b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitEnd() { 289865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 290865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitEnd(); 291865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 292865c3bef54228a353fd449a093b0c8d155618296Raphael Moll generateDelegateCode(); 2934b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 2944b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 2954b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* Writes all annotation from the original method. */ 296f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 2974b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 298865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 299865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return mOrgWriter.visitAnnotation(desc, visible); 300865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } else { 301865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return null; 302865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3034b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3044b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 3054b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* Writes all annotation default values from the original method. */ 306f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3074b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public AnnotationVisitor visitAnnotationDefault() { 308865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 309865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return mOrgWriter.visitAnnotationDefault(); 310865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } else { 311865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return null; 312865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3144b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 315f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, 3174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet boolean visible) { 318865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 319865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return mOrgWriter.visitParameterAnnotation(parameter, desc, visible); 320865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } else { 321865c3bef54228a353fd449a093b0c8d155618296Raphael Moll return null; 322865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 3254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* Writes all attributes from the original method. */ 326f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitAttribute(Attribute attr) { 328865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 329865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitAttribute(attr); 330865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 3334b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* 3344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Only writes the first line number present in the original code so that source 3354b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * viewers can direct to the correct method, even if the content doesn't match. 3364b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 337f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitLineNumber(int line, Label start) { 339865c3bef54228a353fd449a093b0c8d155618296Raphael Moll // Capture the first line values for the new delegate method 340865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mDelegateLineNumber == null) { 341865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mDelegateLineNumber = new Object[] { line, start }; 342865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 343865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 344865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitLineNumber(line, start); 3454b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3474b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 348f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3494b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitInsn(int opcode) { 350865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 351865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitInsn(opcode); 352865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3544b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 355f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3564b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitLabel(Label label) { 357865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 358865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitLabel(label); 359865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 362f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3634b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 364865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 365865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitTryCatchBlock(start, end, handler, type); 366865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3684b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 369f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitMethodInsn(int opcode, String owner, String name, String desc) { 371865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 372865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitMethodInsn(opcode, owner, name, desc); 373865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3744b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 376f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3774b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitFieldInsn(int opcode, String owner, String name, String desc) { 378865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 379865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitFieldInsn(opcode, owner, name, desc); 380865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3814b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3824b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 383f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3844b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { 385865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 386865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitFrame(type, nLocal, local, nStack, stack); 387865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3884b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3894b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 390f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3914b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitIincInsn(int var, int increment) { 392865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 393865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitIincInsn(var, increment); 394865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 3954b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 3964b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 397f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 3984b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitIntInsn(int opcode, int operand) { 399865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 400865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitIntInsn(opcode, operand); 401865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4024b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4034b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 404f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4054b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitJumpInsn(int opcode, Label label) { 406865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 407865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitJumpInsn(opcode, label); 408865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4094b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 411f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitLdcInsn(Object cst) { 413865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 414865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitLdcInsn(cst); 415865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 418f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4194b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitLocalVariable(String name, String desc, String signature, 4204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Label start, Label end, int index) { 421865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 422865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index); 423865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 426f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 428865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 429865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels); 430865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 433f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitMultiANewArrayInsn(String desc, int dims) { 435865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 436865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitMultiANewArrayInsn(desc, dims); 437865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4394b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 440f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4414b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { 442865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 443865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels); 444865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4454b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 447f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4484b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitTypeInsn(int opcode, String type) { 449865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 450865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitTypeInsn(opcode, type); 451865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4524b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 454f7270ba9083e5b0069f73fc88aec439ab439275bTor Norbye @Override 4554b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void visitVarInsn(int opcode, int var) { 456865c3bef54228a353fd449a093b0c8d155618296Raphael Moll if (mOrgWriter != null) { 457865c3bef54228a353fd449a093b0c8d155618296Raphael Moll mOrgWriter.visitVarInsn(opcode, var); 458865c3bef54228a353fd449a093b0c8d155618296Raphael Moll } 4594b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 4604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 4614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet} 462