| OLD | NEW |
| 1 import * as dartStyle from 'dart-style'; |
| 1 import * as fs from 'fs'; | 2 import * as fs from 'fs'; |
| 2 import * as path from 'path'; | 3 import * as path from 'path'; |
| 3 import * as ts from 'typescript'; | 4 import * as ts from 'typescript'; |
| 4 | 5 |
| 5 import * as base from './base'; | 6 import * as base from './base'; |
| 6 import {Set, TranspilerBase} from './base'; | 7 import {Set, TranspilerBase} from './base'; |
| 7 | 8 import DeclarationTranspiler from './declaration'; |
| 9 import {FacadeConverter, NameRewriter} from './facade_converter'; |
| 10 import * as merge from './merge'; |
| 8 import mkdirP from './mkdirp'; | 11 import mkdirP from './mkdirp'; |
| 9 import DeclarationTranspiler from './declaration'; | |
| 10 import * as merge from './merge'; | |
| 11 import ModuleTranspiler from './module'; | 12 import ModuleTranspiler from './module'; |
| 12 import TypeTranspiler from './type'; | 13 import TypeTranspiler from './type'; |
| 13 import {FacadeConverter, NameRewriter} from './facade_converter'; | |
| 14 import * as dartStyle from 'dart-style'; | |
| 15 | 14 |
| 16 export interface TranspilerOptions { | 15 export interface TranspilerOptions { |
| 17 /** | 16 /** |
| 18 * Fail on the first error, do not collect multiple. Allows easier debugging a
s stack traces lead | 17 * Fail on the first error, do not collect multiple. Allows easier debugging a
s stack traces lead |
| 19 * directly to the offending line. | 18 * directly to the offending line. |
| 20 */ | 19 */ |
| 21 failFast?: boolean; | 20 failFast?: boolean; |
| 22 /** Whether to generate 'library a.b.c;' names from relative file paths. */ | 21 /** |
| 23 generateLibraryName?: boolean; | 22 * Pass in a module name (e.g.) d3 instead of determining the module name fro
the d.ts files. |
| 23 * This is useful when using libraries that assume they will be loaded with a
JS module loader |
| 24 * without having to use a JS module loader. |
| 25 */ |
| 26 moduleName?: string; |
| 24 /** | 27 /** |
| 25 * A base path to relativize absolute file paths against. This is useful for l
ibrary name | 28 * A base path to relativize absolute file paths against. This is useful for l
ibrary name |
| 26 * generation (see above) and nicer file names in error messages. | 29 * generation (see above) and nicer file names in error messages. |
| 27 */ | 30 */ |
| 28 basePath?: string; | 31 basePath?: string; |
| 29 /** | 32 /** |
| 30 * Use dart:html instead of the raw JavaScript DOM when generated Dart code. | |
| 31 */ | |
| 32 useHtml?: boolean; | |
| 33 /** | |
| 34 * Enforce conventions of public/private keyword and underscore prefix | 33 * Enforce conventions of public/private keyword and underscore prefix |
| 35 */ | 34 */ |
| 36 enforceUnderscoreConventions?: boolean; | 35 enforceUnderscoreConventions?: boolean; |
| 37 /** | 36 /** |
| 38 * Sets a root path to look for typings used by the facade converter. | 37 * Sets a root path to look for typings used by the facade converter. |
| 39 */ | 38 */ |
| 40 typingsRoot?: string; | 39 typingsRoot?: string; |
| 41 | 40 |
| 42 /** | 41 /** |
| 43 * Experimental JS Interop specific option to promote properties with function | 42 * Experimental JS Interop specific option to promote properties with function |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 importsEmitted: Set; | 74 importsEmitted: Set; |
| 76 // Comments attach to all following AST nodes before the next 'physical' token
. Track the earliest | 75 // Comments attach to all following AST nodes before the next 'physical' token
. Track the earliest |
| 77 // offset to avoid printing comments multiple times. | 76 // offset to avoid printing comments multiple times. |
| 78 private lastCommentIdx: number = -1; | 77 private lastCommentIdx: number = -1; |
| 79 private errors: string[] = []; | 78 private errors: string[] = []; |
| 80 | 79 |
| 81 private transpilers: TranspilerBase[]; | 80 private transpilers: TranspilerBase[]; |
| 82 private declarationTranspiler: DeclarationTranspiler; | 81 private declarationTranspiler: DeclarationTranspiler; |
| 83 private fc: FacadeConverter; | 82 private fc: FacadeConverter; |
| 84 private nameRewriter: NameRewriter; | 83 private nameRewriter: NameRewriter; |
| 84 private typeArgumentDepth = 0; |
| 85 | 85 |
| 86 constructor(private options: TranspilerOptions = {}) { | 86 constructor(private options: TranspilerOptions = {}) { |
| 87 this.nameRewriter = new NameRewriter(); | 87 this.nameRewriter = new NameRewriter(); |
| 88 this.fc = new FacadeConverter(this, options.typingsRoot, this.nameRewriter,
options.useHtml); | 88 this.fc = new FacadeConverter(this, options.typingsRoot, this.nameRewriter); |
| 89 this.declarationTranspiler = new DeclarationTranspiler( | 89 this.declarationTranspiler = new DeclarationTranspiler( |
| 90 this, this.fc, options.enforceUnderscoreConventions, options.promoteFunc
tionLikeMembers); | 90 this, this.fc, options.enforceUnderscoreConventions, options.promoteFunc
tionLikeMembers); |
| 91 this.transpilers = [ | 91 this.transpilers = [ |
| 92 new ModuleTranspiler(this, this.fc, options.moduleName), |
| 92 this.declarationTranspiler, | 93 this.declarationTranspiler, |
| 93 new ModuleTranspiler(this, this.fc, options.generateLibraryName), | |
| 94 new TypeTranspiler(this, this.fc), | 94 new TypeTranspiler(this, this.fc), |
| 95 ]; | 95 ]; |
| 96 } | 96 } |
| 97 | 97 |
| 98 /** | 98 /** |
| 99 * Transpiles the given files to Dart. | 99 * Transpiles the given files to Dart. |
| 100 * @param fileNames The input files. | 100 * @param fileNames The input files. |
| 101 * @param destination Location to write files to. Creates files next to their
sources if absent. | 101 * @param destination Location to write files to. Creates files next to their
sources if absent. |
| 102 */ | 102 */ |
| 103 transpile(fileNames: string[], destination?: string): void { | 103 transpile(fileNames: string[], destination?: string): void { |
| 104 if (this.options.basePath) { | 104 if (this.options.basePath) { |
| 105 this.options.basePath = this.normalizeSlashes(path.resolve(this.options.ba
sePath)); | 105 this.options.basePath = this.normalizeSlashes(path.resolve(this.options.ba
sePath)); |
| 106 } | 106 } |
| 107 fileNames = fileNames.map((f) => this.normalizeSlashes(f)); | 107 fileNames = fileNames.map((f) => this.normalizeSlashes(f)); |
| 108 let host = this.createCompilerHost(); | 108 let host = this.createCompilerHost(); |
| 109 if (this.options.basePath && destination === undefined) { | |
| 110 throw new Error( | |
| 111 'Must have a destination path when a basePath is specified ' + this.op
tions.basePath); | |
| 112 } | |
| 113 let destinationRoot = destination || this.options.basePath || ''; | |
| 114 let program = ts.createProgram(fileNames, this.getCompilerOptions(), host); | 109 let program = ts.createProgram(fileNames, this.getCompilerOptions(), host); |
| 115 this.fc.setTypeChecker(program.getTypeChecker()); | 110 this.fc.setTypeChecker(program.getTypeChecker()); |
| 116 this.declarationTranspiler.setTypeChecker(program.getTypeChecker()); | 111 this.declarationTranspiler.setTypeChecker(program.getTypeChecker()); |
| 117 | 112 |
| 118 // Only write files that were explicitly passed in. | 113 // Only write files that were explicitly passed in. |
| 119 let fileSet: {[s: string]: boolean} = {}; | 114 let fileSet: {[s: string]: boolean} = {}; |
| 120 fileNames.forEach((f) => fileSet[f] = true); | 115 fileNames.forEach((f) => fileSet[f] = true); |
| 121 let sourceFiles = program.getSourceFiles().filter((sourceFile) => fileSet[so
urceFile.fileName]); | 116 let sourceFiles = program.getSourceFiles().filter((sourceFile) => fileSet[so
urceFile.fileName]); |
| 122 | 117 |
| 123 this.errors = []; | 118 this.errors = []; |
| 124 | 119 |
| 120 let sourceFileMap: {[s: string]: ts.SourceFile} = {}; |
| 121 sourceFiles.forEach((f: ts.SourceFile) => { sourceFileMap[f.fileName] = f; }
); |
| 122 |
| 123 // Check for global module export declarations and propogate them to |
| 124 // and propogate |
| 125 sourceFiles.forEach((f: ts.SourceFile) => { |
| 126 f.statements.forEach((n: ts.Node) => { |
| 127 if (n.kind !== ts.SyntaxKind.GlobalModuleExportDeclaration) return; |
| 128 // This is the name we are interested in for Dart purposes until Dart su
pports AMD module |
| 129 // loaders. This module name should all be reflected by all modules expo
rted by this |
| 130 // library as we need to specify a global module location for every Dart
library. |
| 131 let globalModuleName = base.ident((n as ts.GlobalModuleExportDeclaration
).name); |
| 132 f.moduleName = globalModuleName; |
| 133 |
| 134 f.statements.forEach((e: ts.Node) => { |
| 135 if (e.kind !== ts.SyntaxKind.ExportDeclaration) return; |
| 136 let exportDecl = e as ts.ExportDeclaration; |
| 137 if (!exportDecl.moduleSpecifier) return; |
| 138 let moduleLocation = <ts.StringLiteral>exportDecl.moduleSpecifier; |
| 139 let location = moduleLocation.text; |
| 140 let resolvedPath = host.resolveModuleNames([location], f.fileName); |
| 141 resolvedPath.forEach((p) => { |
| 142 if (p.isExternalLibraryImport) return; |
| 143 let exportedFile = sourceFileMap[p.resolvedFileName]; |
| 144 exportedFile.moduleName = globalModuleName; |
| 145 }); |
| 146 }); |
| 147 }); |
| 148 }); |
| 149 |
| 125 sourceFiles.forEach((f: ts.SourceFile) => { | 150 sourceFiles.forEach((f: ts.SourceFile) => { |
| 126 let dartCode = this.translate(f); | 151 let dartCode = this.translate(f); |
| 127 let outputFile = this.getOutputPath(path.resolve(f.fileName), destinationR
oot); | 152 |
| 128 mkdirP(path.dirname(outputFile)); | 153 if (destination) { |
| 129 fs.writeFileSync(outputFile, dartCode); | 154 let outputFile = this.getOutputPath(path.resolve(f.fileName), destinatio
n); |
| 155 console.log('Output file:', outputFile); |
| 156 mkdirP(path.dirname(outputFile)); |
| 157 fs.writeFileSync(outputFile, dartCode); |
| 158 } else { |
| 159 console.log(dartCode); |
| 160 } |
| 130 }); | 161 }); |
| 131 this.checkForErrors(program); | 162 this.checkForErrors(program); |
| 132 } | 163 } |
| 133 | 164 |
| 134 translateProgram(program: ts.Program): {[path: string]: string} { | 165 translateProgram(program: ts.Program): {[path: string]: string} { |
| 135 this.fc.setTypeChecker(program.getTypeChecker()); | 166 this.fc.setTypeChecker(program.getTypeChecker()); |
| 136 this.declarationTranspiler.setTypeChecker(program.getTypeChecker()); | 167 this.declarationTranspiler.setTypeChecker(program.getTypeChecker()); |
| 137 | 168 |
| 138 let paths: {[path: string]: string} = {}; | 169 let paths: {[path: string]: string} = {}; |
| 139 this.errors = []; | 170 this.errors = []; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 getCanonicalFileName: (filename) => filename, | 205 getCanonicalFileName: (filename) => filename, |
| 175 getCurrentDirectory: () => '', | 206 getCurrentDirectory: () => '', |
| 176 getNewLine: () => '\n', | 207 getNewLine: () => '\n', |
| 177 }; | 208 }; |
| 178 compilerHost.resolveModuleNames = getModuleResolver(compilerHost); | 209 compilerHost.resolveModuleNames = getModuleResolver(compilerHost); |
| 179 return compilerHost; | 210 return compilerHost; |
| 180 } | 211 } |
| 181 | 212 |
| 182 // Visible for testing. | 213 // Visible for testing. |
| 183 getOutputPath(filePath: string, destinationRoot: string): string { | 214 getOutputPath(filePath: string, destinationRoot: string): string { |
| 184 let relative = this.getRelativeFileName(filePath); | 215 let relative = this.getDartFileName(filePath); |
| 185 let dartFile = relative.replace(/.(js|es6|d\.ts|ts)$/, '.dart'); | 216 return this.normalizeSlashes(path.join(destinationRoot, relative)); |
| 186 return this.normalizeSlashes(path.join(destinationRoot, dartFile)); | |
| 187 } | 217 } |
| 188 | 218 |
| 189 public pushContext(context: OutputContext) { this.outputStack.push(this.output
s[context]); } | 219 public pushContext(context: OutputContext) { this.outputStack.push(this.output
s[context]); } |
| 190 | 220 |
| 191 public popContext() { | 221 public popContext() { |
| 192 if (this.outputStack.length === 0) { | 222 if (this.outputStack.length === 0) { |
| 193 this.reportError(null, 'Attempting to pop output stack when already empty'
); | 223 this.reportError(null, 'Attempting to pop output stack when already empty'
); |
| 194 } | 224 } |
| 195 this.outputStack.pop(); | 225 this.outputStack.pop(); |
| 196 } | 226 } |
| 197 | 227 |
| 198 private translate(sourceFile: ts.SourceFile): string { | 228 private translate(sourceFile: ts.SourceFile): string { |
| 199 this.currentFile = sourceFile; | 229 this.currentFile = sourceFile; |
| 200 this.outputs = []; | 230 this.outputs = []; |
| 201 this.outputStack = []; | 231 this.outputStack = []; |
| 202 this.importsEmitted = {}; | 232 this.importsEmitted = {}; |
| 203 for (let i = 0; i < NUM_OUTPUT_CONTEXTS; ++i) { | 233 for (let i = 0; i < NUM_OUTPUT_CONTEXTS; ++i) { |
| 204 this.outputs.push(new Output()); | 234 this.outputs.push(new Output()); |
| 205 } | 235 } |
| 206 | 236 |
| 207 this.lastCommentIdx = -1; | 237 this.lastCommentIdx = -1; |
| 208 merge.normalizeSourceFile(sourceFile); | 238 merge.normalizeSourceFile(sourceFile, this.fc); |
| 209 this.pushContext(OutputContext.Default); | 239 this.pushContext(OutputContext.Default); |
| 210 this.visit(sourceFile); | 240 this.visit(sourceFile); |
| 211 this.popContext(); | 241 this.popContext(); |
| 212 if (this.outputStack.length > 0) { | 242 if (this.outputStack.length > 0) { |
| 213 this.reportError( | 243 this.reportError( |
| 214 sourceFile, 'Internal error managing output contexts. ' + | 244 sourceFile, 'Internal error managing output contexts. ' + |
| 215 'Inconsistent push and pop context calls.'); | 245 'Inconsistent push and pop context calls.'); |
| 216 } | 246 } |
| 217 let result = ''; | 247 let result = ''; |
| 218 for (let output of this.outputs) { | 248 for (let output of this.outputs) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 let e = new Error(errors.join('\n')); | 290 let e = new Error(errors.join('\n')); |
| 261 e.name = 'DartFacadeError'; | 291 e.name = 'DartFacadeError'; |
| 262 throw e; | 292 throw e; |
| 263 } | 293 } |
| 264 } | 294 } |
| 265 | 295 |
| 266 /** | 296 /** |
| 267 * Returns `filePath`, relativized to the program's `basePath`. | 297 * Returns `filePath`, relativized to the program's `basePath`. |
| 268 * @param filePath Optional path to relativize, defaults to the current file's
path. | 298 * @param filePath Optional path to relativize, defaults to the current file's
path. |
| 269 */ | 299 */ |
| 270 getRelativeFileName(filePath?: string) { | 300 getRelativeFileName(filePath?: string): string { |
| 271 if (filePath === undefined) filePath = path.resolve(this.currentFile.fileNam
e); | 301 if (filePath === undefined) filePath = path.resolve(this.currentFile.fileNam
e); |
| 272 // TODO(martinprobst): Use path.isAbsolute on node v0.12. | 302 // TODO(jacobr): Use path.isAbsolute on node v0.12. |
| 273 if (this.normalizeSlashes(path.resolve('/x/', filePath)) !== filePath) { | 303 if (this.normalizeSlashes(path.resolve('/x/', filePath)) !== filePath) { |
| 274 return filePath; // already relative. | 304 return filePath; // already relative. |
| 275 } | 305 } |
| 276 let base = this.options.basePath || ''; | 306 let base = this.options.basePath || ''; |
| 277 if (filePath.indexOf(base) !== 0 && !filePath.match(/\.d\.ts$/)) { | 307 if (filePath.indexOf(base) !== 0 && !filePath.match(/\.d\.ts$/)) { |
| 278 throw new Error(`Files must be located under base, got ${filePath} vs ${ba
se}`); | 308 throw new Error(`Files must be located under base, got ${filePath} vs ${ba
se}`); |
| 279 } | 309 } |
| 280 return this.normalizeSlashes(path.relative(base, filePath)); | 310 return this.normalizeSlashes(path.relative(base, filePath)); |
| 281 } | 311 } |
| 282 | 312 |
| 313 getDartFileName(filePath?: string): string { |
| 314 if (filePath === undefined) filePath = path.resolve(this.currentFile.fileNam
e); |
| 315 filePath = this.normalizeSlashes(filePath); |
| 316 filePath = filePath.replace(/\.(js|es6|d\.ts|ts)$/, '.dart'); |
| 317 // Normalize from node module file path pattern to |
| 318 filePath = filePath.replace(/([^/]+)\/index.dart$/, '$1.dart'); |
| 319 return this.getRelativeFileName(filePath); |
| 320 } |
| 321 |
| 322 isJsModuleFile(): boolean { |
| 323 // Treat files as being part of js modules if they match the node module fil
e location |
| 324 // convention of module_name/index.js. |
| 325 return !('/' + this.currentFile.fileName).match(/\/index\.(js|es6|d\.ts|ts)$
/); |
| 326 } |
| 327 |
| 283 private get currentOutput(): Output { return this.outputStack[this.outputStack
.length - 1]; } | 328 private get currentOutput(): Output { return this.outputStack[this.outputStack
.length - 1]; } |
| 284 | 329 |
| 285 emit(s: string) { this.currentOutput.emit(s); } | 330 emit(s: string) { this.currentOutput.emit(s); } |
| 286 emitNoSpace(s: string) { this.currentOutput.emitNoSpace(s); } | 331 emitNoSpace(s: string) { this.currentOutput.emitNoSpace(s); } |
| 287 maybeLineBreak() { return this.currentOutput.maybeLineBreak(); } | 332 maybeLineBreak() { return this.currentOutput.maybeLineBreak(); } |
| 288 enterCodeComment() { return this.currentOutput.enterCodeComment(); } | 333 enterCodeComment() { return this.currentOutput.enterCodeComment(); } |
| 289 exitCodeComment() { return this.currentOutput.exitCodeComment(); } | 334 exitCodeComment() { return this.currentOutput.exitCodeComment(); } |
| 335 |
| 336 enterTypeArgument() { this.typeArgumentDepth++; } |
| 337 exitTypeArgument() { this.typeArgumentDepth--; } |
| 338 get insideTypeArgument(): boolean { return this.typeArgumentDepth > 0; } |
| 339 |
| 290 emitType(s: string, comment: string) { return this.currentOutput.emitType(s, c
omment); } | 340 emitType(s: string, comment: string) { return this.currentOutput.emitType(s, c
omment); } |
| 291 get insideCodeComment() { return this.currentOutput.insideCodeComment; } | 341 get insideCodeComment() { return this.currentOutput.insideCodeComment; } |
| 292 | 342 |
| 293 reportError(n: ts.Node, message: string) { | 343 reportError(n: ts.Node, message: string) { |
| 294 let file = n.getSourceFile() || this.currentFile; | 344 let file = n.getSourceFile() || this.currentFile; |
| 295 let fileName = this.getRelativeFileName(file.fileName); | 345 let fileName = this.getRelativeFileName(file.fileName); |
| 296 let start = n.getStart(file); | 346 let start = n.getStart(file); |
| 297 let pos = file.getLineAndCharacterOfPosition(start); | 347 let pos = file.getLineAndCharacterOfPosition(start); |
| 298 // Line and character are 0-based. | 348 // Line and character are 0-based. |
| 299 let fullMessage = `${fileName}:${pos.line + 1}:${pos.character + 1}: ${messa
ge}`; | 349 let fullMessage = `${fileName}:${pos.line + 1}:${pos.character + 1}: ${messa
ge}`; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 // Avoid line breaks inside code comments. | 454 // Avoid line breaks inside code comments. |
| 405 return; | 455 return; |
| 406 } | 456 } |
| 407 | 457 |
| 408 if (!this.firstColumn) { | 458 if (!this.firstColumn) { |
| 409 this.emitNoSpace('\n'); | 459 this.emitNoSpace('\n'); |
| 410 } | 460 } |
| 411 } | 461 } |
| 412 | 462 |
| 413 emit(str: string) { | 463 emit(str: string) { |
| 414 if (this.result.length > 0) { | 464 let buffer = this.insideCodeComment ? this.codeCommentResult : this.result; |
| 415 let buffer = this.insideCodeComment ? this.codeCommentResult : this.result
; | 465 if (buffer.length > 0) { |
| 416 let lastChar = buffer[buffer.length - 1]; | 466 let lastChar = buffer.slice(-1); |
| 417 if (lastChar !== ' ' && lastChar !== '(' && lastChar !== '<' && lastChar !
== '[') { | 467 if (lastChar !== ' ' && lastChar !== '(' && lastChar !== '<' && lastChar !
== '[') { |
| 418 // Avoid emitting a space in obvious cases where a space is not required | 468 // Avoid emitting a space in obvious cases where a space is not required |
| 419 // to make the output slightly prettier in cases where the DartFormatter | 469 // to make the output slightly prettier in cases where the DartFormatter |
| 420 // cannot run such as within a comment where code we emit is not quite | 470 // cannot run such as within a comment where code we emit is not quite |
| 421 // valid Dart code. | 471 // valid Dart code. |
| 422 this.emitNoSpace(' '); | 472 this.emitNoSpace(' '); |
| 423 } | 473 } |
| 424 } | 474 } |
| 425 this.emitNoSpace(str); | 475 this.emitNoSpace(str); |
| 426 } | 476 } |
| 427 | 477 |
| 428 emitNoSpace(str: string) { | 478 emitNoSpace(str: string) { |
| 429 if (str.length === 0) return; | 479 if (str.length === 0) return; |
| 430 if (this.insideCodeComment) { | 480 if (this.insideCodeComment) { |
| 431 this.codeCommentResult += str; | 481 this.codeCommentResult += str; |
| 432 return; | 482 return; |
| 433 } | 483 } |
| 434 this.result += str; | 484 this.result += str; |
| 435 this.firstColumn = str[str.length - 1] === '\n'; | 485 this.firstColumn = str.slice(-1) === '\n'; |
| 436 } | 486 } |
| 437 | 487 |
| 438 enterCodeComment() { | 488 enterCodeComment() { |
| 439 if (this.insideCodeComment) { | 489 if (this.insideCodeComment) { |
| 440 throw 'Cannot nest code comments' + this.codeCommentResult; | 490 throw 'Cannot nest code comments' + this.codeCommentResult; |
| 441 } | 491 } |
| 442 this.insideCodeComment = true; | 492 this.insideCodeComment = true; |
| 443 this.codeCommentResult = ''; | 493 this.codeCommentResult = ''; |
| 444 } | 494 } |
| 445 | 495 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 try { | 544 try { |
| 495 let transpiler = new Transpiler(args); | 545 let transpiler = new Transpiler(args); |
| 496 console.error('Transpiling', args._, 'to', args.destination); | 546 console.error('Transpiling', args._, 'to', args.destination); |
| 497 transpiler.transpile(args._, args.destination); | 547 transpiler.transpile(args._, args.destination); |
| 498 } catch (e) { | 548 } catch (e) { |
| 499 if (e.name !== 'DartFacadeError') throw e; | 549 if (e.name !== 'DartFacadeError') throw e; |
| 500 console.error(e.message); | 550 console.error(e.message); |
| 501 process.exit(1); | 551 process.exit(1); |
| 502 } | 552 } |
| 503 } | 553 } |
| OLD | NEW |