1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2012 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.VisibleForTesting;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.AnnotationVisitor;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Attribute;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.ClassReader;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.ClassVisitor;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.FieldVisitor;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Label;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.MethodVisitor;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Opcodes;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.Type;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.signature.SignatureReader;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.objectweb.asm.signature.SignatureVisitor;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.ArrayList;
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Enumeration;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.List;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Map;
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Map.Entry;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Set;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.TreeMap;
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.TreeSet;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.zip.ZipEntry;
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.zip.ZipFile;
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Analyzes the input JAR using the ASM java bytecode manipulation library
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * to list the classes and their dependencies. A "dependency" is a class
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * used by another class.
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic class DependencyFinder {
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Output logger. */
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final Log mLog;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Creates a new analyzer.
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param log The log output.
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public DependencyFinder(Log log) {
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog = log;
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Starts the analysis using parameters from the constructor.
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param osJarPath The input source JARs to parse.
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }.
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 [1]: map { missing class FQCN => set of FQCN class that uses it. }
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException {
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, ClassReader> zipClasses = parseZip(osJarPath);
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("Found %d classes in input JAR%s.",
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                zipClasses.size(),
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                osJarPath.size() > 1 ? "s" : "");
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> deps = findClassesDeps(zipClasses);
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2);
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result.add(deps);
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result.add(missing);
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Prints dependencies to the current logger, found stuff and missing stuff.
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void printAllDeps(List<Map<String, Set<String>>> result) {
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assert result.size() == 2;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> deps = result.get(0);
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> missing = result.get(1);
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Print all dependences found in the format:
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // +Found: <FQCN from zip>
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //     uses: FQCN
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("++++++ %d Entries found in source JARs", deps.size());
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("");
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Entry<String, Set<String>> entry : deps.entrySet()) {
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.info(    "+Found  : %s", entry.getKey());
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (String dep : entry.getValue()) {
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mLog.info("    uses: %s", dep);
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.info("");
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now print all missing dependences in the format:
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // -Missing <FQCN>:
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //     used by: <FQCN>
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("");
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("------ %d Entries missing from source JARs", missing.size());
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mLog.info("");
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Entry<String, Set<String>> entry : missing.entrySet()) {
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.info(    "-Missing  : %s", entry.getKey());
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (String dep : entry.getValue()) {
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mLog.info("   used by: %s", dep);
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.info("");
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Prints only a summary of the missing dependencies to the current logger.
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void printMissingDeps(List<Map<String, Set<String>>> result) {
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        assert result.size() == 2;
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> missing = result.get(1);
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (String fqcn : missing.keySet()) {
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.info("%s", fqcn);
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ----------------
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Parses a JAR file and returns a list of all classes founds using a map
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * class name => ASM ClassReader. Class names are in the form "android.view.View".
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (String jarPath : jarPathList) {
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ZipFile zip = new ZipFile(jarPath);
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Enumeration<? extends ZipEntry> entries = zip.entries();
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ZipEntry entry;
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (entries.hasMoreElements()) {
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                entry = entries.nextElement();
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (entry.getName().endsWith(".class")) {
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String className = classReaderToClassName(cr);
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    classes.put(className, cr);
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return classes;
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Utility that returns the fully qualified binary class name for a ClassReader.
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * E.g. it returns something like android.view.View.
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static String classReaderToClassName(ClassReader classReader) {
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (classReader == null) {
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return classReader.getClassName().replace('/', '.');
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Utility that returns the fully qualified binary class name from a path-like FQCN.
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * E.g. it returns android.view.View from android/view/View.
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static String internalToBinaryClassName(String className) {
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (className == null) {
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return className.replace('/', '.');
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Finds all dependencies for all classes in keepClasses which are also
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * listed in zipClasses. Returns a map of all the dependencies found.
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // The dependencies that we'll collect.
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // It's a map Class name => uses class names.
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>();
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        DependencyVisitor visitor = getVisitor();
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = 0;
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String name = entry.getKey();
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                TreeSet<String> set = new TreeSet<String>();
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                dependencyMap.put(name, set);
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                visitor.setDependencySet(set);
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ClassReader cr = entry.getValue();
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                cr.accept(visitor, 0 /* flags */);
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                visitor.setDependencySet(null);
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mLog.debugNoln("Visited %d classes\r", ++count);
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } finally {
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mLog.debugNoln("\n");
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return dependencyMap;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Computes which classes FQCN were found as dependencies that are NOT listed
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * in the original JAR classes.
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}.
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param zipClasses The set of all classes FQCN found in the JAR files.
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return A map { FQCN not found in the zipClasses => classes using it }
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Map<String, Set<String>> findMissingClasses(
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Map<String, Set<String>> deps,
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Set<String> zipClasses) {
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Map<String, Set<String>> missing = new TreeMap<String, Set<String>>();
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Entry<String, Set<String>> entry : deps.entrySet()) {
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String name = entry.getKey();
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (String dep : entry.getValue()) {
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!zipClasses.contains(dep)) {
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // This dependency doesn't exist in the zip classes.
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Set<String> set = missing.get(dep);
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (set == null) {
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        set = new TreeSet<String>();
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        missing.put(dep, set);
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    set.add(name);
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return missing;
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ----------------------------------
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Instantiates a new DependencyVisitor. Useful for unit tests.
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @VisibleForTesting(visibility=Visibility.PRIVATE)
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DependencyVisitor getVisitor() {
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return new DependencyVisitor();
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Visitor to collect all the type dependencies from a class.
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public class DependencyVisitor extends ClassVisitor {
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private Set<String> mCurrentDepSet;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Creates a new visitor that will find all the dependencies for the visited class.
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public DependencyVisitor() {
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            super(Opcodes.ASM4);
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Sets the {@link Set} where to record direct dependencies for this class.
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call.
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void setDependencySet(Set<String> set) {
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mCurrentDepSet = set;
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Considers the given class name as a dependency.
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void considerName(String className) {
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (className == null) {
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return;
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            className = internalToBinaryClassName(className);
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            try {
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // exclude classes that are part of the default JRE (the one executing this program)
31086caef1892e1ce063e0e880396c8deaa3a6a171dDeepanshu Gupta                // or in java package (we won't be able to load them anyway).
31186caef1892e1ce063e0e880396c8deaa3a6a171dDeepanshu Gupta                if (className.startsWith("java.") ||
31286caef1892e1ce063e0e880396c8deaa3a6a171dDeepanshu Gupta                        getClass().getClassLoader().loadClass(className) != null) {
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return;
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } catch (ClassNotFoundException e) {
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // ignore
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add it to the dependency set for the currently visited class, as needed.
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            assert mCurrentDepSet != null;
321d2a411840c58eaee05499bab0190e3f3656e2e84Deepanshu Gupta            mCurrentDepSet.add(className);
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Considers this array of names using considerName().
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void considerNames(String[] classNames) {
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (classNames != null) {
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (String className : classNames) {
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerName(className);
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Considers this signature or type signature by invoking the {@link SignatureVisitor}
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * on it.
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void considerSignature(String signature) {
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (signature != null) {
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SignatureReader sr = new SignatureReader(signature);
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // SignatureReader.accept will call accessType so we don't really have
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // to differentiate where the signature comes from.
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sr.accept(new MySignatureVisitor());
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Considers this {@link Type}. For arrays, the element type is considered.
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * If the type is an object, it's internal name is considered.
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void considerType(Type t) {
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t != null) {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t.getSort() == Type.ARRAY) {
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    t = t.getElementType();
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t.getSort() == Type.OBJECT) {
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerName(t.getInternalName());
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /**
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * Considers a descriptor string. The descriptor is converted to a {@link Type}
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * and then considerType() is invoked.
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public boolean considerDesc(String desc) {
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (desc != null) {
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                try {
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (desc.length() > 0 && desc.charAt(0) == '(') {
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // This is a method descriptor with arguments and a return type.
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Type t = Type.getReturnType(desc);
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        considerType(t);
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (Type arg : Type.getArgumentTypes(desc)) {
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            considerType(arg);
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Type t = Type.getType(desc);
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        considerType(t);
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return true;
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } catch (ArrayIndexOutOfBoundsException e) {
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // ignore, not a valid type.
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // --- ClassVisitor, FieldVisitor
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Visits a class header
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visit(int version, int access, String name,
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String signature, String superName, String[] interfaces) {
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // signature is the signature of this class. May be null if the class is not a generic
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // one, and does not extend or implement generic classes or interfaces.
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (signature != null) {
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerSignature(signature);
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // superName is the internal of name of the super class (see getInternalName).
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For interfaces, the super class is Object. May be null but only for the Object class.
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerName(superName);
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // interfaces is the internal names of the class's interfaces (see getInternalName).
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // May be null.
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerNames(interfaces);
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // desc is the class descriptor of the annotation class.
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerDesc(desc);
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return new MyAnnotationVisitor();
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visitAttribute(Attribute attr) {
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // pass
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Visits the end of a class
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visitEnd() {
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // pass
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private class MyFieldVisitor extends FieldVisitor {
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public MyFieldVisitor() {
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                super(Opcodes.ASM4);
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the class descriptor of the annotation class.
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MyAnnotationVisitor();
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitAttribute(Attribute attr) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Visits the end of a class
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitEnd() {
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public FieldVisitor visitField(int access, String name, String desc,
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String signature, Object value) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // desc is the field's descriptor (see Type).
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerDesc(desc);
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // signature is the field's signature. May be null if the field's type does not use
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // generic types.
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerSignature(signature);
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return new MyFieldVisitor();
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visitInnerClass(String name, String outerName, String innerName, int access) {
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // name is the internal name of an inner class (see getInternalName).
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Note: outerName/innerName seems to be null when we're reading the
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // _Original_ClassName classes generated by layoutlib_create.
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outerName != null) {
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerName(name);
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public MethodVisitor visitMethod(int access, String name, String desc,
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String signature, String[] exceptions) {
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // desc is the method's descriptor (see Type).
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerDesc(desc);
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // signature is the method's signature. May be null if the method parameters, return
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // type and exceptions do not use generic types.
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            considerSignature(signature);
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return new MyMethodVisitor();
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visitOuterClass(String owner, String name, String desc) {
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // pass
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        @Override
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        public void visitSource(String source, String debug) {
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // pass
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // --- MethodVisitor
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private class MyMethodVisitor extends MethodVisitor {
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public MyMethodVisitor() {
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                super(Opcodes.ASM4);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public AnnotationVisitor visitAnnotationDefault() {
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MyAnnotationVisitor();
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitCode() {
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // field instruction
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitFieldInsn(int opcode, String owner, String name, String desc) {
5304a0f93bd32b8dd9b3c351680ad82e461d5111f38Deepanshu Gupta                // owner is the class that declares the field.
5314a0f93bd32b8dd9b3c351680ad82e461d5111f38Deepanshu Gupta                considerName(owner);
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the field's descriptor (see Type).
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitIincInsn(int var, int increment) {
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- an IINC instruction
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitInsn(int opcode) {
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a zero operand instruction
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitIntInsn(int opcode, int operand) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a single int operand instruction
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitJumpInsn(int opcode, Label label) {
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a jump instruction
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitLabel(Label label) {
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a label target
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // instruction to load a constant from the stack
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitLdcInsn(Object cst) {
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (cst instanceof Type) {
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerType((Type) cst);
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitLineNumber(int line, Label start) {
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitLocalVariable(String name, String desc,
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String signature, Label start, Label end, int index) {
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the type descriptor of this local variable.
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // signature is the type signature of this local variable. May be null if the local
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // variable type does not use generic types.
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerSignature(signature);
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a lookup switch instruction
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitMaxs(int maxStack, int maxLocals) {
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // instruction that invokes a method
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitMethodInsn(int opcode, String owner, String name, String desc) {
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // owner is the internal name of the method's owner class
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!considerDesc(owner) && owner.indexOf('/') != -1) {
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerName(owner);
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the method's descriptor (see Type).
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // instruction multianewarray, whatever that is
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitMultiANewArrayInsn(String desc, int dims) {
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc an array type descriptor.
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    boolean visible) {
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the class descriptor of the annotation class.
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MyAnnotationVisitor();
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- table switch instruction
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // type is the internal name of the type of exceptions handled by the handler,
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // or null to catch any exceptions (for "finally" blocks).
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerName(type);
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // type instruction
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitTypeInsn(int opcode, String type) {
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // type is the operand of the instruction to be visited. This operand must be the
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // internal name of an object or array class.
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerName(type);
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitVarInsn(int opcode, int var) {
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- local variable instruction
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private class MySignatureVisitor extends SignatureVisitor {
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public MySignatureVisitor() {
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                super(Opcodes.ASM4);
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // ---------------------------------------------------
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // --- SignatureVisitor
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // ---------------------------------------------------
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            private String mCurrentSignatureClass = null;
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Starts the visit of a signature corresponding to a class or interface type
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitClassType(String name) {
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mCurrentSignatureClass = name;
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerName(name);
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Visits an inner class
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitInnerClassType(String name) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mCurrentSignatureClass != null) {
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mCurrentSignatureClass += "$" + name;
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerName(mCurrentSignatureClass);
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitArrayType() {
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitBaseType(char descriptor) {
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass -- a primitive type, ignored
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitClassBound() {
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitExceptionType() {
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitFormalTypeParameter(String name) {
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitInterface() {
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitInterfaceBound() {
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitParameterType() {
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitReturnType() {
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitSuperclass() {
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public SignatureVisitor visitTypeArgument(char wildcard) {
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MySignatureVisitor();
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitTypeVariable(String name) {
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitTypeArgument() {
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // pass
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // --- AnnotationVisitor
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // ---------------------------------------------------
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        private class MyAnnotationVisitor extends AnnotationVisitor {
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public MyAnnotationVisitor() {
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                super(Opcodes.ASM4);
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Visits a primitive value of an annotation
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visit(String name, Object value) {
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // value is the actual value, whose type must be Byte, Boolean, Character, Short,
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Integer, Long, Float, Double, String or Type
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (value instanceof Type) {
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    considerType((Type) value);
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public AnnotationVisitor visitAnnotation(String name, String desc) {
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the class descriptor of the nested annotation class.
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MyAnnotationVisitor();
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public AnnotationVisitor visitArray(String name) {
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return new MyAnnotationVisitor();
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void visitEnum(String name, String desc, String value) {
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // desc is the class descriptor of the enumeration class.
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                considerDesc(desc);
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
789