| OLD | NEW |
| 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.dart'; | 9 import 'common.dart'; |
| 10 import 'common/names.dart' show | 10 import 'common/names.dart' show Uris; |
| 11 Uris; | 11 import 'common/tasks.dart' show CompilerTask; |
| 12 import 'common/tasks.dart' show | 12 import 'compiler.dart' show Compiler; |
| 13 CompilerTask; | 13 import 'elements/elements.dart' |
| 14 import 'compiler.dart' show | 14 show |
| 15 Compiler; | 15 CompilationUnitElement, |
| 16 import 'elements/elements.dart' show | 16 Element, |
| 17 CompilationUnitElement, | 17 ImportElement, |
| 18 Element, | 18 ExportElement, |
| 19 ImportElement, | 19 LibraryElement, |
| 20 ExportElement, | 20 PrefixElement; |
| 21 LibraryElement, | 21 import 'elements/modelx.dart' |
| 22 PrefixElement; | 22 show |
| 23 import 'elements/modelx.dart' show | 23 CompilationUnitElementX, |
| 24 CompilationUnitElementX, | 24 DeferredLoaderGetterElementX, |
| 25 DeferredLoaderGetterElementX, | 25 ErroneousElementX, |
| 26 ErroneousElementX, | 26 ExportElementX, |
| 27 ExportElementX, | 27 ImportElementX, |
| 28 ImportElementX, | 28 LibraryElementX, |
| 29 LibraryElementX, | 29 LibraryDependencyElementX, |
| 30 LibraryDependencyElementX, | 30 PrefixElementX, |
| 31 PrefixElementX, | 31 SyntheticImportElement; |
| 32 SyntheticImportElement; | |
| 33 import 'environment.dart'; | 32 import 'environment.dart'; |
| 34 import 'script.dart'; | 33 import 'script.dart'; |
| 35 import 'serialization/serialization.dart' show LibraryDeserializer; | 34 import 'serialization/serialization.dart' show LibraryDeserializer; |
| 36 import 'tree/tree.dart'; | 35 import 'tree/tree.dart'; |
| 37 import 'util/util.dart' show | 36 import 'util/util.dart' show Link, LinkBuilder; |
| 38 Link, | |
| 39 LinkBuilder; | |
| 40 | 37 |
| 41 /** | 38 /** |
| 42 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 39 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
| 43 * | 40 * |
| 44 * The library loader uses four different kinds of URIs in different parts of | 41 * The library loader uses four different kinds of URIs in different parts of |
| 45 * the loading process. | 42 * the loading process. |
| 46 * | 43 * |
| 47 * ## User URI ## | 44 * ## User URI ## |
| 48 * | 45 * |
| 49 * A 'user URI' is a URI provided by the user in code and as the main entry URI | 46 * A 'user URI' is a URI provided by the user in code and as the main entry URI |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 * that these imports | 123 * that these imports |
| 127 * | 124 * |
| 128 * import 'package:foo.dart' as a; | 125 * import 'package:foo.dart' as a; |
| 129 * import 'packages/foo.dart' as b; | 126 * import 'packages/foo.dart' as b; |
| 130 * | 127 * |
| 131 * do _not_ resolve to the same library when the package root URI happens to | 128 * do _not_ resolve to the same library when the package root URI happens to |
| 132 * point to the 'packages' folder. | 129 * point to the 'packages' folder. |
| 133 * | 130 * |
| 134 */ | 131 */ |
| 135 abstract class LibraryLoaderTask implements CompilerTask { | 132 abstract class LibraryLoaderTask implements CompilerTask { |
| 136 factory LibraryLoaderTask(Compiler compiler, | 133 factory LibraryLoaderTask( |
| 134 Compiler compiler, |
| 137 ResolvedUriTranslator uriTranslator, | 135 ResolvedUriTranslator uriTranslator, |
| 138 ScriptLoader scriptLoader, | 136 ScriptLoader scriptLoader, |
| 139 ElementScanner scriptScanner, | 137 ElementScanner scriptScanner, |
| 140 LibraryDeserializer deserializer, | 138 LibraryDeserializer deserializer, |
| 141 LibraryLoaderListener listener, | 139 LibraryLoaderListener listener, |
| 142 Environment environment) = _LibraryLoaderTask; | 140 Environment environment) = _LibraryLoaderTask; |
| 143 | 141 |
| 144 /// Returns all libraries that have been loaded. | 142 /// Returns all libraries that have been loaded. |
| 145 Iterable<LibraryElement> get libraries; | 143 Iterable<LibraryElement> get libraries; |
| 146 | 144 |
| 147 /// Looks up the library with the [canonicalUri]. | 145 /// Looks up the library with the [canonicalUri]. |
| 148 LibraryElement lookupLibrary(Uri canonicalUri); | 146 LibraryElement lookupLibrary(Uri canonicalUri); |
| 149 | 147 |
| 150 /// Loads the library specified by the [resolvedUri] and returns its | 148 /// Loads the library specified by the [resolvedUri] and returns its |
| 151 /// [LibraryElement]. | 149 /// [LibraryElement]. |
| 152 /// | 150 /// |
| 153 /// If the library is not already loaded, the method creates the | 151 /// If the library is not already loaded, the method creates the |
| 154 /// [LibraryElement] for the library and computes the import/export scope, | 152 /// [LibraryElement] for the library and computes the import/export scope, |
| 155 /// loading and computing the import/export scopes of all required libraries | 153 /// loading and computing the import/export scopes of all required libraries |
| 156 /// in the process. The method handles cyclic dependency between libraries. | 154 /// in the process. The method handles cyclic dependency between libraries. |
| 157 /// | 155 /// |
| 158 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the | 156 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the |
| 159 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only | 157 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only |
| 160 /// used for analysis through [Compiler.analyzeUri]. | 158 /// used for analysis through [Compiler.analyzeUri]. |
| 161 Future<LibraryElement> loadLibrary( | 159 Future<LibraryElement> loadLibrary(Uri resolvedUri, |
| 162 Uri resolvedUri, | |
| 163 {bool skipFileWithPartOfTag: false}); | 160 {bool skipFileWithPartOfTag: false}); |
| 164 | 161 |
| 165 /// Reset the library loader task to prepare for compilation. If provided, | 162 /// Reset the library loader task to prepare for compilation. If provided, |
| 166 /// libraries matching [reuseLibrary] are reused. | 163 /// libraries matching [reuseLibrary] are reused. |
| 167 /// | 164 /// |
| 168 /// This method is used for incremental compilation. | 165 /// This method is used for incremental compilation. |
| 169 void reset({bool reuseLibrary(LibraryElement library)}); | 166 void reset({bool reuseLibrary(LibraryElement library)}); |
| 170 | 167 |
| 171 /// Asynchronous version of [reset]. | 168 /// Asynchronous version of [reset]. |
| 172 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)); | 169 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 final LibraryDeserializer deserializer; | 283 final LibraryDeserializer deserializer; |
| 287 | 284 |
| 288 /// Hooks to inform others about progress done by this loader. | 285 /// Hooks to inform others about progress done by this loader. |
| 289 // TODO(sigmund): move away from this. | 286 // TODO(sigmund): move away from this. |
| 290 final LibraryLoaderListener listener; | 287 final LibraryLoaderListener listener; |
| 291 | 288 |
| 292 /// Definitions provided via the `-D` command line flags. Used to resolve | 289 /// Definitions provided via the `-D` command line flags. Used to resolve |
| 293 /// conditional imports. | 290 /// conditional imports. |
| 294 final Environment environment; | 291 final Environment environment; |
| 295 | 292 |
| 296 _LibraryLoaderTask( | 293 _LibraryLoaderTask(Compiler compiler, this.uriTranslator, this.scriptLoader, |
| 297 Compiler compiler, this.uriTranslator, this.scriptLoader, | |
| 298 this.scanner, this.deserializer, this.listener, this.environment) | 294 this.scanner, this.deserializer, this.listener, this.environment) |
| 299 // TODO(sigmund): make measurements separate from compiler | 295 // TODO(sigmund): make measurements separate from compiler |
| 300 : super(compiler); | 296 : super(compiler); |
| 301 | 297 |
| 302 String get name => 'LibraryLoader'; | 298 String get name => 'LibraryLoader'; |
| 303 | 299 |
| 304 final Map<Uri, LibraryElement> libraryCanonicalUriMap = | 300 final Map<Uri, LibraryElement> libraryCanonicalUriMap = |
| 305 new Map<Uri, LibraryElement>(); | 301 new Map<Uri, LibraryElement>(); |
| 306 final Map<Uri, LibraryElement> libraryResourceUriMap = | 302 final Map<Uri, LibraryElement> libraryResourceUriMap = |
| 307 new Map<Uri, LibraryElement>(); | 303 new Map<Uri, LibraryElement>(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { | 344 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { |
| 349 return measure(() { | 345 return measure(() { |
| 350 assert(currentHandler == null); | 346 assert(currentHandler == null); |
| 351 | 347 |
| 352 wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null); | 348 wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null); |
| 353 List<Future<LibraryElement>> reusedLibrariesFuture = | 349 List<Future<LibraryElement>> reusedLibrariesFuture = |
| 354 // TODO(sigmund): make measurements separate from compiler | 350 // TODO(sigmund): make measurements separate from compiler |
| 355 compiler.reuseLibraryTask.measure( | 351 compiler.reuseLibraryTask.measure( |
| 356 () => libraryCanonicalUriMap.values.map(wrapper).toList()); | 352 () => libraryCanonicalUriMap.values.map(wrapper).toList()); |
| 357 | 353 |
| 358 return Future.wait(reusedLibrariesFuture).then( | 354 return Future |
| 359 (List<LibraryElement> reusedLibraries) { | 355 .wait(reusedLibrariesFuture) |
| 360 resetImplementation(reusedLibraries.where((e) => e != null)); | 356 .then((List<LibraryElement> reusedLibraries) { |
| 361 }); | 357 resetImplementation(reusedLibraries.where((e) => e != null)); |
| 358 }); |
| 362 }); | 359 }); |
| 363 } | 360 } |
| 364 | 361 |
| 365 /// Insert [library] in the internal maps. Used for compiler reuse. | 362 /// Insert [library] in the internal maps. Used for compiler reuse. |
| 366 void mapLibrary(LibraryElement library) { | 363 void mapLibrary(LibraryElement library) { |
| 367 libraryCanonicalUriMap[library.canonicalUri] = library; | 364 libraryCanonicalUriMap[library.canonicalUri] = library; |
| 368 | 365 |
| 369 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; | 366 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; |
| 370 libraryResourceUriMap[resourceUri] = library; | 367 libraryResourceUriMap[resourceUri] = library; |
| 371 | 368 |
| 372 if (library.hasLibraryName) { | 369 if (library.hasLibraryName) { |
| 373 String name = library.libraryName; | 370 String name = library.libraryName; |
| 374 libraryNames[name] = library; | 371 libraryNames[name] = library; |
| 375 } | 372 } |
| 376 } | 373 } |
| 377 | 374 |
| 378 Future<LibraryElement> loadLibrary(Uri resolvedUri, | 375 Future<LibraryElement> loadLibrary(Uri resolvedUri, |
| 379 {bool skipFileWithPartOfTag: false}) { | 376 {bool skipFileWithPartOfTag: false}) { |
| 380 return measure(() { | 377 return measure(() { |
| 381 assert(currentHandler == null); | 378 assert(currentHandler == null); |
| 382 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the | 379 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the |
| 383 // loading of a library cluster. | 380 // loading of a library cluster. |
| 384 currentHandler = new LibraryDependencyHandler(this); | 381 currentHandler = new LibraryDependencyHandler(this); |
| 385 return createLibrary(currentHandler, null, resolvedUri, | 382 return createLibrary(currentHandler, null, resolvedUri, |
| 386 skipFileWithPartOfTag: skipFileWithPartOfTag) | 383 skipFileWithPartOfTag: skipFileWithPartOfTag) |
| 387 .then((LibraryElement library) { | 384 .then((LibraryElement library) { |
| 388 if (library == null) { | 385 if (library == null) { |
| 389 currentHandler = null; | 386 currentHandler = null; |
| 390 return null; | 387 return null; |
| 391 } | 388 } |
| 392 return reporter.withCurrentElement(library, () { | 389 return reporter.withCurrentElement(library, () { |
| 393 return measure(() { | 390 return measure(() { |
| 394 currentHandler.computeExports(); | 391 currentHandler.computeExports(); |
| 395 LoadedLibraries loadedLibraries = new _LoadedLibraries( | 392 LoadedLibraries loadedLibraries = new _LoadedLibraries(library, |
| 396 library, | 393 currentHandler.newLibraries, currentHandler.nodeMap, this); |
| 397 currentHandler.newLibraries, | |
| 398 currentHandler.nodeMap, | |
| 399 this); | |
| 400 currentHandler = null; | 394 currentHandler = null; |
| 401 return listener.onLibrariesLoaded(loadedLibraries) | 395 return listener |
| 396 .onLibrariesLoaded(loadedLibraries) |
| 402 .then((_) => library); | 397 .then((_) => library); |
| 403 }); | 398 }); |
| 404 }); | 399 }); |
| 405 }); | 400 }); |
| 406 }); | 401 }); |
| 407 } | 402 } |
| 408 | 403 |
| 409 /** | 404 /** |
| 410 * Processes the library tags in [library]. | 405 * Processes the library tags in [library]. |
| 411 * | 406 * |
| 412 * The imported/exported libraries are loaded and processed recursively but | 407 * The imported/exported libraries are loaded and processed recursively but |
| 413 * the import/export scopes are not set up. | 408 * the import/export scopes are not set up. |
| 414 */ | 409 */ |
| 415 Future processLibraryTags(LibraryDependencyHandler handler, | 410 Future processLibraryTags( |
| 416 LibraryElementX library) { | 411 LibraryDependencyHandler handler, LibraryElementX library) { |
| 417 TagState tagState = new TagState(); | 412 TagState tagState = new TagState(); |
| 418 | 413 |
| 419 bool importsDartCore = false; | 414 bool importsDartCore = false; |
| 420 LinkBuilder<LibraryDependencyElementX> libraryDependencies = | 415 LinkBuilder<LibraryDependencyElementX> libraryDependencies = |
| 421 new LinkBuilder<LibraryDependencyElementX>(); | 416 new LinkBuilder<LibraryDependencyElementX>(); |
| 422 Uri base = library.entryCompilationUnit.script.readableUri; | 417 Uri base = library.entryCompilationUnit.script.readableUri; |
| 423 | 418 |
| 424 return Future.forEach(library.tags, (LibraryTag tag) { | 419 return Future.forEach(library.tags, (LibraryTag tag) { |
| 425 return reporter.withCurrentElement(library, () { | 420 return reporter.withCurrentElement(library, () { |
| 426 | |
| 427 Uri computeUri(LibraryDependency node) { | 421 Uri computeUri(LibraryDependency node) { |
| 428 StringNode uriNode = node.uri; | 422 StringNode uriNode = node.uri; |
| 429 if (node.conditionalUris != null) { | 423 if (node.conditionalUris != null) { |
| 430 for (ConditionalUri conditionalUri in node.conditionalUris) { | 424 for (ConditionalUri conditionalUri in node.conditionalUris) { |
| 431 String key = conditionalUri.key.slowNameString; | 425 String key = conditionalUri.key.slowNameString; |
| 432 String value = conditionalUri.value == null | 426 String value = conditionalUri.value == null |
| 433 ? "true" | 427 ? "true" |
| 434 : conditionalUri.value.dartString.slowToString(); | 428 : conditionalUri.value.dartString.slowToString(); |
| 435 String actual = environment.valueOf(key); | 429 String actual = environment.valueOf(key); |
| 436 if (value == actual) { | 430 if (value == actual) { |
| 437 uriNode = conditionalUri.uri; | 431 uriNode = conditionalUri.uri; |
| 438 break; | 432 break; |
| 439 } | 433 } |
| 440 } | 434 } |
| 441 } | 435 } |
| 442 String tagUriString = uriNode.dartString.slowToString(); | 436 String tagUriString = uriNode.dartString.slowToString(); |
| 443 try { | 437 try { |
| 444 return Uri.parse(tagUriString); | 438 return Uri.parse(tagUriString); |
| 445 } on FormatException { | 439 } on FormatException { |
| 446 reporter.reportErrorMessage( | 440 reporter.reportErrorMessage( |
| 447 node.uri, | 441 node.uri, MessageKind.INVALID_URI, {'uri': tagUriString}); |
| 448 MessageKind.INVALID_URI, {'uri': tagUriString}); | |
| 449 return null; | 442 return null; |
| 450 } | 443 } |
| 451 } | 444 } |
| 452 | 445 |
| 453 if (tag.isImport) { | 446 if (tag.isImport) { |
| 454 Uri uri = computeUri(tag); | 447 Uri uri = computeUri(tag); |
| 455 if (uri == null) { | 448 if (uri == null) { |
| 456 // Skip this erroneous import. | 449 // Skip this erroneous import. |
| 457 return new Future.value(); | 450 return new Future.value(); |
| 458 } | 451 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 }).then((_) { | 490 }).then((_) { |
| 498 return listener.onLibraryScanned(library, handler); | 491 return listener.onLibraryScanned(library, handler); |
| 499 }).then((_) { | 492 }).then((_) { |
| 500 return reporter.withCurrentElement(library, () { | 493 return reporter.withCurrentElement(library, () { |
| 501 checkDuplicatedLibraryName(library); | 494 checkDuplicatedLibraryName(library); |
| 502 | 495 |
| 503 // Import dart:core if not already imported. | 496 // Import dart:core if not already imported. |
| 504 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { | 497 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { |
| 505 return createLibrary(handler, null, Uris.dart_core) | 498 return createLibrary(handler, null, Uris.dart_core) |
| 506 .then((LibraryElement coreLibrary) { | 499 .then((LibraryElement coreLibrary) { |
| 507 handler.registerDependency(library, | 500 handler.registerDependency( |
| 501 library, |
| 508 new SyntheticImportElement( | 502 new SyntheticImportElement( |
| 509 library.entryCompilationUnit, Uris.dart_core), | 503 library.entryCompilationUnit, Uris.dart_core), |
| 510 coreLibrary); | 504 coreLibrary); |
| 511 }); | 505 }); |
| 512 } | 506 } |
| 513 }); | 507 }); |
| 514 }).then((_) { | 508 }).then((_) { |
| 515 return Future.forEach(libraryDependencies.toList(), | 509 return Future.forEach(libraryDependencies.toList(), |
| 516 (LibraryDependencyElementX libraryDependency) { | 510 (LibraryDependencyElementX libraryDependency) { |
| 517 return reporter.withCurrentElement(library, () { | 511 return reporter.withCurrentElement(library, () { |
| 518 return registerLibraryFromImportExport( | 512 return registerLibraryFromImportExport( |
| 519 handler, library, libraryDependency); | 513 handler, library, libraryDependency); |
| 520 }); | 514 }); |
| 521 }); | 515 }); |
| 522 }); | 516 }); |
| 523 } | 517 } |
| 524 | 518 |
| 525 void checkDuplicatedLibraryName(LibraryElement library) { | 519 void checkDuplicatedLibraryName(LibraryElement library) { |
| 526 if (library.isInternalLibrary) return; | 520 if (library.isInternalLibrary) return; |
| 527 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; | 521 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; |
| 528 LibraryElement existing = | 522 LibraryElement existing = |
| 529 libraryResourceUriMap.putIfAbsent(resourceUri, () => library); | 523 libraryResourceUriMap.putIfAbsent(resourceUri, () => library); |
| 530 if (!identical(existing, library)) { | 524 if (!identical(existing, library)) { |
| 531 if (library.hasLibraryName) { | 525 if (library.hasLibraryName) { |
| 532 reporter.withCurrentElement(library, () { | 526 reporter.withCurrentElement(library, () { |
| 533 reporter.reportWarningMessage( | 527 reporter.reportWarningMessage( |
| 534 library, | 528 library, MessageKind.DUPLICATED_LIBRARY_RESOURCE, { |
| 535 MessageKind.DUPLICATED_LIBRARY_RESOURCE, | 529 'libraryName': library.libraryName, |
| 536 {'libraryName': library.libraryName, | 530 'resourceUri': resourceUri, |
| 537 'resourceUri': resourceUri, | 531 'canonicalUri1': library.canonicalUri, |
| 538 'canonicalUri1': library.canonicalUri, | 532 'canonicalUri2': existing.canonicalUri |
| 539 'canonicalUri2': existing.canonicalUri}); | 533 }); |
| 540 }); | 534 }); |
| 541 } else { | 535 } else { |
| 542 reporter.reportHintMessage( | 536 reporter.reportHintMessage(library, MessageKind.DUPLICATED_RESOURCE, { |
| 543 library, | 537 'resourceUri': resourceUri, |
| 544 MessageKind.DUPLICATED_RESOURCE, | 538 'canonicalUri1': library.canonicalUri, |
| 545 {'resourceUri': resourceUri, | 539 'canonicalUri2': existing.canonicalUri |
| 546 'canonicalUri1': library.canonicalUri, | 540 }); |
| 547 'canonicalUri2': existing.canonicalUri}); | |
| 548 } | 541 } |
| 549 } else if (library.hasLibraryName) { | 542 } else if (library.hasLibraryName) { |
| 550 String name = library.libraryName; | 543 String name = library.libraryName; |
| 551 existing = libraryNames.putIfAbsent(name, () => library); | 544 existing = libraryNames.putIfAbsent(name, () => library); |
| 552 if (!identical(existing, library)) { | 545 if (!identical(existing, library)) { |
| 553 reporter.withCurrentElement(library, () { | 546 reporter.withCurrentElement(library, () { |
| 554 reporter.reportWarningMessage( | 547 reporter.reportWarningMessage(library, |
| 555 library, | 548 MessageKind.DUPLICATED_LIBRARY_NAME, {'libraryName': name}); |
| 556 MessageKind.DUPLICATED_LIBRARY_NAME, | |
| 557 {'libraryName': name}); | |
| 558 }); | 549 }); |
| 559 reporter.withCurrentElement(existing, () { | 550 reporter.withCurrentElement(existing, () { |
| 560 reporter.reportWarningMessage( | 551 reporter.reportWarningMessage(existing, |
| 561 existing, | 552 MessageKind.DUPLICATED_LIBRARY_NAME, {'libraryName': name}); |
| 562 MessageKind.DUPLICATED_LIBRARY_NAME, | |
| 563 {'libraryName': name}); | |
| 564 }); | 553 }); |
| 565 } | 554 } |
| 566 } | 555 } |
| 567 } | 556 } |
| 568 | 557 |
| 569 /** | 558 /** |
| 570 * Handle a part tag in the scope of [library]. The [resolvedUri] given is | 559 * Handle a part tag in the scope of [library]. The [resolvedUri] given is |
| 571 * used as is, any URI resolution should be done beforehand. | 560 * used as is, any URI resolution should be done beforehand. |
| 572 */ | 561 */ |
| 573 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { | 562 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { |
| 574 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); | 563 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); |
| 575 Uri readableUri = uriTranslator.translate(library, resolvedUri, part); | 564 Uri readableUri = uriTranslator.translate(library, resolvedUri, part); |
| 576 if (readableUri == null) return new Future.value(); | 565 if (readableUri == null) return new Future.value(); |
| 577 return reporter.withCurrentElement(library, () { | 566 return reporter.withCurrentElement(library, () { |
| 578 return scriptLoader.readScript(readableUri, part).then((Script script) { | 567 return scriptLoader.readScript(readableUri, part).then((Script script) { |
| 579 if (script == null) return; | 568 if (script == null) return; |
| 580 createUnitSync(script, library); | 569 createUnitSync(script, library); |
| 581 }); | 570 }); |
| 582 }); | 571 }); |
| 583 } | 572 } |
| 584 | 573 |
| 585 /** | 574 /** |
| 586 * Handle an import/export tag by loading the referenced library and | 575 * Handle an import/export tag by loading the referenced library and |
| 587 * registering its dependency in [handler] for the computation of the import/ | 576 * registering its dependency in [handler] for the computation of the import/ |
| 588 * export scope. If the tag does not contain a valid URI, then its dependency | 577 * export scope. If the tag does not contain a valid URI, then its dependency |
| 589 * is not registered in [handler]. | 578 * is not registered in [handler]. |
| 590 */ | 579 */ |
| 591 Future<Null> registerLibraryFromImportExport( | 580 Future<Null> registerLibraryFromImportExport(LibraryDependencyHandler handler, |
| 592 LibraryDependencyHandler handler, | 581 LibraryElement library, LibraryDependencyElementX libraryDependency) { |
| 593 LibraryElement library, | |
| 594 LibraryDependencyElementX libraryDependency) { | |
| 595 Uri base = library.canonicalUri; | 582 Uri base = library.canonicalUri; |
| 596 Uri resolvedUri = base.resolveUri(libraryDependency.uri); | 583 Uri resolvedUri = base.resolveUri(libraryDependency.uri); |
| 597 return createLibrary(handler, library, resolvedUri, node: libraryDependency) | 584 return createLibrary(handler, library, resolvedUri, node: libraryDependency) |
| 598 .then((LibraryElement loadedLibrary) { | 585 .then((LibraryElement loadedLibrary) { |
| 599 if (loadedLibrary == null) return; | 586 if (loadedLibrary == null) return; |
| 600 reporter.withCurrentElement(library, () { | 587 reporter.withCurrentElement(library, () { |
| 601 libraryDependency.libraryDependency = loadedLibrary; | 588 libraryDependency.libraryDependency = loadedLibrary; |
| 602 handler.registerDependency( | 589 handler.registerDependency(library, libraryDependency, loadedLibrary); |
| 603 library, libraryDependency, loadedLibrary); | 590 }); |
| 604 }); | 591 }); |
| 605 }); | |
| 606 } | 592 } |
| 607 | 593 |
| 608 /// Loads the deserialized [library] with the [handler]. | 594 /// Loads the deserialized [library] with the [handler]. |
| 609 /// | 595 /// |
| 610 /// All libraries imported or exported transitively from [library] will be | 596 /// All libraries imported or exported transitively from [library] will be |
| 611 /// loaded as well. | 597 /// loaded as well. |
| 612 Future<LibraryElement> loadDeserializedLibrary( | 598 Future<LibraryElement> loadDeserializedLibrary( |
| 613 LibraryDependencyHandler handler, | 599 LibraryDependencyHandler handler, LibraryElement library) { |
| 614 LibraryElement library) { | |
| 615 libraryCanonicalUriMap[library.canonicalUri] = library; | 600 libraryCanonicalUriMap[library.canonicalUri] = library; |
| 616 handler.registerNewLibrary(library); | 601 handler.registerNewLibrary(library); |
| 617 return listener.onLibraryScanned(library, handler).then((_) { | 602 return listener.onLibraryScanned(library, handler).then((_) { |
| 618 return Future.forEach(library.imports, (ImportElement import) { | 603 return Future.forEach(library.imports, (ImportElement import) { |
| 619 return createLibrary(handler, library, import.uri); | 604 return createLibrary(handler, library, import.uri); |
| 620 }).then((_) { | 605 }).then((_) { |
| 621 return Future.forEach(library.exports, (ExportElement export) { | 606 return Future.forEach(library.exports, (ExportElement export) { |
| 622 return createLibrary(handler, library, export.uri); | 607 return createLibrary(handler, library, export.uri); |
| 623 }).then((_) => library); | 608 }).then((_) => library); |
| 624 }); | 609 }); |
| 625 }); | 610 }); |
| 626 } | 611 } |
| 627 | 612 |
| 628 Future<Script> _readScript(Spannable spannable, | 613 Future<Script> _readScript( |
| 629 Uri readableUri, Uri resolvedUri) { | 614 Spannable spannable, Uri readableUri, Uri resolvedUri) { |
| 630 if (readableUri == null) { | 615 if (readableUri == null) { |
| 631 return new Future.value(new Script.synthetic(resolvedUri)); | 616 return new Future.value(new Script.synthetic(resolvedUri)); |
| 632 } else { | 617 } else { |
| 633 return scriptLoader.readScript(readableUri, spannable); | 618 return scriptLoader.readScript(readableUri, spannable); |
| 634 } | 619 } |
| 635 } | 620 } |
| 636 | 621 |
| 637 /** | 622 /** |
| 638 * Create (or reuse) a library element for the library specified by the | 623 * Create (or reuse) a library element for the library specified by the |
| 639 * [resolvedUri]. | 624 * [resolvedUri]. |
| 640 * | 625 * |
| 641 * If a new library is created, the [handler] is notified. | 626 * If a new library is created, the [handler] is notified. |
| 642 */ | 627 */ |
| 643 Future<LibraryElement> createLibrary( | 628 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, |
| 644 LibraryDependencyHandler handler, | 629 LibraryElement importingLibrary, Uri resolvedUri, |
| 645 LibraryElement importingLibrary, | 630 {Spannable node, bool skipFileWithPartOfTag: false}) { |
| 646 Uri resolvedUri, | |
| 647 {Spannable node, | |
| 648 bool skipFileWithPartOfTag: false}) { | |
| 649 Uri readableUri = | 631 Uri readableUri = |
| 650 uriTranslator.translate(importingLibrary, resolvedUri, node); | 632 uriTranslator.translate(importingLibrary, resolvedUri, node); |
| 651 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; | 633 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; |
| 652 if (library != null) { | 634 if (library != null) { |
| 653 return new Future.value(library); | 635 return new Future.value(library); |
| 654 } | 636 } |
| 655 library = deserializer.readLibrary(resolvedUri); | 637 library = deserializer.readLibrary(resolvedUri); |
| 656 if (library != null) { | 638 if (library != null) { |
| 657 return loadDeserializedLibrary(handler, library); | 639 return loadDeserializedLibrary(handler, library); |
| 658 } | 640 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 676 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF)); | 658 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF)); |
| 677 reporter.reportError(error); | 659 reporter.reportError(error); |
| 678 } else { | 660 } else { |
| 679 DiagnosticMessage error = reporter.withCurrentElement( | 661 DiagnosticMessage error = reporter.withCurrentElement( |
| 680 compilationUnit, | 662 compilationUnit, |
| 681 () => reporter.createMessage( | 663 () => reporter.createMessage( |
| 682 compilationUnit.partTag, MessageKind.IMPORT_PART_OF)); | 664 compilationUnit.partTag, MessageKind.IMPORT_PART_OF)); |
| 683 DiagnosticMessage info = reporter.withCurrentElement( | 665 DiagnosticMessage info = reporter.withCurrentElement( |
| 684 importingLibrary, | 666 importingLibrary, |
| 685 () => reporter.createMessage( | 667 () => reporter.createMessage( |
| 686 node, | 668 node, MessageKind.IMPORT_PART_OF_HERE)); |
| 687 MessageKind.IMPORT_PART_OF_HERE)); | |
| 688 reporter.reportError(error, [info]); | 669 reporter.reportError(error, [info]); |
| 689 } | 670 } |
| 690 } | 671 } |
| 691 return processLibraryTags(handler, element).then((_) { | 672 return processLibraryTags(handler, element).then((_) { |
| 692 reporter.withCurrentElement(element, () { | 673 reporter.withCurrentElement(element, () { |
| 693 handler.registerLibraryExports(element); | 674 handler.registerLibraryExports(element); |
| 694 }); | 675 }); |
| 695 return element; | 676 return element; |
| 696 }); | 677 }); |
| 697 }); | 678 }); |
| 698 }); | 679 }); |
| 699 } | 680 } |
| 700 | 681 |
| 701 LibraryElement createLibrarySync(LibraryDependencyHandler handler, | 682 LibraryElement createLibrarySync( |
| 702 Script script, Uri resolvedUri) { | 683 LibraryDependencyHandler handler, Script script, Uri resolvedUri) { |
| 703 LibraryElement element = new LibraryElementX(script, resolvedUri); | 684 LibraryElement element = new LibraryElementX(script, resolvedUri); |
| 704 return reporter.withCurrentElement(element, () { | 685 return reporter.withCurrentElement(element, () { |
| 705 if (handler != null) { | 686 if (handler != null) { |
| 706 handler.registerNewLibrary(element); | 687 handler.registerNewLibrary(element); |
| 707 libraryCanonicalUriMap[resolvedUri] = element; | 688 libraryCanonicalUriMap[resolvedUri] = element; |
| 708 } | 689 } |
| 709 scanner.scanLibrary(element); | 690 scanner.scanLibrary(element); |
| 710 return element; | 691 return element; |
| 711 }); | 692 }); |
| 712 } | 693 } |
| 713 | 694 |
| 714 CompilationUnitElement createUnitSync(Script script, LibraryElement library) { | 695 CompilationUnitElement createUnitSync(Script script, LibraryElement library) { |
| 715 CompilationUnitElementX unit = new CompilationUnitElementX(script, library); | 696 CompilationUnitElementX unit = new CompilationUnitElementX(script, library); |
| 716 reporter.withCurrentElement(unit, () { | 697 reporter.withCurrentElement(unit, () { |
| 717 scanner.scanUnit(unit); | 698 scanner.scanUnit(unit); |
| 718 if (unit.partTag == null && !script.isSynthesized) { | 699 if (unit.partTag == null && !script.isSynthesized) { |
| 719 reporter.reportErrorMessage(unit, MessageKind.MISSING_PART_OF_TAG); | 700 reporter.reportErrorMessage(unit, MessageKind.MISSING_PART_OF_TAG); |
| 720 } | 701 } |
| 721 }); | 702 }); |
| 722 return unit; | 703 return unit; |
| 723 } | 704 } |
| 724 } | 705 } |
| 725 | 706 |
| 726 | |
| 727 /// A state machine for checking script tags come in the correct order. | 707 /// A state machine for checking script tags come in the correct order. |
| 728 class TagState { | 708 class TagState { |
| 729 /// Initial state. | 709 /// Initial state. |
| 730 static const int NO_TAG_SEEN = 0; | 710 static const int NO_TAG_SEEN = 0; |
| 731 | 711 |
| 732 /// Passed to [checkTag] when a library declaration (the syntax "library | 712 /// Passed to [checkTag] when a library declaration (the syntax "library |
| 733 /// name;") has been seen. Not an actual state. | 713 /// name;") has been seen. Not an actual state. |
| 734 static const int LIBRARY = 1; | 714 static const int LIBRARY = 1; |
| 735 | 715 |
| 736 /// The state after the first library declaration. | 716 /// The state after the first library declaration. |
| 737 static const int AFTER_LIBRARY_DECLARATION = 2; | 717 static const int AFTER_LIBRARY_DECLARATION = 2; |
| 738 | 718 |
| 739 /// The state after a import or export declaration has been seen, but before | 719 /// The state after a import or export declaration has been seen, but before |
| 740 /// a part tag has been seen. | 720 /// a part tag has been seen. |
| 741 static const int IMPORT_OR_EXPORT = 3; | 721 static const int IMPORT_OR_EXPORT = 3; |
| 742 | 722 |
| 743 /// The state after a part tag has been seen. | 723 /// The state after a part tag has been seen. |
| 744 static const int PART = 4; | 724 static const int PART = 4; |
| 745 | 725 |
| 746 /// Encodes transition function for state machine. | 726 /// Encodes transition function for state machine. |
| 747 static const List<int> NEXT = const <int>[ | 727 static const List<int> NEXT = const <int>[ |
| 748 NO_TAG_SEEN, | 728 NO_TAG_SEEN, |
| 749 AFTER_LIBRARY_DECLARATION, // Only one library tag is allowed. | 729 AFTER_LIBRARY_DECLARATION, // Only one library tag is allowed. |
| 750 IMPORT_OR_EXPORT, | 730 IMPORT_OR_EXPORT, |
| 751 IMPORT_OR_EXPORT, | 731 IMPORT_OR_EXPORT, |
| 752 PART, | 732 PART, |
| 753 ]; | 733 ]; |
| 754 | 734 |
| 755 int tagState = TagState.NO_TAG_SEEN; | 735 int tagState = TagState.NO_TAG_SEEN; |
| 756 | 736 |
| 757 bool hasLibraryDeclaration = false; | 737 bool hasLibraryDeclaration = false; |
| 758 | 738 |
| 759 /// If [value] is less than [tagState] complain. Regardless, update | 739 /// If [value] is less than [tagState] complain. Regardless, update |
| 760 /// [tagState] using transition function for state machine. | 740 /// [tagState] using transition function for state machine. |
| 761 void checkTag(int value, LibraryTag tag, DiagnosticReporter reporter) { | 741 void checkTag(int value, LibraryTag tag, DiagnosticReporter reporter) { |
| 762 if (tagState > value) { | 742 if (tagState > value) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 */ | 777 */ |
| 798 class ImportLink { | 778 class ImportLink { |
| 799 final ImportElementX import; | 779 final ImportElementX import; |
| 800 final LibraryElement importedLibrary; | 780 final LibraryElement importedLibrary; |
| 801 | 781 |
| 802 ImportLink(this.import, this.importedLibrary); | 782 ImportLink(this.import, this.importedLibrary); |
| 803 | 783 |
| 804 /** | 784 /** |
| 805 * Imports the library into the [importingLibrary]. | 785 * Imports the library into the [importingLibrary]. |
| 806 */ | 786 */ |
| 807 void importLibrary(DiagnosticReporter reporter, | 787 void importLibrary( |
| 808 LibraryElementX importingLibrary) { | 788 DiagnosticReporter reporter, LibraryElementX importingLibrary) { |
| 809 assert(invariant(importingLibrary, | 789 assert(invariant(importingLibrary, importedLibrary.exportsHandled, |
| 810 importedLibrary.exportsHandled, | 790 message: 'Exports not handled on $importedLibrary')); |
| 811 message: 'Exports not handled on $importedLibrary')); | |
| 812 Import tag = import.node; | 791 Import tag = import.node; |
| 813 CombinatorFilter combinatorFilter = | 792 CombinatorFilter combinatorFilter = new CombinatorFilter.fromTag(tag); |
| 814 new CombinatorFilter.fromTag(tag); | |
| 815 if (tag != null && tag.prefix != null) { | 793 if (tag != null && tag.prefix != null) { |
| 816 String prefix = tag.prefix.source; | 794 String prefix = tag.prefix.source; |
| 817 Element existingElement = importingLibrary.find(prefix); | 795 Element existingElement = importingLibrary.find(prefix); |
| 818 PrefixElementX prefixElement; | 796 PrefixElementX prefixElement; |
| 819 if (existingElement == null || !existingElement.isPrefix) { | 797 if (existingElement == null || !existingElement.isPrefix) { |
| 820 prefixElement = new PrefixElementX( | 798 prefixElement = new PrefixElementX( |
| 821 prefix, | 799 prefix, |
| 822 importingLibrary.entryCompilationUnit, | 800 importingLibrary.entryCompilationUnit, |
| 823 tag.getBeginToken(), | 801 tag.getBeginToken(), |
| 824 tag.isDeferred ? import : null); | 802 tag.isDeferred ? import : null); |
| 825 } else { | 803 } else { |
| 826 prefixElement = existingElement; | 804 prefixElement = existingElement; |
| 827 } | 805 } |
| 828 importingLibrary.addToScope(prefixElement, reporter); | 806 importingLibrary.addToScope(prefixElement, reporter); |
| 829 importedLibrary.forEachExport((Element element) { | 807 importedLibrary.forEachExport((Element element) { |
| 830 if (combinatorFilter.exclude(element)) return; | 808 if (combinatorFilter.exclude(element)) return; |
| 831 prefixElement.addImport(element, import, reporter); | 809 prefixElement.addImport(element, import, reporter); |
| 832 }); | 810 }); |
| 833 import.prefix = prefixElement; | 811 import.prefix = prefixElement; |
| 834 if (prefixElement.isDeferred) { | 812 if (prefixElement.isDeferred) { |
| 835 prefixElement.addImport( | 813 prefixElement.addImport( |
| 836 new DeferredLoaderGetterElementX(prefixElement), | 814 new DeferredLoaderGetterElementX(prefixElement), import, reporter); |
| 837 import, reporter); | |
| 838 } | 815 } |
| 839 } else { | 816 } else { |
| 840 importedLibrary.forEachExport((Element element) { | 817 importedLibrary.forEachExport((Element element) { |
| 841 reporter.withCurrentElement(importingLibrary, () { | 818 reporter.withCurrentElement(importingLibrary, () { |
| 842 if (combinatorFilter.exclude(element)) return; | 819 if (combinatorFilter.exclude(element)) return; |
| 843 importingLibrary.addImport(element, import, reporter); | 820 importingLibrary.addImport(element, import, reporter); |
| 844 }); | 821 }); |
| 845 }); | 822 }); |
| 846 } | 823 } |
| 847 } | 824 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 * exports performed in [LibraryDependencyHandler.computeExports]. | 857 * exports performed in [LibraryDependencyHandler.computeExports]. |
| 881 */ | 858 */ |
| 882 class LibraryDependencyNode { | 859 class LibraryDependencyNode { |
| 883 final LibraryElementX library; | 860 final LibraryElementX library; |
| 884 | 861 |
| 885 // TODO(ahe): Remove [hashCodeCounter] and [hashCode] when | 862 // TODO(ahe): Remove [hashCodeCounter] and [hashCode] when |
| 886 // VM implementation of Object.hashCode is not slow. | 863 // VM implementation of Object.hashCode is not slow. |
| 887 final int hashCode = ++hashCodeCounter; | 864 final int hashCode = ++hashCodeCounter; |
| 888 static int hashCodeCounter = 0; | 865 static int hashCodeCounter = 0; |
| 889 | 866 |
| 890 | |
| 891 /** | 867 /** |
| 892 * A linked list of the import tags that import [library] mapped to the | 868 * A linked list of the import tags that import [library] mapped to the |
| 893 * corresponding libraries. This is used to propagate exports into imports | 869 * corresponding libraries. This is used to propagate exports into imports |
| 894 * after the export scopes have been computed. | 870 * after the export scopes have been computed. |
| 895 */ | 871 */ |
| 896 Link<ImportLink> imports = const Link<ImportLink>(); | 872 Link<ImportLink> imports = const Link<ImportLink>(); |
| 897 | 873 |
| 898 /// A linked list of all libraries directly exported by [library]. | 874 /// A linked list of all libraries directly exported by [library]. |
| 899 Link<LibraryElement> exports = const Link<LibraryElement>(); | 875 Link<LibraryElement> exports = const Link<LibraryElement>(); |
| 900 | 876 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 922 */ | 898 */ |
| 923 Map<Element, Link<ExportElement>> pendingExportMap = | 899 Map<Element, Link<ExportElement>> pendingExportMap = |
| 924 <Element, Link<ExportElement>>{}; | 900 <Element, Link<ExportElement>>{}; |
| 925 | 901 |
| 926 LibraryDependencyNode(this.library); | 902 LibraryDependencyNode(this.library); |
| 927 | 903 |
| 928 /** | 904 /** |
| 929 * Registers that the library of this node imports [importLibrary] through the | 905 * Registers that the library of this node imports [importLibrary] through the |
| 930 * [import] tag. | 906 * [import] tag. |
| 931 */ | 907 */ |
| 932 void registerImportDependency(ImportElementX import, | 908 void registerImportDependency( |
| 933 LibraryElement importedLibrary) { | 909 ImportElementX import, LibraryElement importedLibrary) { |
| 934 imports = imports.prepend(new ImportLink(import, importedLibrary)); | 910 imports = imports.prepend(new ImportLink(import, importedLibrary)); |
| 935 } | 911 } |
| 936 | 912 |
| 937 /** | 913 /** |
| 938 * Registers that the library of this node is exported by | 914 * Registers that the library of this node is exported by |
| 939 * [exportingLibraryNode] through the [export] tag. | 915 * [exportingLibraryNode] through the [export] tag. |
| 940 */ | 916 */ |
| 941 void registerExportDependency(ExportElementX export, | 917 void registerExportDependency( |
| 942 LibraryDependencyNode exportingLibraryNode) { | 918 ExportElementX export, LibraryDependencyNode exportingLibraryNode) { |
| 943 // Register the exported library in the exporting library node. | 919 // Register the exported library in the exporting library node. |
| 944 exportingLibraryNode.exports = | 920 exportingLibraryNode.exports = |
| 945 exportingLibraryNode.exports.prepend(library); | 921 exportingLibraryNode.exports.prepend(library); |
| 946 // Register the export in the exported library node. | 922 // Register the export in the exported library node. |
| 947 dependencies = | 923 dependencies = |
| 948 dependencies.prepend(new ExportLink(export, exportingLibraryNode)); | 924 dependencies.prepend(new ExportLink(export, exportingLibraryNode)); |
| 949 } | 925 } |
| 950 | 926 |
| 951 /** | 927 /** |
| 952 * Registers all non-private locally declared members of the library of this | 928 * Registers all non-private locally declared members of the library of this |
| 953 * node to be exported. This forms the basis for the work-list computation of | 929 * node to be exported. This forms the basis for the work-list computation of |
| 954 * the export scopes performed in [LibraryDependencyHandler.computeExports]. | 930 * the export scopes performed in [LibraryDependencyHandler.computeExports]. |
| 955 */ | 931 */ |
| 956 void registerInitialExports() { | 932 void registerInitialExports() { |
| 957 for (Element element in library.getNonPrivateElementsInScope()) { | 933 for (Element element in library.getNonPrivateElementsInScope()) { |
| 958 pendingExportMap[element] = const Link<ExportElement>(); | 934 pendingExportMap[element] = const Link<ExportElement>(); |
| 959 } | 935 } |
| 960 } | 936 } |
| 961 | 937 |
| 962 /// Register the already computed export scope of [exportedLibraryElement] to | 938 /// Register the already computed export scope of [exportedLibraryElement] to |
| 963 /// export from the library of this node through the [export] declaration | 939 /// export from the library of this node through the [export] declaration |
| 964 /// with the given combination [filter]. | 940 /// with the given combination [filter]. |
| 965 /// | 941 /// |
| 966 /// Additionally, check that all names in the show/hide combinators are in the | 942 /// Additionally, check that all names in the show/hide combinators are in the |
| 967 /// export scope of [exportedLibraryElement]. | 943 /// export scope of [exportedLibraryElement]. |
| 968 void registerHandledExports(DiagnosticReporter reporter, | 944 void registerHandledExports( |
| 969 LibraryElement exportedLibraryElement, | 945 DiagnosticReporter reporter, |
| 970 ExportElementX export, | 946 LibraryElement exportedLibraryElement, |
| 971 CombinatorFilter filter) { | 947 ExportElementX export, |
| 948 CombinatorFilter filter) { |
| 972 assert(invariant(library, exportedLibraryElement.exportsHandled)); | 949 assert(invariant(library, exportedLibraryElement.exportsHandled)); |
| 973 exportedLibraryElement.forEachExport((Element exportedElement) { | 950 exportedLibraryElement.forEachExport((Element exportedElement) { |
| 974 if (!filter.exclude(exportedElement)) { | 951 if (!filter.exclude(exportedElement)) { |
| 975 Link<ExportElement> exports = | 952 Link<ExportElement> exports = pendingExportMap.putIfAbsent( |
| 976 pendingExportMap.putIfAbsent(exportedElement, | 953 exportedElement, () => const Link<ExportElement>()); |
| 977 () => const Link<ExportElement>()); | |
| 978 pendingExportMap[exportedElement] = exports.prepend(export); | 954 pendingExportMap[exportedElement] = exports.prepend(export); |
| 979 } | 955 } |
| 980 }); | 956 }); |
| 981 if (!reporter.options.suppressHints) { | 957 if (!reporter.options.suppressHints) { |
| 982 reporter.withCurrentElement(library, () { | 958 reporter.withCurrentElement(library, () { |
| 983 checkLibraryDependency(reporter, export.node, exportedLibraryElement); | 959 checkLibraryDependency(reporter, export.node, exportedLibraryElement); |
| 984 }); | 960 }); |
| 985 } | 961 } |
| 986 } | 962 } |
| 987 | 963 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1008 Map<Element, Link<ExportElement>> pendingExports = | 984 Map<Element, Link<ExportElement>> pendingExports = |
| 1009 new Map<Element, Link<ExportElement>>.from(pendingExportMap); | 985 new Map<Element, Link<ExportElement>>.from(pendingExportMap); |
| 1010 pendingExportMap.clear(); | 986 pendingExportMap.clear(); |
| 1011 return pendingExports; | 987 return pendingExports; |
| 1012 } | 988 } |
| 1013 | 989 |
| 1014 /** | 990 /** |
| 1015 * Adds [element] to the export scope for this node. If the [element] name | 991 * Adds [element] to the export scope for this node. If the [element] name |
| 1016 * is a duplicate, an error element is inserted into the export scope. | 992 * is a duplicate, an error element is inserted into the export scope. |
| 1017 */ | 993 */ |
| 1018 Element addElementToExportScope( | 994 Element addElementToExportScope(DiagnosticReporter reporter, Element element, |
| 1019 DiagnosticReporter reporter, | |
| 1020 Element element, | |
| 1021 Link<ExportElement> exports) { | 995 Link<ExportElement> exports) { |
| 1022 String name = element.name; | 996 String name = element.name; |
| 1023 DiagnosticMessage error; | 997 DiagnosticMessage error; |
| 1024 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 998 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 1025 | 999 |
| 1026 void createDuplicateExportMessage( | 1000 void createDuplicateExportMessage( |
| 1027 Element duplicate, | 1001 Element duplicate, Link<ExportElement> duplicateExports) { |
| 1028 Link<ExportElement> duplicateExports) { | |
| 1029 assert(invariant(library, !duplicateExports.isEmpty, | 1002 assert(invariant(library, !duplicateExports.isEmpty, |
| 1030 message: "No export for $duplicate from ${duplicate.library} " | 1003 message: "No export for $duplicate from ${duplicate.library} " |
| 1031 "in $library.")); | 1004 "in $library.")); |
| 1032 reporter.withCurrentElement(library, () { | 1005 reporter.withCurrentElement(library, () { |
| 1033 for (ExportElement export in duplicateExports) { | 1006 for (ExportElement export in duplicateExports) { |
| 1034 if (error == null) { | 1007 if (error == null) { |
| 1035 error = reporter.createMessage( | 1008 error = reporter.createMessage( |
| 1036 export, | 1009 export, MessageKind.DUPLICATE_EXPORT, {'name': name}); |
| 1037 MessageKind.DUPLICATE_EXPORT, | |
| 1038 {'name': name}); | |
| 1039 } else { | 1010 } else { |
| 1040 infos.add(reporter.createMessage( | 1011 infos.add(reporter.createMessage( |
| 1041 export, | 1012 export, MessageKind.DUPLICATE_EXPORT_CONT, {'name': name})); |
| 1042 MessageKind.DUPLICATE_EXPORT_CONT, | |
| 1043 {'name': name})); | |
| 1044 } | 1013 } |
| 1045 } | 1014 } |
| 1046 }); | 1015 }); |
| 1047 } | 1016 } |
| 1048 | 1017 |
| 1049 void createDuplicateExportDeclMessage( | 1018 void createDuplicateExportDeclMessage( |
| 1050 Element duplicate, | 1019 Element duplicate, Link<ExportElement> duplicateExports) { |
| 1051 Link<ExportElement> duplicateExports) { | |
| 1052 assert(invariant(library, !duplicateExports.isEmpty, | 1020 assert(invariant(library, !duplicateExports.isEmpty, |
| 1053 message: "No export for $duplicate from ${duplicate.library} " | 1021 message: "No export for $duplicate from ${duplicate.library} " |
| 1054 "in $library.")); | 1022 "in $library.")); |
| 1055 infos.add(reporter.createMessage( | 1023 infos.add(reporter.createMessage( |
| 1056 duplicate, | 1024 duplicate, |
| 1057 MessageKind.DUPLICATE_EXPORT_DECL, | 1025 MessageKind.DUPLICATE_EXPORT_DECL, |
| 1058 {'name': name, 'uriString': duplicateExports.head.uri})); | 1026 {'name': name, 'uriString': duplicateExports.head.uri})); |
| 1059 } | 1027 } |
| 1060 | 1028 |
| 1061 Element existingElement = exportScope[name]; | 1029 Element existingElement = exportScope[name]; |
| 1062 if (existingElement != null && existingElement != element) { | 1030 if (existingElement != null && existingElement != element) { |
| 1063 if (existingElement.isMalformed) { | 1031 if (existingElement.isMalformed) { |
| 1064 createDuplicateExportMessage(element, exports); | 1032 createDuplicateExportMessage(element, exports); |
| 1065 createDuplicateExportDeclMessage(element, exports); | 1033 createDuplicateExportDeclMessage(element, exports); |
| 1066 element = existingElement; | 1034 element = existingElement; |
| 1067 } else if (existingElement.library == library) { | 1035 } else if (existingElement.library == library) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 }); | 1101 }); |
| 1134 for (ExportLink exportLink in dependencies) { | 1102 for (ExportLink exportLink in dependencies) { |
| 1135 reporter.withCurrentElement(exportLink.exportNode.library, () { | 1103 reporter.withCurrentElement(exportLink.exportNode.library, () { |
| 1136 checkLibraryDependency(reporter, exportLink.export.node, library); | 1104 checkLibraryDependency(reporter, exportLink.export.node, library); |
| 1137 }); | 1105 }); |
| 1138 } | 1106 } |
| 1139 } | 1107 } |
| 1140 | 1108 |
| 1141 /// Check that all names in the show/hide combinators of [tag] are in the | 1109 /// Check that all names in the show/hide combinators of [tag] are in the |
| 1142 /// export scope of [library]. | 1110 /// export scope of [library]. |
| 1143 void checkLibraryDependency( | 1111 void checkLibraryDependency(DiagnosticReporter reporter, |
| 1144 DiagnosticReporter reporter, | 1112 LibraryDependency tag, LibraryElement library) { |
| 1145 LibraryDependency tag, | |
| 1146 LibraryElement library) { | |
| 1147 if (tag == null || tag.combinators == null) return; | 1113 if (tag == null || tag.combinators == null) return; |
| 1148 for (Combinator combinator in tag.combinators) { | 1114 for (Combinator combinator in tag.combinators) { |
| 1149 for (Identifier identifier in combinator.identifiers) { | 1115 for (Identifier identifier in combinator.identifiers) { |
| 1150 String name = identifier.source; | 1116 String name = identifier.source; |
| 1151 Element element = library.findExported(name); | 1117 Element element = library.findExported(name); |
| 1152 if (element == null) { | 1118 if (element == null) { |
| 1153 if (combinator.isHide) { | 1119 if (combinator.isHide) { |
| 1154 if (library.isPackageLibrary && | 1120 if (library.isPackageLibrary && |
| 1155 reporter.options.hidePackageWarnings) { | 1121 reporter.options.hidePackageWarnings) { |
| 1156 // Only report hide hint on packages if we show warnings on these: | 1122 // Only report hide hint on packages if we show warnings on these: |
| 1157 // The hide may be non-empty in some versions of the package, in | 1123 // The hide may be non-empty in some versions of the package, in |
| 1158 // which case you shouldn't remove the combinator. | 1124 // which case you shouldn't remove the combinator. |
| 1159 continue; | 1125 continue; |
| 1160 } | 1126 } |
| 1161 reporter.reportHintMessage( | 1127 reporter.reportHintMessage(identifier, MessageKind.EMPTY_HIDE, |
| 1162 identifier, | 1128 {'uri': library.canonicalUri, 'name': name}); |
| 1163 MessageKind.EMPTY_HIDE, | |
| 1164 {'uri': library.canonicalUri, | |
| 1165 'name': name}); | |
| 1166 } else { | 1129 } else { |
| 1167 reporter.reportHintMessage( | 1130 reporter.reportHintMessage(identifier, MessageKind.EMPTY_SHOW, |
| 1168 identifier, | 1131 {'uri': library.canonicalUri, 'name': name}); |
| 1169 MessageKind.EMPTY_SHOW, | |
| 1170 {'uri': library.canonicalUri, | |
| 1171 'name': name}); | |
| 1172 } | 1132 } |
| 1173 } | 1133 } |
| 1174 } | 1134 } |
| 1175 } | 1135 } |
| 1176 } | 1136 } |
| 1177 | |
| 1178 } | 1137 } |
| 1179 | 1138 |
| 1180 /** | 1139 /** |
| 1181 * Helper class used for computing the possibly cyclic import/export scopes of | 1140 * Helper class used for computing the possibly cyclic import/export scopes of |
| 1182 * a set of libraries. | 1141 * a set of libraries. |
| 1183 * | 1142 * |
| 1184 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded | 1143 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded |
| 1185 * libraries and to compute their import/export scopes through a fixed-point | 1144 * libraries and to compute their import/export scopes through a fixed-point |
| 1186 * algorithm. | 1145 * algorithm. |
| 1187 */ | 1146 */ |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 // elements. So we must propagate local elements first. We | 1180 // elements. So we must propagate local elements first. We |
| 1222 // ensure this by pulling the pending exports before | 1181 // ensure this by pulling the pending exports before |
| 1223 // propagating. This enforces that we handle exports | 1182 // propagating. This enforces that we handle exports |
| 1224 // breadth-first, with locally defined elements being level 0. | 1183 // breadth-first, with locally defined elements being level 0. |
| 1225 nodeMap.forEach((_, LibraryDependencyNode node) { | 1184 nodeMap.forEach((_, LibraryDependencyNode node) { |
| 1226 Map<Element, Link<ExportElement>> pendingExports = | 1185 Map<Element, Link<ExportElement>> pendingExports = |
| 1227 node.pullPendingExports(); | 1186 node.pullPendingExports(); |
| 1228 tasks[node] = pendingExports; | 1187 tasks[node] = pendingExports; |
| 1229 }); | 1188 }); |
| 1230 tasks.forEach((LibraryDependencyNode node, | 1189 tasks.forEach((LibraryDependencyNode node, |
| 1231 Map<Element, Link<ExportElement>> pendingExports) { | 1190 Map<Element, Link<ExportElement>> pendingExports) { |
| 1232 pendingExports.forEach((Element element, Link<ExportElement> exports) { | 1191 pendingExports.forEach((Element element, Link<ExportElement> exports) { |
| 1233 element = node.addElementToExportScope(reporter, element, exports); | 1192 element = node.addElementToExportScope(reporter, element, exports); |
| 1234 if (node.propagateElement(element)) { | 1193 if (node.propagateElement(element)) { |
| 1235 changed = true; | 1194 changed = true; |
| 1236 } | 1195 } |
| 1237 }); | 1196 }); |
| 1238 }); | 1197 }); |
| 1239 } | 1198 } |
| 1240 | 1199 |
| 1241 // Setup export scopes. These have to be set before computing the import | 1200 // Setup export scopes. These have to be set before computing the import |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1252 | 1211 |
| 1253 if (!reporter.options.suppressHints) { | 1212 if (!reporter.options.suppressHints) { |
| 1254 nodeMap.forEach((LibraryElement library, LibraryDependencyNode node) { | 1213 nodeMap.forEach((LibraryElement library, LibraryDependencyNode node) { |
| 1255 node.checkCombinators(reporter); | 1214 node.checkCombinators(reporter); |
| 1256 }); | 1215 }); |
| 1257 } | 1216 } |
| 1258 } | 1217 } |
| 1259 | 1218 |
| 1260 /// Registers that [library] depends on [loadedLibrary] through | 1219 /// Registers that [library] depends on [loadedLibrary] through |
| 1261 /// [libraryDependency]. | 1220 /// [libraryDependency]. |
| 1262 void registerDependency(LibraryElementX library, | 1221 void registerDependency( |
| 1263 LibraryDependencyElementX libraryDependency, | 1222 LibraryElementX library, |
| 1264 LibraryElement loadedLibrary) { | 1223 LibraryDependencyElementX libraryDependency, |
| 1224 LibraryElement loadedLibrary) { |
| 1265 if (libraryDependency.isExport) { | 1225 if (libraryDependency.isExport) { |
| 1266 // [loadedLibrary] is exported by [library]. | 1226 // [loadedLibrary] is exported by [library]. |
| 1267 LibraryDependencyNode exportingNode = nodeMap[library]; | 1227 LibraryDependencyNode exportingNode = nodeMap[library]; |
| 1268 if (loadedLibrary.exportsHandled) { | 1228 if (loadedLibrary.exportsHandled) { |
| 1269 // Export scope already computed on [loadedLibrary]. | 1229 // Export scope already computed on [loadedLibrary]. |
| 1270 CombinatorFilter combinatorFilter = | 1230 CombinatorFilter combinatorFilter = |
| 1271 new CombinatorFilter.fromTag(libraryDependency.node); | 1231 new CombinatorFilter.fromTag(libraryDependency.node); |
| 1272 exportingNode.registerHandledExports( | 1232 exportingNode.registerHandledExports( |
| 1273 reporter, loadedLibrary, libraryDependency, combinatorFilter); | 1233 reporter, loadedLibrary, libraryDependency, combinatorFilter); |
| 1274 return; | 1234 return; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 | 1289 |
| 1330 /// Applies all imports chains of [uri] in this bulk to [callback]. | 1290 /// Applies all imports chains of [uri] in this bulk to [callback]. |
| 1331 /// | 1291 /// |
| 1332 /// The argument [importChainReversed] to [callback] contains the chain of | 1292 /// The argument [importChainReversed] to [callback] contains the chain of |
| 1333 /// imports uris that lead to importing [uri] starting in [uri] and ending in | 1293 /// imports uris that lead to importing [uri] starting in [uri] and ending in |
| 1334 /// [rootUri]. | 1294 /// [rootUri]. |
| 1335 /// | 1295 /// |
| 1336 /// [callback] is called once for each chain of imports leading to [uri] until | 1296 /// [callback] is called once for each chain of imports leading to [uri] until |
| 1337 /// [callback] returns `false`. | 1297 /// [callback] returns `false`. |
| 1338 void forEachImportChain(Uri uri, | 1298 void forEachImportChain(Uri uri, |
| 1339 {bool callback(Link<Uri> importChainReversed)}); | 1299 {bool callback(Link<Uri> importChainReversed)}); |
| 1340 } | 1300 } |
| 1341 | 1301 |
| 1342 class _LoadedLibraries implements LoadedLibraries { | 1302 class _LoadedLibraries implements LoadedLibraries { |
| 1343 final _LibraryLoaderTask task; | 1303 final _LibraryLoaderTask task; |
| 1344 final LibraryElement rootLibrary; | 1304 final LibraryElement rootLibrary; |
| 1345 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; | 1305 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; |
| 1346 final Map<LibraryElement, LibraryDependencyNode> nodeMap; | 1306 final Map<LibraryElement, LibraryDependencyNode> nodeMap; |
| 1347 | 1307 |
| 1348 _LoadedLibraries( | 1308 _LoadedLibraries(this.rootLibrary, Iterable<LibraryElement> libraries, |
| 1349 this.rootLibrary, | 1309 this.nodeMap, this.task) { |
| 1350 Iterable<LibraryElement> libraries, | |
| 1351 this.nodeMap, | |
| 1352 this.task) { | |
| 1353 libraries.forEach((LibraryElement loadedLibrary) { | 1310 libraries.forEach((LibraryElement loadedLibrary) { |
| 1354 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; | 1311 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; |
| 1355 }); | 1312 }); |
| 1356 } | 1313 } |
| 1357 | 1314 |
| 1358 Uri get rootUri => rootLibrary.canonicalUri; | 1315 Uri get rootUri => rootLibrary.canonicalUri; |
| 1359 | 1316 |
| 1360 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri); | 1317 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri); |
| 1361 | 1318 |
| 1362 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri]; | 1319 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri]; |
| 1363 | 1320 |
| 1364 void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f); | 1321 void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f); |
| 1365 | 1322 |
| 1366 void forEachImportChain(Uri targetUri, | 1323 void forEachImportChain(Uri targetUri, |
| 1367 {bool callback(Link<Uri> importChainReversed)}) { | 1324 {bool callback(Link<Uri> importChainReversed)}) { |
| 1368 bool aborted = false; | 1325 bool aborted = false; |
| 1369 | 1326 |
| 1370 /// Map from libraries to the set of (unreversed) paths to [uri]. | 1327 /// Map from libraries to the set of (unreversed) paths to [uri]. |
| 1371 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap = | 1328 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap = |
| 1372 <LibraryElement, Iterable<Link<Uri>>>{}; | 1329 <LibraryElement, Iterable<Link<Uri>>>{}; |
| 1373 | 1330 |
| 1374 /// Computes the set of (unreversed) paths to [targetUri]. | 1331 /// Computes the set of (unreversed) paths to [targetUri]. |
| 1375 /// | 1332 /// |
| 1376 /// Finds all paths (suffixes) from the current library to [uri] and stores | 1333 /// Finds all paths (suffixes) from the current library to [uri] and stores |
| 1377 /// it in [suffixChainMap]. | 1334 /// it in [suffixChainMap]. |
| 1378 /// | 1335 /// |
| 1379 /// For every found suffix it prepends the given [prefix] and the canonical | 1336 /// For every found suffix it prepends the given [prefix] and the canonical |
| 1380 /// uri of [library] and invokes the [callback] with the concatenated chain. | 1337 /// uri of [library] and invokes the [callback] with the concatenated chain. |
| 1381 void computeSuffixes(LibraryElement library, | 1338 void computeSuffixes(LibraryElement library, Link<Uri> prefix) { |
| 1382 Link<Uri> prefix) { | |
| 1383 if (aborted) return; | 1339 if (aborted) return; |
| 1384 | 1340 |
| 1385 Uri canonicalUri = library.canonicalUri; | 1341 Uri canonicalUri = library.canonicalUri; |
| 1386 prefix = prefix.prepend(canonicalUri); | 1342 prefix = prefix.prepend(canonicalUri); |
| 1387 if (suffixChainMap.containsKey(library)) return; | 1343 if (suffixChainMap.containsKey(library)) return; |
| 1388 suffixChainMap[library] = const <Link<Uri>>[]; | 1344 suffixChainMap[library] = const <Link<Uri>>[]; |
| 1389 List<Link<Uri>> suffixes = []; | 1345 List<Link<Uri>> suffixes = []; |
| 1390 if (targetUri != canonicalUri) { | 1346 if (targetUri != canonicalUri) { |
| 1391 LibraryDependencyNode node = nodeMap[library]; | 1347 LibraryDependencyNode node = nodeMap[library]; |
| 1392 | 1348 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1421 } | 1377 } |
| 1422 | 1378 |
| 1423 for (ImportLink import in node.imports.reverse()) { | 1379 for (ImportLink import in node.imports.reverse()) { |
| 1424 processLibrary(import.importedLibrary); | 1380 processLibrary(import.importedLibrary); |
| 1425 if (aborted) return; | 1381 if (aborted) return; |
| 1426 } | 1382 } |
| 1427 for (LibraryElement exportedLibrary in node.exports.reverse()) { | 1383 for (LibraryElement exportedLibrary in node.exports.reverse()) { |
| 1428 processLibrary(exportedLibrary); | 1384 processLibrary(exportedLibrary); |
| 1429 if (aborted) return; | 1385 if (aborted) return; |
| 1430 } | 1386 } |
| 1431 } else { // Here `targetUri == canonicalUri`. | 1387 } else { |
| 1388 // Here `targetUri == canonicalUri`. |
| 1432 if (!callback(prefix)) { | 1389 if (!callback(prefix)) { |
| 1433 aborted = true; | 1390 aborted = true; |
| 1434 return; | 1391 return; |
| 1435 } | 1392 } |
| 1436 suffixes.add(const Link<Uri>().prepend(canonicalUri)); | 1393 suffixes.add(const Link<Uri>().prepend(canonicalUri)); |
| 1437 } | 1394 } |
| 1438 suffixChainMap[library] = suffixes; | 1395 suffixChainMap[library] = suffixes; |
| 1439 return; | 1396 return; |
| 1440 } | 1397 } |
| 1441 | 1398 |
| 1442 computeSuffixes(rootLibrary, const Link<Uri>()); | 1399 computeSuffixes(rootLibrary, const Link<Uri>()); |
| 1443 } | 1400 } |
| 1444 | 1401 |
| 1445 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}'; | 1402 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}'; |
| 1446 } | 1403 } |
| 1447 | 1404 |
| 1448 /// API used by the library loader to translate internal SDK URIs into file | 1405 /// API used by the library loader to translate internal SDK URIs into file |
| 1449 /// system readable URIs. | 1406 /// system readable URIs. |
| 1450 abstract class ResolvedUriTranslator { | 1407 abstract class ResolvedUriTranslator { |
| 1451 // TODO(sigmund): move here the comments from library loader. | 1408 // TODO(sigmund): move here the comments from library loader. |
| 1452 /// Translate the resolved [uri] in the context of [importingLibrary]. | 1409 /// Translate the resolved [uri] in the context of [importingLibrary]. |
| 1453 /// | 1410 /// |
| 1454 /// Use [spannable] for error reporting. | 1411 /// Use [spannable] for error reporting. |
| 1455 Uri translate( | 1412 Uri translate(LibraryElement importingLibrary, Uri uri, |
| 1456 LibraryElement importingLibrary, Uri uri, [Spannable spannable]); | 1413 [Spannable spannable]); |
| 1457 } | 1414 } |
| 1458 | 1415 |
| 1459 | |
| 1460 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems | 1416 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems |
| 1461 // rather low-level. It might be more practical to split the library-loading | 1417 // rather low-level. It might be more practical to split the library-loading |
| 1462 // task itself. The task would continue to do the work of recursively loading | 1418 // task itself. The task would continue to do the work of recursively loading |
| 1463 // dependencies, but it can delegate to a set of subloaders how to do the actual | 1419 // dependencies, but it can delegate to a set of subloaders how to do the actual |
| 1464 // loading. We would then have a list of subloaders that use different | 1420 // loading. We would then have a list of subloaders that use different |
| 1465 // implementations: in-memory cache, deserialization, scanning from files. | 1421 // implementations: in-memory cache, deserialization, scanning from files. |
| 1466 // | 1422 // |
| 1467 // For example, the API might look like this: | 1423 // For example, the API might look like this: |
| 1468 // | 1424 // |
| 1469 // /// APIs to create [LibraryElement] and [CompilationUnitElements] given it's | 1425 // /// APIs to create [LibraryElement] and [CompilationUnitElements] given it's |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 Future<Script> readScript(Uri uri, [Spannable spannable]); | 1458 Future<Script> readScript(Uri uri, [Spannable spannable]); |
| 1503 } | 1459 } |
| 1504 | 1460 |
| 1505 /// API used by the library loader to synchronously scan a library or | 1461 /// API used by the library loader to synchronously scan a library or |
| 1506 /// compilation unit and ensure that their library tags are computed. | 1462 /// compilation unit and ensure that their library tags are computed. |
| 1507 abstract class ElementScanner { | 1463 abstract class ElementScanner { |
| 1508 void scanLibrary(LibraryElement library); | 1464 void scanLibrary(LibraryElement library); |
| 1509 void scanUnit(CompilationUnitElement unit); | 1465 void scanUnit(CompilationUnitElement unit); |
| 1510 } | 1466 } |
| 1511 | 1467 |
| 1512 | |
| 1513 /// TODO(sigmund): remove this abstraction. Ideally the loader can produce the | 1468 /// TODO(sigmund): remove this abstraction. Ideally the loader can produce the |
| 1514 /// LoadedLibraries results once, and the compiler and choose what to do with | 1469 /// LoadedLibraries results once, and the compiler and choose what to do with |
| 1515 /// it instead. | 1470 /// it instead. |
| 1516 abstract class LibraryLoaderListener { | 1471 abstract class LibraryLoaderListener { |
| 1517 /// Called after a request to load a library. The [results] will include all | 1472 /// Called after a request to load a library. The [results] will include all |
| 1518 /// transitive libraries loaded as a result of the initial request. | 1473 /// transitive libraries loaded as a result of the initial request. |
| 1519 Future onLibrariesLoaded(LoadedLibraries results); | 1474 Future onLibrariesLoaded(LoadedLibraries results); |
| 1520 | 1475 |
| 1521 /// Called whenever a library element is created. | 1476 /// Called whenever a library element is created. |
| 1522 void onLibraryCreated(LibraryElement library); | 1477 void onLibraryCreated(LibraryElement library); |
| 1523 | 1478 |
| 1524 /// Called whenever a library is scanned from a script file. | 1479 /// Called whenever a library is scanned from a script file. |
| 1525 Future onLibraryScanned(LibraryElement library, LibraryLoader loader); | 1480 Future onLibraryScanned(LibraryElement library, LibraryLoader loader); |
| 1526 } | 1481 } |
| OLD | NEW |