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