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

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: format 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);
130
131 // TODO(jmesserly): this hack is to avoid compiling the same compilation
132 // unit to JS twice. We mutate the AST, so it's not safe to run more than
133 // once on the same unit.
134 if (element.library == library) {
135 if (unit.getProperty(_propertyName) == true) return;
136 unit.setProperty(_propertyName, true);
137 }
138
117 units.add(unit); 139 units.add(unit);
118 failureInLib = logErrors(element.source) || failureInLib; 140 failureInLib = logErrors(element.source) || failureInLib;
119 checker.visitCompilationUnit(unit); 141 checker.visitCompilationUnit(unit);
120 if (checker.failure) failureInLib = true; 142 if (checker.failure) failureInLib = true;
121 } 143 }
122 144
123 if (failureInLib) { 145 if (failureInLib) {
124 _failure = true; 146 _failure = true;
125 if (!options.codegenOptions.forceCompile) return; 147 if (!options.codegenOptions.forceCompile) return;
126 } 148 }
127 149
128 if (_jsGen != null) { 150 if (_jsGen != null) {
129 var unit = units.first; 151 var unit = units.first;
130 var parts = units.skip(1).toList(); 152 var parts = units.skip(1).toList();
131 153
132 // TODO(jmesserly): this hack is to avoid compiling the same compilation
133 // unit to JS twice. We mutate the AST, so it's not safe to run more than
134 // once on the same unit.
135 if (unit.getProperty(_propertyName) == true) return;
136 unit.setProperty(_propertyName, true);
137
138 _jsGen.generateLibrary(new LibraryUnit(unit, parts)); 154 _jsGen.generateLibrary(new LibraryUnit(unit, parts));
139 } 155 }
140 } 156 }
141 157
142 static const String _propertyName = 'dev_compiler.BatchCompiler.isCompiled'; 158 static const String _propertyName = 'dev_compiler.BatchCompiler.isCompiled';
vsm 2015/07/23 16:42:45 Perhaps rename _propertyName to _isCompiled?
Jennifer Messerly 2015/07/23 16:50:35 _propertyName is gone after I rebase against maste
143 159
144 void compileHtml(Source source) { 160 void _copyDartRuntime() {
161 for (var file in defaultRuntimeFiles) {
162 var input = path.join(options.runtimeDir, file);
163 var output = path.join(_runtimeOutputDir, file);
164 new Directory(path.dirname(output)).createSync(recursive: true);
165 new File(input).copySync(output);
166 }
167 }
168
169 void _compileHtml(Source source) {
145 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste. 170 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste.
146 var contents = context.getContents(source); 171 var contents = context.getContents(source);
147 var document = html.parse(contents.data, generateSpans: true); 172 var document = html.parse(contents.data, generateSpans: true);
148 var scripts = document.querySelectorAll('script[type="application/dart"]'); 173 var scripts = document.querySelectorAll('script[type="application/dart"]');
149 174
150 var loadedLibs = new LinkedHashSet<Uri>(); 175 var loadedLibs = new LinkedHashSet<Uri>();
151 176
177 var htmlOutDir = path.dirname(getOutputPath(source.uri));
152 for (var script in scripts) { 178 for (var script in scripts) {
153 Source scriptSource = null; 179 Source scriptSource = null;
154 var srcAttr = script.attributes['src']; 180 var srcAttr = script.attributes['src'];
155 if (srcAttr == null) { 181 if (srcAttr == null) {
156 if (script.hasContent()) { 182 if (script.hasContent()) {
157 var fragments = <ScriptFragment>[]; 183 var fragments = <ScriptFragment>[];
158 for (var node in script.nodes) { 184 for (var node in script.nodes) {
159 if (node is html.Text) { 185 if (node is html.Text) {
160 var start = node.sourceSpan.start; 186 var start = node.sourceSpan.start;
161 fragments.add(new ScriptFragment( 187 fragments.add(new ScriptFragment(
162 start.offset, start.line, start.column, node.data)); 188 start.offset, start.line, start.column, node.data));
163 } 189 }
164 } 190 }
165 scriptSource = new DartScript(source, fragments); 191 scriptSource = new DartScript(source, fragments);
166 } 192 }
167 } else if (AnalysisEngine.isDartFileName(srcAttr)) { 193 } else if (AnalysisEngine.isDartFileName(srcAttr)) {
168 scriptSource = context.sourceFactory.resolveUri(source, srcAttr); 194 scriptSource = context.sourceFactory.resolveUri(source, srcAttr);
169 } 195 }
170 196
171 if (scriptSource != null) { 197 if (scriptSource != null) {
172 var lib = context.computeLibraryElement(scriptSource); 198 var lib = context.computeLibraryElement(scriptSource);
173 compileLibrary(lib); 199 compileLibrary(lib);
174 script.replaceWith(_linkLibraries(lib, loadedLibs)); 200 script.replaceWith(_linkLibraries(lib, loadedLibs, from: htmlOutDir));
175 } 201 }
176 } 202 }
177 203
178 // TODO(jmesserly): we need to clean this up so we aren't treating these
179 // as a special case.
180 for (var file in defaultRuntimeFiles) {
181 var input = path.join(options.runtimeDir, file);
182 var output = path.join(outputDir, runtimeFileOutput(file));
183 new Directory(path.dirname(output)).createSync(recursive: true);
184 new File(input).copySync(output);
185 }
186
187 new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE) 204 new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE)
188 ..writeStringSync(document.outerHtml) 205 ..writeStringSync(document.outerHtml)
189 ..writeStringSync('\n') 206 ..writeStringSync('\n')
190 ..closeSync(); 207 ..closeSync();
191 } 208 }
192 209
193 html.DocumentFragment _linkLibraries( 210 html.DocumentFragment _linkLibraries(
194 LibraryElement mainLib, LinkedHashSet<Uri> loaded) { 211 LibraryElement mainLib, LinkedHashSet<Uri> loaded, {String from}) {
212 assert(from != null);
195 var alreadyLoaded = loaded.length; 213 var alreadyLoaded = loaded.length;
196 _collectLibraries(mainLib, loaded); 214 _collectLibraries(mainLib, loaded);
197 215
198 var newLibs = loaded.skip(alreadyLoaded); 216 var newLibs = loaded.skip(alreadyLoaded);
199 var df = new html.DocumentFragment(); 217 var df = new html.DocumentFragment();
200 for (var path in defaultRuntimeFiles) { 218
201 df.append(html_codegen.libraryInclude(runtimeFileOutput(path))); 219 for (var uri in newLibs) {
220 if (uri.scheme == 'dart') {
221 if (uri.path == 'core') {
222 // TODO(jmesserly): it would be nice to not special case these.
223 for (var file in defaultRuntimeFiles) {
vsm 2015/07/23 16:42:45 Will this pick up dart:mirrors? I think core does
Jennifer Messerly 2015/07/23 16:50:35 dart:mirrors depends on dart:core, so we always hi
224 file = path.join(_runtimeOutputDir, file);
225 df.append(
226 html_codegen.libraryInclude(path.relative(file, from: from)));
227 }
228 }
229 } else {
230 var file = path.join(outputDir, getModulePath(uri));
231 df.append(html_codegen.libraryInclude(path.relative(file, from: from)));
232 }
202 } 233 }
203 for (var uri in newLibs) { 234
204 if (uri.scheme == 'dart') continue;
205 df.append(html_codegen.libraryInclude(getModulePath(uri)));
206 }
207 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri))); 235 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri)));
208 return df; 236 return df;
209 } 237 }
210 238
211 void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) { 239 void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) {
212 var uri = lib.source.uri; 240 var uri = lib.source.uri;
213 if (!loaded.add(uri)) return; 241 if (!loaded.add(uri)) return;
242 _collectLibraries(_dartCore, loaded);
214 for (var l in lib.importedLibraries) _collectLibraries(l, loaded); 243 for (var l in lib.importedLibraries) _collectLibraries(l, loaded);
215 for (var l in lib.exportedLibraries) _collectLibraries(l, loaded); 244 for (var l in lib.exportedLibraries) _collectLibraries(l, loaded);
216 // Move the item to the end of the list. 245 // Move the item to the end of the list.
217 loaded.remove(uri); 246 loaded.remove(uri);
218 loaded.add(uri); 247 loaded.add(uri);
219 } 248 }
220
221 String runtimeFileOutput(String file) =>
222 path.join('dev_compiler', 'runtime', file);
223 } 249 }
224 250
225 abstract class AbstractCompiler { 251 abstract class AbstractCompiler {
226 final CompilerOptions options; 252 final CompilerOptions options;
227 final AnalysisContext context; 253 final AnalysisContext context;
228 final CodeChecker checker; 254 final CodeChecker checker;
229 255
230 AbstractCompiler(AnalysisContext context, CompilerOptions options, 256 AbstractCompiler(AnalysisContext context, CompilerOptions options,
231 [AnalysisErrorListener reporter]) 257 [AnalysisErrorListener reporter])
232 : context = context, 258 : context = context,
233 options = options, 259 options = options,
234 checker = createChecker(context.typeProvider, options.strongOptions, 260 checker = createChecker(context.typeProvider, options.strongOptions,
235 reporter == null ? AnalysisErrorListener.NULL_LISTENER : reporter) { 261 reporter == null ? AnalysisErrorListener.NULL_LISTENER : reporter) {
236 enableDevCompilerInference(context, options.strongOptions); 262 enableDevCompilerInference(context, options.strongOptions);
237 } 263 }
238 264
239 static CodeChecker createChecker(TypeProvider typeProvider, 265 static CodeChecker createChecker(TypeProvider typeProvider,
240 StrongModeOptions options, AnalysisErrorListener reporter) { 266 StrongModeOptions options, AnalysisErrorListener reporter) {
241 return new CodeChecker( 267 return new CodeChecker(
242 new RestrictedRules(typeProvider, options: options), reporter, options); 268 new RestrictedRules(typeProvider, options: options), reporter, options);
243 } 269 }
244 270
245 String get outputDir => options.codegenOptions.outputDir; 271 String get outputDir => options.codegenOptions.outputDir;
246 TypeRules get rules => checker.rules; 272 TypeRules get rules => checker.rules;
247 AnalysisErrorListener get reporter => checker.reporter; 273 AnalysisErrorListener get reporter => checker.reporter;
248 274
249 Uri stringToUri(String uriString) { 275 Uri stringToUri(String uriString) {
250 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') 276 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:')
251 ? Uri.parse(uriString) 277 ? Uri.parse(uriString)
252 : new Uri.file(uriString); 278 : new Uri.file(path.absolute(uriString));
253 return uri; 279 return uri;
254 } 280 }
255 281
256 /// Directory presumed to be the common prefix for all input file:// URIs. 282 /// Directory presumed to be the common prefix for all input file:// URIs.
257 /// Used when computing output paths. 283 /// Used when computing output paths.
258 /// 284 ///
259 /// For example: 285 /// For example:
260 /// dartdevc -o out foo/a.dart bar/b.dart 286 /// dartdevc -o out foo/a.dart bar/b.dart
261 /// 287 ///
262 /// Will produce: 288 /// Will produce:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 /// * dart:core -> dart/core 332 /// * dart:core -> dart/core
307 /// * file:foo/bar/baz.dart -> foo/bar/baz 333 /// * file:foo/bar/baz.dart -> foo/bar/baz
308 /// * package:qux/qux.dart -> qux/qux 334 /// * package:qux/qux.dart -> qux/qux
309 /// 335 ///
310 /// For file: URLs this will also make them relative to [inputBaseDir]. 336 /// For file: URLs this will also make them relative to [inputBaseDir].
311 // TODO(jmesserly): we need to figure out a way to keep package and file URLs 337 // TODO(jmesserly): we need to figure out a way to keep package and file URLs
312 // from conflicting. 338 // from conflicting.
313 String getModuleName(Uri uri) { 339 String getModuleName(Uri uri) {
314 var filepath = path.withoutExtension(uri.path); 340 var filepath = path.withoutExtension(uri.path);
315 if (uri.scheme == 'dart') { 341 if (uri.scheme == 'dart') {
316 filepath = 'dart/$filepath'; 342 return 'dart/$filepath';
317 } else if (uri.scheme == 'file') { 343 } else if (uri.scheme == 'file') {
318 filepath = path.relative(filepath, from: inputBaseDir); 344 return path.relative(filepath, from: inputBaseDir);
319 } else { 345 } else {
320 assert(uri.scheme == 'package'); 346 assert(uri.scheme == 'package');
321 // filepath is good here, we want the output to start with a directory 347 // filepath is good here, we want the output to start with a directory
322 // matching the package name. 348 // matching the package name.
349 return filepath;
323 } 350 }
324 return filepath;
325 } 351 }
326 352
327 /// Log any errors encountered when resolving [source] and return whether any 353 /// Log any errors encountered when resolving [source] and return whether any
328 /// errors were found. 354 /// errors were found.
329 bool logErrors(Source source) { 355 bool logErrors(Source source) {
330 List<AnalysisError> errors = context.computeErrors(source); 356 List<AnalysisError> errors = context.computeErrors(source);
331 bool failure = false; 357 bool failure = false;
332 if (errors.isNotEmpty) { 358 if (errors.isNotEmpty) {
333 for (var error in errors) { 359 for (var error in errors) {
334 // Always skip TODOs. 360 // Always skip TODOs.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 '_rtti.js', 420 '_rtti.js',
395 '_classes.js', 421 '_classes.js',
396 '_operations.js', 422 '_operations.js',
397 'dart_runtime.js', 423 'dart_runtime.js',
398 ]; 424 ];
399 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); 425 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js'));
400 return files; 426 return files;
401 }(); 427 }();
402 428
403 final _log = new Logger('dev_compiler.src.compiler'); 429 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