Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / scripts / compiler-runner / src / org / chromium / devtools / compiler / Runner.java
1 package org.chromium.devtools.compiler;
2
3 import com.google.common.collect.Lists;
4 import com.google.javascript.jscomp.CommandLineRunner;
5 import com.google.javascript.jscomp.CompilerOptions;
6
7 import org.kohsuke.args4j.CmdLineException;
8 import org.kohsuke.args4j.CmdLineParser;
9 import org.kohsuke.args4j.Option;
10
11 import java.io.BufferedReader;
12 import java.io.ByteArrayOutputStream;
13 import java.io.FileInputStream;
14 import java.io.IOException;
15 import java.io.InputStreamReader;
16 import java.io.PrintStream;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.Future;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27 /**
28  * Prepares and executes several instances of the closure compiler.
29  */
30 public class Runner {
31     protected final Flags flags = new Flags();
32     private final PrintStream err;
33     private boolean isConfigValid;
34
35     public Runner(String[] args, PrintStream err) {
36         this.err = err;
37         List<String> argList = processArgs(args);
38         CmdLineParser parser = new CmdLineParser(flags);
39         isConfigValid = true;
40         try {
41             parser.parseArgument(argList.toArray(new String[] {}));
42             if (flags.compilerArgsFile == null) {
43                 isConfigValid = false;
44             }
45         } catch (CmdLineException e) {
46             err.println(e.getMessage());
47             isConfigValid = false;
48         }
49
50         if (!isConfigValid) {
51             parser.printUsage(err);
52         }
53     }
54
55     private List<String> processArgs(String[] args) {
56         Pattern argPattern = Pattern.compile("(--[a-zA-Z_]+)=(.*)");
57         Pattern quotesPattern = Pattern.compile("^['\"](.*)['\"]$");
58         List<String> processedArgs = Lists.newArrayList();
59
60         for (String arg : args) {
61             Matcher matcher = argPattern.matcher(arg);
62             if (matcher.matches()) {
63                 processedArgs.add(matcher.group(1));
64
65                 String value = matcher.group(2);
66                 Matcher quotesMatcher = quotesPattern.matcher(value);
67                 if (quotesMatcher.matches()) {
68                     processedArgs.add(quotesMatcher.group(1));
69                 } else {
70                     processedArgs.add(value);
71                 }
72             } else {
73                 processedArgs.add(arg);
74             }
75         }
76
77         return processedArgs;
78     }
79
80     private boolean shouldRunCompiler() {
81         return isConfigValid;
82     }
83
84     protected void logError(String message, Exception e) {
85         err.println("ERROR: " + message);
86         if (e != null) {
87             e.printStackTrace(err);
88         }
89     }
90
91     private void run() {
92         List<CompilerInstanceDescriptor> descriptors = getDescriptors();
93         if (descriptors == null) {
94             return;
95         }
96         ExecutorService executor = Executors.newFixedThreadPool(
97                 Math.min(descriptors.size(), Runtime.getRuntime().availableProcessors() / 2 + 1));
98         try {
99             runWithExecutor(descriptors, executor);
100         } finally {
101             executor.shutdown();
102         }
103     }
104
105     private void runWithExecutor(
106             List<CompilerInstanceDescriptor> descriptors, ExecutorService executor) {
107         List<Future<CompilerRunner>> futures = new ArrayList<>(descriptors.size());
108         for (CompilerInstanceDescriptor descriptor : descriptors) {
109             CompilerRunner task = new CompilerRunner(descriptor, new ByteArrayOutputStream(512));
110             futures.add(executor.submit(task));
111         }
112
113         for (Future<CompilerRunner> future : futures) {
114             try {
115                 CompilerRunner task = future.get();
116                 int result = task.result;
117                 if (result != 0) {
118                     System.err.println("ERROR: Compiler returned " + result);
119                 }
120                 task.errStream.flush();
121                 System.err.println("@@ START_MODULE:" + task.descriptor.moduleName + " @@");
122                 System.err.println(task.errStream.toString("UTF-8"));
123                 System.err.println("@@ END_MODULE @@");
124             } catch (Exception e) {
125                 System.err.println("ERROR - " + e.getMessage());
126             }
127         }
128         System.exit(0);
129     }
130
131     private List<CompilerInstanceDescriptor> getDescriptors() {
132         List<CompilerInstanceDescriptor> result = new ArrayList<>();
133         try (BufferedReader reader = new BufferedReader(
134                 new InputStreamReader(
135                         new FileInputStream(flags.compilerArgsFile), "UTF-8"))) {
136             int lineIndex = 0;
137             while (true) {
138                 ++lineIndex;
139                 String line = reader.readLine();
140                 if (line == null) {
141                     break;
142                 }
143                 if (line.length() == 0) {
144                     continue;
145                 }
146                 String[] moduleAndArgs = line.split(" +", 2);
147                 if (moduleAndArgs.length != 2) {
148                     logError(String.format(
149                             "Line %d does not contain module name and compiler arguments",
150                             lineIndex), null);
151                     continue;
152                 }
153                 result.add(new CompilerInstanceDescriptor(moduleAndArgs[0], moduleAndArgs[1]));
154             }
155         } catch (IOException e) {
156             logError("Failed to read compiler arguments file", e);
157             return null;
158         }
159
160         return result;
161     }
162
163     public static void main(String[] args) {
164         Runner runner = new Runner(args, System.err);
165         if (runner.shouldRunCompiler()) {
166             runner.run();
167         } else {
168             System.exit(-1);
169         }
170     }
171
172     private static class LocalCommandLineRunner extends CommandLineRunner {
173         protected LocalCommandLineRunner(String[] args, PrintStream out, PrintStream err) {
174             super(args, out, err);
175         }
176
177         @Override
178         protected CompilerOptions createOptions() {
179             CompilerOptions options = super.createOptions();
180             options.setIdeMode(true);
181             options.setExtraAnnotationNames(Collections.singletonList("suppressReceiverCheck"));
182             return options;
183         }
184
185         @Override
186         protected void setRunOptions(CompilerOptions options)
187                 throws FlagUsageException, IOException {
188             super.setRunOptions(options);
189             options.setCodingConvention(new DevToolsCodingConvention());
190         }
191
192         int execute() {
193             int result = 0;
194             int runs = 1;
195             try {
196                 for (int i = 0; i < runs && result == 0; i++) {
197                     result = doRun();
198                 }
199             } catch (Throwable t) {
200                 t.printStackTrace();
201                 result = -2;
202             }
203             return result;
204         }
205     }
206
207     private static class CompilerRunner implements Callable<CompilerRunner> {
208         private final CompilerInstanceDescriptor descriptor;
209         private final ByteArrayOutputStream errStream;
210         private int result;
211
212         public CompilerRunner(
213                 CompilerInstanceDescriptor descriptor, ByteArrayOutputStream errStream) {
214             this.descriptor = descriptor;
215             this.errStream = errStream;
216         }
217
218         @Override
219         public CompilerRunner call() throws Exception {
220             PrintStream errPrintStream = new PrintStream(errStream, false, "UTF-8");
221             LocalCommandLineRunner runner =
222                     new LocalCommandLineRunner(prepareArgs(), System.out, errPrintStream);
223             if (!runner.shouldRunCompiler()) {
224                 this.result = -1;
225             }
226             this.result = runner.execute();
227             return this;
228         }
229
230         private String[] prepareArgs() {
231             // FIXME: This does not support quoted arguments.
232             return descriptor.commandLine.split(" +");
233         }
234     }
235
236     private static class Flags {
237         @Option(name = "--compiler-args-file",
238                 usage = "Full path to file containing compiler arguments (one line per instance)")
239         private String compilerArgsFile = null;
240     }
241
242     private static class CompilerInstanceDescriptor {
243         private final String moduleName;
244         private final String commandLine;
245
246         public CompilerInstanceDescriptor(String moduleName, String commandLine) {
247             this.moduleName = moduleName;
248             this.commandLine = commandLine;
249         }
250     }
251 }