| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 package com.google.dart.runner; | |
| 6 | |
| 7 import com.google.common.base.Joiner; | |
| 8 import com.google.common.collect.Lists; | |
| 9 import com.google.common.io.CharStreams; | |
| 10 import com.google.common.io.Files; | |
| 11 import com.google.dart.compiler.Backend; | |
| 12 import com.google.dart.compiler.CommandLineOptions; | |
| 13 import com.google.dart.compiler.CommandLineOptions.DartRunnerOptions; | |
| 14 import com.google.dart.compiler.CompilerConfiguration; | |
| 15 import com.google.dart.compiler.DartArtifactProvider; | |
| 16 import com.google.dart.compiler.DartCompiler; | |
| 17 import com.google.dart.compiler.DartCompilerListener; | |
| 18 import com.google.dart.compiler.DefaultCompilerConfiguration; | |
| 19 import com.google.dart.compiler.DefaultDartCompilerListener; | |
| 20 import com.google.dart.compiler.LibrarySource; | |
| 21 import com.google.dart.compiler.Source; | |
| 22 import com.google.dart.compiler.UnitTestBatchRunner; | |
| 23 import com.google.dart.compiler.UnitTestBatchRunner.Invocation; | |
| 24 import com.google.dart.compiler.UrlLibrarySource; | |
| 25 import com.google.dart.compiler.backend.js.JavascriptBackend; | |
| 26 | |
| 27 import org.kohsuke.args4j.CmdLineException; | |
| 28 import org.kohsuke.args4j.CmdLineParser; | |
| 29 | |
| 30 import java.io.ByteArrayOutputStream; | |
| 31 import java.io.File; | |
| 32 import java.io.IOException; | |
| 33 import java.io.OutputStream; | |
| 34 import java.io.PrintStream; | |
| 35 import java.io.Reader; | |
| 36 import java.io.StringReader; | |
| 37 import java.io.StringWriter; | |
| 38 import java.io.Writer; | |
| 39 import java.net.URI; | |
| 40 import java.nio.charset.Charset; | |
| 41 import java.util.ArrayList; | |
| 42 import java.util.Collections; | |
| 43 import java.util.List; | |
| 44 import java.util.Map; | |
| 45 import java.util.concurrent.ConcurrentHashMap; | |
| 46 | |
| 47 public class DartRunner { | |
| 48 | |
| 49 private static DartRunnerOptions processCommandLineOptions(String[] args) thro
ws RunnerError { | |
| 50 CmdLineParser cmdLineParser = null; | |
| 51 DartRunnerOptions parsedOptions = null; | |
| 52 try { | |
| 53 parsedOptions = new DartRunnerOptions(); | |
| 54 cmdLineParser = CommandLineOptions.parse(args, parsedOptions); | |
| 55 if (args.length == 0 || parsedOptions.showHelp()) { | |
| 56 printUsageAndThrow(cmdLineParser, ""); | |
| 57 System.exit(1); | |
| 58 } | |
| 59 } catch (CmdLineException e) { | |
| 60 printUsageAndThrow(cmdLineParser, e.getLocalizedMessage()); | |
| 61 System.exit(1); | |
| 62 } | |
| 63 | |
| 64 assert parsedOptions != null; | |
| 65 return parsedOptions; | |
| 66 } | |
| 67 | |
| 68 public static void main(String[] args) { | |
| 69 try { | |
| 70 boolean runBatch = false; | |
| 71 DartRunnerOptions options = processCommandLineOptions(args); | |
| 72 if (options.shouldBatch()) { | |
| 73 runBatch = true; | |
| 74 if (args.length > 1) { | |
| 75 System.err | |
| 76 .println("(Extra arguments specified with -batch ignored.)"); | |
| 77 } | |
| 78 } | |
| 79 if (runBatch) { | |
| 80 UnitTestBatchRunner.runAsBatch(args, new Invocation() { | |
| 81 @Override | |
| 82 public boolean invoke(String[] args) throws Throwable { | |
| 83 try { | |
| 84 throwingMain(args, System.out, System.err); | |
| 85 } catch (RunnerError e) { | |
| 86 System.out.println(e.getLocalizedMessage()); | |
| 87 return false; | |
| 88 } | |
| 89 return true; | |
| 90 } | |
| 91 }); | |
| 92 } else { | |
| 93 throwingMain(args, System.out, System.err); | |
| 94 } | |
| 95 } catch (RunnerError e) { | |
| 96 System.err.println(e.getLocalizedMessage()); | |
| 97 System.exit(1); | |
| 98 } catch (Throwable e) { | |
| 99 e.printStackTrace(); | |
| 100 DartCompiler.crash(); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 public static void throwingMain(String[] args, | |
| 105 PrintStream stdout, | |
| 106 PrintStream stderr) | |
| 107 throws RunnerError { | |
| 108 DartRunnerOptions options = processCommandLineOptions(args); | |
| 109 List<LibrarySource> imports = Lists.newArrayList(); | |
| 110 if (options.getSourceFiles().isEmpty()) { | |
| 111 throw new RunnerError("No script files specified on the command line: " +
Joiner.on(" ").join(args)); | |
| 112 } | |
| 113 | |
| 114 String script = options.getSourceFiles().get(0); | |
| 115 ArrayList<String> scriptArguments = new ArrayList<String>(); | |
| 116 | |
| 117 LibrarySource app = new UrlLibrarySource(new File(script)); | |
| 118 | |
| 119 File outFile = options.getOutputFilename(); | |
| 120 | |
| 121 DefaultDartCompilerListener listener = | |
| 122 new DefaultDartCompilerListener(stderr, options.printErrorFormat()); | |
| 123 | |
| 124 String compiled; | |
| 125 compiled = compileApp(app, imports, options, listener); | |
| 126 | |
| 127 if (listener.getErrorCount() != 0) { | |
| 128 throw new RunnerError("Compilation failed."); | |
| 129 } | |
| 130 | |
| 131 if (outFile != null) { | |
| 132 File dir = outFile.getParentFile(); | |
| 133 if (dir != null) { | |
| 134 if (!dir.exists()) { | |
| 135 throw new RunnerError("Cannot create: " + outFile.getName() | |
| 136 + ". " + dir + " does not exist"); | |
| 137 } | |
| 138 if (!dir.canWrite()) { | |
| 139 throw new RunnerError("Cannot write " + outFile.getName() + " to " | |
| 140 + dir + ": Permission denied."); | |
| 141 } | |
| 142 } else { | |
| 143 dir = new File ("."); | |
| 144 if (!dir.canWrite()) { | |
| 145 throw new RunnerError("Cannot write " + outFile.getName() + " to " | |
| 146 + dir + ": Permission denied."); | |
| 147 } | |
| 148 } | |
| 149 try { | |
| 150 Files.write(compiled, outFile, Charset.defaultCharset()); | |
| 151 } catch (IOException e) { | |
| 152 throw new RunnerError(e); | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 if (!options.shouldCompileOnly() && !options.checkOnly()) { | |
| 157 runApp(compiled, app.getName(), options, scriptArguments.toArray(new Strin
g[0]), | |
| 158 stdout, stderr); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 private static void printUsageAndThrow(CmdLineParser cmdLineParser, String rea
son) | |
| 163 throws RunnerError { | |
| 164 | |
| 165 StringBuilder usage = new StringBuilder(); | |
| 166 usage.append(reason); | |
| 167 usage.append("\n"); | |
| 168 usage.append("Usage: "); | |
| 169 usage.append(System.getProperty("com.google.dart.runner.progname", | |
| 170 DartRunner.class.getSimpleName())); | |
| 171 usage.append(" [<options>] <dart-script-file> [<script-arguments>]\n"); | |
| 172 usage.append("\n"); | |
| 173 | |
| 174 OutputStream s = new ByteArrayOutputStream(); | |
| 175 if (cmdLineParser == null) { | |
| 176 cmdLineParser = new CmdLineParser(new DartRunnerOptions()); | |
| 177 } | |
| 178 usage.append(s); | |
| 179 throw new RunnerError(usage.toString()); | |
| 180 } | |
| 181 | |
| 182 private static class RunnerDartArtifactProvider extends DartArtifactProvider { | |
| 183 private final Map<String, StringWriter> artifacts = new ConcurrentHashMap<St
ring, StringWriter>(); | |
| 184 | |
| 185 @Override | |
| 186 public Reader getArtifactReader(Source source, String part, String ext) { | |
| 187 String key = getKey(source, part, ext); | |
| 188 StringWriter w = artifacts.get(key); | |
| 189 if (w == null) { | |
| 190 return null; | |
| 191 } | |
| 192 return new StringReader(w.toString()); | |
| 193 } | |
| 194 | |
| 195 @Override | |
| 196 public URI getArtifactUri(Source source, String part, String ext) { | |
| 197 String key = getKey(source, part, ext); | |
| 198 return URI.create(key); | |
| 199 } | |
| 200 | |
| 201 @Override | |
| 202 public Writer getArtifactWriter(Source source, String part, String ext) { | |
| 203 StringWriter w = new StringWriter(); | |
| 204 String key = getKey(source, part, ext); | |
| 205 StringWriter oldValue = artifacts.put(key, w); | |
| 206 if (oldValue != null) { | |
| 207 throw new RuntimeException("Can only write artifact once for " + key); | |
| 208 } | |
| 209 return w; | |
| 210 } | |
| 211 | |
| 212 private String getKey(Source source, String part, String ext) { | |
| 213 String keyPart = (part.isEmpty()) ? "" : "$" + part; | |
| 214 return source.getName() + keyPart + "." + ext; | |
| 215 } | |
| 216 | |
| 217 public String getGeneratedFileContents(String name) { | |
| 218 StringWriter w = artifacts.get(name); | |
| 219 if (w == null) { | |
| 220 return null; | |
| 221 } | |
| 222 return w.toString(); | |
| 223 } | |
| 224 | |
| 225 @Override | |
| 226 public boolean isOutOfDate(Source source, Source base, String ext) { | |
| 227 return true; | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 public static void compileAndRunApp(LibrarySource app, | |
| 232 DartRunnerOptions options, | |
| 233 CompilerConfiguration config, | |
| 234 DartCompilerListener listener, | |
| 235 String[] dartArguments, | |
| 236 PrintStream stdout, | |
| 237 PrintStream stderr) | |
| 238 throws RunnerError { | |
| 239 String compiled = compileApp( | |
| 240 app, options, Collections.<LibrarySource>emptyList(), config, listener)
; | |
| 241 runApp(compiled, app.getName(), options, dartArguments, stdout, stderr); | |
| 242 } | |
| 243 | |
| 244 private static void runApp(String compiled, | |
| 245 String sourceName, | |
| 246 DartRunnerOptions options, | |
| 247 String[] scriptArguments, | |
| 248 PrintStream stdout, | |
| 249 PrintStream stderr) | |
| 250 throws RunnerError { | |
| 251 | |
| 252 new V8Launcher().execute(compiled, sourceName, scriptArguments, options, | |
| 253 stdout, stderr); | |
| 254 } | |
| 255 | |
| 256 private static String compileApp (LibrarySource app, List<LibrarySource> impor
ts, | |
| 257 final DartRunnerOptions options, DartCompilerListener listener) throws Run
nerError { | |
| 258 Backend backend = new JavascriptBackend(); | |
| 259 CompilerConfiguration config = new DefaultCompilerConfiguration(backend, opt
ions) { | |
| 260 @Override | |
| 261 public boolean expectEntryPoint() { | |
| 262 return true; | |
| 263 } | |
| 264 | |
| 265 @Override | |
| 266 public boolean typeErrorsAreFatal() { | |
| 267 return options.typeErrorsAreFatal(); | |
| 268 } | |
| 269 }; | |
| 270 return compileApp(app, options, imports, config, listener); | |
| 271 } | |
| 272 | |
| 273 /** | |
| 274 * Parses and compiles an application to Javascript. | |
| 275 */ | |
| 276 private static String compileApp(LibrarySource app, | |
| 277 final DartRunnerOptions options, | |
| 278 List<LibrarySource> imports, | |
| 279 CompilerConfiguration config, | |
| 280 DartCompilerListener listener) throws Runner
Error { | |
| 281 try { | |
| 282 final RunnerDartArtifactProvider provider = new RunnerDartArtifactProvider
(); | |
| 283 String errmsg = DartCompiler.compileLib(app, imports, config, provider, li
stener); | |
| 284 if (errmsg != null) { | |
| 285 throw new RunnerError(errmsg); | |
| 286 } | |
| 287 Backend backend = config.getBackends().get(0); | |
| 288 | |
| 289 if (!options.checkOnly()) { | |
| 290 Reader r = provider.getArtifactReader(app, "", backend.getAppExtension()
); | |
| 291 String js = CharStreams.toString(r); | |
| 292 r.close(); | |
| 293 return js; | |
| 294 } | |
| 295 return null; | |
| 296 } catch (IOException e) { | |
| 297 // This can't happen; it's just a StringWriter. | |
| 298 throw new AssertionError(e); | |
| 299 } | |
| 300 } | |
| 301 } | |
| OLD | NEW |