| Index: third_party/WebKit/Source/devtools/scripts/compiler-runner/src/org/chromium/devtools/compiler/Runner.java
|
| diff --git a/third_party/WebKit/Source/devtools/scripts/compiler-runner/src/org/chromium/devtools/compiler/Runner.java b/third_party/WebKit/Source/devtools/scripts/compiler-runner/src/org/chromium/devtools/compiler/Runner.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6cf6f70992bdb0c9edcf160609b05dd9e334bfc7
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/devtools/scripts/compiler-runner/src/org/chromium/devtools/compiler/Runner.java
|
| @@ -0,0 +1,259 @@
|
| +package org.chromium.devtools.compiler;
|
| +
|
| +import com.google.common.collect.Lists;
|
| +import com.google.common.io.Resources;
|
| +import com.google.javascript.jscomp.*;
|
| +
|
| +import org.kohsuke.args4j.CmdLineException;
|
| +import org.kohsuke.args4j.CmdLineParser;
|
| +import org.kohsuke.args4j.Option;
|
| +
|
| +import javax.xml.transform.Source;
|
| +import java.io.*;
|
| +import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| +import java.util.List;
|
| +import java.util.concurrent.Callable;
|
| +import java.util.concurrent.ExecutorService;
|
| +import java.util.concurrent.Executors;
|
| +import java.util.concurrent.Future;
|
| +import java.util.regex.Matcher;
|
| +import java.util.regex.Pattern;
|
| +
|
| +/**
|
| + * Prepares and executes several instances of the closure compiler.
|
| + */
|
| +public class Runner {
|
| + protected final Flags flags = new Flags();
|
| + private final PrintStream err;
|
| + private boolean isConfigValid;
|
| +
|
| + public Runner(String[] args, PrintStream err) {
|
| + this.err = err;
|
| + List<String> argList = processArgs(args);
|
| + CmdLineParser parser = new CmdLineParser(flags);
|
| + isConfigValid = true;
|
| + try {
|
| + parser.parseArgument(argList.toArray(new String[] {}));
|
| + if (flags.compilerArgsFile == null) {
|
| + isConfigValid = false;
|
| + }
|
| + } catch (CmdLineException e) {
|
| + err.println(e.getMessage());
|
| + isConfigValid = false;
|
| + }
|
| +
|
| + if (!isConfigValid) {
|
| + parser.printUsage(err);
|
| + }
|
| + }
|
| +
|
| + private List<String> processArgs(String[] args) {
|
| + Pattern argPattern = Pattern.compile("(--[a-zA-Z_]+)=(.*)");
|
| + Pattern quotesPattern = Pattern.compile("^['\"](.*)['\"]$");
|
| + List<String> processedArgs = Lists.newArrayList();
|
| +
|
| + for (String arg : args) {
|
| + Matcher matcher = argPattern.matcher(arg);
|
| + if (matcher.matches()) {
|
| + processedArgs.add(matcher.group(1));
|
| +
|
| + String value = matcher.group(2);
|
| + Matcher quotesMatcher = quotesPattern.matcher(value);
|
| + if (quotesMatcher.matches()) {
|
| + processedArgs.add(quotesMatcher.group(1));
|
| + } else {
|
| + processedArgs.add(value);
|
| + }
|
| + } else {
|
| + processedArgs.add(arg);
|
| + }
|
| + }
|
| +
|
| + return processedArgs;
|
| + }
|
| +
|
| + private boolean shouldRunCompiler() {
|
| + return isConfigValid;
|
| + }
|
| +
|
| + protected void logError(String message, Exception e) {
|
| + err.println("ERROR: " + message);
|
| + if (e != null) {
|
| + e.printStackTrace(err);
|
| + }
|
| + }
|
| +
|
| + private void run() {
|
| + List<CompilerInstanceDescriptor> descriptors = getDescriptors();
|
| + if (descriptors == null) {
|
| + return;
|
| + }
|
| + ExecutorService executor = Executors.newFixedThreadPool(
|
| + Math.min(descriptors.size(), Runtime.getRuntime().availableProcessors() / 2 + 1));
|
| + try {
|
| + runWithExecutor(descriptors, executor);
|
| + } finally {
|
| + executor.shutdown();
|
| + }
|
| + }
|
| +
|
| + private void runWithExecutor(
|
| + List<CompilerInstanceDescriptor> descriptors, ExecutorService executor) {
|
| + List<Future<CompilerRunner>> futures = new ArrayList<>(descriptors.size());
|
| + for (CompilerInstanceDescriptor descriptor : descriptors) {
|
| + try {
|
| + ByteArrayOutputStream rawStream = new ByteArrayOutputStream(512);
|
| + PrintStream errPrintStream = new PrintStream(rawStream, false, "UTF-8");
|
| + // We have to create instance of LocalCommandLineRunner object here,
|
| + // because its constructor should be executed on a single thread.
|
| + // Constructor is parsing flags and creating options object that can
|
| + // be used later in parallel during compilation.
|
| + LocalCommandLineRunner runner =
|
| + new LocalCommandLineRunner(descriptor.commandLine.split(" +"),
|
| + System.out, errPrintStream);
|
| +
|
| + CompilerRunner task = new CompilerRunner(descriptor, rawStream, runner);
|
| + futures.add(executor.submit(task));
|
| + } catch (Exception e) {
|
| + System.err.println("ERROR - " + e.getMessage());
|
| + e.printStackTrace(System.err);
|
| + }
|
| + }
|
| +
|
| + for (Future<CompilerRunner> future : futures) {
|
| + try {
|
| + CompilerRunner task = future.get();
|
| + int result = task.result;
|
| + if (result != 0) {
|
| + System.err.println("ERROR: Compiler returned " + result);
|
| + }
|
| + task.errStream.flush();
|
| + System.err.println("@@ START_MODULE:" + task.descriptor.moduleName + " @@");
|
| + System.err.println(task.errStream.toString("UTF-8"));
|
| + System.err.println("@@ END_MODULE @@");
|
| + } catch (Exception e) {
|
| + System.err.println("ERROR - " + e.getMessage());
|
| + e.printStackTrace(System.err);
|
| + }
|
| + }
|
| + System.exit(0);
|
| + }
|
| +
|
| + private List<CompilerInstanceDescriptor> getDescriptors() {
|
| + List<CompilerInstanceDescriptor> result = new ArrayList<>();
|
| + try (BufferedReader reader = new BufferedReader(
|
| + new InputStreamReader(
|
| + new FileInputStream(flags.compilerArgsFile), "UTF-8"))) {
|
| + int lineIndex = 0;
|
| + while (true) {
|
| + ++lineIndex;
|
| + String line = reader.readLine();
|
| + if (line == null) {
|
| + break;
|
| + }
|
| + if (line.length() == 0) {
|
| + continue;
|
| + }
|
| + String[] moduleAndArgs = line.split(" +", 2);
|
| + if (moduleAndArgs.length != 2) {
|
| + logError(String.format(
|
| + "Line %d does not contain module name and compiler arguments",
|
| + lineIndex), null);
|
| + continue;
|
| + }
|
| + result.add(new CompilerInstanceDescriptor(moduleAndArgs[0], moduleAndArgs[1]));
|
| + }
|
| + } catch (IOException e) {
|
| + logError("Failed to read compiler arguments file", e);
|
| + return null;
|
| + }
|
| +
|
| + return result;
|
| + }
|
| +
|
| + public static void main(String[] args) {
|
| + Runner runner = new Runner(args, System.err);
|
| + if (runner.shouldRunCompiler()) {
|
| + runner.run();
|
| + } else {
|
| + System.exit(-1);
|
| + }
|
| + }
|
| +
|
| + private static class LocalCommandLineRunner extends CommandLineRunner {
|
| +
|
| + protected LocalCommandLineRunner(String[] args, PrintStream out, PrintStream err) {
|
| + super(args, out, err);
|
| + }
|
| +
|
| + @Override
|
| + protected CompilerOptions createOptions() {
|
| + CompilerOptions options = super.createOptions();
|
| + options.setIdeMode(true);
|
| + options.setReportMissingOverride(CheckLevel.ERROR);
|
| + return options;
|
| + }
|
| +
|
| + @Override
|
| + protected void setRunOptions(CompilerOptions options)
|
| + throws FlagUsageException, IOException {
|
| + super.setRunOptions(options);
|
| + options.setCodingConvention(new DevToolsCodingConvention());
|
| + }
|
| +
|
| + int execute() {
|
| + int result = 0;
|
| + int runs = 1;
|
| + try {
|
| + for (int i = 0; i < runs && result == 0; i++) {
|
| + result = doRun();
|
| + }
|
| + } catch (Throwable t) {
|
| + t.printStackTrace();
|
| + result = -2;
|
| + }
|
| + return result;
|
| + }
|
| + }
|
| +
|
| + private static class CompilerRunner implements Callable<CompilerRunner> {
|
| + private final CompilerInstanceDescriptor descriptor;
|
| + private final ByteArrayOutputStream errStream;
|
| + private int result;
|
| + private final LocalCommandLineRunner runner;
|
| +
|
| + public CompilerRunner(
|
| + CompilerInstanceDescriptor descriptor, ByteArrayOutputStream errStream,
|
| + LocalCommandLineRunner runner) {
|
| + this.descriptor = descriptor;
|
| + this.errStream = errStream;
|
| + this.runner = runner;
|
| + }
|
| +
|
| + @Override
|
| + public CompilerRunner call() throws Exception {
|
| + if (!this.runner.shouldRunCompiler()) {
|
| + this.result = -1;
|
| + }
|
| + this.result = this.runner.execute();
|
| + return this;
|
| + }
|
| + }
|
| +
|
| + private static class Flags {
|
| + @Option(name = "--compiler-args-file",
|
| + usage = "Full path to file containing compiler arguments (one line per instance)")
|
| + private String compilerArgsFile = null;
|
| + }
|
| +
|
| + private static class CompilerInstanceDescriptor {
|
| + private final String moduleName;
|
| + private final String commandLine;
|
| +
|
| + public CompilerInstanceDescriptor(String moduleName, String commandLine) {
|
| + this.moduleName = moduleName;
|
| + this.commandLine = commandLine;
|
| + }
|
| + }
|
| +}
|
|
|