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

Side by Side Diff: pkg/analyzer/lib/src/summary/pub_summary.dart

Issue 2358213002: Include referenced declared variables and their values into the linked bundle hash. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/pub_summary_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/pub_summary_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698