Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 deferred_load; | 5 library deferred_load; |
| 6 | 6 |
| 7 import 'dart2jslib.dart' show | 7 import 'dart2jslib.dart' show |
| 8 Backend, | 8 Backend, |
| 9 Compiler, | 9 Compiler, |
| 10 CompilerTask, | 10 CompilerTask, |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 void _addImportToOutputUnitOfConstant(Constant constant, Import import) { | 231 void _addImportToOutputUnitOfConstant(Constant constant, Import import) { |
| 232 // Only one file should be loaded when the program starts, so make | 232 // Only one file should be loaded when the program starts, so make |
| 233 // sure that only one OutputUnit is created for [fakeMainImport]. | 233 // sure that only one OutputUnit is created for [fakeMainImport]. |
| 234 if (import == _fakeMainImport) { | 234 if (import == _fakeMainImport) { |
| 235 _constantToOutputUnit[constant] = mainOutputUnit; | 235 _constantToOutputUnit[constant] = mainOutputUnit; |
| 236 } | 236 } |
| 237 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) | 237 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) |
| 238 .imports.add(import); | 238 .imports.add(import); |
| 239 } | 239 } |
| 240 | 240 |
| 241 /// Answers whether the [import] has a [DeferredLibrary] annotation. | |
| 242 bool _isImportDeferred(Import import) { | |
| 243 return _allDeferredImports.containsKey(import); | |
| 244 } | |
| 245 | |
| 246 /// Checks whether the [import] has a [DeferredLibrary] annotation and stores | |
| 247 /// the information in [_allDeferredImports] and on the corresponding | |
| 248 /// prefixElement. | |
| 249 void _markIfDeferred(Import import, LibraryElement library) { | |
| 250 // Check if the import is deferred by a keyword. | |
| 251 if (import.isDeferred) { | |
| 252 _allDeferredImports[import] = library.getLibraryFromTag(import); | |
| 253 return; | |
| 254 } | |
| 255 // Check if the import is deferred by a metadata annotation. | |
| 256 Link<MetadataAnnotation> metadataList = import.metadata; | |
| 257 if (metadataList == null) return; | |
| 258 for (MetadataAnnotation metadata in metadataList) { | |
| 259 metadata.ensureResolved(compiler); | |
| 260 Element element = metadata.value.computeType(compiler).element; | |
| 261 if (element == deferredLibraryClass) { | |
| 262 _allDeferredImports[import] = library.getLibraryFromTag(import); | |
| 263 // On encountering a deferred library without a prefix we report an | |
| 264 // error, but continue the compilation to possibly give more | |
| 265 // information. Therefore it is neccessary to check if there is a prefix | |
| 266 // here. | |
| 267 Element maybePrefix = library.find(import.prefix.toString()); | |
| 268 if (maybePrefix != null && maybePrefix.isPrefix) { | |
| 269 PrefixElement prefix = maybePrefix; | |
| 270 prefix.markAsDeferred(import); | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 /// Answers whether [element] is explicitly deferred when referred to from | 241 /// Answers whether [element] is explicitly deferred when referred to from |
| 277 /// [library]. | 242 /// [library]. |
| 278 bool _isExplicitlyDeferred(Element element, LibraryElement library) { | 243 bool _isExplicitlyDeferred(Element element, LibraryElement library) { |
| 279 Link<Import> imports = _getImports(element, library); | 244 Link<Import> imports = _getImports(element, library); |
| 280 // If the element is not imported explicitly, it is implicitly imported | 245 // If the element is not imported explicitly, it is implicitly imported |
| 281 // not deferred. | 246 // not deferred. |
| 282 if (imports.isEmpty) return false; | 247 if (imports.isEmpty) return false; |
| 283 // An element could potentially be loaded by several imports. If all of them | 248 // An element could potentially be loaded by several imports. If all of them |
| 284 // is explicitly deferred, we say the element is explicitly deferred. | 249 // is explicitly deferred, we say the element is explicitly deferred. |
| 285 // TODO(sigurdm): We might want to give a warning if the imports do not | 250 // TODO(sigurdm): We might want to give a warning if the imports do not |
| 286 // agree. | 251 // agree. |
| 287 return imports.every(_isImportDeferred); | 252 return imports.every((Import import) => import.isDeferred); |
| 288 } | 253 } |
| 289 | 254 |
| 290 /// Returns a [Link] of every [Import] that imports [element] into [library]. | 255 /// Returns a [Link] of every [Import] that imports [element] into [library]. |
| 291 Link<Import> _getImports(Element element, LibraryElement library) { | 256 Link<Import> _getImports(Element element, LibraryElement library) { |
| 292 if (element.isClassMember) { | 257 if (element.isClassMember) { |
| 293 element = element.enclosingClass; | 258 element = element.enclosingClass; |
| 294 } | 259 } |
| 295 if (element.isAccessor) { | 260 if (element.isAccessor) { |
| 296 element = (element as FunctionElement).abstractField; | 261 element = (element as FunctionElement).abstractField; |
| 297 } | 262 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 void traverseLibrary(LibraryElement library) { | 371 void traverseLibrary(LibraryElement library) { |
| 407 if (result.contains(library)) return; | 372 if (result.contains(library)) return; |
| 408 result.add(library); | 373 result.add(library); |
| 409 | 374 |
| 410 iterateTags(LibraryElement library) { | 375 iterateTags(LibraryElement library) { |
| 411 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is | 376 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is |
| 412 // changed to be a List instead of a Link. | 377 // changed to be a List instead of a Link. |
| 413 for (LibraryTag tag in library.tags) { | 378 for (LibraryTag tag in library.tags) { |
| 414 if (tag is! LibraryDependency) continue; | 379 if (tag is! LibraryDependency) continue; |
| 415 LibraryDependency libraryDependency = tag; | 380 LibraryDependency libraryDependency = tag; |
| 416 if (!(libraryDependency is Import | 381 if (!(libraryDependency is Import && libraryDependency.isDeferred)) { |
| 417 && _isImportDeferred(libraryDependency))) { | |
| 418 LibraryElement importedLibrary = library.getLibraryFromTag(tag); | 382 LibraryElement importedLibrary = library.getLibraryFromTag(tag); |
| 419 traverseLibrary(importedLibrary); | 383 traverseLibrary(importedLibrary); |
| 420 } | 384 } |
| 421 } | 385 } |
| 422 } | 386 } |
| 423 | 387 |
| 424 iterateTags(library); | 388 iterateTags(library); |
| 425 if (library.isPatched) { | 389 if (library.isPatched) { |
| 426 iterateTags(library.implementation); | 390 iterateTags(library.implementation); |
| 427 } | 391 } |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 719 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); | 683 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); |
| 720 for (LibraryElement library in compiler.libraryLoader.libraries) { | 684 for (LibraryElement library in compiler.libraryLoader.libraries) { |
| 721 compiler.withCurrentElement(library, () { | 685 compiler.withCurrentElement(library, () { |
| 722 prefixDeferredImport.clear(); | 686 prefixDeferredImport.clear(); |
| 723 usedPrefixes.clear(); | 687 usedPrefixes.clear(); |
| 724 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List | 688 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List |
| 725 // instead of a Link. | 689 // instead of a Link. |
| 726 for (LibraryTag tag in library.tags) { | 690 for (LibraryTag tag in library.tags) { |
| 727 if (tag is! Import) continue; | 691 if (tag is! Import) continue; |
| 728 Import import = tag; | 692 Import import = tag; |
| 729 _markIfDeferred(import, library); | 693 |
| 694 /// Give an error if the old annotation-based syntax has been used. | |
| 695 Link<MetadataAnnotation> metadataList = import.metadata; | |
| 696 if (metadataList != null) { | |
| 697 for (MetadataAnnotation metadata in metadataList) { | |
| 698 metadata.ensureResolved(compiler); | |
| 699 Element element = metadata.value.computeType(compiler).element; | |
| 700 if (element == deferredLibraryClass) { | |
| 701 compiler.reportFatalError(import, MessageKind.DEFERRED_OLD_SYNT AX); | |
|
floitsch
2014/08/28 20:05:20
long line.
Maybe just a warning? Talk to Johnni/P
sigurdm
2014/09/02 11:23:18
Giving a warning would entail keeping in all the f
| |
| 702 } | |
| 703 } | |
| 704 } | |
| 705 | |
| 730 String prefix = (import.prefix != null) | 706 String prefix = (import.prefix != null) |
| 731 ? import.prefix.toString() | 707 ? import.prefix.toString() |
| 732 : null; | 708 : null; |
| 733 // The last import we saw with the same prefix. | 709 // The last import we saw with the same prefix. |
| 734 Import previousDeferredImport = prefixDeferredImport[prefix]; | 710 Import previousDeferredImport = prefixDeferredImport[prefix]; |
| 735 bool isDeferred = _isImportDeferred(import); | 711 if (import.isDeferred) { |
| 736 if (isDeferred) { | 712 _allDeferredImports[import] = library.getLibraryFromTag(import); |
| 713 | |
| 737 if (prefix == null) { | 714 if (prefix == null) { |
| 738 compiler.reportError(import, | 715 compiler.reportError(import, |
| 739 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); | 716 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); |
| 740 } else { | 717 } else { |
| 741 prefixDeferredImport[prefix] = import; | 718 prefixDeferredImport[prefix] = import; |
| 742 } | 719 } |
| 743 splitProgram = true; | 720 splitProgram = true; |
| 744 lastDeferred = import; | 721 lastDeferred = import; |
| 745 } | 722 } |
| 746 if (prefix != null) { | 723 if (prefix != null) { |
| 747 if (previousDeferredImport != null || | 724 if (previousDeferredImport != null || |
| 748 (isDeferred && usedPrefixes.contains(prefix))) { | 725 (import.isDeferred && usedPrefixes.contains(prefix))) { |
| 749 Import failingImport = (previousDeferredImport != null) | 726 Import failingImport = (previousDeferredImport != null) |
| 750 ? previousDeferredImport | 727 ? previousDeferredImport |
| 751 : import; | 728 : import; |
| 752 compiler.reportError(failingImport.prefix, | 729 compiler.reportError(failingImport.prefix, |
| 753 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); | 730 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); |
| 754 } | 731 } |
| 755 usedPrefixes.add(prefix); | 732 usedPrefixes.add(prefix); |
| 756 } | 733 } |
| 757 } | 734 } |
| 758 }); | 735 }); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 Element maybePrefix = elements[identifier]; | 795 Element maybePrefix = elements[identifier]; |
| 819 if (maybePrefix != null && maybePrefix.isPrefix) { | 796 if (maybePrefix != null && maybePrefix.isPrefix) { |
| 820 PrefixElement prefixElement = maybePrefix; | 797 PrefixElement prefixElement = maybePrefix; |
| 821 if (prefixElement.isDeferred) { | 798 if (prefixElement.isDeferred) { |
| 822 return prefixElement; | 799 return prefixElement; |
| 823 } | 800 } |
| 824 } | 801 } |
| 825 return null; | 802 return null; |
| 826 } | 803 } |
| 827 } | 804 } |
| OLD | NEW |