javacompiler.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,491 行 · 第 1/4 页
JAVA
1,491 行
public boolean verbose; /** Emit plain Java source files rather than class files. */ public boolean sourceOutput; /** Emit stub source files rather than class files. */ public boolean stubOutput; /** Generate attributed parse tree only. */ public boolean attrParseOnly; /** Switch: relax some constraints for producing the jsr14 prototype. */ boolean relax; /** Debug switch: Emit Java sources after inner class flattening. */ public boolean printFlat; /** The encoding to be used for source input. */ public String encoding; /** Generate code with the LineNumberTable attribute for debugging */ public boolean lineDebugInfo; /** Switch: should we store the ending positions? */ public boolean genEndPos; /** Switch: should we debug ignored exceptions */ protected boolean devVerbose; /** Switch: should we (annotation) process packages as well */ protected boolean processPcks; /** Switch: is annotation processing requested explitly via * CompilationTask.setProcessors? */ protected boolean explicitAnnotationProcessingRequested = false; /** * The policy for the order in which to perform the compilation */ protected CompilePolicy compilePolicy; /** * The policy for what to do with implicitly read source files */ protected ImplicitSourcePolicy implicitSourcePolicy; /** * Report activity related to compilePolicy */ public boolean verboseCompilePolicy; /** A queue of all as yet unattributed classes. */ public Todo todo; private Set<Env<AttrContext>> deferredSugar = new HashSet<Env<AttrContext>>(); /** The set of currently compiled inputfiles, needed to ensure * we don't accidentally overwrite an input file when -s is set. * initialized by `compile'. */ protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>(); /** The number of errors reported so far. */ public int errorCount() { if (delegateCompiler != null && delegateCompiler != this) return delegateCompiler.errorCount(); else return log.nerrors; } protected final <T> List<T> stopIfError(ListBuffer<T> listBuffer) { if (errorCount() == 0) return listBuffer.toList(); else return List.nil(); } protected final <T> List<T> stopIfError(List<T> list) { if (errorCount() == 0) return list; else return List.nil(); } /** The number of warnings reported so far. */ public int warningCount() { if (delegateCompiler != null && delegateCompiler != this) return delegateCompiler.warningCount(); else return log.nwarnings; } /** Whether or not any parse errors have occurred. */ public boolean parseErrors() { return parseErrors; } protected Scanner.Factory getScannerFactory() { return Scanner.Factory.instance(context); } /** Try to open input stream with given name. * Report an error if this fails. * @param filename The file name of the input stream to be opened. */ public CharSequence readSource(JavaFileObject filename) { try { inputFiles.add(filename); return filename.getCharContent(false); } catch (IOException e) { log.error("error.reading.file", filename, e.getLocalizedMessage()); return null; } } /** Parse contents of input stream. * @param filename The name of the file from which input stream comes. * @param input The input stream to be parsed. */ protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) { long msec = now(); JCCompilationUnit tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); if (content != null) { if (verbose) { printVerbose("parsing.started", filename); } if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); } int initialErrorCount = log.nerrors; Scanner scanner = getScannerFactory().newScanner(content); Parser parser = parserFactory.newParser(scanner, keepComments(), genEndPos); tree = parser.compilationUnit(); parseErrors |= (log.nerrors > initialErrorCount); if (lineDebugInfo) { tree.lineMap = scanner.getLineMap(); } if (verbose) { printVerbose("parsing.done", Long.toString(elapsed(msec))); } } tree.sourcefile = filename; if (content != null && taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree); taskListener.finished(e); } return tree; } // where public boolean keepComments = false; protected boolean keepComments() { return keepComments || sourceOutput || stubOutput; } /** Parse contents of file. * @param filename The name of the file to be parsed. */ @Deprecated public JCTree.JCCompilationUnit parse(String filename) throws IOException { JavacFileManager fm = (JavacFileManager)fileManager; return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next()); } /** Parse contents of file. * @param filename The name of the file to be parsed. */ public JCTree.JCCompilationUnit parse(JavaFileObject filename) { JavaFileObject prev = log.useSource(filename); try { JCTree.JCCompilationUnit t = parse(filename, readSource(filename)); if (t.endPositions != null) log.setEndPosTable(filename, t.endPositions); return t; } finally { log.useSource(prev); } } /** Resolve an identifier. * @param name The identifier to resolve */ public Symbol resolveIdent(String name) { if (name.equals("")) return syms.errSymbol; JavaFileObject prev = log.useSource(null); try { JCExpression tree = null; for (String s : name.split("\\.", -1)) { if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords return syms.errSymbol; tree = (tree == null) ? make.Ident(names.fromString(s)) : make.Select(tree, names.fromString(s)); } JCCompilationUnit toplevel = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); toplevel.packge = syms.unnamedPackage; return attr.attribIdent(tree, toplevel); } finally { log.useSource(prev); } } /** Emit plain Java source for a class. * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); return null; } else { BufferedWriter out = new BufferedWriter(outFile.openWriter()); try { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) printVerbose("wrote.file", outFile); } finally { out.close(); } return outFile; } } /** Generate code and emit a class file for a given class * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition from which code is generated. */ JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException { try { if (gen.genClass(env, cdef)) return writer.writeClass(cdef.sym); } catch (ClassWriter.PoolOverflow ex) { log.error(cdef.pos(), "limit.pool"); } catch (ClassWriter.StringOverflow ex) { log.error(cdef.pos(), "limit.string.overflow", ex.value.substring(0, 20)); } catch (CompletionFailure ex) { chk.completionError(cdef.pos(), ex); } return null; } /** Complete compiling a source file that has been accessed * by the class file reader. * @param c The class the source file of which needs to be compiled. * @param filename The name of the source file. * @param f An input stream that reads the source file. */ public void complete(ClassSymbol c) throws CompletionFailure {// System.err.println("completing " + c);//DEBUG if (completionFailureName == c.fullname) { throw new CompletionFailure(c, "user-selected completion failure by class name"); } JCCompilationUnit tree; JavaFileObject filename = c.classfile; JavaFileObject prev = log.useSource(filename); try { tree = parse(filename, filename.getCharContent(false)); } catch (IOException e) { log.error("error.reading.file", filename, e); tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); } finally { log.useSource(prev); } if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); taskListener.started(e); } enter.complete(List.of(tree), c); if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); taskListener.finished(e); } if (enter.getEnv(c) == null) { boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); if (isPkgInfo) { if (enter.getEnv(tree.packge) == null) { String msg = log.getLocalizedString("file.does.not.contain.package", c.location()); throw new ClassReader.BadClassFile(c, filename, msg); } } else { throw new ClassReader.BadClassFile(c, filename, log. getLocalizedString("file.doesnt.contain.class", c.fullname)); } } implicitSourceFilesRead = true; } /** Track when the JavaCompiler has been used to compile something. */ private boolean hasBeenUsed = false; private long start_msec = 0; public long elapsed_msec = 0; /** Track whether any errors occurred while parsing source text. */ private boolean parseErrors = false; public void compile(List<JavaFileObject> sourceFileObject) throws Throwable { compile(sourceFileObject, List.<String>nil(), null); } /** * Main method: compile a list of files, return all compiled classes * * @param sourceFileObjects file objects to be compiled * @param classnames class names to process for annotations * @param processors user provided annotation processors to bypass * discovery, {@code null} means that no processors were provided */ public void compile(List<JavaFileObject> sourceFileObjects, List<String> classnames, Iterable<? extends Processor> processors) throws IOException // TODO: temp, from JavacProcessingEnvironment { if (processors != null && processors.iterator().hasNext()) explicitAnnotationProcessingRequested = true; // as a JavaCompiler can only be used once, throw an exception if // it has been used before. if (hasBeenUsed) throw new AssertionError("attempt to reuse JavaCompiler"); hasBeenUsed = true; start_msec = now(); try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations(enterTrees(stopIfError(parseFiles(sourceFileObjects))), classnames); delegateCompiler.compile2(); delegateCompiler.close(); elapsed_msec = delegateCompiler.elapsed_msec;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?