aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java9
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java1
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/ReducedClasspathJavaLibraryBuilder.java50
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java40
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavaCompiler.java17
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacArguments.java9
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacMain.java114
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacResult.java64
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/FormattedDiagnostic.java122
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/JavacRunner.java11
10 files changed, 284 insertions, 153 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java
index 607adcd7d1..0fb8456212 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BazelJavaBuilder.java
@@ -16,6 +16,8 @@ package com.google.devtools.build.buildjar;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.buildjar.javac.BlazeJavacResult;
+import com.google.devtools.build.buildjar.javac.FormattedDiagnostic;
import com.google.devtools.build.buildjar.javac.JavacOptions;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
@@ -85,7 +87,12 @@ public abstract class BazelJavaBuilder {
build.getDependencyModule().reduceClasspath()
? new ReducedClasspathJavaLibraryBuilder()
: new SimpleJavaLibraryBuilder()) {
- return builder.run(build, err).exitCode;
+ BlazeJavacResult result = builder.run(build);
+ for (FormattedDiagnostic d : result.diagnostics()) {
+ err.write(d.getFormatted());
+ }
+ err.write(result.output());
+ return result.javacResult().exitCode;
}
} catch (InvalidCommandLineException e) {
err.println(CMDNAME + " threw exception: " + e.getMessage());
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
index df09cf055b..ece6484ba2 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java
@@ -295,6 +295,7 @@ public final class JavaLibraryBuildRequest {
.processors(null)
.sourceOutput(getSourceGenDir() != null ? Paths.get(getSourceGenDir()) : null)
.processorPath(toPaths(getProcessorPath()))
+ .plugins(getPlugins())
.build();
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/ReducedClasspathJavaLibraryBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/ReducedClasspathJavaLibraryBuilder.java
index 8e29cf1644..507e2eba5b 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/ReducedClasspathJavaLibraryBuilder.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/ReducedClasspathJavaLibraryBuilder.java
@@ -14,11 +14,11 @@
package com.google.devtools.build.buildjar;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.buildjar.javac.BlazeJavacResult;
+import com.google.devtools.build.buildjar.javac.FormattedDiagnostic;
import com.google.devtools.build.buildjar.javac.JavacRunner;
-import com.sun.tools.javac.main.Main.Result;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.regex.Pattern;
/**
@@ -36,11 +36,10 @@ public class ReducedClasspathJavaLibraryBuilder extends SimpleJavaLibraryBuilder
* regular compile.
*
* @param build A JavaLibraryBuildRequest request object describing what to compile
- * @return result code of the javac compilation
* @throws IOException clean-up up the output directory fails
*/
@Override
- Result compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner, PrintWriter err)
+ BlazeJavacResult compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner)
throws IOException {
// Minimize classpath, but only if we're actually compiling some sources (some invocations of
// JavaBuilder are only building resource jars).
@@ -58,31 +57,19 @@ public class ReducedClasspathJavaLibraryBuilder extends SimpleJavaLibraryBuilder
}
// Compile!
- StringWriter javacOutput = new StringWriter();
- PrintWriter javacOutputWriter = new PrintWriter(javacOutput);
- Result result =
- javacRunner.invokeJavac(
- build.getPlugins(),
- build.toBlazeJavacArguments(compressedClasspath),
- javacOutputWriter);
- javacOutputWriter.close();
+ BlazeJavacResult result =
+ javacRunner.invokeJavac(build.toBlazeJavacArguments(compressedClasspath));
// If javac errored out because of missing entries on the classpath, give it another try.
// TODO(bazel-team): check performance impact of additional retries.
- if (!result.isOK() && hasRecognizedError(javacOutput.toString())) {
- if (debug) {
- err.println("warning: [transitive] Target uses transitive classpath to compile.");
- }
+ if (!result.javacResult().isOK() && hasRecognizedError(result.diagnostics())) {
+ // TODO(cushon): warn for transitive classpath fallback
// Reset output directories
prepareSourceCompilation(build);
// Fall back to the regular compile, but add extra checks to catch transitive uses
- result =
- javacRunner.invokeJavac(
- build.getPlugins(), build.toBlazeJavacArguments(build.getClassPath()), err);
- } else {
- err.print(javacOutput.getBuffer());
+ result = javacRunner.invokeJavac(build.toBlazeJavacArguments(build.getClassPath()));
}
return result;
}
@@ -90,12 +77,17 @@ public class ReducedClasspathJavaLibraryBuilder extends SimpleJavaLibraryBuilder
private static final Pattern MISSING_PACKAGE =
Pattern.compile("error: package ([\\p{javaJavaIdentifierPart}\\.]+) does not exist");
- private boolean hasRecognizedError(String javacOutput) {
- return javacOutput.contains("error: cannot access")
- || javacOutput.contains("error: cannot find symbol")
- || javacOutput.contains("com.sun.tools.javac.code.Symbol$CompletionFailure")
- || MISSING_PACKAGE.matcher(javacOutput).find()
- // TODO(cushon): -Xdoclint:reference is probably a bad idea
- || javacOutput.contains("error: reference not found");
+ private boolean hasRecognizedError(ImmutableList<FormattedDiagnostic> diagnostics) {
+ // TODO(cushon): usage diagnostic codes instead
+ for (FormattedDiagnostic diagnostic : diagnostics) {
+ String message = diagnostic.getFormatted();
+ return message.contains("error: cannot access")
+ || message.contains("error: cannot find symbol")
+ || message.contains("com.sun.tools.javac.code.Symbol$CompletionFailure")
+ || MISSING_PACKAGE.matcher(message).find()
+ // TODO(cushon): -Xdoclint:reference is probably a bad idea
+ || message.contains("error: reference not found");
+ }
+ return false;
}
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java
index 96c9688196..858c884b3e 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java
@@ -15,20 +15,17 @@
package com.google.devtools.build.buildjar;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
import com.google.devtools.build.buildjar.instrumentation.JacocoInstrumentationProcessor;
import com.google.devtools.build.buildjar.jarhelper.JarCreator;
import com.google.devtools.build.buildjar.javac.BlazeJavacArguments;
import com.google.devtools.build.buildjar.javac.BlazeJavacMain;
+import com.google.devtools.build.buildjar.javac.BlazeJavacResult;
import com.google.devtools.build.buildjar.javac.JavacRunner;
-import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
-import com.sun.tools.javac.main.Main.Result;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.PrintWriter;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
@@ -48,9 +45,6 @@ public class SimpleJavaLibraryBuilder implements Closeable {
/** The name of the protobuf meta file. */
private static final String PROTOBUF_META_NAME = "protobuf.meta";
- /** Enables more verbose output from the compiler. */
- protected boolean debug = false;
-
/** Cache of opened zip filesystems for srcjars. */
private final Map<Path, FileSystem> filesystems = new HashMap<>();
@@ -110,10 +104,9 @@ public class SimpleJavaLibraryBuilder implements Closeable {
}
}
- Result compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner, PrintWriter err)
+ BlazeJavacResult compileSources(JavaLibraryBuildRequest build, JavacRunner javacRunner)
throws IOException {
- return javacRunner.invokeJavac(
- build.getPlugins(), build.toBlazeJavacArguments(build.getClassPath()), err);
+ return javacRunner.invokeJavac(build.toBlazeJavacArguments(build.getClassPath()));
}
protected void prepareSourceCompilation(JavaLibraryBuildRequest build) throws IOException {
@@ -157,25 +150,20 @@ public class SimpleJavaLibraryBuilder implements Closeable {
* can be compiled. Invokes compileSources to do the actual compilation.
*
* @param build A JavaLibraryBuildRequest request object describing what to compile
- * @param err PrintWriter for logging any diagnostic output
*/
- public Result compileJavaLibrary(final JavaLibraryBuildRequest build, final PrintWriter err)
- throws Exception {
+ public BlazeJavacResult compileJavaLibrary(final JavaLibraryBuildRequest build) throws Exception {
prepareSourceCompilation(build);
if (build.getSourceFiles().isEmpty()) {
- return Result.OK;
+ return BlazeJavacResult.ok();
}
JavacRunner javacRunner =
new JavacRunner() {
@Override
- public Result invokeJavac(
- ImmutableList<BlazeJavaCompilerPlugin> plugins,
- BlazeJavacArguments arguments,
- PrintWriter output) {
- return new BlazeJavacMain(output, plugins).compile(arguments);
+ public BlazeJavacResult invokeJavac(BlazeJavacArguments arguments) {
+ return BlazeJavacMain.compile(arguments);
}
};
- Result result = compileSources(build, javacRunner, err);
+ BlazeJavacResult result = compileSources(build, javacRunner);
JacocoInstrumentationProcessor processor = build.getJacocoInstrumentationProcessor();
if (processor != null) {
processor.processRequest(build);
@@ -184,11 +172,11 @@ public class SimpleJavaLibraryBuilder implements Closeable {
}
/** Perform the build. */
- public Result run(JavaLibraryBuildRequest build, PrintWriter err) throws Exception {
- Result result = Result.ERROR;
+ public BlazeJavacResult run(JavaLibraryBuildRequest build) throws Exception {
+ BlazeJavacResult result = BlazeJavacResult.error("");
try {
- result = compileJavaLibrary(build, err);
- if (result.isOK()) {
+ result = compileJavaLibrary(build);
+ if (result.javacResult().isOK()) {
buildJar(build);
}
if (!build.getProcessors().isEmpty()) {
@@ -197,7 +185,9 @@ public class SimpleJavaLibraryBuilder implements Closeable {
}
}
} finally {
- build.getDependencyModule().emitDependencyInformation(build.getClassPath(), result.isOK());
+ build
+ .getDependencyModule()
+ .emitDependencyInformation(build.getClassPath(), result.javacResult().isOK());
build.getProcessingModule().emitManifestProto();
}
return result;
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavaCompiler.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavaCompiler.java
index 7cee54b0f8..d5db1e5fc4 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavaCompiler.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavaCompiler.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.buildjar.javac;
-import com.google.common.base.Function;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.CompileStates.CompileState;
@@ -24,7 +23,6 @@ import com.sun.tools.javac.util.Context;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
-import javax.annotation.Nullable;
/**
* An extended version of the javac compiler, providing support for composable static analyses via a
@@ -63,9 +61,7 @@ public class BlazeJavaCompiler extends JavaCompiler {
* and save the output after its call for introspection.
*/
public static void preRegister(
- final Context context,
- final Iterable<BlazeJavaCompilerPlugin> plugins,
- @Nullable final Function<BlazeJavaCompiler, Void> listener) {
+ final Context context, final Iterable<BlazeJavaCompilerPlugin> plugins) {
context.put(
compilerKey,
new Context.Factory<JavaCompiler>() {
@@ -77,20 +73,11 @@ public class BlazeJavaCompiler extends JavaCompiler {
throw new AssertionError("Expected a single creation of BlazeJavaCompiler.");
}
first = false;
- BlazeJavaCompiler compiler = new BlazeJavaCompiler(c, plugins);
- if (listener != null) {
- listener.apply(compiler);
- }
- return compiler;
+ return new BlazeJavaCompiler(c, plugins);
}
});
}
- public static void preRegister(
- final Context context, final Iterable<BlazeJavaCompilerPlugin> plugins) {
- preRegister(context, plugins, null);
- }
-
@Override
public Env<AttrContext> attribute(Env<AttrContext> env) {
Env<AttrContext> result = super.attribute(env);
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacArguments.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacArguments.java
index 7554ddc2e1..37c96e8ca8 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacArguments.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacArguments.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.buildjar.javac;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import java.nio.file.Path;
import javax.annotation.Nullable;
import javax.annotation.processing.Processor;
@@ -44,6 +45,9 @@ public abstract class BlazeJavacArguments {
/** The classpath to load processors from. */
public abstract ImmutableList<Path> processorPath();
+ /** The compiler plugins. */
+ public abstract ImmutableList<BlazeJavaCompilerPlugin> plugins();
+
/**
* Annotation processor classes. In production builds, processors are specified by string class
* name in {@link javacOptions}; this is used for tests that instantate processors directly.
@@ -67,7 +71,8 @@ public abstract class BlazeJavacArguments {
.sourceFiles(ImmutableList.of())
.processors(null)
.sourceOutput(null)
- .processorPath(ImmutableList.of());
+ .processorPath(ImmutableList.of())
+ .plugins(ImmutableList.of());
}
/** {@link BlazeJavacArguments}Builder. */
@@ -89,6 +94,8 @@ public abstract class BlazeJavacArguments {
Builder processorPath(ImmutableList<Path> processorPath);
+ Builder plugins(ImmutableList<BlazeJavaCompilerPlugin> plugins);
+
BlazeJavacArguments build();
}
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacMain.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacMain.java
index ecd1161baa..fae6e2c111 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacMain.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacMain.java
@@ -14,34 +14,32 @@
package com.google.devtools.build.buildjar.javac;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Verify.verifyNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.buildjar.InvalidCommandLineException;
+import com.google.devtools.build.buildjar.javac.FormattedDiagnostic.Listener;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin.PluginException;
+import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.Main.Result;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.PropagatedException;
import java.io.IOError;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.List;
-import javax.tools.DiagnosticListener;
-import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
/**
@@ -54,77 +52,48 @@ import javax.tools.StandardLocation;
public class BlazeJavacMain {
/**
- * Compose {@link com.sun.tools.javac.main.Main} and perform custom setup before deferring to its
- * compile() method.
- *
- * <p>Historically BlazeJavacMain extended javac's Main and overrode methods to get the desired
- * custom behaviour. That approach created incompatibilities when upgrading to newer versions of
- * javac, so composition is preferred.
- */
- private List<BlazeJavaCompilerPlugin> plugins;
-
- private final PrintWriter errOutput;
- private BlazeJavaCompiler compiler = null;
-
- public BlazeJavacMain(PrintWriter errOutput, List<BlazeJavaCompilerPlugin> plugins) {
- this.errOutput = errOutput;
- this.plugins = plugins;
- }
-
- /**
- * Installs the BlazeJavaCompiler within the provided context. Enables plugins based on field
- * values.
+ * Sets up a BlazeJavaCompiler with the given plugins within the given context.
*
* @param context JavaCompiler's associated Context
*/
@VisibleForTesting
- void setupBlazeJavaCompiler(Context context) {
+ static void setupBlazeJavaCompiler(
+ ImmutableList<BlazeJavaCompilerPlugin> plugins, Context context) {
for (BlazeJavaCompilerPlugin plugin : plugins) {
plugin.initializeContext(context);
}
- BlazeJavaCompiler.preRegister(context, plugins, compilerListener);
+ BlazeJavaCompiler.preRegister(context, plugins);
}
- private final Function<BlazeJavaCompiler, Void> compilerListener =
- new Function<BlazeJavaCompiler, Void>() {
- @Override
- public Void apply(BlazeJavaCompiler compiler) {
- Verify.verify(BlazeJavacMain.this.compiler == null);
- BlazeJavacMain.this.compiler = checkNotNull(compiler);
- return null;
- }
- };
-
- public Result compile(BlazeJavacArguments arguments) {
- return compile(null, arguments);
- }
-
- public Result compile(
- DiagnosticListener<JavaFileObject> diagnosticListener, BlazeJavacArguments arguments) {
-
- JavacFileManager fileManager = new ClassloaderMaskingFileManager();
+ public static BlazeJavacResult compile(BlazeJavacArguments arguments) {
List<String> javacArguments = arguments.javacOptions();
try {
- javacArguments = processPluginArgs(javacArguments);
+ javacArguments = processPluginArgs(arguments.plugins(), javacArguments);
} catch (InvalidCommandLineException e) {
- errOutput.println(e.getMessage());
- return Result.CMDERR;
+ return BlazeJavacResult.error(e.getMessage());
}
Context context = new Context();
- setupBlazeJavaCompiler(context);
+ setupBlazeJavaCompiler(arguments.plugins(), context);
Result result = Result.ABNORMAL;
- JavacTool tool = JavacTool.create();
- JavacTaskImpl task =
- (JavacTaskImpl)
- tool.getTask(
- errOutput,
+ StringWriter errOutput = new StringWriter();
+ // TODO(cushon): where is this used when a diagnostic listener is registered? Consider removing
+ // it and handling exceptions directly in callers.
+ PrintWriter errWriter = new PrintWriter(errOutput);
+ Listener diagnostics = new Listener(context);
+ BlazeJavaCompiler compiler;
+
+ JavacFileManager fileManager = new ClassloaderMaskingFileManager();
+ JavacTask task =
+ JavacTool.create()
+ .getTask(
+ errWriter,
fileManager,
- diagnosticListener,
+ diagnostics,
javacArguments,
- ImmutableList.<String>of() /*classes*/,
+ ImmutableList.of() /*classes*/,
fileManager.getJavaFileObjectsFromPaths(arguments.sourceFiles()),
context);
if (arguments.processors() != null) {
@@ -134,36 +103,39 @@ public class BlazeJavacMain {
setLocations(fileManager, arguments);
try {
try {
- result = task.doCall();
+ result = ((JavacTaskImpl) task).doCall();
} catch (PropagatedException e) {
throw e.getCause();
}
} catch (PluginException e) {
- errOutput.println(e.getMessage());
+ errWriter.println(e.getMessage());
result = e.getResult();
} catch (Throwable t) {
- t.printStackTrace(errOutput);
+ t.printStackTrace(errWriter);
result = Result.ABNORMAL;
} finally {
+ compiler = (BlazeJavaCompiler) JavaCompiler.instance(context);
if (result.isOK()) {
- verifyNotNull(compiler);
// There could be situations where we incorrectly skip Error Prone and the compilation
// ends up succeeding, e.g., if there are errors that are fixed by subsequent round of
// annotation processing. This check ensures that if there were any flow events at all,
// then plugins were run. There may legitimately not be any flow events, e.g. -proc:only
// or empty source files.
if (compiler.skippedFlowEvents() > 0 && compiler.flowEvents() == 0) {
- errOutput.println("Expected at least one FLOW event");
+ errWriter.println("Expected at least one FLOW event");
result = Result.ABNORMAL;
}
}
}
- return result;
+ errWriter.flush();
+ return new BlazeJavacResult(result, diagnostics.build(), errOutput.toString(), compiler);
}
/** Processes Plugin-specific arguments and removes them from the args array. */
@VisibleForTesting
- List<String> processPluginArgs(List<String> args) throws InvalidCommandLineException {
+ static List<String> processPluginArgs(
+ ImmutableList<BlazeJavaCompilerPlugin> plugins, List<String> args)
+ throws InvalidCommandLineException {
List<String> processedArgs = args;
for (BlazeJavaCompilerPlugin plugin : plugins) {
processedArgs = plugin.processArgs(processedArgs);
@@ -171,17 +143,13 @@ public class BlazeJavacMain {
return processedArgs;
}
- @VisibleForTesting
- BlazeJavaCompiler getCompiler() {
- return verifyNotNull(compiler);
- }
-
- private void setLocations(JavacFileManager fileManager, BlazeJavacArguments arguments) {
+ private static void setLocations(JavacFileManager fileManager, BlazeJavacArguments arguments) {
try {
fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, arguments.classPath());
fileManager.setLocationFromPaths(
StandardLocation.CLASS_OUTPUT, ImmutableList.of(arguments.classOutput()));
- fileManager.setLocationFromPaths(StandardLocation.SOURCE_PATH, ImmutableList.<Path>of());
+ fileManager.setLocationFromPaths(StandardLocation.SOURCE_PATH, ImmutableList.of());
+ // TODO(cushon): require an explicit bootclasspath
Iterable<Path> bootClassPath = arguments.bootClassPath();
if (!Iterables.isEmpty(bootClassPath)) {
fileManager.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
@@ -190,7 +158,7 @@ public class BlazeJavacMain {
StandardLocation.ANNOTATION_PROCESSOR_PATH, arguments.processorPath());
if (arguments.sourceOutput() != null) {
fileManager.setLocationFromPaths(
- StandardLocation.SOURCE_OUTPUT, ImmutableList.<Path>of(arguments.sourceOutput()));
+ StandardLocation.SOURCE_OUTPUT, ImmutableList.of(arguments.sourceOutput()));
}
} catch (IOException e) {
throw new IOError(e);
@@ -228,4 +196,6 @@ public class BlazeJavacMain {
});
}
}
+
+ private BlazeJavacMain() {}
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacResult.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacResult.java
new file mode 100644
index 0000000000..61702ffa09
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/BlazeJavacResult.java
@@ -0,0 +1,64 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.buildjar.javac;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.sun.tools.javac.main.Main.Result;
+
+/** The result of a single compilation performed by {@link BlazeJavacMain}. */
+public class BlazeJavacResult {
+
+ private final Result javacResult;
+ private final ImmutableList<FormattedDiagnostic> diagnostics;
+ private final String output;
+ private final BlazeJavaCompiler compiler;
+
+ public static BlazeJavacResult ok() {
+ return new BlazeJavacResult(Result.OK, ImmutableList.of(), "", null);
+ }
+
+ public static BlazeJavacResult error(String message) {
+ return new BlazeJavacResult(Result.ERROR, ImmutableList.of(), message, null);
+ }
+
+ public BlazeJavacResult(
+ Result javacResult,
+ ImmutableList<FormattedDiagnostic> diagnostics,
+ String output,
+ BlazeJavaCompiler compiler) {
+ this.javacResult = javacResult;
+ this.diagnostics = diagnostics;
+ this.output = output;
+ this.compiler = compiler;
+ }
+
+ public Result javacResult() {
+ return javacResult;
+ }
+
+ public ImmutableList<FormattedDiagnostic> diagnostics() {
+ return diagnostics;
+ }
+
+ public String output() {
+ return output;
+ }
+
+ @VisibleForTesting
+ public BlazeJavaCompiler compiler() {
+ return compiler;
+ }
+}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/FormattedDiagnostic.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/FormattedDiagnostic.java
new file mode 100644
index 0000000000..477d7cee50
--- /dev/null
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/FormattedDiagnostic.java
@@ -0,0 +1,122 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.buildjar.javac;
+
+import com.google.common.collect.ImmutableList;
+import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
+import com.sun.tools.javac.api.DiagnosticFormatter;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JavacMessages;
+import com.sun.tools.javac.util.Log;
+import java.util.Locale;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileObject;
+
+/**
+ * A {@link Diagnostic<JavaFileObject>} that includes the full formatted message produced by javac,
+ * which relies on compilation internals and can't be reproduced after the compilation is complete.
+ */
+public class FormattedDiagnostic implements Diagnostic<JavaFileObject> {
+
+ public final Diagnostic<? extends JavaFileObject> diagnostic;
+ public final String formatted;
+
+ public FormattedDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic, String formatted) {
+ this.diagnostic = diagnostic;
+ this.formatted = formatted;
+ }
+
+ /** The formatted diagnostic message produced by javac's diagnostic formatter. */
+ public String getFormatted() {
+ return formatted;
+ }
+
+ @Override
+ public String toString() {
+ return formatted;
+ }
+
+ @Override
+ public Kind getKind() {
+ return diagnostic.getKind();
+ }
+
+ @Override
+ public JavaFileObject getSource() {
+ return diagnostic.getSource();
+ }
+
+ @Override
+ public long getPosition() {
+ return diagnostic.getPosition();
+ }
+
+ @Override
+ public long getStartPosition() {
+ return diagnostic.getStartPosition();
+ }
+
+ @Override
+ public long getEndPosition() {
+ return diagnostic.getEndPosition();
+ }
+
+ @Override
+ public long getLineNumber() {
+ return diagnostic.getLineNumber();
+ }
+
+ @Override
+ public long getColumnNumber() {
+ return diagnostic.getColumnNumber();
+ }
+
+ @Override
+ public String getCode() {
+ return diagnostic.getCode();
+ }
+
+ @Override
+ public String getMessage(Locale locale) {
+ return diagnostic.getMessage(locale);
+ }
+
+ /** A {@link DiagnosticListener<JavaFileObject>} that saves {@link FormattedDiagnostic}s. */
+ @Trusted
+ static class Listener implements DiagnosticListener<JavaFileObject> {
+
+ private final ImmutableList.Builder<FormattedDiagnostic> diagnostics = ImmutableList.builder();
+ private final Context context;
+
+ Listener(Context context) {
+ // retrieve context values later, in case it isn't initialized yet
+ this.context = context;
+ }
+
+ @Override
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ DiagnosticFormatter<JCDiagnostic> formatter = Log.instance(context).getDiagnosticFormatter();
+ Locale locale = JavacMessages.instance(context).getCurrentLocale();
+ String formatted = formatter.format((JCDiagnostic) diagnostic, locale);
+ diagnostics.add(new FormattedDiagnostic(diagnostic, formatted));
+ }
+
+ ImmutableList<FormattedDiagnostic> build() {
+ return diagnostics.build();
+ }
+ }
+}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/JavacRunner.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/JavacRunner.java
index 11f72b2f2d..6505b32dec 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/JavacRunner.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/JavacRunner.java
@@ -14,19 +14,10 @@
package com.google.devtools.build.buildjar.javac;
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
-import com.sun.tools.javac.main.Main.Result;
-import java.io.PrintWriter;
-
/**
* The JavacRunner is a type that can be used to invoke javac and provides a convenient hook for
* modifications.
*/
public interface JavacRunner {
-
- Result invokeJavac(
- ImmutableList<BlazeJavaCompilerPlugin> plugins,
- BlazeJavacArguments arguments,
- PrintWriter err);
+ BlazeJavacResult invokeJavac(BlazeJavacArguments arguments);
}