Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1209)

Side by Side Diff: lib/src/compiler.dart

Issue 1243693002: fix for bin/devc relative path (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: rebase Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/src/options.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// Command line tool to run the checker on a Dart program. 5 /// Command line tool to run the checker on a Dart program.
6 library dev_compiler.src.compiler; 6 library dev_compiler.src.compiler;
7 7
8 import 'dart:async'; 8 import 'dart:async';
9 import 'dart:collection'; 9 import 'dart:collection';
10 import 'dart:math' as math; 10 import 'dart:math' as math;
(...skipping 30 matching lines...) Expand all
41 /// messages. 41 /// messages.
42 StreamSubscription setupLogger(Level level, printFn) { 42 StreamSubscription setupLogger(Level level, printFn) {
43 Logger.root.level = level; 43 Logger.root.level = level;
44 return Logger.root.onRecord.listen((LogRecord rec) { 44 return Logger.root.onRecord.listen((LogRecord rec) {
45 printFn('${rec.level.name.toLowerCase()}: ${rec.message}'); 45 printFn('${rec.level.name.toLowerCase()}: ${rec.message}');
46 }); 46 });
47 } 47 }
48 48
49 class BatchCompiler extends AbstractCompiler { 49 class BatchCompiler extends AbstractCompiler {
50 JSGenerator _jsGen; 50 JSGenerator _jsGen;
51 LibraryElement _dartCore;
52 String _runtimeOutputDir;
51 53
52 /// Already compiled sources, so we don't compile them again. 54 /// Already compiled sources, so we don't compile them again.
53 final _compiled = new HashSet<LibraryElement>(); 55 final _compiled = new HashSet<LibraryElement>();
54 56
55 bool _failure = false; 57 bool _failure = false;
56 bool get failure => _failure; 58 bool get failure => _failure;
57 59
58 BatchCompiler(AnalysisContext context, CompilerOptions options, 60 BatchCompiler(AnalysisContext context, CompilerOptions options,
59 {AnalysisErrorListener reporter}) 61 {AnalysisErrorListener reporter})
60 : super(context, options, reporter) { 62 : super(context, options, reporter) {
63 _inputBaseDir = options.inputBaseDir;
61 if (outputDir != null) { 64 if (outputDir != null) {
62 _jsGen = new JSGenerator(this); 65 _jsGen = new JSGenerator(this);
66 _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime');
63 } 67 }
68 _dartCore = context.typeProvider.objectType.element.library;
64 } 69 }
65 70
66 void reset() { 71 void reset() {
67 _compiled.clear(); 72 _compiled.clear();
68 } 73 }
69 74
70 /// Compiles every file in [options.inputs]. 75 /// Compiles every file in [options.inputs].
71 /// Returns true on successful compile. 76 /// Returns true on successful compile.
72 bool run() { 77 bool run() {
73 var clock = new Stopwatch()..start(); 78 var clock = new Stopwatch()..start();
74 options.inputs.forEach(compileFromUriString); 79 options.inputs.forEach(compileFromUriString);
75 clock.stop(); 80 clock.stop();
76 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); 81 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2);
77 _log.fine('Compiled ${_compiled.length} libraries in ${time} s\n'); 82 _log.fine('Compiled ${_compiled.length} libraries in ${time} s\n');
78 83
79 return !_failure; 84 return !_failure;
80 } 85 }
81 86
82 void compileFromUriString(String uriString) { 87 void compileFromUriString(String uriString) {
83 compileFromUri(stringToUri(uriString)); 88 _compileFromUri(stringToUri(uriString));
84 } 89 }
85 90
86 void compileFromUri(Uri uri) { 91 void _compileFromUri(Uri uri) {
92 if (!uri.isAbsolute) {
93 throw new ArgumentError.value('$uri', 'uri', 'must be absolute');
94 }
87 var source = context.sourceFactory.forUri(Uri.encodeFull('$uri')); 95 var source = context.sourceFactory.forUri(Uri.encodeFull('$uri'));
88 if (source == null) throw new ArgumentError.value( 96 if (source == null) {
89 uri.toString(), 'uri', 'could not find source for'); 97 throw new ArgumentError.value('$uri', 'uri', 'could not find source for');
98 }
90 compileSource(source); 99 compileSource(source);
91 } 100 }
92 101
93 void compileSource(Source source) { 102 void compileSource(Source source) {
94 if (AnalysisEngine.isHtmlFileName(source.uri.path)) { 103 if (AnalysisEngine.isHtmlFileName(source.uri.path)) {
95 compileHtml(source); 104 _compileHtml(source);
96 return; 105 return;
97 } 106 }
98
99 compileLibrary(context.computeLibraryElement(source)); 107 compileLibrary(context.computeLibraryElement(source));
100 } 108 }
101 109
102 void compileLibrary(LibraryElement library) { 110 void compileLibrary(LibraryElement library) {
103 if (!_compiled.add(library)) return; 111 if (!_compiled.add(library)) return;
104 if (!options.checkSdk && library.source.uri.scheme == 'dart') return; 112
113 if (!options.checkSdk && library.source.uri.scheme == 'dart') {
114 if (_jsGen != null) _copyDartRuntime();
115 return;
116 }
105 117
106 // TODO(jmesserly): in incremental mode, we can skip the transitive 118 // TODO(jmesserly): in incremental mode, we can skip the transitive
107 // compile of imports/exports. 119 // compile of imports/exports.
120 compileLibrary(_dartCore); // implicit dart:core dependency
108 library.importedLibraries.forEach(compileLibrary); 121 library.importedLibraries.forEach(compileLibrary);
109 library.exportedLibraries.forEach(compileLibrary); 122 library.exportedLibraries.forEach(compileLibrary);
110 123
111 var unitElements = [library.definingCompilationUnit]..addAll(library.parts); 124 var unitElements = [library.definingCompilationUnit]..addAll(library.parts);
112 var units = <CompilationUnit>[]; 125 var units = <CompilationUnit>[];
113 126
114 bool failureInLib = false; 127 bool failureInLib = false;
115 for (var element in unitElements) { 128 for (var element in unitElements) {
116 var unit = context.resolveCompilationUnit(element.source, library); 129 var unit = context.resolveCompilationUnit(element.source, library);
117 units.add(unit); 130 units.add(unit);
118 failureInLib = logErrors(element.source) || failureInLib; 131 failureInLib = logErrors(element.source) || failureInLib;
119 checker.visitCompilationUnit(unit); 132 checker.visitCompilationUnit(unit);
120 if (checker.failure) failureInLib = true; 133 if (checker.failure) failureInLib = true;
121 } 134 }
122 135
123 if (failureInLib) { 136 if (failureInLib) {
124 _failure = true; 137 _failure = true;
125 if (!options.codegenOptions.forceCompile) return; 138 if (!options.codegenOptions.forceCompile) return;
126 } 139 }
127 140
128 if (_jsGen != null) { 141 if (_jsGen != null) {
129 var unit = units.first; 142 var unit = units.first;
130 var parts = units.skip(1).toList(); 143 var parts = units.skip(1).toList();
131 _jsGen.generateLibrary(new LibraryUnit(unit, parts)); 144 _jsGen.generateLibrary(new LibraryUnit(unit, parts));
132 } 145 }
133 } 146 }
134 147
135 void compileHtml(Source source) { 148 void _copyDartRuntime() {
149 for (var file in defaultRuntimeFiles) {
150 var input = path.join(options.runtimeDir, file);
151 var output = path.join(_runtimeOutputDir, file);
152 new Directory(path.dirname(output)).createSync(recursive: true);
153 new File(input).copySync(output);
154 }
155 }
156
157 void _compileHtml(Source source) {
136 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste. 158 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste.
137 var contents = context.getContents(source); 159 var contents = context.getContents(source);
138 var document = html.parse(contents.data, generateSpans: true); 160 var document = html.parse(contents.data, generateSpans: true);
139 var scripts = document.querySelectorAll('script[type="application/dart"]'); 161 var scripts = document.querySelectorAll('script[type="application/dart"]');
140 162
141 var loadedLibs = new LinkedHashSet<Uri>(); 163 var loadedLibs = new LinkedHashSet<Uri>();
142 164
165 var htmlOutDir = path.dirname(getOutputPath(source.uri));
143 for (var script in scripts) { 166 for (var script in scripts) {
144 Source scriptSource = null; 167 Source scriptSource = null;
145 var srcAttr = script.attributes['src']; 168 var srcAttr = script.attributes['src'];
146 if (srcAttr == null) { 169 if (srcAttr == null) {
147 if (script.hasContent()) { 170 if (script.hasContent()) {
148 var fragments = <ScriptFragment>[]; 171 var fragments = <ScriptFragment>[];
149 for (var node in script.nodes) { 172 for (var node in script.nodes) {
150 if (node is html.Text) { 173 if (node is html.Text) {
151 var start = node.sourceSpan.start; 174 var start = node.sourceSpan.start;
152 fragments.add(new ScriptFragment( 175 fragments.add(new ScriptFragment(
153 start.offset, start.line, start.column, node.data)); 176 start.offset, start.line, start.column, node.data));
154 } 177 }
155 } 178 }
156 scriptSource = new DartScript(source, fragments); 179 scriptSource = new DartScript(source, fragments);
157 } 180 }
158 } else if (AnalysisEngine.isDartFileName(srcAttr)) { 181 } else if (AnalysisEngine.isDartFileName(srcAttr)) {
159 scriptSource = context.sourceFactory.resolveUri(source, srcAttr); 182 scriptSource = context.sourceFactory.resolveUri(source, srcAttr);
160 } 183 }
161 184
162 if (scriptSource != null) { 185 if (scriptSource != null) {
163 var lib = context.computeLibraryElement(scriptSource); 186 var lib = context.computeLibraryElement(scriptSource);
164 compileLibrary(lib); 187 compileLibrary(lib);
165 script.replaceWith(_linkLibraries(lib, loadedLibs)); 188 script.replaceWith(_linkLibraries(lib, loadedLibs, from: htmlOutDir));
166 } 189 }
167 } 190 }
168 191
169 // TODO(jmesserly): we need to clean this up so we aren't treating these
170 // as a special case.
171 for (var file in defaultRuntimeFiles) {
172 var input = path.join(options.runtimeDir, file);
173 var output = path.join(outputDir, runtimeFileOutput(file));
174 new Directory(path.dirname(output)).createSync(recursive: true);
175 new File(input).copySync(output);
176 }
177
178 new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE) 192 new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE)
179 ..writeStringSync(document.outerHtml) 193 ..writeStringSync(document.outerHtml)
180 ..writeStringSync('\n') 194 ..writeStringSync('\n')
181 ..closeSync(); 195 ..closeSync();
182 } 196 }
183 197
184 html.DocumentFragment _linkLibraries( 198 html.DocumentFragment _linkLibraries(
185 LibraryElement mainLib, LinkedHashSet<Uri> loaded) { 199 LibraryElement mainLib, LinkedHashSet<Uri> loaded, {String from}) {
200 assert(from != null);
186 var alreadyLoaded = loaded.length; 201 var alreadyLoaded = loaded.length;
187 _collectLibraries(mainLib, loaded); 202 _collectLibraries(mainLib, loaded);
188 203
189 var newLibs = loaded.skip(alreadyLoaded); 204 var newLibs = loaded.skip(alreadyLoaded);
190 var df = new html.DocumentFragment(); 205 var df = new html.DocumentFragment();
191 for (var path in defaultRuntimeFiles) { 206
192 df.append(html_codegen.libraryInclude(runtimeFileOutput(path))); 207 for (var uri in newLibs) {
208 if (uri.scheme == 'dart') {
209 if (uri.path == 'core') {
210 // TODO(jmesserly): it would be nice to not special case these.
211 for (var file in defaultRuntimeFiles) {
212 file = path.join(_runtimeOutputDir, file);
213 df.append(
214 html_codegen.libraryInclude(path.relative(file, from: from)));
215 }
216 }
217 } else {
218 var file = path.join(outputDir, getModulePath(uri));
219 df.append(html_codegen.libraryInclude(path.relative(file, from: from)));
220 }
193 } 221 }
194 for (var uri in newLibs) { 222
195 if (uri.scheme == 'dart') continue;
196 df.append(html_codegen.libraryInclude(getModulePath(uri)));
197 }
198 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri))); 223 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri)));
199 return df; 224 return df;
200 } 225 }
201 226
202 void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) { 227 void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) {
203 var uri = lib.source.uri; 228 var uri = lib.source.uri;
204 if (!loaded.add(uri)) return; 229 if (!loaded.add(uri)) return;
230 _collectLibraries(_dartCore, loaded);
205 for (var l in lib.importedLibraries) _collectLibraries(l, loaded); 231 for (var l in lib.importedLibraries) _collectLibraries(l, loaded);
206 for (var l in lib.exportedLibraries) _collectLibraries(l, loaded); 232 for (var l in lib.exportedLibraries) _collectLibraries(l, loaded);
207 // Move the item to the end of the list. 233 // Move the item to the end of the list.
208 loaded.remove(uri); 234 loaded.remove(uri);
209 loaded.add(uri); 235 loaded.add(uri);
210 } 236 }
211
212 String runtimeFileOutput(String file) =>
213 path.join('dev_compiler', 'runtime', file);
214 } 237 }
215 238
216 abstract class AbstractCompiler { 239 abstract class AbstractCompiler {
217 final CompilerOptions options; 240 final CompilerOptions options;
218 final AnalysisContext context; 241 final AnalysisContext context;
219 final CodeChecker checker; 242 final CodeChecker checker;
220 243
221 AbstractCompiler(AnalysisContext context, CompilerOptions options, 244 AbstractCompiler(AnalysisContext context, CompilerOptions options,
222 [AnalysisErrorListener reporter]) 245 [AnalysisErrorListener reporter])
223 : context = context, 246 : context = context,
224 options = options, 247 options = options,
225 checker = createChecker(context.typeProvider, options.strongOptions, 248 checker = createChecker(context.typeProvider, options.strongOptions,
226 reporter == null ? AnalysisErrorListener.NULL_LISTENER : reporter) { 249 reporter == null ? AnalysisErrorListener.NULL_LISTENER : reporter) {
227 enableDevCompilerInference(context, options.strongOptions); 250 enableDevCompilerInference(context, options.strongOptions);
228 } 251 }
229 252
230 static CodeChecker createChecker(TypeProvider typeProvider, 253 static CodeChecker createChecker(TypeProvider typeProvider,
231 StrongModeOptions options, AnalysisErrorListener reporter) { 254 StrongModeOptions options, AnalysisErrorListener reporter) {
232 return new CodeChecker( 255 return new CodeChecker(
233 new RestrictedRules(typeProvider, options: options), reporter, options); 256 new RestrictedRules(typeProvider, options: options), reporter, options);
234 } 257 }
235 258
236 String get outputDir => options.codegenOptions.outputDir; 259 String get outputDir => options.codegenOptions.outputDir;
237 TypeRules get rules => checker.rules; 260 TypeRules get rules => checker.rules;
238 AnalysisErrorListener get reporter => checker.reporter; 261 AnalysisErrorListener get reporter => checker.reporter;
239 262
240 Uri stringToUri(String uriString) { 263 Uri stringToUri(String uriString) {
241 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') 264 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:')
242 ? Uri.parse(uriString) 265 ? Uri.parse(uriString)
243 : new Uri.file(uriString); 266 : new Uri.file(path.absolute(uriString));
244 return uri; 267 return uri;
245 } 268 }
246 269
247 /// Directory presumed to be the common prefix for all input file:// URIs. 270 /// Directory presumed to be the common prefix for all input file:// URIs.
248 /// Used when computing output paths. 271 /// Used when computing output paths.
249 /// 272 ///
250 /// For example: 273 /// For example:
251 /// dartdevc -o out foo/a.dart bar/b.dart 274 /// dartdevc -o out foo/a.dart bar/b.dart
252 /// 275 ///
253 /// Will produce: 276 /// Will produce:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 /// * dart:core -> dart/core 320 /// * dart:core -> dart/core
298 /// * file:foo/bar/baz.dart -> foo/bar/baz 321 /// * file:foo/bar/baz.dart -> foo/bar/baz
299 /// * package:qux/qux.dart -> qux/qux 322 /// * package:qux/qux.dart -> qux/qux
300 /// 323 ///
301 /// For file: URLs this will also make them relative to [inputBaseDir]. 324 /// For file: URLs this will also make them relative to [inputBaseDir].
302 // TODO(jmesserly): we need to figure out a way to keep package and file URLs 325 // TODO(jmesserly): we need to figure out a way to keep package and file URLs
303 // from conflicting. 326 // from conflicting.
304 String getModuleName(Uri uri) { 327 String getModuleName(Uri uri) {
305 var filepath = path.withoutExtension(uri.path); 328 var filepath = path.withoutExtension(uri.path);
306 if (uri.scheme == 'dart') { 329 if (uri.scheme == 'dart') {
307 filepath = 'dart/$filepath'; 330 return 'dart/$filepath';
308 } else if (uri.scheme == 'file') { 331 } else if (uri.scheme == 'file') {
309 filepath = path.relative(filepath, from: inputBaseDir); 332 return path.relative(filepath, from: inputBaseDir);
310 } else { 333 } else {
311 assert(uri.scheme == 'package'); 334 assert(uri.scheme == 'package');
312 // filepath is good here, we want the output to start with a directory 335 // filepath is good here, we want the output to start with a directory
313 // matching the package name. 336 // matching the package name.
337 return filepath;
314 } 338 }
315 return filepath;
316 } 339 }
317 340
318 /// Log any errors encountered when resolving [source] and return whether any 341 /// Log any errors encountered when resolving [source] and return whether any
319 /// errors were found. 342 /// errors were found.
320 bool logErrors(Source source) { 343 bool logErrors(Source source) {
321 List<AnalysisError> errors = context.computeErrors(source); 344 List<AnalysisError> errors = context.computeErrors(source);
322 bool failure = false; 345 bool failure = false;
323 if (errors.isNotEmpty) { 346 if (errors.isNotEmpty) {
324 for (var error in errors) { 347 for (var error in errors) {
325 // Always skip TODOs. 348 // Always skip TODOs.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 'dart.async', 382 'dart.async',
360 'dart._foreign_helper', 383 'dart._foreign_helper',
361 'dart._js_embedded_names', 384 'dart._js_embedded_names',
362 'dart._js_helper', 385 'dart._js_helper',
363 'dart.isolate', 386 'dart.isolate',
364 'dart.typed_data', 387 'dart.typed_data',
365 'dart._native_typed_data', 388 'dart._native_typed_data',
366 'dart._isolate_helper', 389 'dart._isolate_helper',
367 'dart._js_primitives', 390 'dart._js_primitives',
368 'dart.convert', 391 'dart.convert',
392 // TODO(jmesserly): these are not part of corelib library cycle, and shouldn't
393 // be listed here. Instead, their source should be copied on demand if they
394 // are actually used by the application.
369 'dart.mirrors', 395 'dart.mirrors',
370 'dart._js_mirrors', 396 'dart._js_mirrors',
371 'dart.js' 397 'dart.js'
372 // _foreign_helper is not included, as it only defines the JS builtin that 398 // _foreign_helper is not included, as it only defines the JS builtin that
373 // the compiler handles at compile time. 399 // the compiler handles at compile time.
374 ]; 400 ];
375 401
376 /// Runtime files added to all applications when running the compiler in the 402 /// Runtime files added to all applications when running the compiler in the
377 /// command line. 403 /// command line.
378 final defaultRuntimeFiles = () { 404 final defaultRuntimeFiles = () {
379 var files = [ 405 var files = [
380 'harmony_feature_check.js', 406 'harmony_feature_check.js',
381 'dart_utils.js', 407 'dart_utils.js',
382 'dart_library.js', 408 'dart_library.js',
383 '_errors.js', 409 '_errors.js',
384 '_types.js', 410 '_types.js',
385 '_rtti.js', 411 '_rtti.js',
386 '_classes.js', 412 '_classes.js',
387 '_operations.js', 413 '_operations.js',
388 'dart_runtime.js', 414 'dart_runtime.js',
389 ]; 415 ];
390 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); 416 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js'));
391 return files; 417 return files;
392 }(); 418 }();
393 419
394 final _log = new Logger('dev_compiler.src.compiler'); 420 final _log = new Logger('dev_compiler.src.compiler');
OLDNEW
« no previous file with comments | « no previous file | lib/src/options.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698