Mercurial > hg > openjdk > jdk6 > langtools
changeset 101:08e8b05e3770
6813059: replace use of JavaCompiler.errorCount with shouldContinue
Reviewed-by: mcimadamore
author | jjg |
---|---|
date | Tue, 31 Mar 2009 11:16:15 -0700 |
parents | e8cf1a74be06 |
children | e7e6982abb38 |
files | src/share/classes/com/sun/tools/javac/main/JavaCompiler.java test/tools/javac/policy/test3/A.java test/tools/javac/policy/test3/Test.java |
diffstat | 3 files changed, 253 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Jun 18 17:00:50 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Mar 31 11:16:15 2009 -0700 @@ -379,6 +379,11 @@ (options.get("failcomplete") != null) ? names.fromString(options.get("failcomplete")) : null; + + shouldStopPolicy = + (options.get("shouldStopPolicy") != null) + ? CompileState.valueOf(options.get("shouldStopPolicy")) + : null; } /* Switches: @@ -448,14 +453,26 @@ */ public boolean verboseCompilePolicy; + /** + * Policy of how far to continue processing. null means until first + * error. + */ + public CompileState shouldStopPolicy; + /** A queue of all as yet unattributed classes. */ public Todo todo; + /** Ordered list of compiler phases for each compilation unit. */ protected enum CompileState { - TODO(0), - ATTR(1), - FLOW(2); + PARSE(1), + ENTER(2), + PROCESS(3), + ATTR(4), + FLOW(5), + TRANSTYPES(6), + LOWER(7), + GENERATE(8); CompileState(int value) { this.value = value; } @@ -464,6 +481,9 @@ } private int value; }; + /** Partial map to record which compiler phases have been executed + * for each compilation unit. Used for ATTR and FLOW phases. + */ protected class CompileStates extends HashMap<Env<AttrContext>,CompileState> { boolean isDone(Env<AttrContext> env, CompileState cs) { CompileState ecs = get(env); @@ -478,6 +498,13 @@ */ protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>(); + protected boolean shouldStop(CompileState cs) { + if (shouldStopPolicy == null) + return (errorCount() > 0); + else + return cs.ordinal() > shouldStopPolicy.ordinal(); + } + /** The number of errors reported so far. */ public int errorCount() { @@ -487,18 +514,12 @@ return log.nerrors; } - protected final <T> Queue<T> stopIfError(Queue<T> queue) { - if (errorCount() == 0) - return queue; - else - return ListBuffer.lb(); + protected final <T> Queue<T> stopIfError(CompileState cs, Queue<T> queue) { + return shouldStop(cs) ? ListBuffer.<T>lb() : queue; } - protected final <T> List<T> stopIfError(List<T> list) { - if (errorCount() == 0) - return list; - else - return List.nil(); + protected final <T> List<T> stopIfError(CompileState cs, List<T> list) { + return shouldStop(cs) ? List.<T>nil() : list; } /** The number of warnings reported so far. @@ -655,7 +676,7 @@ */ JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException { try { - if (gen.genClass(env, cdef)) + if (gen.genClass(env, cdef) && (errorCount() == 0)) return writer.writeClass(cdef.sym); } catch (ClassWriter.PoolOverflow ex) { log.error(cdef.pos(), "limit.pool"); @@ -762,8 +783,10 @@ initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks - delegateCompiler = processAnnotations(enterTrees(stopIfError(parseFiles(sourceFileObjects))), - classnames); + delegateCompiler = + processAnnotations( + enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), + classnames); delegateCompiler.compile2(); delegateCompiler.close(); @@ -798,7 +821,7 @@ case BY_FILE: { Queue<Queue<Env<AttrContext>>> q = todo.groupByFile(); - while (!q.isEmpty() && errorCount() == 0) { + while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) { generate(desugar(flow(attribute(q.remove())))); } } @@ -836,7 +859,7 @@ * Parses a list of files. */ public List<JCCompilationUnit> parseFiles(List<JavaFileObject> fileObjects) throws IOException { - if (errorCount() > 0) + if (shouldStop(CompileState.PARSE)) return List.nil(); //parse all files @@ -949,7 +972,7 @@ public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, List<String> classnames) throws IOException { // TODO: see TEMP note in JavacProcessingEnvironment - if (errorCount() != 0) { + if (shouldStop(CompileState.PROCESS)) { // 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 @@ -1060,7 +1083,7 @@ ListBuffer<Env<AttrContext>> results = lb(); while (!envs.isEmpty()) results.append(attribute(envs.remove())); - return results; + return stopIfError(CompileState.ATTR, results); } /** @@ -1107,7 +1130,7 @@ for (Env<AttrContext> env: envs) { flow(env, results); } - return stopIfError(results); + return stopIfError(CompileState.FLOW, results); } /** @@ -1116,7 +1139,7 @@ public Queue<Env<AttrContext>> flow(Env<AttrContext> env) { ListBuffer<Env<AttrContext>> results = lb(); flow(env, results); - return stopIfError(results); + return stopIfError(CompileState.FLOW, results); } /** @@ -1124,7 +1147,7 @@ */ protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) { try { - if (errorCount() > 0) + if (shouldStop(CompileState.FLOW)) return; if (relax || compileStates.isDone(env, CompileState.FLOW)) { @@ -1133,7 +1156,7 @@ } if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[flow " + env.enclClass.sym + "]"); + printNote("[flow " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource( env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : @@ -1144,7 +1167,7 @@ flow.analyzeTree(env.tree, localMake); compileStates.put(env, CompileState.FLOW); - if (errorCount() > 0) + if (shouldStop(CompileState.FLOW)) return; results.add(env); @@ -1171,7 +1194,7 @@ ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = lb(); for (Env<AttrContext> env: envs) desugar(env, results); - return stopIfError(results); + return stopIfError(CompileState.FLOW, results); } /** @@ -1181,7 +1204,7 @@ * The preparation stops as soon as an error is found. */ protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) { - if (errorCount() > 0) + if (shouldStop(CompileState.TRANSTYPES)) return; if (implicitSourcePolicy == ImplicitSourcePolicy.NONE @@ -1196,6 +1219,7 @@ */ class ScanNested extends TreeScanner { Set<Env<AttrContext>> dependencies = new LinkedHashSet<Env<AttrContext>>(); + @Override public void visitClassDef(JCClassDecl node) { Type st = types.supertype(node.sym.type); if (st.tag == TypeTags.CLASS) { @@ -1218,11 +1242,11 @@ //We need to check for error another time as more classes might //have been attributed and analyzed at this stage - if (errorCount() > 0) + if (shouldStop(CompileState.TRANSTYPES)) return; if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]"); + printNote("[desugar " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : @@ -1236,6 +1260,8 @@ if (env.tree instanceof JCCompilationUnit) { if (!(stubOutput || sourceOutput || printFlat)) { + if (shouldStop(CompileState.LOWER)) + return; List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake); if (pdef.head != null) { assert pdef.tail.isEmpty(); @@ -1258,9 +1284,12 @@ return; } + if (shouldStop(CompileState.TRANSTYPES)) + return; + env.tree = transTypes.translateTopLevelClass(env.tree, localMake); - if (errorCount() != 0) + if (shouldStop(CompileState.LOWER)) return; if (sourceOutput) { @@ -1277,7 +1306,7 @@ //translate out inner classes List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake); - if (errorCount() != 0) + if (shouldStop(CompileState.LOWER)) return; //generate code for each class @@ -1302,6 +1331,9 @@ } public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) { + if (shouldStop(CompileState.GENERATE)) + return; + boolean usePrintSource = (stubOutput || sourceOutput || printFlat); for (Pair<Env<AttrContext>, JCClassDecl> x: queue) { @@ -1309,7 +1341,7 @@ JCClassDecl cdef = x.snd; if (verboseCompilePolicy) { - log.printLines(log.noticeWriter, "[generate " + printNote("[generate " + (usePrintSource ? " source" : "code") + " " + cdef.sym + "]"); } @@ -1363,6 +1395,7 @@ JCClassDecl removeMethodBodies(JCClassDecl cdef) { final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0; class MethodBodyRemover extends TreeTranslator { + @Override public void visitMethodDef(JCMethodDecl tree) { tree.mods.flags &= ~Flags.SYNCHRONIZED; for (JCVariableDecl vd : tree.params) @@ -1370,11 +1403,13 @@ tree.body = null; super.visitMethodDef(tree); } + @Override public void visitVarDef(JCVariableDecl tree) { if (tree.init != null && tree.init.type.constValue() == null) tree.init = null; super.visitVarDef(tree); } + @Override public void visitClassDef(JCClassDecl tree) { ListBuffer<JCTree> newdefs = lb(); for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) { @@ -1461,12 +1496,16 @@ } } + protected void printNote(String lines) { + Log.printLines(log.noticeWriter, lines); + } + /** Output for "-verbose" option. * @param key The key to look up the correct internationalized string. * @param arg An argument for substitution into the output string. */ protected void printVerbose(String key, Object arg) { - Log.printLines(log.noticeWriter, log.getLocalizedString("verbose." + key, arg)); + Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg)); } /** Print numbers of errors and warnings. @@ -1475,9 +1514,9 @@ if (count != 0) { String text; if (count == 1) - text = log.getLocalizedString("count." + kind, String.valueOf(count)); + text = Log.getLocalizedString("count." + kind, String.valueOf(count)); else - text = log.getLocalizedString("count." + kind + ".plural", String.valueOf(count)); + text = Log.getLocalizedString("count." + kind + ".plural", String.valueOf(count)); Log.printLines(log.errWriter, text); log.errWriter.flush(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/policy/test3/A.java Tue Mar 31 11:16:15 2009 -0700 @@ -0,0 +1,10 @@ +class A { + void m1() { + System.err.println("hello"); + 0 // syntax error + System.err.println("world"); + } + + void m2() { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/policy/test3/Test.java Tue Mar 31 11:16:15 2009 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright 2009 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. + * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* @test + * @bug 6813059 + * @summary + */ + +import java.io.*; +import java.util.*; + +// Simple test of -XDshouldStopPolicy. +// For each of the permissable values, we compile a file with an error in it, +// then using -XDverboseCompilePolicy we check that the compilation gets as +// far as expected, but no further. + +public class Test { + enum ShouldStopPolicy { + BLANK(false, null, "attr"), + PROCESS(true, null, "attr"), + ATTR(true, "attr", "flow"), + FLOW(true, "flow", "desugar"), + TRANSTYPES(true, "desugar", "generate"), + LOWER(true, "desugar", "generate"), + GENERATE(true, "generate", null); + ShouldStopPolicy(boolean needOption, String expect, String dontExpect) { + this.needOption = needOption; + this.expect = expect; + this.dontExpect = dontExpect; + } + boolean needOption; + String expect; + String dontExpect; + } + + enum CompilePolicy { + BYFILE, + BYTODO + } + + public static void main(String... args) throws Exception { + new Test().run(); + } + + public void run() throws Exception { + for (CompilePolicy cp: CompilePolicy.values()) { + for (ShouldStopPolicy ssp: ShouldStopPolicy.values()) { + test(cp, ssp); + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + public void test(CompilePolicy cp, ShouldStopPolicy ssp) { + System.err.println(); + System.err.println("test " + cp + " " + ssp); + List<String> args = new ArrayList<String>(); + args.add("-XDverboseCompilePolicy"); + args.add("-XDcompilePolicy=" + cp.toString().toLowerCase()); + args.add("-d"); + args.add("."); + if (ssp.needOption) + args.add("-XDshouldStopPolicy=" + ssp); + args.add(new File(System.getProperty("test.src", "."), "A.java").getPath()); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + System.err.println("compile " + args); + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + if (rc == 0) + throw new Error("compilation succeeded unexpectedly"); + //System.err.println(sw); + + // The following is a workaround for the current javac implementation, + // that in bytodo mode, it will still attribute files after syntax errors. + // Changing that behavior may surprise existing users, so for now, we + // work around it. + if (cp == CompilePolicy.BYTODO && ssp == ShouldStopPolicy.PROCESS) + ssp = ShouldStopPolicy.ATTR; + + boolean foundExpected = (ssp.expect == null); + String[] lines = sw.toString().split("\n"); + for (String line: lines) { + if (ssp.expect != null && line.startsWith("[" + ssp.expect)) + foundExpected = true; + if (ssp.dontExpect != null && line.startsWith("[" + ssp.dontExpect)) { + error("Unexpected output: " + ssp.dontExpect + "\n" + sw); + return; + } + } + + if (!foundExpected) + error("Expected output not found: " + ssp.expect + "\n" + sw); + } + + void error(String message) { + System.err.println(message); + errors++; + } + + int errors; +} + + + + + + + + + + + + +// These tests test the ability of the compiler to continue in the face of +// errors, accordining to the shouldStopPolicy + +/* @ test /nodynamiccopyright/ + * @bug 6813059 + * @summary + * @compile/fail/ref=flow.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=FLOW Test.java + + * @compile/fail/ref=default.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy Test.java + * @compile/fail/ref=enter.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=ENTER Test.java + * @compile/fail/ref=attr.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=ATTR Test.java + * @compile/fail/ref=transtypes.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=TRANSTYPES Test.java + * @compile/fail/ref=lower.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=LOWER Test.java + * @compile/fail/ref=generate.out -XDrawDiagnostics -XDcompilePolicy=byfile -XDverboseCompilePolicy -XDshouldStopPolicy=GENERATE Test.java + */ + +/* +class Test { + void m1() { + System.err.println("hello"); + 0 // syntax error + System.err.println("world"); + } + + void m2() { + } +} + +class Test2 { +} +*/ +