createsymbols.java

来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 496 行 · 第 1/2 页

JAVA
496
字号
/* * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.sym;import com.sun.tools.javac.api.JavacTaskImpl;import com.sun.tools.javac.code.Kinds;import com.sun.tools.javac.code.Scope;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.code.Symbol;import com.sun.tools.javac.code.Attribute;import com.sun.tools.javac.code.Symtab;import com.sun.tools.javac.code.Type;import com.sun.tools.javac.jvm.ClassReader;import com.sun.tools.javac.jvm.ClassWriter;import com.sun.tools.javac.jvm.Pool;import com.sun.tools.javac.processing.JavacProcessingEnvironment;import com.sun.tools.javac.util.List;import com.sun.tools.javac.util.Pair;import com.sun.tools.javac.util.Name;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.EnumSet;import java.util.Enumeration;import java.util.HashSet;import java.util.Properties;import java.util.ResourceBundle;import java.util.Set;import javax.annotation.processing.AbstractProcessor;import javax.annotation.processing.RoundEnvironment;import javax.annotation.processing.SupportedAnnotationTypes;import javax.annotation.processing.SupportedOptions;import javax.lang.model.SourceVersion;import javax.lang.model.element.ElementKind;import javax.lang.model.element.TypeElement;import javax.tools.Diagnostic;import javax.tools.JavaCompiler;import javax.tools.JavaFileManager.Location;import javax.tools.JavaFileObject;import static javax.tools.JavaFileObject.Kind.CLASS;import javax.tools.StandardJavaFileManager;import javax.tools.StandardLocation;import javax.tools.ToolProvider;/** * Used to generate a "symbol file" representing rt.jar that only * includes supported or legacy proprietary API.  Valid annotation * processor options: * * <dl> * <dt>com.sun.tools.javac.sym.Jar</dt> * <dd>Specifies the location of rt.jar.</dd> * <dt>com.sun.tools.javac.sym.Dest</dt> * <dd>Specifies the destination directory.</dd> * </dl> * * <p><b>This is NOT part of any API supported by Sun Microsystems. * If you write code that depends on this, you do so at your own * risk.  This code and its internal interfaces are subject to change * or deletion without notice.</b></p> * * @author Peter von der Ah\u00e9 */@SupportedOptions({"com.sun.tools.javac.sym.Jar","com.sun.tools.javac.sym.Dest"})@SupportedAnnotationTypes("*")public class CreateSymbols extends AbstractProcessor {    static Set<String> getLegacyPackages() {        ResourceBundle legacyBundle            = ResourceBundle.getBundle("com.sun.tools.javac.resources.legacy");        Set<String> keys = new HashSet<String>();        for (Enumeration<String> e = legacyBundle.getKeys(); e.hasMoreElements(); )            keys.add(e.nextElement());        return keys;    }    public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {        try {            if (renv.processingOver())                createSymbols();        } catch (IOException e) {            processingEnv.getMessager()                .printMessage(Diagnostic.Kind.ERROR, e.getLocalizedMessage());        } catch (Throwable t) {            Throwable cause = t.getCause();            if (cause == null)                cause = t;            processingEnv.getMessager()                .printMessage(Diagnostic.Kind.ERROR, cause.getLocalizedMessage());        }        return true;    }    void createSymbols() throws IOException {        Set<String> legacy = getLegacyPackages();        Set<String> legacyProprietary = getLegacyPackages();        Set<String> documented = new HashSet<String>();        Set<PackageSymbol> packages =            ((JavacProcessingEnvironment)processingEnv).getSpecifiedPackages();        String jarName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Jar");        if (jarName == null)            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR");        String destName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Dest");        if (destName == null)            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR");        for (PackageSymbol psym : packages) {            String name = psym.getQualifiedName().toString();            legacyProprietary.remove(name);            documented.add(name);        }        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);        Location jarLocation = StandardLocation.locationFor(jarName);        File jarFile = new File(jarName);        fm.setLocation(jarLocation, List.of(jarFile));        fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil());        fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil());        {            ArrayList<File> bootClassPath = new ArrayList<File>();            bootClassPath.add(jarFile);            for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {                if (!new File(path.getName()).equals(new File("rt.jar")))                    bootClassPath.add(path);            }            System.err.println("Using boot class path = " + bootClassPath);            fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);        }        // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));        File destDir = new File(destName);        if (!destDir.exists())            if (!destDir.mkdirs())                throw new RuntimeException("Could not create " + destDir);        fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir));        Set<String> hiddenPackages = new HashSet<String>();        Set<String> crisp = new HashSet<String>();        List<String> options = List.of("-XDdev");        // options = options.prepend("-doe");        // options = options.prepend("-verbose");        JavacTaskImpl task = (JavacTaskImpl)            tool.getTask(null, fm, null, options, null, null);        com.sun.tools.javac.main.JavaCompiler compiler =            com.sun.tools.javac.main.JavaCompiler.instance(task.getContext());        ClassReader reader = ClassReader.instance(task.getContext());        ClassWriter writer = ClassWriter.instance(task.getContext());        Symtab syms = Symtab.instance(task.getContext());        Attribute.Compound proprietary =            new Attribute.Compound(syms.proprietaryType,                                   List.<Pair<Symbol.MethodSymbol,Attribute>>nil());        Type.moreInfo = true;        Pool pool = new Pool();        for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {            String className = fm.inferBinaryName(jarLocation, file);            int index = className.lastIndexOf('.');            String pckName = index == -1 ? "" : className.substring(0, index);            boolean addLegacyAnnotation = false;            if (documented.contains(pckName)) {                if (!legacy.contains(pckName))                    crisp.add(pckName);                // System.out.println("Documented: " + className);            } else if (legacyProprietary.contains(pckName)) {                addLegacyAnnotation = true;                // System.out.println("Legacy proprietary: " + className);            } else {                // System.out.println("Hidden " + className);                hiddenPackages.add(pckName);                continue;            }            TypeSymbol sym = (TypeSymbol)compiler.resolveIdent(className);            if (sym.kind != Kinds.TYP) {                if (className.indexOf('$') < 0) {                    System.err.println("Ignoring (other) " + className + " : " + sym);                    System.err.println("   " + sym.getClass().getSimpleName() + " " + sym.type);                }                continue;            }            sym.complete();            if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) {                System.err.println("Ignoring (bad) " + sym.getQualifiedName());                continue;            }            ClassSymbol cs = (ClassSymbol) sym;            if (addLegacyAnnotation) {                cs.attributes_field = (cs.attributes_field == null)                    ? List.of(proprietary)                    : cs.attributes_field.prepend(proprietary);            }            writeClass(pool, cs, writer);        }        if (false) {            for (String pckName : crisp)                System.out.println("Crisp: " + pckName);            for (String pckName : hiddenPackages)                System.out.println("Hidden: " + pckName);            for (String pckName : legacyProprietary)                System.out.println("Legacy proprietary: " + pckName);            for (String pckName : documented)                System.out.println("Documented: " + pckName);        }    }    void writeClass(final Pool pool, final ClassSymbol cs, final ClassWriter writer)        throws IOException    {        try {            pool.reset();            cs.pool = pool;            writer.writeClass(cs);            for (Scope.Entry e = cs.members().elems; e != null; e = e.sibling) {                if (e.sym.kind == Kinds.TYP) {                    ClassSymbol nestedClass = (ClassSymbol)e.sym;                    nestedClass.complete();                    writeClass(pool, nestedClass, writer);                }            }        } catch (ClassWriter.StringOverflow ex) {            throw new RuntimeException(ex);        } catch (ClassWriter.PoolOverflow ex) {            throw new RuntimeException(ex);        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?