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' hide Resource; | 7 import 'dart:core' hide Resource; |
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'; |
11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
12 import 'package:analyzer/src/dart/scanner/reader.dart'; | 12 import 'package:analyzer/src/dart/scanner/reader.dart'; |
13 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 13 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
14 import 'package:analyzer/src/dart/sdk/sdk.dart'; | |
15 import 'package:analyzer/src/generated/engine.dart'; | 14 import 'package:analyzer/src/generated/engine.dart'; |
16 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
17 import 'package:analyzer/src/generated/parser.dart'; | 16 import 'package:analyzer/src/generated/parser.dart'; |
18 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
19 import 'package:analyzer/src/generated/utilities_dart.dart'; | |
20 import 'package:analyzer/src/summary/api_signature.dart'; | 18 import 'package:analyzer/src/summary/api_signature.dart'; |
21 import 'package:analyzer/src/summary/format.dart'; | 19 import 'package:analyzer/src/summary/format.dart'; |
22 import 'package:analyzer/src/summary/idl.dart'; | 20 import 'package:analyzer/src/summary/idl.dart'; |
23 import 'package:analyzer/src/summary/link.dart'; | 21 import 'package:analyzer/src/summary/link.dart'; |
24 import 'package:analyzer/src/summary/package_bundle_reader.dart' | 22 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
25 show ResynthesizerResultProvider, SummaryDataStore; | 23 show ResynthesizerResultProvider, SummaryDataStore; |
26 import 'package:analyzer/src/summary/summarize_ast.dart' | 24 import 'package:analyzer/src/summary/summarize_ast.dart' |
27 show serializeAstUnlinked; | 25 show serializeAstUnlinked; |
28 import 'package:analyzer/src/summary/summarize_elements.dart' | 26 import 'package:analyzer/src/summary/summarize_elements.dart' |
29 show PackageBundleAssembler; | 27 show PackageBundleAssembler; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 _onUnlinkedCompleteCompleter ??= new Completer(); | 130 _onUnlinkedCompleteCompleter ??= new Completer(); |
133 return _onUnlinkedCompleteCompleter.future; | 131 return _onUnlinkedCompleteCompleter.future; |
134 } | 132 } |
135 | 133 |
136 /** | 134 /** |
137 * Return the [pathos.Context] corresponding to the [resourceProvider]. | 135 * Return the [pathos.Context] corresponding to the [resourceProvider]. |
138 */ | 136 */ |
139 pathos.Context get pathContext => resourceProvider.pathContext; | 137 pathos.Context get pathContext => resourceProvider.pathContext; |
140 | 138 |
141 /** | 139 /** |
142 * Compute and return the linked bundle for the SDK extension for the given | |
143 * [context], or `null` if none of the packages has an SDK extension. At most | |
144 * one extension library is supported, if more than one is found, then an | |
145 * error will be logged, and `null` returned. | |
146 */ | |
147 PackageBundle computeSdkExtension( | |
148 AnalysisContext context, PackageBundle sdkBundle) { | |
149 // Prepare SDK extension library files. | |
150 String libUriStr; | |
151 String libPath; | |
152 { | |
153 Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap; | |
154 SdkExtensionFinder extFinder = new SdkExtensionFinder(packageMap); | |
155 Map<String, String> sdkExtMappings = extFinder.urlMappings; | |
156 if (sdkExtMappings.length == 1) { | |
157 libUriStr = sdkExtMappings.keys.first; | |
158 libPath = sdkExtMappings.values.first; | |
159 } else if (sdkExtMappings.length > 1) { | |
160 AnalysisEngine.instance.logger | |
161 .logError('At most one _sdkext file is supported, ' | |
162 'with at most one extension library. $sdkExtMappings found.'); | |
163 return null; | |
164 } else { | |
165 return null; | |
166 } | |
167 } | |
168 // Compute the extension unlinked bundle. | |
169 bool strong = context.analysisOptions.strongMode; | |
170 PackageBundleAssembler assembler = new PackageBundleAssembler(); | |
171 try { | |
172 File libFile = resourceProvider.getFile(libPath); | |
173 Uri libUri = FastUri.parse(libUriStr); | |
174 Source libSource = libFile.createSource(libUri); | |
175 CompilationUnit libraryUnit = _parse(libSource, strong); | |
176 // Add the library unit. | |
177 assembler.addUnlinkedUnit(libSource, serializeAstUnlinked(libraryUnit)); | |
178 // Add part units. | |
179 for (Directive directive in libraryUnit.directives) { | |
180 if (directive is PartDirective) { | |
181 Source partSource; | |
182 { | |
183 String partUriStr = directive.uri.stringValue; | |
184 Uri partUri = resolveRelativeUri(libUri, FastUri.parse(partUriStr)); | |
185 pathos.Context pathContext = resourceProvider.pathContext; | |
186 String partPath = | |
187 pathContext.join(pathContext.dirname(libPath), partUriStr); | |
188 File partFile = resourceProvider.getFile(partPath); | |
189 partSource = partFile.createSource(partUri); | |
190 } | |
191 CompilationUnit partUnit = _parse(partSource, strong); | |
192 assembler.addUnlinkedUnit(partSource, serializeAstUnlinked(partUnit)); | |
193 } | |
194 } | |
195 // Add the SDK and the unlinked extension bundle. | |
196 PackageBundleBuilder unlinkedBuilder = assembler.assemble(); | |
197 SummaryDataStore store = new SummaryDataStore(const <String>[]); | |
198 store.addBundle(null, sdkBundle); | |
199 store.addBundle(null, unlinkedBuilder); | |
200 // Link the extension bundle. | |
201 Map<String, LinkedLibraryBuilder> linkedLibraries = | |
202 link([libUriStr].toSet(), (String absoluteUri) { | |
203 return store.linkedMap[absoluteUri]; | |
204 }, (String absoluteUri) { | |
205 return store.unlinkedMap[absoluteUri]; | |
206 }, strong); | |
207 if (linkedLibraries.length != 1) { | |
208 return null; | |
209 } | |
210 // Append linked libraries into the assembler. | |
211 linkedLibraries.forEach((uri, library) { | |
212 assembler.addLinkedLibrary(uri, library); | |
213 }); | |
214 List<int> bytes = assembler.assemble().toBuffer(); | |
215 return new PackageBundle.fromBuffer(bytes); | |
216 } on FileSystemException { | |
217 return null; | |
218 } | |
219 } | |
220 | |
221 /** | |
222 * Complete when the unlinked bundles for the package with the given [name] | 140 * Complete when the unlinked bundles for the package with the given [name] |
223 * and the [libFolder] are computed and written to the files. | 141 * and the [libFolder] are computed and written to the files. |
224 * | 142 * |
225 * This method is intended to be used for generating unlinked bundles for | 143 * This method is intended to be used for generating unlinked bundles for |
226 * the `Flutter` packages. | 144 * the `Flutter` packages. |
227 */ | 145 */ |
228 Future<Null> computeUnlinkedForFolder(String name, Folder libFolder) async { | 146 Future<Null> computeUnlinkedForFolder(String name, Folder libFolder) async { |
229 PubPackage package = new PubPackage(name, libFolder); | 147 PubPackage package = new PubPackage(name, libFolder); |
230 _scheduleUnlinked(package); | 148 _scheduleUnlinked(package); |
231 await onUnlinkedComplete; | 149 await onUnlinkedComplete; |
(...skipping 10 matching lines...) Expand all Loading... |
242 // Stopwatch timer = new Stopwatch()..start(); | 160 // Stopwatch timer = new Stopwatch()..start(); |
243 | 161 |
244 SourceFactory sourceFactory = context.sourceFactory; | 162 SourceFactory sourceFactory = context.sourceFactory; |
245 _ListedPackages listedPackages = new _ListedPackages(sourceFactory); | 163 _ListedPackages listedPackages = new _ListedPackages(sourceFactory); |
246 | 164 |
247 PackageBundle sdkBundle = sourceFactory.dartSdk.getLinkedBundle(); | 165 PackageBundle sdkBundle = sourceFactory.dartSdk.getLinkedBundle(); |
248 if (sdkBundle == null) { | 166 if (sdkBundle == null) { |
249 return const <LinkedPubPackage>[]; | 167 return const <LinkedPubPackage>[]; |
250 } | 168 } |
251 | 169 |
252 // Prepare all SDK bundles. | |
253 List<PackageBundle> sdkBundles = <PackageBundle>[sdkBundle]; | |
254 { | |
255 PackageBundle extension = computeSdkExtension(context, sdkBundle); | |
256 if (extension != null) { | |
257 sdkBundles.add(extension); | |
258 } | |
259 } | |
260 | |
261 bool strong = context.analysisOptions.strongMode; | 170 bool strong = context.analysisOptions.strongMode; |
262 Map<PubPackage, PackageBundle> unlinkedBundles = | 171 Map<PubPackage, PackageBundle> unlinkedBundles = |
263 getUnlinkedBundles(context); | 172 getUnlinkedBundles(context); |
264 | 173 |
265 // TODO(scheglov) remove debug output after optimizing | 174 // TODO(scheglov) remove debug output after optimizing |
266 // print('LOADED ${unlinkedBundles.length} unlinked bundles' | 175 // print('LOADED ${unlinkedBundles.length} unlinked bundles' |
267 // ' in ${timer.elapsedMilliseconds} ms'); | 176 // ' in ${timer.elapsedMilliseconds} ms'); |
268 // timer..reset(); | 177 // timer..reset(); |
269 | 178 |
270 // If no unlinked bundles, there is nothing we can try to link. | 179 // If no unlinked bundles, there is nothing we can try to link. |
271 if (unlinkedBundles.isEmpty) { | 180 if (unlinkedBundles.isEmpty) { |
272 return const <LinkedPubPackage>[]; | 181 return const <LinkedPubPackage>[]; |
273 } | 182 } |
274 | 183 |
275 // Create graph nodes for packages. | 184 // Create graph nodes for packages. |
276 List<_LinkedNode> nodes = <_LinkedNode>[]; | 185 List<_LinkedNode> nodes = <_LinkedNode>[]; |
277 Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{}; | 186 Map<String, _LinkedNode> packageToNode = <String, _LinkedNode>{}; |
278 unlinkedBundles.forEach((package, unlinked) { | 187 unlinkedBundles.forEach((package, unlinked) { |
279 _LinkedNode node = new _LinkedNode( | 188 _LinkedNode node = new _LinkedNode( |
280 sdkBundles, listedPackages, package, unlinked, packageToNode); | 189 sdkBundle, listedPackages, package, unlinked, packageToNode); |
281 nodes.add(node); | 190 nodes.add(node); |
282 packageToNode[package.name] = node; | 191 packageToNode[package.name] = node; |
283 }); | 192 }); |
284 | 193 |
285 // Compute transitive dependencies, mark some nodes as failed. | 194 // Compute transitive dependencies, mark some nodes as failed. |
286 for (_LinkedNode node in nodes) { | 195 for (_LinkedNode node in nodes) { |
287 node.computeTransitiveDependencies(); | 196 node.computeTransitiveDependencies(); |
288 } | 197 } |
289 | 198 |
290 // Attempt to read existing linked bundles. | 199 // Attempt to read existing linked bundles. |
291 for (_LinkedNode node in nodes) { | 200 for (_LinkedNode node in nodes) { |
292 _readLinked(node, strong); | 201 _readLinked(node, strong); |
293 } | 202 } |
294 | 203 |
295 // Fill the store with bundles. | 204 // Fill the store with bundles. |
296 // Append linked SDK bundles. | 205 // Append the linked SDK bundle. |
297 // Append unlinked and (if read from a cache) linked package bundles. | 206 // Append unlinked and (if read from a cache) linked package bundles. |
298 SummaryDataStore store = new SummaryDataStore(const <String>[]); | 207 SummaryDataStore store = new SummaryDataStore(const <String>[]); |
299 sdkBundles.forEach((bundle) => store.addBundle(null, bundle)); | 208 store.addBundle(null, sdkBundle); |
300 for (_LinkedNode node in nodes) { | 209 for (_LinkedNode node in nodes) { |
301 store.addBundle(null, node.unlinked); | 210 store.addBundle(null, node.unlinked); |
302 if (node.linked != null) { | 211 if (node.linked != null) { |
303 store.addBundle(null, node.linked); | 212 store.addBundle(null, node.linked); |
304 } | 213 } |
305 } | 214 } |
306 | 215 |
307 // Link each package node. | 216 // Link each package node. |
308 for (_LinkedNode node in nodes) { | 217 for (_LinkedNode node in nodes) { |
309 if (!node.isEvaluated) { | 218 if (!node.isEvaluated) { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 } | 528 } |
620 } | 529 } |
621 return false; | 530 return false; |
622 } | 531 } |
623 } | 532 } |
624 | 533 |
625 /** | 534 /** |
626 * Specialization of [Node] for linking packages in proper dependency order. | 535 * Specialization of [Node] for linking packages in proper dependency order. |
627 */ | 536 */ |
628 class _LinkedNode extends Node<_LinkedNode> { | 537 class _LinkedNode extends Node<_LinkedNode> { |
629 final List<PackageBundle> sdkBundles; | 538 final PackageBundle sdkBundle; |
630 final _ListedPackages listedPackages; | 539 final _ListedPackages listedPackages; |
631 final PubPackage package; | 540 final PubPackage package; |
632 final PackageBundle unlinked; | 541 final PackageBundle unlinked; |
633 final Map<String, _LinkedNode> packageToNode; | 542 final Map<String, _LinkedNode> packageToNode; |
634 | 543 |
635 bool failed = false; | 544 bool failed = false; |
636 Set<_LinkedNode> transitiveDependencies; | 545 Set<_LinkedNode> transitiveDependencies; |
637 String _linkedHash; | 546 String _linkedHash; |
638 | 547 |
639 List<int> linkedNewBytes; | 548 List<int> linkedNewBytes; |
640 PackageBundle linked; | 549 PackageBundle linked; |
641 | 550 |
642 _LinkedNode(this.sdkBundles, this.listedPackages, this.package, this.unlinked, | 551 _LinkedNode(this.sdkBundle, this.listedPackages, this.package, this.unlinked, |
643 this.packageToNode); | 552 this.packageToNode); |
644 | 553 |
645 @override | 554 @override |
646 bool get isEvaluated => linked != null || failed; | 555 bool get isEvaluated => linked != null || failed; |
647 | 556 |
648 /** | 557 /** |
649 * Return the hash string that corresponds to this linked bundle in the | 558 * Return the hash string that corresponds to this linked bundle in the |
650 * context of its [sdkBundles] and transitive dependencies. Return `null` if | 559 * context of its [sdkBundles] and transitive dependencies. Return `null` if |
651 * the hash computation fails, because for example the full transitive | 560 * the hash computation fails, because for example the full transitive |
652 * dependencies cannot computed. | 561 * dependencies cannot computed. |
653 */ | 562 */ |
654 String get linkedHash { | 563 String get linkedHash { |
655 if (_linkedHash == null && transitiveDependencies != null) { | 564 if (_linkedHash == null && transitiveDependencies != null) { |
656 // Collect all unlinked API signatures. | 565 // Collect all unlinked API signatures. |
657 List<String> signatures = <String>[]; | 566 List<String> signatures = <String>[]; |
658 sdkBundles | 567 signatures.add(sdkBundle.apiSignature); |
659 .map((sdkBundle) => sdkBundle.apiSignature) | |
660 .forEach(signatures.add); | |
661 transitiveDependencies | 568 transitiveDependencies |
662 .map((node) => node.unlinked.apiSignature) | 569 .map((node) => node.unlinked.apiSignature) |
663 .forEach(signatures.add); | 570 .forEach(signatures.add); |
664 signatures.sort(); | 571 signatures.sort(); |
665 // Combine sorted unlinked API signatures into a single hash. | 572 // Combine sorted unlinked API signatures into a single hash. |
666 ApiSignature signature = new ApiSignature(); | 573 ApiSignature signature = new ApiSignature(); |
667 signatures.forEach(signature.addString); | 574 signatures.forEach(signature.addString); |
668 _linkedHash = signature.toHex(); | 575 _linkedHash = signature.toHex(); |
669 } | 576 } |
670 return _linkedHash; | 577 return _linkedHash; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 } | 707 } |
801 | 708 |
802 /** | 709 /** |
803 * Check whether the given `package:` [uri] is listed in the package map. | 710 * Check whether the given `package:` [uri] is listed in the package map. |
804 */ | 711 */ |
805 bool isListed(String uri) { | 712 bool isListed(String uri) { |
806 String package = PubSummaryManager.getPackageName(uri); | 713 String package = PubSummaryManager.getPackageName(uri); |
807 return names.contains(package); | 714 return names.contains(package); |
808 } | 715 } |
809 } | 716 } |
OLD | NEW |