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); } }
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); } }