Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'dart:core'; | 7 import 'dart:core'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 show serializeAstUnlinked; | 26 show serializeAstUnlinked; |
| 27 import 'package:analyzer/src/summary/summarize_elements.dart' | 27 import 'package:analyzer/src/summary/summarize_elements.dart' |
| 28 show PackageBundleAssembler; | 28 show PackageBundleAssembler; |
| 29 import 'package:analyzer/src/util/fast_uri.dart'; | 29 import 'package:analyzer/src/util/fast_uri.dart'; |
| 30 import 'package:convert/convert.dart'; | 30 import 'package:convert/convert.dart'; |
| 31 import 'package:crypto/crypto.dart'; | 31 import 'package:crypto/crypto.dart'; |
| 32 import 'package:meta/meta.dart'; | 32 import 'package:meta/meta.dart'; |
| 33 import 'package:path/path.dart' as pathos; | 33 import 'package:path/path.dart' as pathos; |
| 34 | 34 |
| 35 /** | 35 /** |
| 36 * Return the raw string value of the variable with the given [name], | |
| 37 * or `null` of the variable is not defined. | |
| 38 */ | |
| 39 typedef String _GetDeclaredVariable(String name); | |
| 40 | |
| 41 /** | |
| 36 * Unlinked and linked information about a [PubPackage]. | 42 * Unlinked and linked information about a [PubPackage]. |
| 37 */ | 43 */ |
| 38 class LinkedPubPackage { | 44 class LinkedPubPackage { |
| 39 final PubPackage package; | 45 final PubPackage package; |
| 40 final PackageBundle unlinked; | 46 final PackageBundle unlinked; |
| 41 final PackageBundle linked; | 47 final PackageBundle linked; |
| 42 | 48 |
| 43 final String linkedHash; | 49 final String linkedHash; |
| 44 | 50 |
| 45 LinkedPubPackage(this.package, this.unlinked, this.linked, this.linkedHash); | 51 LinkedPubPackage(this.package, this.unlinked, this.linked, this.linkedHash); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 * The client should call [getLinkedBundles] after creating a new | 83 * The client should call [getLinkedBundles] after creating a new |
| 78 * [AnalysisContext] and configuring its source factory, but before computing | 84 * [AnalysisContext] and configuring its source factory, but before computing |
| 79 * any analysis results. The returned linked bundles can be used to create and | 85 * any analysis results. The returned linked bundles can be used to create and |
| 80 * configure [ResynthesizerResultProvider] for the context. | 86 * configure [ResynthesizerResultProvider] for the context. |
| 81 */ | 87 */ |
| 82 class PubSummaryManager { | 88 class PubSummaryManager { |
| 83 static const UNLINKED_NAME = 'unlinked.ds'; | 89 static const UNLINKED_NAME = 'unlinked.ds'; |
| 84 static const UNLINKED_SPEC_NAME = 'unlinked_spec.ds'; | 90 static const UNLINKED_SPEC_NAME = 'unlinked_spec.ds'; |
| 85 | 91 |
| 86 /** | 92 /** |
| 93 * If `true` (by default), then linking new bundles is allowed. | |
| 94 * Otherwise only using existing cached bundles can be used. | |
| 95 */ | |
| 96 final bool allowLinking; | |
| 97 | |
| 98 /** | |
| 87 * See [PackageBundleAssembler.currentMajorVersion]. | 99 * See [PackageBundleAssembler.currentMajorVersion]. |
| 88 */ | 100 */ |
| 89 final int majorVersion; | 101 final int majorVersion; |
| 90 | 102 |
| 91 final ResourceProvider resourceProvider; | 103 final ResourceProvider resourceProvider; |
| 92 | 104 |
| 93 /** | 105 /** |
| 94 * The name of the temporary file that is used for atomic writes. | 106 * The name of the temporary file that is used for atomic writes. |
| 95 */ | 107 */ |
| 96 final String tempFileName; | 108 final String tempFileName; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 119 */ | 131 */ |
| 120 final Set<PubPackage> seenPackages = new Set<PubPackage>(); | 132 final Set<PubPackage> seenPackages = new Set<PubPackage>(); |
| 121 | 133 |
| 122 /** | 134 /** |
| 123 * The [Completer] that completes when computing of all scheduled unlinked | 135 * The [Completer] that completes when computing of all scheduled unlinked |
| 124 * bundles is complete. | 136 * bundles is complete. |
| 125 */ | 137 */ |
| 126 Completer _onUnlinkedCompleteCompleter; | 138 Completer _onUnlinkedCompleteCompleter; |
| 127 | 139 |
| 128 PubSummaryManager(this.resourceProvider, this.tempFileName, | 140 PubSummaryManager(this.resourceProvider, this.tempFileName, |
| 129 {@visibleForTesting this.majorVersion: | 141 {@visibleForTesting this.allowLinking: true, |
| 142 @visibleForTesting this.majorVersion: | |
| 130 PackageBundleAssembler.currentMajorVersion}); | 143 PackageBundleAssembler.currentMajorVersion}); |
| 131 | 144 |
| 132 /** | 145 /** |
| 133 * The [Future] that completes when computing of all scheduled unlinked | 146 * The [Future] that completes when computing of all scheduled unlinked |
| 134 * bundles is complete. | 147 * bundles is complete. |
| 135 */ | 148 */ |
| 136 Future get onUnlinkedComplete { | 149 Future get onUnlinkedComplete { |
| 137 if (packagesToComputeUnlinked.isEmpty) { | 150 if (packagesToComputeUnlinked.isEmpty) { |
| 138 return new Future.value(); | 151 return new Future.value(); |
| 139 } | 152 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 // If no unlinked bundles, there is nothing we can try to link. | 202 // If no unlinked bundles, there is nothing we can try to link. |
| 190 if (unlinkedBundles.isEmpty) { | 203 if (unlinkedBundles.isEmpty) { |
| 191 return const <LinkedPubPackage>[]; | 204 return const <LinkedPubPackage>[]; |
| 192 } | 205 } |
| 193 | 206 |
| 194 // Create graph nodes for packages. | 207 // Create graph nodes for packages. |
| 195 List<_LinkedNode> nodes = <_LinkedNode>[]; | 208 List<_LinkedNode> nodes = <_LinkedNode>[]; |
| 196 Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{}; | 209 Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{}; |
| 197 unlinkedBundles.forEach((package, unlinked) { | 210 unlinkedBundles.forEach((package, unlinked) { |
| 198 _LinkedNode node = new _LinkedNode( | 211 _LinkedNode node = new _LinkedNode( |
| 199 sdkBundle, listedPackages, package, unlinked, packageToNode); | 212 sdkBundle, |
| 213 context.declaredVariables.get, | |
| 214 listedPackages, | |
| 215 package, | |
| 216 unlinked, | |
| 217 packageToNode); | |
| 200 nodes.add(node); | 218 nodes.add(node); |
| 201 packageToNode[package.name] = node; | 219 packageToNode[package.name] = node; |
| 202 }); | 220 }); |
| 203 | 221 |
| 204 // Compute transitive dependencies, mark some nodes as failed. | 222 // Compute transitive dependencies, mark some nodes as failed. |
| 205 for (_LinkedNode node in nodes) { | 223 for (_LinkedNode node in nodes) { |
| 206 node.computeTransitiveDependencies(); | 224 node.computeTransitiveDependencies(); |
| 207 } | 225 } |
| 208 | 226 |
| 209 // Attempt to read existing linked bundles. | 227 // Attempt to read existing linked bundles. |
| 210 for (_LinkedNode node in nodes) { | 228 for (_LinkedNode node in nodes) { |
| 211 _readLinked(node, strong); | 229 _readLinked(node, strong); |
| 212 } | 230 } |
| 213 | 231 |
| 214 // Fill the store with bundles. | 232 // Link new bundles, if allowed. |
| 215 // Append the linked SDK bundle. | 233 if (allowLinking) { |
| 216 // Append unlinked and (if read from a cache) linked package bundles. | 234 // Fill the store with bundles. |
| 217 SummaryDataStore store = new SummaryDataStore(const <String>[]); | 235 // Append the linked SDK bundle. |
| 218 store.addBundle(null, sdkBundle); | 236 // Append unlinked and (if read from a cache) linked package bundles. |
| 219 for (_LinkedNode node in nodes) { | 237 SummaryDataStore store = new SummaryDataStore(const <String>[]); |
| 220 store.addBundle(null, node.unlinked); | 238 store.addBundle(null, sdkBundle); |
| 221 if (node.linked != null) { | 239 for (_LinkedNode node in nodes) { |
| 222 store.addBundle(null, node.linked); | 240 store.addBundle(null, node.unlinked); |
| 241 if (node.linked != null) { | |
| 242 store.addBundle(null, node.linked); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 // Link each package node. | |
| 247 for (_LinkedNode node in nodes) { | |
| 248 if (!node.isEvaluated) { | |
| 249 new _LinkedWalker(listedPackages, store, strong).walk(node); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 // Write newly linked bundles. | |
| 254 for (_LinkedNode node in nodes) { | |
| 255 _writeLinked(node, strong); | |
| 223 } | 256 } |
| 224 } | 257 } |
| 225 | 258 |
| 226 // Link each package node. | |
| 227 for (_LinkedNode node in nodes) { | |
| 228 if (!node.isEvaluated) { | |
| 229 new _LinkedWalker(listedPackages, store, strong).walk(node); | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 // Write newly linked bundles. | |
| 234 for (_LinkedNode node in nodes) { | |
| 235 _writeLinked(node, strong); | |
| 236 } | |
| 237 | |
| 238 // Create successfully linked packages. | 259 // Create successfully linked packages. |
| 239 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[]; | 260 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[]; |
| 240 for (_LinkedNode node in nodes) { | 261 for (_LinkedNode node in nodes) { |
| 241 if (node.linked != null) { | 262 if (node.linked != null) { |
| 242 linkedPackages.add(new LinkedPubPackage( | 263 linkedPackages.add(new LinkedPubPackage( |
| 243 node.package, node.unlinked, node.linked, node._linkedHash)); | 264 node.package, node.unlinked, node.linked, node.linkedHash)); |
| 244 } | 265 } |
| 245 } | 266 } |
| 246 | 267 |
| 247 // TODO(scheglov) remove debug output after optimizing | 268 // TODO(scheglov) remove debug output after optimizing |
| 248 // print('LINKED ${linkedPackages.length} bundles' | 269 // print('LINKED ${linkedPackages.length} bundles' |
| 249 // ' in ${timer.elapsedMilliseconds} ms'); | 270 // ' in ${timer.elapsedMilliseconds} ms'); |
| 250 | 271 |
| 251 // Done. | 272 // Done. |
| 252 return linkedPackages; | 273 return linkedPackages; |
| 253 } | 274 } |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 597 } | 618 } |
| 598 return false; | 619 return false; |
| 599 } | 620 } |
| 600 } | 621 } |
| 601 | 622 |
| 602 /** | 623 /** |
| 603 * Specialization of [Node] for linking packages in proper dependency order. | 624 * Specialization of [Node] for linking packages in proper dependency order. |
| 604 */ | 625 */ |
| 605 class _LinkedNode extends Node<_LinkedNode> { | 626 class _LinkedNode extends Node<_LinkedNode> { |
| 606 final PackageBundle sdkBundle; | 627 final PackageBundle sdkBundle; |
| 628 final _GetDeclaredVariable getDeclaredVariable; | |
| 607 final _ListedPackages listedPackages; | 629 final _ListedPackages listedPackages; |
| 608 final PubPackage package; | 630 final PubPackage package; |
| 609 final PackageBundle unlinked; | 631 final PackageBundle unlinked; |
| 610 final Map<String, _LinkedNode> packageToNode; | 632 final Map<String, _LinkedNode> packageToNode; |
| 611 | 633 |
| 612 bool failed = false; | 634 bool failed = false; |
| 613 Set<_LinkedNode> transitiveDependencies; | 635 Set<_LinkedNode> transitiveDependencies; |
| 614 String _linkedHash; | 636 String _linkedHash; |
| 615 | 637 |
| 616 List<int> linkedNewBytes; | 638 List<int> linkedNewBytes; |
| 617 PackageBundle linked; | 639 PackageBundle linked; |
| 618 | 640 |
| 619 _LinkedNode(this.sdkBundle, this.listedPackages, this.package, this.unlinked, | 641 _LinkedNode(this.sdkBundle, this.getDeclaredVariable, this.listedPackages, |
| 620 this.packageToNode); | 642 this.package, this.unlinked, this.packageToNode); |
| 621 | 643 |
| 622 @override | 644 @override |
| 623 bool get isEvaluated => linked != null || failed; | 645 bool get isEvaluated => linked != null || failed; |
| 624 | 646 |
| 625 /** | 647 /** |
| 626 * Return the hash string that corresponds to this linked bundle in the | 648 * Return the hash string that corresponds to this linked bundle in the |
| 627 * context of its [sdkBundles] and transitive dependencies. Return `null` if | 649 * context of its [sdkBundle] and transitive dependencies. Return `null` if |
| 628 * the hash computation fails, because for example the full transitive | 650 * the hash computation fails, because for example the full transitive |
| 629 * dependencies cannot computed. | 651 * dependencies cannot computed. |
| 630 */ | 652 */ |
| 631 String get linkedHash { | 653 String get linkedHash { |
| 632 if (_linkedHash == null && transitiveDependencies != null) { | 654 if (_linkedHash == null && transitiveDependencies != null) { |
| 633 // Collect all unlinked API signatures. | 655 ApiSignature signature = new ApiSignature(); |
| 656 // Add all unlinked API signatures. | |
| 634 List<String> signatures = <String>[]; | 657 List<String> signatures = <String>[]; |
| 635 signatures.add(sdkBundle.apiSignature); | 658 signatures.add(sdkBundle.apiSignature); |
| 636 transitiveDependencies | 659 transitiveDependencies |
| 637 .map((node) => node.unlinked.apiSignature) | 660 .map((node) => node.unlinked.apiSignature) |
| 638 .forEach(signatures.add); | 661 .forEach(signatures.add); |
| 639 signatures.sort(); | 662 signatures.sort(); |
| 640 // Combine sorted unlinked API signatures into a single hash. | |
| 641 ApiSignature signature = new ApiSignature(); | |
| 642 signatures.forEach(signature.addString); | 663 signatures.forEach(signature.addString); |
| 664 // Combine into a single hash. | |
| 665 _appendDeclaredVariables(signature); | |
| 643 _linkedHash = signature.toHex(); | 666 _linkedHash = signature.toHex(); |
| 644 } | 667 } |
| 645 return _linkedHash; | 668 return _linkedHash; |
| 646 } | 669 } |
| 647 | 670 |
| 648 @override | 671 @override |
| 649 List<_LinkedNode> computeDependencies() { | 672 List<_LinkedNode> computeDependencies() { |
| 650 Set<_LinkedNode> dependencies = new Set<_LinkedNode>(); | 673 Set<_LinkedNode> dependencies = new Set<_LinkedNode>(); |
| 651 | 674 |
| 652 void appendDependency(String uriStr) { | 675 void appendDependency(String uriStr) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 | 725 |
| 703 appendDependencies(this); | 726 appendDependencies(this); |
| 704 if (transitiveDependencies.any((node) => node.failed)) { | 727 if (transitiveDependencies.any((node) => node.failed)) { |
| 705 failed = true; | 728 failed = true; |
| 706 } | 729 } |
| 707 } | 730 } |
| 708 } | 731 } |
| 709 | 732 |
| 710 @override | 733 @override |
| 711 String toString() => package.toString(); | 734 String toString() => package.toString(); |
| 735 | |
| 736 /** | |
| 737 * Append names and values of all referenced declared variables (even the | |
| 738 * ones without actually declared values) to the given [signature]. | |
| 739 */ | |
| 740 void _appendDeclaredVariables(ApiSignature signature) { | |
| 741 Set<String> names = new Set<String>(); | |
| 742 for (_LinkedNode node in transitiveDependencies) { | |
| 743 for (UnlinkedUnit unit in node.unlinked.unlinkedUnits) { | |
| 744 for (UnlinkedImport import in unit.imports) { | |
| 745 for (UnlinkedConfiguration configuration in import.configurations) { | |
| 746 names.add(configuration.name); | |
| 747 } | |
| 748 } | |
| 749 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | |
| 750 for (UnlinkedConfiguration configuration in export.configurations) { | |
| 751 names.add(configuration.name); | |
| 752 } | |
| 753 } | |
| 754 } | |
| 755 } | |
| 756 for (String name in names) { | |
|
Paul Berry
2016/09/21 19:47:22
Before the for loop, add:
signature.addInt(names.
scheglov
2016/09/21 20:34:49
Done.
| |
| 757 signature.addString(name); | |
| 758 signature.addString(getDeclaredVariable(name) ?? ''); | |
| 759 } | |
| 760 } | |
| 712 } | 761 } |
| 713 | 762 |
| 714 /** | 763 /** |
| 715 * Specialization of [DependencyWalker] for linking packages. | 764 * Specialization of [DependencyWalker] for linking packages. |
| 716 */ | 765 */ |
| 717 class _LinkedWalker extends DependencyWalker<_LinkedNode> { | 766 class _LinkedWalker extends DependencyWalker<_LinkedNode> { |
| 718 final _ListedPackages listedPackages; | 767 final _ListedPackages listedPackages; |
| 719 final SummaryDataStore store; | 768 final SummaryDataStore store; |
| 720 final bool strong; | 769 final bool strong; |
| 721 | 770 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 778 } | 827 } |
| 779 | 828 |
| 780 /** | 829 /** |
| 781 * Check whether the given `package:` [uri] is listed in the package map. | 830 * Check whether the given `package:` [uri] is listed in the package map. |
| 782 */ | 831 */ |
| 783 bool isListed(String uri) { | 832 bool isListed(String uri) { |
| 784 String package = PubSummaryManager.getPackageName(uri); | 833 String package = PubSummaryManager.getPackageName(uri); |
| 785 return names.contains(package); | 834 return names.contains(package); |
| 786 } | 835 } |
| 787 } | 836 } |
| OLD | NEW |