1ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/*
2ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Copyright (C) 2012 The Android Open Source Project
3ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
4ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * you may not use this file except in compliance with the License.
6ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * You may obtain a copy of the License at
7ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
8ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
10ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * See the License for the specific language governing permissions and
14ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * limitations under the License.
15ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
16ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
17ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipackage com.android.tools.layoutlib.create;
18ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
19ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.tools.layoutlib.annotations.VisibleForTesting;
20ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
21ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
22ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.AnnotationVisitor;
23ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Attribute;
24ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.ClassReader;
25ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.ClassVisitor;
26ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.FieldVisitor;
27ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Label;
28ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.MethodVisitor;
29ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Type;
30ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.signature.SignatureReader;
31ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.signature.SignatureVisitor;
32ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
33ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.io.IOException;
34ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.ArrayList;
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Enumeration;
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.List;
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Map;
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Map.Entry;
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Set;
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.TreeMap;
41ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.TreeSet;
42ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.zip.ZipEntry;
43ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.zip.ZipFile;
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
45ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
46ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Analyzes the input JAR using the ASM java bytecode manipulation library
47ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * to list the classes and their dependencies. A "dependency" is a class
48ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * used by another class.
49ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
50ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipublic class DependencyFinder {
51ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
52ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
53ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
54ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** Output logger. */
55ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final Log mLog;
56ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
57ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
58ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates a new analyzer.
59ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
60ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param log The log output.
61ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
62ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public DependencyFinder(Log log) {
63ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog = log;
64ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
65ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
66ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
67ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Starts the analysis using parameters from the constructor.
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
69ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param osJarPath The input source JARs to parse.
70ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }.
71ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 [1]: map { missing class FQCN => set of FQCN class that uses it. }
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
73ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException {
74ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
75ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, ClassReader> zipClasses = parseZip(osJarPath);
76ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("Found %d classes in input JAR%s.",
77ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                zipClasses.size(),
78ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                osJarPath.size() > 1 ? "s" : "");
79ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
80ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, Set<String>> deps = findClassesDeps(zipClasses);
81ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
82ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
83ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
84528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta        List<Map<String, Set<String>>> result = new ArrayList<>(2);
85ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        result.add(deps);
86ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        result.add(missing);
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return result;
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
89ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Prints dependencies to the current logger, found stuff and missing stuff.
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
93ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void printAllDeps(List<Map<String, Set<String>>> result) {
94ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        assert result.size() == 2;
95ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, Set<String>> deps = result.get(0);
96ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, Set<String>> missing = result.get(1);
97ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
98ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // Print all dependences found in the format:
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // +Found: <FQCN from zip>
100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        //     uses: FQCN
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("++++++ %d Entries found in source JARs", deps.size());
103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("");
104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (Entry<String, Set<String>> entry : deps.entrySet()) {
106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.info(    "+Found  : %s", entry.getKey());
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (String dep : entry.getValue()) {
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mLog.info("    uses: %s", dep);
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.info("");
112ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
113ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // Now print all missing dependences in the format:
116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // -Missing <FQCN>:
117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        //     used by: <FQCN>
118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("");
120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("------ %d Entries missing from source JARs", missing.size());
121ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mLog.info("");
122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (Entry<String, Set<String>> entry : missing.entrySet()) {
124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.info(    "-Missing  : %s", entry.getKey());
125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (String dep : entry.getValue()) {
126ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mLog.info("   used by: %s", dep);
127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.info("");
130ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
131ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
132ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
133ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
134ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Prints only a summary of the missing dependencies to the current logger.
135ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
136ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void printMissingDeps(List<Map<String, Set<String>>> result) {
137ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        assert result.size() == 2;
138ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Map<String, Set<String>> missing = result.get(1);
140ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
141ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (String fqcn : missing.keySet()) {
142ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.info("%s", fqcn);
143ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ----------------
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Parses a JAR file and returns a list of all classes founds using a map
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * class name => ASM ClassReader. Class names are in the form "android.view.View".
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
153528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta        TreeMap<String, ClassReader> classes = new TreeMap<>();
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (String jarPath : jarPathList) {
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            ZipFile zip = new ZipFile(jarPath);
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Enumeration<? extends ZipEntry> entries = zip.entries();
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            ZipEntry entry;
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            while (entries.hasMoreElements()) {
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                entry = entries.nextElement();
161ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (entry.getName().endsWith(".class")) {
162ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
163ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    String className = classReaderToClassName(cr);
164ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    classes.put(className, cr);
165ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
166ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
167ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return classes;
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Utility that returns the fully qualified binary class name for a ClassReader.
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * E.g. it returns something like android.view.View.
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    static String classReaderToClassName(ClassReader classReader) {
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (classReader == null) {
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return classReader.getClassName().replace('/', '.');
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Utility that returns the fully qualified binary class name from a path-like FQCN.
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * E.g. it returns android.view.View from android/view/View.
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    static String internalToBinaryClassName(String className) {
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (className == null) {
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return className.replace('/', '.');
193ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
194ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
196ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Finds all dependencies for all classes in keepClasses which are also
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * listed in zipClasses. Returns a map of all the dependencies found.
199ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) {
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
202ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // The dependencies that we'll collect.
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // It's a map Class name => uses class names.
204528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta        Map<String, Set<String>> dependencyMap = new TreeMap<>();
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        DependencyVisitor visitor = getVisitor();
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int count = 0;
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
210ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
211ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String name = entry.getKey();
212ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
213528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                TreeSet<String> set = new TreeSet<>();
214ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                dependencyMap.put(name, set);
215ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                visitor.setDependencySet(set);
216ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
217ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                ClassReader cr = entry.getValue();
218ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                cr.accept(visitor, 0 /* flags */);
219ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                visitor.setDependencySet(null);
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mLog.debugNoln("Visited %d classes\r", ++count);
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } finally {
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mLog.debugNoln("\n");
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return dependencyMap;
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Computes which classes FQCN were found as dependencies that are NOT listed
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * in the original JAR classes.
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}.
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param zipClasses The set of all classes FQCN found in the JAR files.
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return A map { FQCN not found in the zipClasses => classes using it }
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Map<String, Set<String>> findMissingClasses(
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Map<String, Set<String>> deps,
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Set<String> zipClasses) {
242528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta        Map<String, Set<String>> missing = new TreeMap<>();
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (Entry<String, Set<String>> entry : deps.entrySet()) {
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            String name = entry.getKey();
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (String dep : entry.getValue()) {
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (!zipClasses.contains(dep)) {
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    // This dependency doesn't exist in the zip classes.
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    Set<String> set = missing.get(dep);
251ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    if (set == null) {
252528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                        set = new TreeSet<>();
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        missing.put(dep, set);
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    }
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    set.add(name);
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return missing;
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
264ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
265ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ----------------------------------
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Instantiates a new DependencyVisitor. Useful for unit tests.
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @VisibleForTesting(visibility=Visibility.PRIVATE)
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    DependencyVisitor getVisitor() {
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return new DependencyVisitor();
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Visitor to collect all the type dependencies from a class.
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public class DependencyVisitor extends ClassVisitor {
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        private Set<String> mCurrentDepSet;
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Creates a new visitor that will find all the dependencies for the visited class.
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public DependencyVisitor() {
286528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta            super(Main.ASM_VERSION);
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Sets the {@link Set} where to record direct dependencies for this class.
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call.
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void setDependencySet(Set<String> set) {
294ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mCurrentDepSet = set;
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Considers the given class name as a dependency.
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
300ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void considerName(String className) {
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (className == null) {
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return;
303ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            className = internalToBinaryClassName(className);
306ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            try {
308ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // exclude classes that are part of the default JRE (the one executing this program)
3094b45b08eb7e472863701f6d78cc08b817aa8d0f1Deepanshu Gupta                // or in java package (we won't be able to load them anyway).
3104b45b08eb7e472863701f6d78cc08b817aa8d0f1Deepanshu Gupta                if (className.startsWith("java.") ||
3114b45b08eb7e472863701f6d78cc08b817aa8d0f1Deepanshu Gupta                        getClass().getClassLoader().loadClass(className) != null) {
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return;
313ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
314ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            } catch (ClassNotFoundException e) {
315ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // ignore
316ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
317ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
318ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Add it to the dependency set for the currently visited class, as needed.
319ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            assert mCurrentDepSet != null;
320b77a349014d1fade2185a53c2a58edaa4b971dbeDeepanshu Gupta            mCurrentDepSet.add(className);
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
323ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Considers this array of names using considerName().
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void considerNames(String[] classNames) {
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (classNames != null) {
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                for (String className : classNames) {
329ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerName(className);
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Considers this signature or type signature by invoking the {@link SignatureVisitor}
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * on it.
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void considerSignature(String signature) {
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (signature != null) {
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                SignatureReader sr = new SignatureReader(signature);
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // SignatureReader.accept will call accessType so we don't really have
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // to differentiate where the signature comes from.
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                sr.accept(new MySignatureVisitor());
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Considers this {@link Type}. For arrays, the element type is considered.
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * If the type is an object, it's internal name is considered.
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void considerType(Type t) {
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (t != null) {
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (t.getSort() == Type.ARRAY) {
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    t = t.getElementType();
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (t.getSort() == Type.OBJECT) {
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerName(t.getInternalName());
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /**
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * Considers a descriptor string. The descriptor is converted to a {@link Type}
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         * and then considerType() is invoked.
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public boolean considerDesc(String desc) {
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (desc != null) {
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                try {
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    if (desc.length() > 0 && desc.charAt(0) == '(') {
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        // This is a method descriptor with arguments and a return type.
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        Type t = Type.getReturnType(desc);
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        considerType(t);
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
374ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        for (Type arg : Type.getArgumentTypes(desc)) {
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                            considerType(arg);
376ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        }
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    } else {
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        Type t = Type.getType(desc);
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        considerType(t);
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    }
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return true;
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                } catch (ArrayIndexOutOfBoundsException e) {
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    // ignore, not a valid type.
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
386ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
389ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
392ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // --- ClassVisitor, FieldVisitor
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
394ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // Visits a class header
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
397ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visit(int version, int access, String name,
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String signature, String superName, String[] interfaces) {
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // signature is the signature of this class. May be null if the class is not a generic
400ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // one, and does not extend or implement generic classes or interfaces.
401ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (signature != null) {
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerSignature(signature);
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // superName is the internal of name of the super class (see getInternalName).
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // For interfaces, the super class is Object. May be null but only for the Object class.
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerName(superName);
409ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // interfaces is the internal names of the class's interfaces (see getInternalName).
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // May be null.
412ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerNames(interfaces);
413ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
414ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
417ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // desc is the class descriptor of the annotation class.
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerDesc(desc);
420ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return new MyAnnotationVisitor();
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
424ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visitAttribute(Attribute attr) {
425ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // pass
426ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
427ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
428ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // Visits the end of a class
429ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
430ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visitEnd() {
431ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // pass
432ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
434ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        private class MyFieldVisitor extends FieldVisitor {
435ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
436ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public MyFieldVisitor() {
437528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                super(Main.ASM_VERSION);
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
439ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the class descriptor of the annotation class.
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MyAnnotationVisitor();
445ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
447ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
448ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitAttribute(Attribute attr) {
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
452ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Visits the end of a class
453ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitEnd() {
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
456ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
457ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
459ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
460ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public FieldVisitor visitField(int access, String name, String desc,
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String signature, Object value) {
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // desc is the field's descriptor (see Type).
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerDesc(desc);
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
465ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // signature is the field's signature. May be null if the field's type does not use
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // generic types.
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerSignature(signature);
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return new MyFieldVisitor();
470ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
473ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visitInnerClass(String name, String outerName, String innerName, int access) {
474ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // name is the internal name of an inner class (see getInternalName).
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Note: outerName/innerName seems to be null when we're reading the
476ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // _Original_ClassName classes generated by layoutlib_create.
477ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (outerName != null) {
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerName(name);
479ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
481ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
482ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public MethodVisitor visitMethod(int access, String name, String desc,
484ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String signature, String[] exceptions) {
485ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // desc is the method's descriptor (see Type).
486ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerDesc(desc);
487ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // signature is the method's signature. May be null if the method parameters, return
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // type and exceptions do not use generic types.
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            considerSignature(signature);
490ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
491ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return new MyMethodVisitor();
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visitOuterClass(String owner, String name, String desc) {
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // pass
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
499ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        @Override
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        public void visitSource(String source, String debug) {
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // pass
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // --- MethodVisitor
507ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        private class MyMethodVisitor extends MethodVisitor {
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public MyMethodVisitor() {
512528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                super(Main.ASM_VERSION);
513ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
516ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public AnnotationVisitor visitAnnotationDefault() {
518ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MyAnnotationVisitor();
519ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
520ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
521ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
522ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitCode() {
523ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
524ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
525ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
526ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // field instruction
527ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
528ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitFieldInsn(int opcode, String owner, String name, String desc) {
5292ff4f504c82e35c1f8d3cae79a32b4400a628c28Deepanshu Gupta                // owner is the class that declares the field.
5302ff4f504c82e35c1f8d3cae79a32b4400a628c28Deepanshu Gupta                considerName(owner);
531ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the field's descriptor (see Type).
532ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
533ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
534ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
535ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
536ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
537ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
538ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitIincInsn(int var, int increment) {
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- an IINC instruction
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitInsn(int opcode) {
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a zero operand instruction
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitIntInsn(int opcode, int operand) {
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a single int operand instruction
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitJumpInsn(int opcode, Label label) {
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a jump instruction
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitLabel(Label label) {
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a label target
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // instruction to load a constant from the stack
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitLdcInsn(Object cst) {
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (cst instanceof Type) {
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerType((Type) cst);
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitLineNumber(int line, Label start) {
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitLocalVariable(String name, String desc,
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    String signature, Label start, Label end, int index) {
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the type descriptor of this local variable.
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // signature is the type signature of this local variable. May be null if the local
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // variable type does not use generic types.
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerSignature(signature);
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a lookup switch instruction
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitMaxs(int maxStack, int maxLocals) {
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // instruction that invokes a method
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
600528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta            public void visitMethodInsn(int opcode, String owner, String name, String desc,
601528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    boolean itf) {
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // owner is the internal name of the method's owner class
604ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (!considerDesc(owner) && owner.indexOf('/') != -1) {
605ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerName(owner);
606ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
607ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the method's descriptor (see Type).
608ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
609ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
610ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
611ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // instruction multianewarray, whatever that is
612ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
613ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitMultiANewArrayInsn(String desc, int dims) {
614ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
615ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc an array type descriptor.
616ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
617ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
618ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
619ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
620ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
621ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    boolean visible) {
622ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the class descriptor of the annotation class.
623ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
624ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MyAnnotationVisitor();
625ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
626ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
627ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
628ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
629ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- table switch instruction
630ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
631ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
632ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
633ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
634ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
635ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // type is the internal name of the type of exceptions handled by the handler,
636ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // or null to catch any exceptions (for "finally" blocks).
637ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerName(type);
638ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
639ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
640ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // type instruction
641ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
642ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitTypeInsn(int opcode, String type) {
643ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // type is the operand of the instruction to be visited. This operand must be the
644ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // internal name of an object or array class.
645ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerName(type);
646ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
647ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
648ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
649ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitVarInsn(int opcode, int var) {
650ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- local variable instruction
651ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
652ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
653ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        private class MySignatureVisitor extends SignatureVisitor {
655ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
656ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public MySignatureVisitor() {
657528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                super(Main.ASM_VERSION);
658ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
659ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
660ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // ---------------------------------------------------
661ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // --- SignatureVisitor
662ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // ---------------------------------------------------
663ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
664ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            private String mCurrentSignatureClass = null;
665ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
666ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Starts the visit of a signature corresponding to a class or interface type
667ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
668ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitClassType(String name) {
669ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mCurrentSignatureClass = name;
670ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerName(name);
671ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
672ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
673ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Visits an inner class
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
675ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitInnerClassType(String name) {
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (mCurrentSignatureClass != null) {
677ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    mCurrentSignatureClass += "$" + name;
678ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerName(mCurrentSignatureClass);
679ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
680ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
681ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
682ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
683ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitArrayType() {
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
685ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitBaseType(char descriptor) {
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass -- a primitive type, ignored
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
691ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
693ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitClassBound() {
694ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
697ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
698ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitExceptionType() {
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
700ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitFormalTypeParameter(String name) {
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitInterface() {
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitInterfaceBound() {
714ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
715ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
716ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
717ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
718ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitParameterType() {
719ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
720ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
721ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
722ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
723ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitReturnType() {
724ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
725ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
726ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitSuperclass() {
729ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
730ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
731ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
732ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
733ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public SignatureVisitor visitTypeArgument(char wildcard) {
734ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MySignatureVisitor();
735ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
736ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
737ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
738ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitTypeVariable(String name) {
739ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
740ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
741ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
742ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
743ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitTypeArgument() {
744ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // pass
745ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
746ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
747ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
748ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
749ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
750ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // --- AnnotationVisitor
751ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // ---------------------------------------------------
752ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
753ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        private class MyAnnotationVisitor extends AnnotationVisitor {
754ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
755ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public MyAnnotationVisitor() {
756528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                super(Main.ASM_VERSION);
757ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
758ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
759ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // Visits a primitive value of an annotation
760ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
761ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visit(String name, Object value) {
762ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // value is the actual value, whose type must be Byte, Boolean, Character, Short,
763ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // Integer, Long, Float, Double, String or Type
764ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if (value instanceof Type) {
765ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    considerType((Type) value);
766ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
767ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
768ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
769ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
770ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public AnnotationVisitor visitAnnotation(String name, String desc) {
771ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the class descriptor of the nested annotation class.
772ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
773ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MyAnnotationVisitor();
774ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
775ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
776ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
777ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public AnnotationVisitor visitArray(String name) {
778ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return new MyAnnotationVisitor();
779ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
780ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
781ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            @Override
782ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            public void visitEnum(String name, String desc, String value) {
783ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // desc is the class descriptor of the enumeration class.
784ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                considerDesc(desc);
785ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
786ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
787ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
788ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
789