OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:convert' show JSON; | 5 import 'dart:convert' show JSON; |
6 import 'dart:io'; | 6 import 'dart:io'; |
7 import 'package:args/command_runner.dart'; | 7 import 'package:args/command_runner.dart'; |
8 import 'package:analyzer/src/generated/source.dart' show Source; | 8 import 'package:analyzer/src/generated/source.dart' show Source; |
9 import 'package:analyzer/src/summary/package_bundle_reader.dart' | 9 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
10 show InSummarySource; | 10 show InSummarySource; |
11 import 'compiler.dart' | 11 import 'compiler.dart' |
12 show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler; | 12 show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler; |
13 import '../analyzer/context.dart' show AnalyzerOptions; | 13 import '../analyzer/context.dart' show AnalyzerOptions; |
14 import 'package:path/path.dart' as path; | 14 import 'package:path/path.dart' as path; |
15 | 15 |
16 typedef void MessageHandler(Object message); | 16 typedef void MessageHandler(Object message); |
17 | 17 |
18 /// The command for invoking the modular compiler. | 18 /// The command for invoking the modular compiler. |
19 class CompileCommand extends Command { | 19 class CompileCommand extends Command { |
20 get name => 'compile'; | |
21 get description => 'Compile a set of Dart files into a JavaScript module.'; | |
22 final MessageHandler messageHandler; | 20 final MessageHandler messageHandler; |
| 21 CompilerOptions _compilerOptions; |
23 | 22 |
24 CompileCommand({MessageHandler messageHandler}) | 23 CompileCommand({MessageHandler messageHandler}) |
25 : this.messageHandler = messageHandler ?? print { | 24 : this.messageHandler = messageHandler ?? print { |
26 argParser.addOption('out', abbr: 'o', help: 'Output file (required)'); | 25 argParser.addOption('out', abbr: 'o', help: 'Output file (required)'); |
27 argParser.addOption('module-root', | 26 argParser.addOption('module-root', |
28 help: 'Root module directory. ' | 27 help: 'Root module directory. ' |
29 'Generated module paths are relative to this root.'); | 28 'Generated module paths are relative to this root.'); |
30 argParser.addOption('build-root', | 29 argParser.addOption('build-root', |
31 help: 'Root of source files. ' | 30 help: 'Root of source files. ' |
32 'Generated library names are relative to this root.'); | 31 'Generated library names are relative to this root.'); |
33 CompilerOptions.addArguments(argParser); | 32 CompilerOptions.addArguments(argParser); |
34 AnalyzerOptions.addArguments(argParser); | 33 AnalyzerOptions.addArguments(argParser); |
35 } | 34 } |
36 | 35 |
| 36 get name => 'compile'; |
| 37 get description => 'Compile a set of Dart files into a JavaScript module.'; |
| 38 |
37 @override | 39 @override |
38 void run() { | 40 void run() { |
39 var compiler = | 41 var compiler = |
40 new ModuleCompiler(new AnalyzerOptions.fromArguments(argResults)); | 42 new ModuleCompiler(new AnalyzerOptions.fromArguments(argResults)); |
41 var compilerOptions = new CompilerOptions.fromArguments(argResults); | 43 _compilerOptions = new CompilerOptions.fromArguments(argResults); |
42 var outPath = argResults['out']; | 44 var outPath = argResults['out']; |
43 | 45 |
44 if (outPath == null) { | 46 if (outPath == null) { |
45 usageException('Please include the output file location. For example:\n' | 47 usageException('Please include the output file location. For example:\n' |
46 ' -o PATH/TO/OUTPUT_FILE.js'); | 48 ' -o PATH/TO/OUTPUT_FILE.js'); |
47 } | 49 } |
48 | 50 |
49 var buildRoot = argResults['build-root'] as String; | 51 var buildRoot = argResults['build-root'] as String; |
50 if (buildRoot != null) { | 52 if (buildRoot != null) { |
51 buildRoot = path.absolute(buildRoot); | 53 buildRoot = path.absolute(buildRoot); |
(...skipping 15 matching lines...) Expand all Loading... |
67 modulePath = path.basenameWithoutExtension(outPath); | 69 modulePath = path.basenameWithoutExtension(outPath); |
68 } | 70 } |
69 | 71 |
70 if (argResults.rest.isEmpty) { | 72 if (argResults.rest.isEmpty) { |
71 usageException('Please pass at least one source file as an argument.'); | 73 usageException('Please pass at least one source file as an argument.'); |
72 } | 74 } |
73 | 75 |
74 var unit = new BuildUnit(modulePath, buildRoot, argResults.rest, | 76 var unit = new BuildUnit(modulePath, buildRoot, argResults.rest, |
75 (source) => _moduleForLibrary(moduleRoot, source)); | 77 (source) => _moduleForLibrary(moduleRoot, source)); |
76 | 78 |
77 JSModuleFile module = compiler.compile(unit, compilerOptions); | 79 JSModuleFile module = compiler.compile(unit, _compilerOptions); |
78 module.errors.forEach(messageHandler); | 80 module.errors.forEach(messageHandler); |
79 | 81 |
80 if (!module.isValid) throw new CompileErrorException(); | 82 if (!module.isValid) throw new CompileErrorException(); |
81 | 83 |
82 // Write JS file, as well as source map and summary (if requested). | 84 // Write JS file, as well as source map and summary (if requested). |
83 new File(outPath).writeAsStringSync(module.code); | 85 new File(outPath).writeAsStringSync(module.code); |
84 if (module.sourceMap != null) { | 86 if (module.sourceMap != null) { |
85 var mapPath = outPath + '.map'; | 87 var mapPath = outPath + '.map'; |
86 new File(mapPath) | 88 new File(mapPath) |
87 .writeAsStringSync(JSON.encode(module.placeSourceMap(mapPath))); | 89 .writeAsStringSync(JSON.encode(module.placeSourceMap(mapPath))); |
88 } | 90 } |
89 if (module.summaryBytes != null) { | 91 if (module.summaryBytes != null) { |
90 var summaryPath = path.withoutExtension(outPath) + '.sum'; | 92 var summaryPath = path.withoutExtension(outPath) + |
| 93 '.${_compilerOptions.summaryExtension}'; |
91 new File(summaryPath).writeAsBytesSync(module.summaryBytes); | 94 new File(summaryPath).writeAsBytesSync(module.summaryBytes); |
92 } | 95 } |
93 } | 96 } |
94 | 97 |
95 String _moduleForLibrary(String moduleRoot, Source source) { | 98 String _moduleForLibrary(String moduleRoot, Source source) { |
96 if (source is InSummarySource) { | 99 if (source is InSummarySource) { |
97 var summaryPath = source.summaryPath; | 100 var summaryPath = source.summaryPath; |
98 if (path.isWithin(moduleRoot, summaryPath)) { | 101 var ext = '.${_compilerOptions.summaryExtension}'; |
99 return path | 102 if (path.isWithin(moduleRoot, summaryPath) && summaryPath.endsWith(ext)) { |
100 .withoutExtension(path.relative(summaryPath, from: moduleRoot)); | 103 var buildUnitPath = |
| 104 summaryPath.substring(0, summaryPath.length - ext.length); |
| 105 return path.relative(buildUnitPath, from: moduleRoot); |
101 } | 106 } |
102 | 107 |
103 throw usageException( | 108 throw usageException( |
104 'Imported file ${source.uri} is not within the module root ' | 109 'Imported file ${source.uri} is not within the module root ' |
105 'directory $moduleRoot'); | 110 'directory $moduleRoot'); |
106 } | 111 } |
107 | 112 |
108 throw usageException( | 113 throw usageException( |
109 'Imported file "${source.uri}" was not found as a summary or source ' | 114 'Imported file "${source.uri}" was not found as a summary or source ' |
110 'file. Please pass in either the summary or the source file ' | 115 'file. Please pass in either the summary or the source file ' |
111 'for this import.'); | 116 'for this import.'); |
112 } | 117 } |
113 } | 118 } |
114 | 119 |
115 /// Thrown when the input source code has errors. | 120 /// Thrown when the input source code has errors. |
116 class CompileErrorException implements Exception { | 121 class CompileErrorException implements Exception { |
117 toString() => '\nPlease fix all errors before compiling (warnings are okay).'; | 122 toString() => '\nPlease fix all errors before compiling (warnings are okay).'; |
118 } | 123 } |
OLD | NEW |