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>&lt;className&gt;_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