14306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll/*
24306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * Copyright (C) 2012 The Android Open Source Project
34306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll *
44306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * Licensed under the Apache License, Version 2.0 (the "License");
54306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * you may not use this file except in compliance with the License.
64306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * You may obtain a copy of the License at
74306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll *
84306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll *      http://www.apache.org/licenses/LICENSE-2.0
94306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll *
104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * Unless required by applicable law or agreed to in writing, software
114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * distributed under the License is distributed on an "AS IS" BASIS,
124306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * See the License for the specific language governing permissions and
144306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * limitations under the License.
154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll */
164306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
174306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollpackage com.android.tools.layoutlib.create;
184306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
194306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport com.android.tools.layoutlib.annotations.VisibleForTesting;
204306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
214306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
224306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.AnnotationVisitor;
234306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.Attribute;
244306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.ClassReader;
254306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.ClassVisitor;
264306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.FieldVisitor;
274306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.Label;
284306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.MethodVisitor;
29bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Mollimport org.objectweb.asm.Opcodes;
304306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.Type;
314306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.signature.SignatureReader;
324306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport org.objectweb.asm.signature.SignatureVisitor;
334306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
344306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.io.IOException;
354306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.ArrayList;
364306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.Enumeration;
374306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.List;
384306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.Map;
394306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.Map.Entry;
404306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.Set;
414306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.TreeMap;
424306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.TreeSet;
434306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.zip.ZipEntry;
444306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollimport java.util.zip.ZipFile;
454306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
464306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll/**
474306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * Analyzes the input JAR using the ASM java bytecode manipulation library
484306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * to list the classes and their dependencies. A "dependency" is a class
494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll * used by another class.
504306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll */
514306096a4351030cab4ea413b5e87460b60a84bfRaphael Mollpublic class DependencyFinder {
524306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
534306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
554306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /** Output logger. */
564306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    private final Log mLog;
574306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
594306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Creates a new analyzer.
604306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     *
614306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @param log The log output.
624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
634306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    public DependencyFinder(Log log) {
644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog = log;
654306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
664306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
684306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Starts the analysis using parameters from the constructor.
694306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     *
704306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @param osJarPath The input source JARs to parse.
714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }.
724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     *                 [1]: map { missing class FQCN => set of FQCN class that uses it. }
734306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException {
754306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
764306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, ClassReader> zipClasses = parseZip(osJarPath);
774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("Found %d classes in input JAR%s.",
784306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                zipClasses.size(),
794306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                osJarPath.size() > 1 ? "s" : "");
804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
814306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> deps = findClassesDeps(zipClasses);
824306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
834306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
844306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2);
864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        result.add(deps);
874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        result.add(missing);
884306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        return result;
894306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
914306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
924306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Prints dependencies to the current logger, found stuff and missing stuff.
934306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
944306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    public void printAllDeps(List<Map<String, Set<String>>> result) {
954306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        assert result.size() == 2;
964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> deps = result.get(0);
974306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> missing = result.get(1);
984306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
994306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // Print all dependences found in the format:
1004306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // +Found: <FQCN from zip>
1014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        //     uses: FQCN
1024306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1034306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("++++++ %d Entries found in source JARs", deps.size());
1044306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("");
1054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1064306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        for (Entry<String, Set<String>> entry : deps.entrySet()) {
1074306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.info(    "+Found  : %s", entry.getKey());
1084306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            for (String dep : entry.getValue()) {
1094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                mLog.info("    uses: %s", dep);
1104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
1114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1124306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.info("");
1134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1144306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1164306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // Now print all missing dependences in the format:
1174306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // -Missing <FQCN>:
1184306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        //     used by: <FQCN>
1194306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1204306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("");
1214306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("------ %d Entries missing from source JARs", missing.size());
1224306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        mLog.info("");
1234306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1244306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        for (Entry<String, Set<String>> entry : missing.entrySet()) {
1254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.info(    "-Missing  : %s", entry.getKey());
1264306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            for (String dep : entry.getValue()) {
1274306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                mLog.info("   used by: %s", dep);
1284306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
1294306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1304306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.info("");
1314306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1324306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
1334306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1344306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
1354306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Prints only a summary of the missing dependencies to the current logger.
1364306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
1374306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    public void printMissingDeps(List<Map<String, Set<String>>> result) {
1384306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        assert result.size() == 2;
1394306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
1404306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> missing = result.get(1);
1414306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1424306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        for (String fqcn : missing.keySet()) {
1434306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.info("%s", fqcn);
1444306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1454306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
1464306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1474306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    // ----------------
1484306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
1504306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Parses a JAR file and returns a list of all classes founds using a map
1514306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * class name => ASM ClassReader. Class names are in the form "android.view.View".
1524306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
1534306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
1544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
1554306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1564306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        for (String jarPath : jarPathList) {
1574306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            ZipFile zip = new ZipFile(jarPath);
1584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            Enumeration<? extends ZipEntry> entries = zip.entries();
1594306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            ZipEntry entry;
1604306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            while (entries.hasMoreElements()) {
1614306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                entry = entries.nextElement();
1624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                if (entry.getName().endsWith(".class")) {
1634306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
1644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    String className = classReaderToClassName(cr);
1654306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    classes.put(className, cr);
1664306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
1674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
1684306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1694306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1704306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        return classes;
1714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
1724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1734306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
1744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Utility that returns the fully qualified binary class name for a ClassReader.
1754306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * E.g. it returns something like android.view.View.
1764306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
1774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    static String classReaderToClassName(ClassReader classReader) {
1784306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        if (classReader == null) {
1794306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            return null;
1804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        } else {
1814306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            return classReader.getClassName().replace('/', '.');
1824306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1834306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
1844306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
1864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Utility that returns the fully qualified binary class name from a path-like FQCN.
1874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * E.g. it returns android.view.View from android/view/View.
1884306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
1894306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    static String internalToBinaryClassName(String className) {
1904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        if (className == null) {
1914306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            return null;
1924306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        } else {
1934306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            return className.replace('/', '.');
1944306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
1954306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
1964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
1974306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
1984306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Finds all dependencies for all classes in keepClasses which are also
1994306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * listed in zipClasses. Returns a map of all the dependencies found.
2004306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
2014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) {
2024306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2034306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // The dependencies that we'll collect.
2044306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // It's a map Class name => uses class names.
2054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>();
2064306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2074306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        DependencyVisitor visitor = getVisitor();
2084306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        int count = 0;
2104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        try {
2114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
2124306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                String name = entry.getKey();
2134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2144306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                TreeSet<String> set = new TreeSet<String>();
2154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                dependencyMap.put(name, set);
2164306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                visitor.setDependencySet(set);
2174306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2184306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                ClassReader cr = entry.getValue();
2194306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                cr.accept(visitor, 0 /* flags */);
2204306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2214306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                visitor.setDependencySet(null);
2224306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2234306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                mLog.debugNoln("Visited %d classes\r", ++count);
2244306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
2254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        } finally {
2264306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mLog.debugNoln("\n");
2274306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
2284306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2294306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        return dependencyMap;
2304306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
2314306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2324306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
2334306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Computes which classes FQCN were found as dependencies that are NOT listed
2344306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * in the original JAR classes.
2354306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     *
2364306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}.
2374306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @param zipClasses The set of all classes FQCN found in the JAR files.
2384306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * @return A map { FQCN not found in the zipClasses => classes using it }
2394306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
2404306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    private Map<String, Set<String>> findMissingClasses(
2414306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            Map<String, Set<String>> deps,
2424306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            Set<String> zipClasses) {
2434306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        Map<String, Set<String>> missing = new TreeMap<String, Set<String>>();
2444306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2454306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        for (Entry<String, Set<String>> entry : deps.entrySet()) {
2464306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            String name = entry.getKey();
2474306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2484306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            for (String dep : entry.getValue()) {
2494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                if (!zipClasses.contains(dep)) {
2504306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    // This dependency doesn't exist in the zip classes.
2514306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    Set<String> set = missing.get(dep);
2524306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    if (set == null) {
2534306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        set = new TreeSet<String>();
2544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        missing.put(dep, set);
2554306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    }
2564306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    set.add(name);
2574306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
2584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
2594306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2604306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
2614306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        return missing;
2634306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
2644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2654306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2664306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    // ----------------------------------
2674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2684306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
2694306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Instantiates a new DependencyVisitor. Useful for unit tests.
2704306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
2714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    @VisibleForTesting(visibility=Visibility.PRIVATE)
2724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    DependencyVisitor getVisitor() {
2734306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        return new DependencyVisitor();
2744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
2754306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2764306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    /**
2774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     * Visitor to collect all the type dependencies from a class.
2784306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll     */
279bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll    public class DependencyVisitor extends ClassVisitor {
2804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2814306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        private Set<String> mCurrentDepSet;
2824306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2834306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
2844306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Creates a new visitor that will find all the dependencies for the visited class.
2854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
2864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public DependencyVisitor() {
287bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            super(Opcodes.ASM4);
2884306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
2894306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
2914306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Sets the {@link Set} where to record direct dependencies for this class.
2924306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call.
2934306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
2944306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void setDependencySet(Set<String> set) {
2954306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            mCurrentDepSet = set;
2964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
2974306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
2984306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
2994306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Considers the given class name as a dependency.
3004306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
3014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void considerName(String className) {
3024306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (className == null) {
3034306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                return;
3044306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3064306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            className = internalToBinaryClassName(className);
3074306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3084306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            try {
3094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                // exclude classes that are part of the default JRE (the one executing this program)
3104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                if (getClass().getClassLoader().loadClass(className) != null) {
3114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    return;
3124306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
3134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            } catch (ClassNotFoundException e) {
3144306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                // ignore
3154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3164306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3174306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // Add it to the dependency set for the currently visited class, as needed.
3184306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            assert mCurrentDepSet != null;
3194306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (mCurrentDepSet != null) {
3204306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                mCurrentDepSet.add(className);
3214306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3224306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
3234306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3244306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
3254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Considers this array of names using considerName().
3264306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
3274306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void considerNames(String[] classNames) {
3284306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (classNames != null) {
3294306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                for (String className : classNames) {
3304306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    considerName(className);
3314306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
3324306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3334306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
3344306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3354306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
3364306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Considers this signature or type signature by invoking the {@link SignatureVisitor}
3374306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * on it.
3384306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
3394306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void considerSignature(String signature) {
3404306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (signature != null) {
3414306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                SignatureReader sr = new SignatureReader(signature);
3424306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                // SignatureReader.accept will call accessType so we don't really have
3434306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                // to differentiate where the signature comes from.
344bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                sr.accept(new MySignatureVisitor());
3454306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3464306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
3474306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3484306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
3494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Considers this {@link Type}. For arrays, the element type is considered.
3504306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * If the type is an object, it's internal name is considered.
3514306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
3524306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void considerType(Type t) {
3534306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (t != null) {
3544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                if (t.getSort() == Type.ARRAY) {
3554306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    t = t.getElementType();
3564306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
3574306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                if (t.getSort() == Type.OBJECT) {
3584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    considerName(t.getInternalName());
3594306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
3604306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3614306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
3624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3634306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        /**
3644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * Considers a descriptor string. The descriptor is converted to a {@link Type}
3654306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         * and then considerType() is invoked.
3664306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll         */
3674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public boolean considerDesc(String desc) {
3684306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (desc != null) {
3694306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                try {
3704306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    if (desc.length() > 0 && desc.charAt(0) == '(') {
3714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        // This is a method descriptor with arguments and a return type.
3724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        Type t = Type.getReturnType(desc);
3734306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        considerType(t);
3744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3754306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        for (Type arg : Type.getArgumentTypes(desc)) {
3764306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                            considerType(arg);
3774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        }
3784306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3794306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    } else {
3804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        Type t = Type.getType(desc);
3814306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                        considerType(t);
3824306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    }
3834306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    return true;
3844306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                } catch (ArrayIndexOutOfBoundsException e) {
3854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                    // ignore, not a valid type.
3864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                }
3874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
3884306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            return false;
3894306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
3904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3914306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3924306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
3934306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // --- ClassVisitor, FieldVisitor
3944306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
3954306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
3964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // Visits a class header
397bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
3984306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visit(int version, int access, String name,
3994306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                String signature, String superName, String[] interfaces) {
4004306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // signature is the signature of this class. May be null if the class is not a generic
4014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // one, and does not extend or implement generic classes or interfaces.
4024306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
4034306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (signature != null) {
4044306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                considerSignature(signature);
4054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
4064306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
4074306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // superName is the internal of name of the super class (see getInternalName).
4084306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // For interfaces, the super class is Object. May be null but only for the Object class.
4094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerName(superName);
4104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
4114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // interfaces is the internal names of the class's interfaces (see getInternalName).
4124306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // May be null.
4134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerNames(interfaces);
4144306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
416bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
417bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4184306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
4194306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // desc is the class descriptor of the annotation class.
4204306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerDesc(desc);
421bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            return new MyAnnotationVisitor();
4224306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4234306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
424bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visitAttribute(Attribute attr) {
4264306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // pass
4274306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4284306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
4294306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // Visits the end of a class
430bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4314306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visitEnd() {
4324306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // pass
4334306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4344306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
435bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        private class MyFieldVisitor extends FieldVisitor {
436bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
437bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public MyFieldVisitor() {
438bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                super(Opcodes.ASM4);
439bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
440bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
441bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
442bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
443bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the class descriptor of the annotation class.
444bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
445bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MyAnnotationVisitor();
446bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
447bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
448bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
449bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitAttribute(Attribute attr) {
450bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
451bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
452bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
453bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // Visits the end of a class
454bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
455bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitEnd() {
456bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
457bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
458bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        }
459bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
460bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4614306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public FieldVisitor visitField(int access, String name, String desc,
4624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                String signature, Object value) {
4634306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // desc is the field's descriptor (see Type).
4644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerDesc(desc);
4654306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
4664306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // signature is the field's signature. May be null if the field's type does not use
4674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // generic types.
4684306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerSignature(signature);
4694306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
470bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            return new MyFieldVisitor();
4714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
473bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visitInnerClass(String name, String outerName, String innerName, int access) {
4754306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // name is the internal name of an inner class (see getInternalName).
4764306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // Note: outerName/innerName seems to be null when we're reading the
4774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // _Original_ClassName classes generated by layoutlib_create.
4784306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            if (outerName != null) {
4794306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                considerName(name);
4804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
4814306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4824306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
483bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4844306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public MethodVisitor visitMethod(int access, String name, String desc,
4854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                String signature, String[] exceptions) {
4864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // desc is the method's descriptor (see Type).
4874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerDesc(desc);
4884306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // signature is the method's signature. May be null if the method parameters, return
4894306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // type and exceptions do not use generic types.
4904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            considerSignature(signature);
4914306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
492bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            return new MyMethodVisitor();
4934306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4944306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
495bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
4964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visitOuterClass(String owner, String name, String desc) {
4974306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // pass
4984306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
4994306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
500bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        @Override
5014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        public void visitSource(String source, String debug) {
5024306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            // pass
5034306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
5044306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
5054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
5064306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
5074306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // --- MethodVisitor
5084306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
5094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
510bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        private class MyMethodVisitor extends MethodVisitor {
5114306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
512bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public MyMethodVisitor() {
513bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                super(Opcodes.ASM4);
514bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
5164306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
517bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
518bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public AnnotationVisitor visitAnnotationDefault() {
519bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MyAnnotationVisitor();
520bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5214306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
522bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
523bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitCode() {
524bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
525bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5264306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
527bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // field instruction
528bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
529bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitFieldInsn(int opcode, String owner, String name, String desc) {
530bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // name is the field's name.
531bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the field's descriptor (see Type).
532bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
533bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5344306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
535bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
536bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
537bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
538bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5394306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
540bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
541bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitIincInsn(int var, int increment) {
542bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- an IINC instruction
543bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5444306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
545bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
546bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitInsn(int opcode) {
547bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a zero operand instruction
548bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
550bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
551bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitIntInsn(int opcode, int operand) {
552bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a single int operand instruction
553bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
555bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
556bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitJumpInsn(int opcode, Label label) {
557bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a jump instruction
5584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
5594306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
560bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
561bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitLabel(Label label) {
562bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a label target
563bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
565bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // instruction to load a constant from the stack
566bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
567bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitLdcInsn(Object cst) {
568bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                if (cst instanceof Type) {
569bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    considerType((Type) cst);
570bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                }
571bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5724306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
573bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
574bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitLineNumber(int line, Label start) {
575bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
576bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5774306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
578bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
579bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitLocalVariable(String name, String desc,
580bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    String signature, Label start, Label end, int index) {
581bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the type descriptor of this local variable.
582bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
583bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // signature is the type signature of this local variable. May be null if the local
584bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // variable type does not use generic types.
585bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerSignature(signature);
586bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
588bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
589bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
590bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a lookup switch instruction
591bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
5924306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
593bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
594bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitMaxs(int maxStack, int maxLocals) {
595bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
5964306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
5974306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
598bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // instruction that invokes a method
599bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
600bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitMethodInsn(int opcode, String owner, String name, String desc) {
6014306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
602bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // owner is the internal name of the method's owner class
603bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                if (!considerDesc(owner) && owner.indexOf('/') != -1) {
604bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    considerName(owner);
605bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                }
606bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the method's descriptor (see Type).
607bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
608bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6094306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
610bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // instruction multianewarray, whatever that is
611bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
612bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitMultiANewArrayInsn(String desc, int dims) {
6134306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
614bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc an array type descriptor.
615bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
616bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6174306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
618bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
619bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
620bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    boolean visible) {
621bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the class descriptor of the annotation class.
622bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
623bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MyAnnotationVisitor();
624bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
626bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
627bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
628bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- table switch instruction
629bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
630bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6314306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
632bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
633bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
634bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // type is the internal name of the type of exceptions handled by the handler,
635bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // or null to catch any exceptions (for "finally" blocks).
6364306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll                considerName(type);
6374306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
6384306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
639bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // type instruction
640bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
641bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitTypeInsn(int opcode, String type) {
642bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // type is the operand of the instruction to be visited. This operand must be the
643bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // internal name of an object or array class.
644bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerName(type);
645bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
646bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
647bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
648bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitVarInsn(int opcode, int var) {
649bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- local variable instruction
650bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6514306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
6524306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
653bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        private class MySignatureVisitor extends SignatureVisitor {
6544306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
655bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public MySignatureVisitor() {
656bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                super(Opcodes.ASM4);
657bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6584306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
659bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // ---------------------------------------------------
660bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // --- SignatureVisitor
661bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // ---------------------------------------------------
6624306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
663bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            private String mCurrentSignatureClass = null;
6644306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
665bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // Starts the visit of a signature corresponding to a class or interface type
666bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
667bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitClassType(String name) {
668bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                mCurrentSignatureClass = name;
669bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerName(name);
6704306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
6714306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
672bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // Visits an inner class
673bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
674bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitInnerClassType(String name) {
675bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                if (mCurrentSignatureClass != null) {
676bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    mCurrentSignatureClass += "$" + name;
677bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    considerName(mCurrentSignatureClass);
678bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                }
679bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6804306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
681bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
682bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitArrayType() {
683bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
684bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
686bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
687bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitBaseType(char descriptor) {
688bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass -- a primitive type, ignored
689bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6904306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
691bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
692bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitClassBound() {
693bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
694bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
6954306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
696bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
697bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitExceptionType() {
698bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
699bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7004306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
701bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
702bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitFormalTypeParameter(String name) {
703bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
704bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7054306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
706bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
707bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitInterface() {
708bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
709bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7104306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
711bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
712bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitInterfaceBound() {
713bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
714bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7154306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
716bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
717bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitParameterType() {
718bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
719bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7204306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
721bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
722bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitReturnType() {
723bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
724bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7254306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
726bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
727bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitSuperclass() {
728bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
729bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7304306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
731bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
732bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public SignatureVisitor visitTypeArgument(char wildcard) {
733bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MySignatureVisitor();
734bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7354306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
736bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
737bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitTypeVariable(String name) {
738bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
739bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
740bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
741bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
742bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitTypeArgument() {
743bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // pass
744bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7454306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
7464306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
7474306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
7484306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
7494306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // --- AnnotationVisitor
7504306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        // ---------------------------------------------------
7514306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
752bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll        private class MyAnnotationVisitor extends AnnotationVisitor {
7534306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
754bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public MyAnnotationVisitor() {
755bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                super(Opcodes.ASM4);
7564306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll            }
7574306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
758bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            // Visits a primitive value of an annotation
759bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
760bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visit(String name, Object value) {
761bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // value is the actual value, whose type must be Byte, Boolean, Character, Short,
762bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // Integer, Long, Float, Double, String or Type
763bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                if (value instanceof Type) {
764bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                    considerType((Type) value);
765bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                }
766bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7674306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
768bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
769bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public AnnotationVisitor visitAnnotation(String name, String desc) {
770bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the class descriptor of the nested annotation class.
771bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
772bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MyAnnotationVisitor();
773bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7744306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll
775bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
776bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public AnnotationVisitor visitArray(String name) {
777bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                return new MyAnnotationVisitor();
778bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
779bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll
780bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            @Override
781bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            public void visitEnum(String name, String desc, String value) {
782bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                // desc is the class descriptor of the enumeration class.
783bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll                considerDesc(desc);
784bce1011dd2a371c587d2e39ad8c3d446b63049d0Raphael Moll            }
7854306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll        }
7864306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll    }
7874306096a4351030cab4ea413b5e87460b60a84bfRaphael Moll}
788