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

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

Issue 2760923004: Eliminate multi-callback structure for LibraryLoader. (Closed)
Patch Set: . Created 3 years, 9 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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 library dart2js.library_loader; 5 library dart2js.library_loader;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'common/names.dart' show Uris; 9 import 'common/names.dart' show Uris;
10 import 'common/tasks.dart' show CompilerTask, Measurer; 10 import 'common/tasks.dart' show CompilerTask, Measurer;
(...skipping 11 matching lines...) Expand all
22 DeferredLoaderGetterElementX, 22 DeferredLoaderGetterElementX,
23 ErroneousElementX, 23 ErroneousElementX,
24 ExportElementX, 24 ExportElementX,
25 ImportElementX, 25 ImportElementX,
26 LibraryElementX, 26 LibraryElementX,
27 LibraryDependencyElementX, 27 LibraryDependencyElementX,
28 PrefixElementX, 28 PrefixElementX,
29 SyntheticImportElement; 29 SyntheticImportElement;
30 import 'enqueue.dart' show DeferredAction; 30 import 'enqueue.dart' show DeferredAction;
31 import 'environment.dart'; 31 import 'environment.dart';
32 import 'io/source_file.dart' show SourceFile;
33 import 'patch_parser.dart' show PatchParserTask;
32 import 'resolved_uri_translator.dart'; 34 import 'resolved_uri_translator.dart';
33 import 'script.dart'; 35 import 'script.dart';
34 import 'serialization/serialization.dart' show LibraryDeserializer; 36 import 'serialization/serialization.dart' show LibraryDeserializer;
35 import 'tree/tree.dart'; 37 import 'tree/tree.dart';
36 import 'util/util.dart' show Link, LinkBuilder; 38 import 'util/util.dart' show Link, LinkBuilder;
37 39
40 import 'package:front_end/src/fasta/scanner.dart' show Token;
41
38 typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction( 42 typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction(
39 Iterable<LibraryElement> libraries); 43 Iterable<LibraryElement> libraries);
40 44
45 typedef Uri PatchResolverFunction(String dartLibraryPath);
46
41 /** 47 /**
42 * [CompilerTask] for loading libraries and setting up the import/export scopes. 48 * [CompilerTask] for loading libraries and setting up the import/export scopes.
43 * 49 *
44 * The library loader uses four different kinds of URIs in different parts of 50 * The library loader uses four different kinds of URIs in different parts of
45 * the loading process. 51 * the loading process.
46 * 52 *
47 * ## User URI ## 53 * ## User URI ##
48 * 54 *
49 * A 'user URI' is a URI provided by the user in code and as the main entry URI 55 * A 'user URI' is a URI provided by the user in code and as the main entry URI
50 * at the command line. These generally come in 3 versions: 56 * at the command line. These generally come in 3 versions:
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 * do _not_ resolve to the same library when the package root URI happens to 137 * do _not_ resolve to the same library when the package root URI happens to
132 * point to the 'packages' folder. 138 * point to the 'packages' folder.
133 * 139 *
134 */ 140 */
135 abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask { 141 abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask {
136 factory LibraryLoaderTask( 142 factory LibraryLoaderTask(
137 ResolvedUriTranslator uriTranslator, 143 ResolvedUriTranslator uriTranslator,
138 ScriptLoader scriptLoader, 144 ScriptLoader scriptLoader,
139 ElementScanner scriptScanner, 145 ElementScanner scriptScanner,
140 LibraryDeserializer deserializer, 146 LibraryDeserializer deserializer,
141 LibraryLoaderListener listener, 147 PatchResolverFunction patchResolverFunc,
148 PatchParserTask patchParser,
142 Environment environment, 149 Environment environment,
143 DiagnosticReporter reporter, 150 DiagnosticReporter reporter,
144 Measurer measurer) = _LibraryLoaderTask; 151 Measurer measurer) = _LibraryLoaderTask;
145 152
146 /// Returns all libraries that have been loaded. 153 /// Returns all libraries that have been loaded.
147 Iterable<LibraryElement> get libraries; 154 Iterable<LibraryElement> get libraries;
148 155
149 /// Loads the library specified by the [resolvedUri] and returns its 156 /// Loads the library specified by the [resolvedUri] and returns the
150 /// [LibraryElement]. 157 /// [LoadedLibraries] that were loaded to load the specified uri. The
158 /// [LibraryElement] itself can be found by calling
159 /// `loadedLibraries.rootLibrary`
Siggi Cherem (dart-lang) 2017/03/24 17:40:28 nit: add a `.` at the end.
Emily Fortuna 2017/03/24 18:30:19 Done.
151 /// 160 ///
152 /// If the library is not already loaded, the method creates the 161 /// If the library is not already loaded, the method creates the
153 /// [LibraryElement] for the library and computes the import/export scope, 162 /// [LibraryElement] for the library and computes the import/export scope,
154 /// loading and computing the import/export scopes of all required libraries 163 /// loading and computing the import/export scopes of all required libraries
155 /// in the process. The method handles cyclic dependency between libraries. 164 /// in the process. The method handles cyclic dependency between libraries.
156 /// 165 ///
157 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the 166 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the
158 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only 167 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only
159 /// used for analysis through [Compiler.analyzeUri]. 168 /// used for analysis through [Compiler.analyzeUri].
160 Future<LibraryElement> loadLibrary(Uri resolvedUri, 169 Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
161 {bool skipFileWithPartOfTag: false}); 170 {bool skipFileWithPartOfTag: false});
162 171
163 /// Reset the library loader task to prepare for compilation. If provided, 172 /// Reset the library loader task to prepare for compilation. If provided,
164 /// libraries matching [reuseLibrary] are reused. 173 /// libraries matching [reuseLibrary] are reused.
165 /// 174 ///
166 /// This method is used for incremental compilation. 175 /// This method is used for incremental compilation.
167 void reset({bool reuseLibrary(LibraryElement library)}); 176 void reset({bool reuseLibrary(LibraryElement library)});
168 177
169 /// Asynchronous version of [reset]. 178 /// Asynchronous version of [reset].
170 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)); 179 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library));
171 180
172 /// Similar to [resetAsync] but [reuseLibrary] maps all libraries to a list 181 /// Similar to [resetAsync] but [reuseLibrary] maps all libraries to a list
173 /// of libraries that can be reused. 182 /// of libraries that can be reused.
174 Future<Null> resetLibraries(ReuseLibrariesFunction reuseLibraries); 183 Future<Null> resetLibraries(ReuseLibrariesFunction reuseLibraries);
175 184
176 // TODO(johnniwinther): Move these to a separate interface. 185 // TODO(johnniwinther): Move these to a separate interface.
177 /// Register a deferred action to be performed during resolution. 186 /// Register a deferred action to be performed during resolution.
178 void registerDeferredAction(DeferredAction action); 187 void registerDeferredAction(DeferredAction action);
179 188
180 /// Returns the deferred actions registered since the last call to 189 /// Returns the deferred actions registered since the last call to
181 /// [pullDeferredActions]. 190 /// [pullDeferredActions].
182 Iterable<DeferredAction> pullDeferredActions(); 191 Iterable<DeferredAction> pullDeferredActions();
192
193 /// The locations of js patch-files relative to the sdk-descriptors.
194 static const _patchLocations = const <String, String>{
195 "async": "_internal/js_runtime/lib/async_patch.dart",
196 "collection": "_internal/js_runtime/lib/collection_patch.dart",
197 "convert": "_internal/js_runtime/lib/convert_patch.dart",
198 "core": "_internal/js_runtime/lib/core_patch.dart",
199 "developer": "_internal/js_runtime/lib/developer_patch.dart",
200 "io": "_internal/js_runtime/lib/io_patch.dart",
201 "isolate": "_internal/js_runtime/lib/isolate_patch.dart",
202 "math": "_internal/js_runtime/lib/math_patch.dart",
203 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
204 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
205 "_internal": "_internal/js_runtime/lib/internal_patch.dart"
206 };
207
208 /// Returns the location of the patch-file associated with [libraryName]
209 /// resolved from [plaformConfigUri].
210 ///
211 /// Returns null if there is none.
212 static Uri resolvePatchUri(String libraryName, Uri platformConfigUri) {
213 String patchLocation = _patchLocations[libraryName];
214 if (patchLocation == null) return null;
215 return platformConfigUri.resolve(patchLocation);
216 }
183 } 217 }
184 218
185 /// Interface for an entity that provide libraries. For instance from normal 219 /// Interface for an entity that provide libraries. For instance from normal
186 /// library loading or from deserialization. 220 /// library loading or from deserialization.
187 // TODO(johnniwinther): Use this to integrate deserialized libraries better. 221 // TODO(johnniwinther): Use this to integrate deserialized libraries better.
188 abstract class LibraryProvider { 222 abstract class LibraryProvider {
189 /// Looks up the library with the [canonicalUri]. 223 /// Looks up the library with the [canonicalUri].
190 LibraryElement lookupLibrary(Uri canonicalUri); 224 LibraryElement lookupLibrary(Uri canonicalUri);
191 } 225 }
192 226
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 final ScriptLoader scriptLoader; 330 final ScriptLoader scriptLoader;
297 331
298 /// Provides a diet element model from a script file containing information 332 /// Provides a diet element model from a script file containing information
299 /// about imports and exports. Used when loading libraries from source. 333 /// about imports and exports. Used when loading libraries from source.
300 final ElementScanner scanner; 334 final ElementScanner scanner;
301 335
302 /// Provides a diet element model for a library. Used when loading libraries 336 /// Provides a diet element model for a library. Used when loading libraries
303 /// from a serialized form. 337 /// from a serialized form.
304 final LibraryDeserializer deserializer; 338 final LibraryDeserializer deserializer;
305 339
306 /// Hooks to inform others about progress done by this loader.
307 // TODO(sigmund): move away from this.
308 final LibraryLoaderListener listener;
309
310 /// Definitions provided via the `-D` command line flags. Used to resolve 340 /// Definitions provided via the `-D` command line flags. Used to resolve
311 /// conditional imports. 341 /// conditional imports.
312 final Environment environment; 342 final Environment environment;
313 343
344 // TODO(efortuna): Don't pass PatchParserTask here.
345 final PatchParserTask _patchParserTask;
346
347 /// Function that accepts the string name of a library and returns the
348 /// path to the corresponding patch file. This is a function that is passed in
349 /// because our test mock_compiler subclasses compiler.
350 // TODO(efortuna): Refactor mock_compiler to not do this.
Siggi Cherem (dart-lang) 2017/03/24 17:40:27 thanks for documenting so nicely the issue :) I h
Emily Fortuna 2017/03/24 18:30:19 makes sense. upcoming CL!
351 final PatchResolverFunction _patchResolverFunc;
352
314 List<DeferredAction> _deferredActions = <DeferredAction>[]; 353 List<DeferredAction> _deferredActions = <DeferredAction>[];
315 354
316 final DiagnosticReporter reporter; 355 final DiagnosticReporter reporter;
317 356
318 _LibraryLoaderTask( 357 _LibraryLoaderTask(
319 this.uriTranslator, 358 this.uriTranslator,
320 this.scriptLoader, 359 this.scriptLoader,
321 this.scanner, 360 this.scanner,
322 this.deserializer, 361 this.deserializer,
323 this.listener, 362 this._patchResolverFunc,
363 this._patchParserTask,
324 this.environment, 364 this.environment,
325 this.reporter, 365 this.reporter,
326 Measurer measurer) 366 Measurer measurer)
327 : super(measurer); 367 : super(measurer);
328 368
329 String get name => 'LibraryLoader'; 369 String get name => 'LibraryLoader';
330 370
331 final Map<Uri, LibraryElement> libraryCanonicalUriMap = 371 final Map<Uri, LibraryElement> libraryCanonicalUriMap =
332 new Map<Uri, LibraryElement>(); 372 new Map<Uri, LibraryElement>();
333 final Map<Uri, LibraryElement> libraryResourceUriMap = 373 final Map<Uri, LibraryElement> libraryResourceUriMap =
334 new Map<Uri, LibraryElement>(); 374 new Map<Uri, LibraryElement>();
335 final Map<String, LibraryElement> libraryNames = 375 final Map<String, LibraryElement> libraryNames =
336 new Map<String, LibraryElement>(); 376 new Map<String, LibraryElement>();
337 377
338 LibraryDependencyHandler currentHandler;
339
340 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values; 378 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values;
341 379
342 LibraryElement lookupLibrary(Uri canonicalUri) { 380 LibraryElement lookupLibrary(Uri canonicalUri) {
343 return libraryCanonicalUriMap[canonicalUri]; 381 return libraryCanonicalUriMap[canonicalUri];
344 } 382 }
345 383
346 void reset({bool reuseLibrary(LibraryElement library)}) { 384 void reset({bool reuseLibrary(LibraryElement library)}) {
347 measure(() { 385 measure(() {
348 assert(currentHandler == null);
349
350 Iterable<LibraryElement> reusedLibraries = null; 386 Iterable<LibraryElement> reusedLibraries = null;
351 if (reuseLibrary != null) { 387 if (reuseLibrary != null) {
352 reusedLibraries = measureSubtask(_reuseLibrarySubtaskName, () { 388 reusedLibraries = measureSubtask(_reuseLibrarySubtaskName, () {
353 // Call [toList] to force eager calls to [reuseLibrary]. 389 // Call [toList] to force eager calls to [reuseLibrary].
354 return libraryCanonicalUriMap.values.where(reuseLibrary).toList(); 390 return libraryCanonicalUriMap.values.where(reuseLibrary).toList();
355 }); 391 });
356 } 392 }
357 393
358 resetImplementation(reusedLibraries); 394 resetImplementation(reusedLibraries);
359 }); 395 });
360 } 396 }
361 397
362 void resetImplementation(Iterable<LibraryElement> reusedLibraries) { 398 void resetImplementation(Iterable<LibraryElement> reusedLibraries) {
363 measure(() { 399 measure(() {
364 libraryCanonicalUriMap.clear(); 400 libraryCanonicalUriMap.clear();
365 libraryResourceUriMap.clear(); 401 libraryResourceUriMap.clear();
366 libraryNames.clear(); 402 libraryNames.clear();
367 403
368 if (reusedLibraries != null) { 404 if (reusedLibraries != null) {
369 reusedLibraries.forEach(mapLibrary); 405 reusedLibraries.forEach(mapLibrary);
370 } 406 }
371 }); 407 });
372 } 408 }
373 409
374 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { 410 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) {
375 return measure(() { 411 return measure(() {
376 assert(currentHandler == null);
377
378 Future<LibraryElement> wrapper(LibraryElement library) { 412 Future<LibraryElement> wrapper(LibraryElement library) {
379 try { 413 try {
380 return reuseLibrary(library) 414 return reuseLibrary(library)
381 .then((bool reuse) => reuse ? library : null); 415 .then((bool reuse) => reuse ? library : null);
382 } catch (exception, trace) { 416 } catch (exception, trace) {
383 reporter.onCrashInUserCode( 417 reporter.onCrashInUserCode(
384 'Uncaught exception in reuseLibrary', exception, trace); 418 'Uncaught exception in reuseLibrary', exception, trace);
385 rethrow; 419 rethrow;
386 } 420 }
387 } 421 }
388 422
389 List<Future<LibraryElement>> reusedLibrariesFuture = measureSubtask( 423 List<Future<LibraryElement>> reusedLibrariesFuture = measureSubtask(
390 _reuseLibrarySubtaskName, 424 _reuseLibrarySubtaskName,
391 () => libraryCanonicalUriMap.values.map(wrapper).toList()); 425 () => libraryCanonicalUriMap.values.map(wrapper).toList());
392 426
393 return Future 427 return Future
394 .wait(reusedLibrariesFuture) 428 .wait(reusedLibrariesFuture)
395 .then((Iterable<LibraryElement> reusedLibraries) { 429 .then((Iterable<LibraryElement> reusedLibraries) {
396 resetImplementation(reusedLibraries.where((e) => e != null)); 430 resetImplementation(reusedLibraries.where((e) => e != null));
397 }); 431 });
398 }); 432 });
399 } 433 }
400 434
401 Future<Null> resetLibraries( 435 Future<Null> resetLibraries(
402 Future<Iterable<LibraryElement>> reuseLibraries( 436 Future<Iterable<LibraryElement>> reuseLibraries(
403 Iterable<LibraryElement> libraries)) { 437 Iterable<LibraryElement> libraries)) {
404 assert(currentHandler == null);
405 return measureSubtask(_reuseLibrarySubtaskName, () { 438 return measureSubtask(_reuseLibrarySubtaskName, () {
406 return new Future<Iterable<LibraryElement>>(() { 439 return new Future<Iterable<LibraryElement>>(() {
407 // Wrap in Future to shield against errors in user code. 440 // Wrap in Future to shield against errors in user code.
408 return reuseLibraries(libraryCanonicalUriMap.values); 441 return reuseLibraries(libraryCanonicalUriMap.values);
409 }).catchError((exception, StackTrace trace) { 442 }).catchError((exception, StackTrace trace) {
410 reporter.onCrashInUserCode( 443 reporter.onCrashInUserCode(
411 'Uncaught exception in reuseLibraries', exception, trace); 444 'Uncaught exception in reuseLibraries', exception, trace);
412 throw exception; // Async rethrow. 445 throw exception; // Async rethrow.
413 }).then((Iterable<LibraryElement> reusedLibraries) { 446 }).then((Iterable<LibraryElement> reusedLibraries) {
414 measure(() { 447 measure(() {
415 resetImplementation(reusedLibraries); 448 resetImplementation(reusedLibraries);
416 }); 449 });
417 }); 450 });
418 }); 451 });
419 } 452 }
420 453
421 /// Insert [library] in the internal maps. Used for compiler reuse. 454 /// Insert [library] in the internal maps. Used for compiler reuse.
422 void mapLibrary(LibraryElement library) { 455 void mapLibrary(LibraryElement library) {
423 libraryCanonicalUriMap[library.canonicalUri] = library; 456 libraryCanonicalUriMap[library.canonicalUri] = library;
424 457
425 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; 458 Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
426 libraryResourceUriMap[resourceUri] = library; 459 libraryResourceUriMap[resourceUri] = library;
427 460
428 if (library.hasLibraryName) { 461 if (library.hasLibraryName) {
429 String name = library.libraryName; 462 String name = library.libraryName;
430 libraryNames[name] = library; 463 libraryNames[name] = library;
431 } 464 }
432 } 465 }
433 466
434 Future<LibraryElement> loadLibrary(Uri resolvedUri, 467 Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
435 {bool skipFileWithPartOfTag: false}) { 468 {bool skipFileWithPartOfTag: false}) async {
Siggi Cherem (dart-lang) 2017/03/24 17:40:28 seems like you don't need async here
Emily Fortuna 2017/03/24 18:30:19 Done.
436 return measure(() { 469 return measure(() async {
437 assert(currentHandler == null); 470 LibraryDependencyHandler loader = new LibraryDependencyHandler(this);
Siggi Cherem (dart-lang) 2017/03/24 17:40:27 nit: maybe rename loader as handler?
Emily Fortuna 2017/03/24 18:30:19 Done.
438 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the 471 LibraryElement library = await createLibrary(
439 // loading of a library cluster. 472 loader, null, resolvedUri, NO_LOCATION_SPANNABLE,
440 currentHandler = new LibraryDependencyHandler(this); 473 skipFileWithPartOfTag: skipFileWithPartOfTag);
441 return createLibrary( 474 if (library == null) {
Siggi Cherem (dart-lang) 2017/03/24 17:40:28 style nit: we don't use the {} on this fast-exit c
Emily Fortuna 2017/03/24 18:30:19 Done.
442 currentHandler, null, resolvedUri, NO_LOCATION_SPANNABLE, 475 return null;
443 skipFileWithPartOfTag: skipFileWithPartOfTag) 476 }
444 .then((LibraryElement library) { 477 return reporter.withCurrentElement(library, () {
445 if (library == null) { 478 return measure(() {
446 currentHandler = null; 479 loader.computeExports();
447 return null; 480 return new _LoadedLibraries(library, loader.newLibraries, this);
448 }
449 return reporter.withCurrentElement(library, () {
450 return measure(() {
451 currentHandler.computeExports();
452 LoadedLibraries loadedLibraries = new _LoadedLibraries(library,
453 currentHandler.newLibraries, currentHandler.nodeMap, this);
454 currentHandler = null;
455 return listener
456 .onLibrariesLoaded(loadedLibraries)
457 .then((_) => library);
458 });
459 }); 481 });
460 }); 482 });
461 }); 483 });
462 } 484 }
463 485
464 /** 486 /**
465 * Processes the library tags in [library]. 487 * Processes the library tags in [library].
466 * 488 *
467 * The imported/exported libraries are loaded and processed recursively but 489 * The imported/exported libraries are loaded and processed recursively but
468 * the import/export scopes are not set up. 490 * the import/export scopes are not set up.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 Part part = tag; 563 Part part = tag;
542 StringNode uri = part.uri; 564 StringNode uri = part.uri;
543 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); 565 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
544 tagState.checkTag(TagState.PART, part, reporter); 566 tagState.checkTag(TagState.PART, part, reporter);
545 return scanPart(part, resolvedUri, library); 567 return scanPart(part, resolvedUri, library);
546 } else { 568 } else {
547 reporter.internalError(tag, "Unhandled library tag."); 569 reporter.internalError(tag, "Unhandled library tag.");
548 } 570 }
549 }); 571 });
550 }).then((_) { 572 }).then((_) {
551 return listener.onLibraryScanned(library, handler);
Siggi Cherem (dart-lang) 2017/03/24 17:40:27 woo hoo!
552 }).then((_) {
553 return reporter.withCurrentElement(library, () { 573 return reporter.withCurrentElement(library, () {
554 checkDuplicatedLibraryName(library); 574 checkDuplicatedLibraryName(library);
555 575
556 // Import dart:core if not already imported. 576 // Import dart:core if not already imported.
557 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { 577 if (!importsDartCore && library.canonicalUri != Uris.dart_core) {
558 return createLibrary(handler, null, Uris.dart_core, library) 578 return createLibrary(handler, null, Uris.dart_core, library)
559 .then((LibraryElement coreLibrary) { 579 .then((LibraryElement coreLibrary) {
560 handler.registerDependency( 580 handler.registerDependency(
561 library, 581 library,
562 new SyntheticImportElement( 582 new SyntheticImportElement(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } 672 }
653 673
654 /// Loads the deserialized [library] with the [handler]. 674 /// Loads the deserialized [library] with the [handler].
655 /// 675 ///
656 /// All libraries imported or exported transitively from [library] will be 676 /// All libraries imported or exported transitively from [library] will be
657 /// loaded as well. 677 /// loaded as well.
658 Future<LibraryElement> loadDeserializedLibrary( 678 Future<LibraryElement> loadDeserializedLibrary(
659 LibraryDependencyHandler handler, LibraryElement library) { 679 LibraryDependencyHandler handler, LibraryElement library) {
660 libraryCanonicalUriMap[library.canonicalUri] = library; 680 libraryCanonicalUriMap[library.canonicalUri] = library;
661 handler.registerNewLibrary(library); 681 handler.registerNewLibrary(library);
662 return listener.onLibraryScanned(library, handler).then((_) { 682 return Future.forEach(library.imports, (ImportElement import) {
663 return Future.forEach(library.imports, (ImportElement import) { 683 Uri resolvedUri = library.canonicalUri.resolveUri(import.uri);
664 Uri resolvedUri = library.canonicalUri.resolveUri(import.uri); 684 return createLibrary(handler, library, resolvedUri, library);
685 }).then((_) {
686 return Future.forEach(library.exports, (ExportElement export) {
687 Uri resolvedUri = library.canonicalUri.resolveUri(export.uri);
665 return createLibrary(handler, library, resolvedUri, library); 688 return createLibrary(handler, library, resolvedUri, library);
666 }).then((_) { 689 }).then((_) {
667 return Future.forEach(library.exports, (ExportElement export) { 690 // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the
668 Uri resolvedUri = library.canonicalUri.resolveUri(export.uri); 691 // implicit import of dart:core?
669 return createLibrary(handler, library, resolvedUri, library); 692 return createLibrary(handler, library, Uris.dart_core, library);
670 }).then((_) { 693 }).then((_) => library);
671 // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the
672 // implicit import of dart:core?
673 return createLibrary(handler, library, Uris.dart_core, library);
674 }).then((_) => library);
675 });
676 }); 694 });
677 } 695 }
678 696
679 Future<Script> _readScript( 697 Future<Script> _readScript(
680 Spannable spannable, Uri readableUri, Uri resolvedUri) { 698 Spannable spannable, Uri readableUri, Uri resolvedUri) {
681 if (readableUri == null) { 699 if (readableUri == null) {
682 return new Future.value(new Script.synthetic(resolvedUri)); 700 return new Future.value(new Script.synthetic(resolvedUri));
683 } else { 701 } else {
684 return scriptLoader.readScript(readableUri, spannable); 702 return scriptLoader.readScript(readableUri, spannable);
685 } 703 }
686 } 704 }
687 705
688 /** 706 /**
689 * Create (or reuse) a library element for the library specified by the 707 * Create (or reuse) a library element for the library specified by the
690 * [resolvedUri]. 708 * [resolvedUri].
691 * 709 *
692 * If a new library is created, the [handler] is notified. 710 * If a new library is created, the [handler] is notified.
693 */ 711 */
694 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, 712 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
695 LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable, 713 LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable,
696 {bool skipFileWithPartOfTag: false}) { 714 {bool skipFileWithPartOfTag: false}) async {
697 Uri readableUri = 715 Uri readableUri =
698 uriTranslator.translate(importingLibrary, resolvedUri, spannable); 716 uriTranslator.translate(importingLibrary, resolvedUri, spannable);
699 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; 717 LibraryElement library = libraryCanonicalUriMap[resolvedUri];
700 if (library != null) { 718 if (library != null) {
701 return new Future.value(library); 719 return new Future.value(library);
702 } 720 }
703 return deserializer.readLibrary(resolvedUri).then((LibraryElement library) { 721 library = await deserializer.readLibrary(resolvedUri);
704 if (library != null) { 722 if (library != null) {
705 return loadDeserializedLibrary(handler, library); 723 return loadDeserializedLibrary(handler, library);
706 } 724 }
707 return reporter.withCurrentElement(importingLibrary, () { 725 return reporter.withCurrentElement(importingLibrary, () {
708 return _readScript(spannable, readableUri, resolvedUri) 726 return _readScript(spannable, readableUri, resolvedUri)
709 .then((Script script) { 727 .then((Script script) async {
710 if (script == null) return null; 728 if (script == null) return null;
711 LibraryElement element = 729 LibraryElement element =
712 createLibrarySync(handler, script, resolvedUri); 730 createLibrarySync(handler, script, resolvedUri);
713 CompilationUnitElementX compilationUnit = 731 CompilationUnitElementX compilationUnit = element.entryCompilationUnit;
714 element.entryCompilationUnit; 732 if (compilationUnit.partTag != null) {
715 if (compilationUnit.partTag != null) { 733 if (skipFileWithPartOfTag) {
716 if (skipFileWithPartOfTag) { 734 // TODO(johnniwinther): Avoid calling
717 // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated] 735 // [compiler.processLoadedLibraries] with this library.
718 // for this library. 736 libraryCanonicalUriMap.remove(resolvedUri);
719 libraryCanonicalUriMap.remove(resolvedUri); 737 return null;
720 return null;
721 }
722 if (importingLibrary == null) {
723 DiagnosticMessage error = reporter.withCurrentElement(
724 compilationUnit,
725 () => reporter.createMessage(
726 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
727 reporter.reportError(error);
728 } else {
729 DiagnosticMessage error = reporter.withCurrentElement(
730 compilationUnit,
731 () => reporter.createMessage(
732 compilationUnit.partTag, MessageKind.IMPORT_PART_OF));
733 DiagnosticMessage info = reporter.withCurrentElement(
734 importingLibrary,
735 () => reporter.createMessage(
736 spannable, MessageKind.IMPORT_PART_OF_HERE));
737 reporter.reportError(error, [info]);
738 }
739 } 738 }
740 return processLibraryTags(handler, element).then((_) { 739 if (importingLibrary == null) {
741 reporter.withCurrentElement(element, () { 740 DiagnosticMessage error = reporter.withCurrentElement(
742 handler.registerLibraryExports(element); 741 compilationUnit,
743 }); 742 () => reporter.createMessage(
744 return element; 743 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
745 }); 744 reporter.reportError(error);
745 } else {
746 DiagnosticMessage error = reporter.withCurrentElement(
747 compilationUnit,
748 () => reporter.createMessage(
749 compilationUnit.partTag, MessageKind.IMPORT_PART_OF));
750 DiagnosticMessage info = reporter.withCurrentElement(
751 importingLibrary,
752 () => reporter.createMessage(
753 spannable, MessageKind.IMPORT_PART_OF_HERE));
754 reporter.reportError(error, [info]);
755 }
756 }
757 await processLibraryTags(handler, element);
758 reporter.withCurrentElement(element, () {
759 handler.registerLibraryExports(element);
746 }); 760 });
761
762 if (element.isPlatformLibrary &&
Siggi Cherem (dart-lang) 2017/03/24 17:40:28 so nice to see patching done while loading, yay!
Emily Fortuna 2017/03/24 18:30:20 done! I aaaaaalmost did that in my cleanup process
763 // Don't patch library currently disallowed.
764 !element.isSynthesized &&
765 !element.isPatched &&
766 // Don't patch deserialized libraries.
767 !deserializer.isDeserialized(element)) {
768 // Apply patch, if any.
769 Uri patchUri = _patchResolverFunc(element.canonicalUri.path);
770 if (patchUri != null) {
771 await _patchParserTask.patchLibrary(handler, patchUri, element);
772 }
773 }
774 return element;
747 }); 775 });
748 }); 776 });
749 } 777 }
750 778
751 LibraryElement createLibrarySync( 779 LibraryElement createLibrarySync(
752 LibraryDependencyHandler handler, Script script, Uri resolvedUri) { 780 LibraryDependencyHandler handler, Script script, Uri resolvedUri) {
753 LibraryElement element = new LibraryElementX(script, resolvedUri); 781 LibraryElement element = new LibraryElementX(script, resolvedUri);
754 return reporter.withCurrentElement(element, () { 782 return reporter.withCurrentElement(element, () {
755 if (handler != null) { 783 if (handler != null) {
756 handler.registerNewLibrary(element); 784 handler.registerNewLibrary(element);
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 assert(invariant(library, importingNode != null, 1351 assert(invariant(library, importingNode != null,
1324 message: "$library has not been registered")); 1352 message: "$library has not been registered"));
1325 importingNode.registerImportDependency(libraryDependency, loadedLibrary); 1353 importingNode.registerImportDependency(libraryDependency, loadedLibrary);
1326 } 1354 }
1327 } 1355 }
1328 1356
1329 /** 1357 /**
1330 * Registers [library] for the processing of its import/export scope. 1358 * Registers [library] for the processing of its import/export scope.
1331 */ 1359 */
1332 void registerNewLibrary(LibraryElement library) { 1360 void registerNewLibrary(LibraryElement library) {
1333 task.listener.onLibraryCreated(library);
1334 _newLibraries.add(library); 1361 _newLibraries.add(library);
1335 if (!library.exportsHandled) { 1362 if (!library.exportsHandled) {
1336 nodeMap[library] = new LibraryDependencyNode(library); 1363 nodeMap[library] = new LibraryDependencyNode(library);
1337 } 1364 }
1338 } 1365 }
1339 1366
1340 /** 1367 /**
1341 * Registers all top-level entities of [library] as starting point for the 1368 * Registers all top-level entities of [library] as starting point for the
1342 * fixed-point computation of the import/export scopes. 1369 * fixed-point computation of the import/export scopes.
1343 */ 1370 */
1344 void registerLibraryExports(LibraryElement library) { 1371 void registerLibraryExports(LibraryElement library) {
1345 nodeMap[library].registerInitialExports(); 1372 nodeMap[library].registerInitialExports();
1346 } 1373 }
1347 1374
1348 Future processLibraryTags(LibraryElement library) { 1375 Future processLibraryTags(LibraryElement library) {
1349 return task.processLibraryTags(this, library); 1376 return task.processLibraryTags(this, library);
1350 } 1377 }
1351 } 1378 }
1352 1379
1353 /// Information on the bulk of newly loaded libraries through a call to 1380 /// Information on the set libraries loaded as a result of a call to
1354 /// [LibraryLoader.loadLibrary]. 1381 /// [LibraryLoader.loadLibrary].
1355 abstract class LoadedLibraries { 1382 abstract class LoadedLibraries {
1356 /// The uri passed to [LibraryLoader.loadLibrary]. 1383 /// The accesss the library object created corresponding to the library
1357 Uri get rootUri; 1384 /// passed to [LibraryLoader.loadLibrary].
1385 LibraryElement get rootLibrary;
1358 1386
1359 /// Returns `true` if a library with canonical [uri] was loaded in this bulk. 1387 /// Returns `true` if a library with canonical [uri] was loaded in this bulk.
1360 bool containsLibrary(Uri uri); 1388 bool containsLibrary(Uri uri);
1361 1389
1362 /// Returns the library with canonical [uri] that was loaded in this bulk. 1390 /// Returns the library with canonical [uri] that was loaded in this bulk.
1363 LibraryElement getLibrary(Uri uri); 1391 LibraryElement getLibrary(Uri uri);
1364 1392
1365 /// Applies all libraries in this bulk to [f]. 1393 /// Applies all libraries in this bulk to [f].
1366 void forEachLibrary(f(LibraryElement library)); 1394 void forEachLibrary(f(LibraryElement library));
1367 1395
1368 /// Applies all imports chains of [uri] in this bulk to [callback]. 1396 /// Applies all imports chains of [uri] in this bulk to [callback].
1369 /// 1397 ///
1370 /// The argument [importChainReversed] to [callback] contains the chain of 1398 /// The argument [importChainReversed] to [callback] contains the chain of
1371 /// imports uris that lead to importing [uri] starting in [uri] and ending in 1399 /// imports uris that lead to importing [uri] starting in [uri] and ending in
1372 /// [rootUri]. 1400 /// the uri that was passed in with [loadLibrary].
1373 /// 1401 ///
1374 /// [callback] is called once for each chain of imports leading to [uri] until 1402 /// [callback] is called once for each chain of imports leading to [uri] until
1375 /// [callback] returns `false`. 1403 /// [callback] returns `false`.
1376 void forEachImportChain(Uri uri, 1404 void forEachImportChain(Uri uri,
1377 {bool callback(Link<Uri> importChainReversed)}); 1405 {bool callback(Link<Uri> importChainReversed)});
1378 } 1406 }
1379 1407
1380 class _LoadedLibraries implements LoadedLibraries { 1408 class _LoadedLibraries implements LoadedLibraries {
1381 final _LibraryLoaderTask task; 1409 final _LibraryLoaderTask task;
1382 final LibraryElement rootLibrary; 1410 final LibraryElement rootLibrary;
1383 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; 1411 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
1384 final Map<LibraryElement, LibraryDependencyNode> nodeMap; 1412 final List<LibraryElement> _newLibraries;
1385 1413
1386 _LoadedLibraries(this.rootLibrary, Iterable<LibraryElement> libraries, 1414 _LoadedLibraries(this.rootLibrary, this._newLibraries, this.task) {
1387 this.nodeMap, this.task) { 1415 _newLibraries.forEach((LibraryElement loadedLibrary) {
1388 libraries.forEach((LibraryElement loadedLibrary) {
1389 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; 1416 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
1390 }); 1417 });
1391 } 1418 }
1392 1419
1393 Uri get rootUri => rootLibrary.canonicalUri;
1394
1395 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri); 1420 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri);
1396 1421
1397 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri]; 1422 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri];
1398 1423
1399 void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f); 1424 void forEachLibrary(f(LibraryElement library)) => _newLibraries.forEach(f);
1400 1425
1401 void forEachImportChain(Uri targetUri, 1426 void forEachImportChain(Uri targetUri,
1402 {bool callback(Link<Uri> importChainReversed)}) { 1427 {bool callback(Link<Uri> importChainReversed)}) {
1403 bool aborted = false; 1428 bool aborted = false;
1404 1429
1405 /// Map from libraries to the set of (unreversed) paths to [uri]. 1430 /// Map from libraries to the set of (unreversed) paths to [uri].
1406 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap = 1431 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap =
1407 <LibraryElement, Iterable<Link<Uri>>>{}; 1432 <LibraryElement, Iterable<Link<Uri>>>{};
1408 1433
1409 /// Computes the set of (unreversed) paths to [targetUri]. 1434 /// Computes the set of (unreversed) paths to [targetUri].
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1468 } 1493 }
1469 suffixes.add(const Link<Uri>().prepend(canonicalUri)); 1494 suffixes.add(const Link<Uri>().prepend(canonicalUri));
1470 } 1495 }
1471 suffixChainMap[library] = suffixes; 1496 suffixChainMap[library] = suffixes;
1472 return; 1497 return;
1473 } 1498 }
1474 1499
1475 computeSuffixes(rootLibrary, const Link<Uri>()); 1500 computeSuffixes(rootLibrary, const Link<Uri>());
1476 } 1501 }
1477 1502
1478 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}'; 1503 String toString() => 'root=$rootLibrary,libraries=${_newLibraries}';
1479 } 1504 }
1480 1505
1481 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems 1506 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
1482 // rather low-level. It might be more practical to split the library-loading 1507 // rather low-level. It might be more practical to split the library-loading
1483 // task itself. The task would continue to do the work of recursively loading 1508 // task itself. The task would continue to do the work of recursively loading
1484 // dependencies, but it can delegate to a set of subloaders how to do the actual 1509 // dependencies, but it can delegate to a set of subloaders how to do the actual
1485 // loading. We would then have a list of subloaders that use different 1510 // loading. We would then have a list of subloaders that use different
1486 // implementations: in-memory cache, deserialization, scanning from files. 1511 // implementations: in-memory cache, deserialization, scanning from files.
1487 // 1512 //
1488 // For example, the API might look like this: 1513 // For example, the API might look like this:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1521 /// Load script from a readable [uri], report any errors using the location of 1546 /// Load script from a readable [uri], report any errors using the location of
1522 /// the given [spannable]. 1547 /// the given [spannable].
1523 Future<Script> readScript(Uri uri, [Spannable spannable]); 1548 Future<Script> readScript(Uri uri, [Spannable spannable]);
1524 } 1549 }
1525 1550
1526 /// API used by the library loader to synchronously scan a library or 1551 /// API used by the library loader to synchronously scan a library or
1527 /// compilation unit and ensure that their library tags are computed. 1552 /// compilation unit and ensure that their library tags are computed.
1528 abstract class ElementScanner { 1553 abstract class ElementScanner {
1529 void scanLibrary(LibraryElement library); 1554 void scanLibrary(LibraryElement library);
1530 void scanUnit(CompilationUnitElement unit); 1555 void scanUnit(CompilationUnitElement unit);
1531 } 1556 Token scanFile(SourceFile file);
Siggi Cherem (dart-lang) 2017/03/24 17:40:27 looks like you don't need scanFile after all? coul
Emily Fortuna 2017/03/24 18:30:20 yes thanks.
1532
1533 /// TODO(sigmund): remove this abstraction. Ideally the loader can produce the
1534 /// LoadedLibraries results once, and the compiler and choose what to do with
1535 /// it instead.
1536 abstract class LibraryLoaderListener {
1537 /// Called after a request to load a library. The [results] will include all
1538 /// transitive libraries loaded as a result of the initial request.
1539 Future onLibrariesLoaded(LoadedLibraries results);
1540
1541 /// Called whenever a library element is created.
1542 void onLibraryCreated(LibraryElement library);
1543
1544 /// Called whenever a library is scanned from a script file.
1545 Future onLibraryScanned(LibraryElement library, LibraryLoader loader);
1546 } 1557 }
1547 1558
1548 const _reuseLibrarySubtaskName = "Reuse library"; 1559 const _reuseLibrarySubtaskName = "Reuse library";
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698