javacompiler.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,491 行 · 第 1/4 页
JAVA
1,491 行
} catch (Abort ex) { if (devVerbose) ex.printStackTrace(); } } /** * The phases following annotation processing: attribution, * desugar, and finally code generation. */ private void compile2() { try { switch (compilePolicy) { case ATTR_ONLY: attribute(todo); break; case CHECK_ONLY: flow(attribute(todo)); break; case SIMPLE: generate(desugar(flow(attribute(todo)))); break; case BY_FILE: for (List<Env<AttrContext>> list : groupByFile(flow(attribute(todo))).values()) generate(desugar(list)); break; case BY_TODO: while (todo.nonEmpty()) generate(desugar(flow(attribute(todo.next())))); break; default: assert false: "unknown compile policy"; } } catch (Abort ex) { if (devVerbose) ex.printStackTrace(); } if (verbose) { elapsed_msec = elapsed(start_msec);; printVerbose("total", Long.toString(elapsed_msec)); } reportDeferredDiagnostics(); if (!log.hasDiagnosticListener()) { printCount("error", errorCount()); printCount("warn", warningCount()); } } private List<JCClassDecl> rootClasses; /** * Parses a list of files. */ public List<JCCompilationUnit> parseFiles(List<JavaFileObject> fileObjects) throws IOException { if (errorCount() > 0) return List.nil(); //parse all files ListBuffer<JCCompilationUnit> trees = lb(); for (JavaFileObject fileObject : fileObjects) trees.append(parse(fileObject)); return trees.toList(); } /** * Enter the symbols found in a list of parse trees. * As a side-effect, this puts elements on the "todo" list. * Also stores a list of all top level classes in rootClasses. */ public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) { //enter symbols for all files if (taskListener != null) { for (JCCompilationUnit unit: roots) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit); taskListener.started(e); } } enter.main(roots); if (taskListener != null) { for (JCCompilationUnit unit: roots) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit); taskListener.finished(e); } } //If generating source, remember the classes declared in //the original compilation units listed on the command line. if (sourceOutput || stubOutput) { ListBuffer<JCClassDecl> cdefs = lb(); for (JCCompilationUnit unit : roots) { for (List<JCTree> defs = unit.defs; defs.nonEmpty(); defs = defs.tail) { if (defs.head instanceof JCClassDecl) cdefs.append((JCClassDecl)defs.head); } } rootClasses = cdefs.toList(); } return roots; } /** * Set to true to enable skeleton annotation processing code. * Currently, we assume this variable will be replaced more * advanced logic to figure out if annotation processing is * needed. */ boolean processAnnotations = false; /** * Object to handle annotation processing. */ JavacProcessingEnvironment procEnvImpl = null; /** * Check if we should process annotations. * If so, and if no scanner is yet registered, then set up the DocCommentScanner * to catch doc comments, and set keepComments so the parser records them in * the compilation unit. * * @param processors user provided annotation processors to bypass * discovery, {@code null} means that no processors were provided */ public void initProcessAnnotations(Iterable<? extends Processor> processors) { // Process annotations if processing is not disabled and there // is at least one Processor available. Options options = Options.instance(context); if (options.get("-proc:none") != null) { processAnnotations = false; } else if (procEnvImpl == null) { procEnvImpl = new JavacProcessingEnvironment(context, processors); processAnnotations = procEnvImpl.atLeastOneProcessor(); if (processAnnotations) { if (context.get(Scanner.Factory.scannerFactoryKey) == null) DocCommentScanner.Factory.preRegister(context); options.put("save-parameter-names", "save-parameter-names"); reader.saveParameterNames = true; keepComments = true; if (taskListener != null) taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); } else { // free resources procEnvImpl.close(); } } } // TODO: called by JavacTaskImpl public JavaCompiler processAnnotations(List<JCCompilationUnit> roots) throws IOException { return processAnnotations(roots, List.<String>nil()); } /** * Process any anotations found in the specifed compilation units. * @param roots a list of compilation units * @return an instance of the compiler in which to complete the compilation */ public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, List<String> classnames) throws IOException { // TODO: see TEMP note in JavacProcessingEnvironment if (errorCount() != 0) { // Errors were encountered. If todo is empty, then the // encountered errors were parse errors. Otherwise, the // errors were found during the enter phase which should // be ignored when processing annotations. if (todo.isEmpty()) return this; } // ASSERT: processAnnotations and procEnvImpl should have been set up by // by initProcessAnnotations // NOTE: The !classnames.isEmpty() checks should be refactored to Main. if (!processAnnotations) { // If there are no annotation processors present, and // annotation processing is to occur with compilation, // emit a warning. Options options = Options.instance(context); if (options.get("-proc:only") != null) { log.warning("proc.proc-only.requested.no.procs"); todo.clear(); } // If not processing annotations, classnames must be empty if (!classnames.isEmpty()) { log.error("proc.no.explicit.annotation.processing.requested", classnames); } return this; // continue regular compilation } try { List<ClassSymbol> classSymbols = List.nil(); List<PackageSymbol> pckSymbols = List.nil(); if (!classnames.isEmpty()) { // Check for explicit request for annotation // processing if (!explicitAnnotationProcessingRequested()) { log.error("proc.no.explicit.annotation.processing.requested", classnames); return this; // TODO: Will this halt compilation? } else { boolean errors = false; for (String nameStr : classnames) { Symbol sym = resolveIdent(nameStr); if (sym == null || (sym.kind == Kinds.PCK && !processPcks)) { log.error("proc.cant.find.class", nameStr); errors = true; continue; } try { if (sym.kind == Kinds.PCK) sym.complete(); if (sym.exists()) { Name name = names.fromString(nameStr); if (sym.kind == Kinds.PCK) pckSymbols = pckSymbols.prepend((PackageSymbol)sym); else classSymbols = classSymbols.prepend((ClassSymbol)sym); continue; } assert sym.kind == Kinds.PCK; log.warning("proc.package.does.not.exist", nameStr); pckSymbols = pckSymbols.prepend((PackageSymbol)sym); } catch (CompletionFailure e) { log.error("proc.cant.find.class", nameStr); errors = true; continue; } } if (errors) return this; } } JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols); if (c != this) annotationProcessingOccurred = c.annotationProcessingOccurred = true; return c; } catch (CompletionFailure ex) { log.error("cant.access", ex.sym, ex.errmsg); return this; } } boolean explicitAnnotationProcessingRequested() { Options options = Options.instance(context); return explicitAnnotationProcessingRequested || options.get("-processor") != null || options.get("-processorpath") != null || options.get("-proc:only") != null || options.get("-Xprint") != null; } /** * Attribute a list of parse trees, such as found on the "todo" list. * Note that attributing classes may cause additional files to be * parsed and entered via the SourceCompleter. * Attribution of the entries in the list does not stop if any errors occur. * @returns a list of environments for attributd classes. */ public List<Env<AttrContext>> attribute(ListBuffer<Env<AttrContext>> envs) { ListBuffer<Env<AttrContext>> results = lb(); while (envs.nonEmpty()) results.append(attribute(envs.next())); return results.toList(); } /** * Attribute a parse tree. * @returns the attributed parse tree */ public Env<AttrContext> attribute(Env<AttrContext> env) { if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); if (verbose) printVerbose("checking.attribution", env.enclClass.sym); if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym); taskListener.started(e); } JavaFileObject prev = log.useSource( env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : env.toplevel.sourcefile); try { attr.attribClass(env.tree.pos(), env.enclClass.sym); } finally { log.useSource(prev); } return env; } /** * Perform dataflow checks on attributed parse trees. * These include checks for definite assignment and unreachable statements. * If any errors occur, an empty list will be returned. * @returns the list of attributed parse trees */ public List<Env<AttrContext>> flow(List<Env<AttrContext>> envs) { ListBuffer<Env<AttrContext>> results = lb(); for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail) { flow(l.head, results); } return stopIfError(results); } /** * Perform dataflow checks on an attributed parse tree. */ public List<Env<AttrContext>> flow(Env<AttrContext> env) { ListBuffer<Env<AttrContext>> results = lb(); flow(env, results); return stopIfError(results); } /** * Perform dataflow checks on an attributed parse tree. */ protected void flow(Env<AttrContext> env, ListBuffer<Env<AttrContext>> results) { try { if (errorCount() > 0) return; if (relax || deferredSugar.contains(env)) { results.append(env); return; } if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[flow " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource( env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : env.toplevel.sourcefile); try { make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); flow.analyzeTree(env.tree, localMake); if (errorCount() > 0) return; results.append(env); } finally { log.useSource(prev); } } finally { if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym); taskListener.finished(e); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?