/** * Generate code corresponding to the given classes. The classes must have previously been * returned from {@link #enter}. If there are classes outstanding to be analyzed, that will be * done before any classes are generated. If null is specified, code will be generated for all * outstanding classes. * * @param classes a list of class elements */ public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) throws IOException { final ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); try { analyze(null); // ensure all classes have been parsed, entered, and analyzed if (classes == null) { compiler.generate(compiler.desugar(genList), results); genList.clear(); } else { Filter f = new Filter() { public void process(Env<AttrContext> env) { compiler.generate(compiler.desugar(ListBuffer.of(env)), results); } }; f.run(genList, classes); } if (genList.isEmpty()) { compiler.reportDeferredDiagnostics(); cleanup(); } } finally { if (compiler != null) compiler.log.flush(); } return results; }
/** * Translate the given abstract syntax trees to elements. * * @param trees a list of abstract syntax trees. * @throws java.io.IOException TODO * @return a list of elements corresponding to the top level classes in the abstract syntax trees */ public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees) throws IOException { prepareCompiler(); ListBuffer<JCCompilationUnit> roots = null; if (trees == null) { // If there are still files which were specified to be compiled // (i.e. in fileObjects) but which have not yet been entered, // then we make sure they have been parsed and add them to the // list to be entered. if (notYetEntered.size() > 0) { if (!parsed) parse(); // TODO would be nice to specify files needed to be parsed for (JavaFileObject file : fileObjects) { JCCompilationUnit unit = notYetEntered.remove(file); if (unit != null) { if (roots == null) roots = new ListBuffer<JCCompilationUnit>(); roots.append(unit); } } notYetEntered.clear(); } } else { for (CompilationUnitTree cu : trees) { if (cu instanceof JCCompilationUnit) { if (roots == null) roots = new ListBuffer<JCCompilationUnit>(); roots.append((JCCompilationUnit) cu); notYetEntered.remove(cu.getSourceFile()); } else throw new IllegalArgumentException(cu.toString()); } } if (roots == null) return List.nil(); try { List<JCCompilationUnit> units = compiler.enterTrees(roots.toList()); if (notYetEntered.isEmpty()) compiler = compiler.processAnnotations(units); ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>(); for (JCCompilationUnit unit : units) { for (JCTree node : unit.defs) { if (node.getTag() == JCTree.CLASSDEF) { JCClassDecl cdef = (JCClassDecl) node; if (cdef.sym != null) // maybe null if errors in anno processing elements.append(cdef.sym); } } } return elements.toList(); } finally { compiler.log.flush(); } }
void cleanup() { if (compiler != null) compiler.close(); compiler = null; compilerMain = null; args = null; classNames = null; context = null; fileObjects = null; notYetEntered = null; }
// This implementation requires that we open up privileges on JavaCompiler. // An alternative implementation would be to move this code to JavaCompiler and // wrap it here public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) throws IOException { enter(null); // ensure all classes have been entered final ListBuffer<Element> results = new ListBuffer<Element>(); try { if (classes == null) { handleFlowResults(compiler.flow(compiler.attribute(compiler.todo)), results); } else { Filter f = new Filter() { public void process(Env<AttrContext> env) { handleFlowResults(compiler.flow(compiler.attribute(env)), results); } }; f.run(compiler.todo, classes); } } finally { compiler.log.flush(); } return results; }
/** * Parse the specified files returning a list of abstract syntax trees. * * @throws java.io.IOException TODO * @return a list of abstract syntax trees */ public Iterable<? extends CompilationUnitTree> parse() throws IOException { try { prepareCompiler(); List<JCCompilationUnit> units = compiler.parseFiles(fileObjects); for (JCCompilationUnit unit : units) { JavaFileObject file = unit.getSourceFile(); if (notYetEntered.containsKey(file)) notYetEntered.put(file, unit); } return units; } finally { parsed = true; if (compiler != null && compiler.log != null) compiler.log.flush(); } }
/** For internal use only. This method will be removed without warning. */ public Type parseType(String expr, TypeElement scope) { if (expr == null || expr.equals("")) throw new IllegalArgumentException(); compiler = JavaCompiler.instance(context); JavaFileObject prev = compiler.log.useSource(null); ParserFactory parserFactory = ParserFactory.instance(context); Attr attr = Attr.instance(context); try { CharBuffer buf = CharBuffer.wrap((expr + "\u0000").toCharArray(), 0, expr.length()); Parser parser = parserFactory.newParser(buf, false, false, false); JCTree tree = parser.parseType(); return attr.attribType(tree, (Symbol.TypeSymbol) scope); } finally { compiler.log.useSource(prev); } }
private void prepareCompiler() throws IOException { if (used.getAndSet(true)) { if (compiler == null) throw new IllegalStateException(); } else { initContext(); compilerMain.setOptions(Options.instance(context)); compilerMain.filenames = new LinkedHashSet<File>(); Collection<File> filenames = compilerMain.processArgs(CommandLine.parse(args), classNames); if (!filenames.isEmpty()) throw new IllegalArgumentException("Malformed arguments " + toString(filenames, " ")); compiler = JavaCompiler.instance(context); compiler.keepComments = true; compiler.genEndPos = true; // NOTE: this value will be updated after annotation processing compiler.initProcessAnnotations(processors); notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>(); for (JavaFileObject file : fileObjects) notYetEntered.put(file, null); genList = new ListBuffer<Env<AttrContext>>(); // endContext will be called when all classes have been generated // TODO: should handle the case after each phase if errors have occurred args = null; classNames = null; } }