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

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

Issue 2233083002: Compute both strong and spec mode unlinked bundles. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Link in strong or spec mode. Created 4 years, 4 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' 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';
(...skipping 10 matching lines...) Expand all
21 import 'package:analyzer/src/summary/package_bundle_reader.dart' 21 import 'package:analyzer/src/summary/package_bundle_reader.dart'
22 show ResynthesizerResultProvider, SummaryDataStore; 22 show ResynthesizerResultProvider, SummaryDataStore;
23 import 'package:analyzer/src/summary/summarize_ast.dart' 23 import 'package:analyzer/src/summary/summarize_ast.dart'
24 show serializeAstUnlinked; 24 show serializeAstUnlinked;
25 import 'package:analyzer/src/summary/summarize_elements.dart' 25 import 'package:analyzer/src/summary/summarize_elements.dart'
26 show PackageBundleAssembler; 26 show PackageBundleAssembler;
27 import 'package:analyzer/src/util/fast_uri.dart'; 27 import 'package:analyzer/src/util/fast_uri.dart';
28 import 'package:path/path.dart' as pathos; 28 import 'package:path/path.dart' as pathos;
29 29
30 /** 30 /**
31 * Unlinked and linked information about a [PubPackage].
32 */
33 class LinkedPubPackage {
34 final PubPackage package;
35 final PackageBundle unlinked;
36 final PackageBundle linked;
37 LinkedPubPackage(this.package, this.unlinked, this.linked);
38 }
39
40 /**
31 * A package in the pub cache. 41 * A package in the pub cache.
32 */ 42 */
33 class PubPackage { 43 class PubPackage {
34 final String name; 44 final String name;
35 final Folder libFolder; 45 final Folder libFolder;
36 46
37 PubPackage(this.name, this.libFolder); 47 PubPackage(this.name, this.libFolder);
38 48
39 Folder get folder => libFolder.parent; 49 Folder get folder => libFolder.parent;
40 50
41 @override 51 @override
42 int get hashCode => libFolder.hashCode; 52 int get hashCode => libFolder.hashCode;
43 53
44 @override 54 @override
45 bool operator ==(other) { 55 bool operator ==(other) {
46 return other is PubPackage && other.libFolder == libFolder; 56 return other is PubPackage && other.libFolder == libFolder;
47 } 57 }
48 58
49 @override 59 @override
50 String toString() => '($name in $folder)'; 60 String toString() => '($name in $folder)';
51 } 61 }
52 62
53 /** 63 /**
54 * Unlinked and linked information about a [PubPackage].
55 */
56 class LinkedPubPackage {
57 final PubPackage package;
58 final PackageBundle unlinked;
59 final PackageBundle linked;
60 LinkedPubPackage(this.package, this.unlinked, this.linked);
61 }
62
63 /**
64 * Class that manages summaries for pub packages. 64 * Class that manages summaries for pub packages.
65 * 65 *
66 * The client should call [getLinkedBundles] after creating a new 66 * The client should call [getLinkedBundles] after creating a new
67 * [AnalysisContext] and configuring its source factory, but before computing 67 * [AnalysisContext] and configuring its source factory, but before computing
68 * any analysis results. The returned linked bundles can be used to create and 68 * any analysis results. The returned linked bundles can be used to create and
69 * configure [ResynthesizerResultProvider] for the context. 69 * configure [ResynthesizerResultProvider] for the context.
70 */ 70 */
71 class PubSummaryManager { 71 class PubSummaryManager {
72 static const UNLINKED_BUNDLE_FILE_NAME = 'unlinked.ds'; 72 static const UNLINKED_NAME = 'unlinked.ds';
73 static const UNLINKED_SPEC_NAME = 'unlinked_spec.ds';
73 74
74 final ResourceProvider resourceProvider; 75 final ResourceProvider resourceProvider;
75 76
76 /** 77 /**
77 * The name of the temporary file that is used for atomic writes. 78 * The name of the temporary file that is used for atomic writes.
78 */ 79 */
79 final String tempFileName; 80 final String tempFileName;
80 81
81 /** 82 /**
82 * The map from [PubPackage]s to their unlinked [PackageBundle]s in the pub 83 * The map from [PubPackage]s to their unlinked [PackageBundle]s in the pub
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 // Fill the store with unlinked bundles. 153 // Fill the store with unlinked bundles.
153 SummaryDataStore store = new SummaryDataStore(const <String>[]); 154 SummaryDataStore store = new SummaryDataStore(const <String>[]);
154 store.addBundle(null, sdkBundle); 155 store.addBundle(null, sdkBundle);
155 for (PackageBundle unlinked in unlinkedBundles.values) { 156 for (PackageBundle unlinked in unlinkedBundles.values) {
156 store.addBundle(null, unlinked); 157 store.addBundle(null, unlinked);
157 } 158 }
158 159
159 // Link each package node. 160 // Link each package node.
160 for (_LinkedNode node in nodes) { 161 for (_LinkedNode node in nodes) {
161 if (!node.isEvaluated) { 162 if (!node.isEvaluated) {
162 new _LinkedWalker(store).walk(node); 163 bool strong = context.analysisOptions.strongMode;
164 new _LinkedWalker(store, strong).walk(node);
163 } 165 }
164 } 166 }
165 167
166 // Create successfully linked packages. 168 // Create successfully linked packages.
167 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[]; 169 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[];
168 for (_LinkedNode node in nodes) { 170 for (_LinkedNode node in nodes) {
169 if (node.linkedBuilder != null) { 171 if (node.linkedBuilder != null) {
170 List<int> bytes = node.linkedBuilder.toBuffer(); 172 List<int> bytes = node.linkedBuilder.toBuffer();
171 PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes); 173 PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes);
172 linkedPackages.add( 174 linkedPackages.add(
173 new LinkedPubPackage(node.package, node.unlinked, linkedBundle)); 175 new LinkedPubPackage(node.package, node.unlinked, linkedBundle));
174 } 176 }
175 } 177 }
176 178
177 // TODO(scheglov) compute dependency hashes and write linked bundles. 179 // TODO(scheglov) compute dependency hashes and write linked bundles.
178 180
179 // Done. 181 // Done.
180 return linkedPackages; 182 return linkedPackages;
181 } 183 }
182 184
183 /** 185 /**
184 * Return all available unlinked [PackageBundle]s for the given [context], 186 * Return all available unlinked [PackageBundle]s for the given [context],
185 * maybe an empty map, but not `null`. 187 * maybe an empty map, but not `null`.
186 */ 188 */
187 Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) { 189 Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) {
190 bool strong = context.analysisOptions.strongMode;
188 Map<PubPackage, PackageBundle> unlinkedBundles = 191 Map<PubPackage, PackageBundle> unlinkedBundles =
189 new HashMap<PubPackage, PackageBundle>(); 192 new HashMap<PubPackage, PackageBundle>();
190 Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap; 193 Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap;
191 if (packageMap != null) { 194 if (packageMap != null) {
192 packageMap.forEach((String packageName, List<Folder> libFolders) { 195 packageMap.forEach((String packageName, List<Folder> libFolders) {
193 if (libFolders.length == 1) { 196 if (libFolders.length == 1) {
194 Folder libFolder = libFolders.first; 197 Folder libFolder = libFolders.first;
195 if (isPathInPubCache(pathContext, libFolder.path)) { 198 if (isPathInPubCache(pathContext, libFolder.path)) {
196 PubPackage package = new PubPackage(packageName, libFolder); 199 PubPackage package = new PubPackage(packageName, libFolder);
197 PackageBundle unlinkedBundle = _getUnlinkedOrSchedule(package); 200 PackageBundle unlinkedBundle =
201 _getUnlinkedOrSchedule(package, strong);
198 if (unlinkedBundle != null) { 202 if (unlinkedBundle != null) {
199 unlinkedBundles[package] = unlinkedBundle; 203 unlinkedBundles[package] = unlinkedBundle;
200 } 204 }
201 } 205 }
202 } 206 }
203 }); 207 });
204 } 208 }
205 return unlinkedBundles; 209 return unlinkedBundles;
206 } 210 }
207 211
208 /** 212 /**
209 * Compute unlinked bundle for a package from [packagesToComputeUnlinked], 213 * Compute unlinked bundle for a package from [packagesToComputeUnlinked],
210 * and schedule delayed computation for the next package, if any. 214 * and schedule delayed computation for the next package, if any.
211 */ 215 */
212 void _computeNextUnlinked() { 216 void _computeNextUnlinked() {
213 if (packagesToComputeUnlinked.isNotEmpty) { 217 if (packagesToComputeUnlinked.isNotEmpty) {
214 PubPackage package = packagesToComputeUnlinked.first; 218 PubPackage package = packagesToComputeUnlinked.first;
215 _computeUnlinked(package); 219 _computeUnlinked(package, false);
220 _computeUnlinked(package, true);
216 packagesToComputeUnlinked.remove(package); 221 packagesToComputeUnlinked.remove(package);
217 _scheduleNextUnlinked(); 222 _scheduleNextUnlinked();
218 } else { 223 } else {
219 if (_onUnlinkedCompleteCompleter != null) { 224 if (_onUnlinkedCompleteCompleter != null) {
220 _onUnlinkedCompleteCompleter.complete(true); 225 _onUnlinkedCompleteCompleter.complete(true);
221 _onUnlinkedCompleteCompleter = null; 226 _onUnlinkedCompleteCompleter = null;
222 } 227 }
223 } 228 }
224 } 229 }
225 230
226 /** 231 /**
227 * Compute the unlinked bundle for the package with the given path, put 232 * Compute the unlinked bundle for the package with the given path, put
228 * it in the [unlinkedBundleMap] and store into the [resourceProvider]. 233 * it in the [unlinkedBundleMap] and store into the [resourceProvider].
229 * 234 *
230 * TODO(scheglov) Consider moving into separate isolate(s). 235 * TODO(scheglov) Consider moving into separate isolate(s).
231 */ 236 */
232 void _computeUnlinked(PubPackage package) { 237 void _computeUnlinked(PubPackage package, bool strong) {
233 Folder libFolder = package.libFolder; 238 Folder libFolder = package.libFolder;
234 String libPath = libFolder.path + pathContext.separator; 239 String libPath = libFolder.path + pathContext.separator;
235 PackageBundleAssembler assembler = new PackageBundleAssembler(); 240 PackageBundleAssembler assembler = new PackageBundleAssembler();
236 241
237 /** 242 /**
238 * Return the `package` [Uri] for the given [path] in the `lib` folder 243 * Return the `package` [Uri] for the given [path] in the `lib` folder
239 * of the current package. 244 * of the current package.
240 */ 245 */
241 Uri getUri(String path) { 246 Uri getUri(String path) {
242 String pathInLib = path.substring(libPath.length); 247 String pathInLib = path.substring(libPath.length);
243 String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib)); 248 String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
244 String uriStr = 'package:${package.name}/$uriPath'; 249 String uriStr = 'package:${package.name}/$uriPath';
245 return FastUri.parse(uriStr); 250 return FastUri.parse(uriStr);
246 } 251 }
247 252
248 /** 253 /**
249 * If the given [file] is a Dart file, add its unlinked unit. 254 * If the given [file] is a Dart file, add its unlinked unit.
250 */ 255 */
251 void addDartFile(File file) { 256 void addDartFile(File file) {
252 String path = file.path; 257 String path = file.path;
253 if (AnalysisEngine.isDartFileName(path)) { 258 if (AnalysisEngine.isDartFileName(path)) {
254 Uri uri = getUri(path); 259 Uri uri = getUri(path);
255 Source source = file.createSource(uri); 260 Source source = file.createSource(uri);
256 CompilationUnit unit = _parse(source); 261 CompilationUnit unit = _parse(source, strong);
257 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); 262 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
258 assembler.addUnlinkedUnit(source, unlinkedUnit); 263 assembler.addUnlinkedUnit(source, unlinkedUnit);
259 } 264 }
260 } 265 }
261 266
262 /** 267 /**
263 * Visit the [folder] recursively. 268 * Visit the [folder] recursively.
264 */ 269 */
265 void addDartFiles(Folder folder) { 270 void addDartFiles(Folder folder) {
266 List<Resource> children = folder.getChildren(); 271 List<Resource> children = folder.getChildren();
267 for (Resource child in children) { 272 for (Resource child in children) {
268 if (child is File) { 273 if (child is File) {
269 addDartFile(child); 274 addDartFile(child);
270 } 275 }
271 } 276 }
272 for (Resource child in children) { 277 for (Resource child in children) {
273 if (child is Folder) { 278 if (child is Folder) {
274 addDartFiles(child); 279 addDartFiles(child);
275 } 280 }
276 } 281 }
277 } 282 }
278 283
279 try { 284 try {
280 addDartFiles(libFolder); 285 addDartFiles(libFolder);
281 List<int> bytes = assembler.assemble().toBuffer(); 286 List<int> bytes = assembler.assemble().toBuffer();
282 _writeAtomic(package.folder, UNLINKED_BUNDLE_FILE_NAME, bytes); 287 String fileName = _getUnlinkedName(strong);
288 _writeAtomic(package.folder, fileName, bytes);
283 } on FileSystemException { 289 } on FileSystemException {
284 // Ignore file system exceptions. 290 // Ignore file system exceptions.
285 } 291 }
286 } 292 }
287 293
288 /** 294 /**
295 * Return the name of the file for an unlinked bundle, in strong or spec mode.
296 */
297 String _getUnlinkedName(bool strong) {
298 if (strong) {
299 return UNLINKED_NAME;
300 } else {
301 return UNLINKED_SPEC_NAME;
302 }
303 }
304
305 /**
289 * Return the unlinked [PackageBundle] for the given [package]. If the bundle 306 * Return the unlinked [PackageBundle] for the given [package]. If the bundle
290 * has not been compute yet, return `null` and schedule its computation. 307 * has not been compute yet, return `null` and schedule its computation.
291 */ 308 */
292 PackageBundle _getUnlinkedOrSchedule(PubPackage package) { 309 PackageBundle _getUnlinkedOrSchedule(PubPackage package, bool strong) {
293 // Try to find in the cache. 310 // Try to find in the cache.
294 PackageBundle bundle = unlinkedBundleMap[package]; 311 PackageBundle bundle = unlinkedBundleMap[package];
295 if (bundle != null) { 312 if (bundle != null) {
296 return bundle; 313 return bundle;
297 } 314 }
298 // Try to read from the file system. 315 // Try to read from the file system.
299 File unlinkedFile = 316 String fileName = _getUnlinkedName(strong);
300 package.folder.getChildAssumingFile(UNLINKED_BUNDLE_FILE_NAME); 317 File unlinkedFile = package.folder.getChildAssumingFile(fileName);
301 if (unlinkedFile.exists) { 318 if (unlinkedFile.exists) {
302 try { 319 try {
303 List<int> bytes = unlinkedFile.readAsBytesSync(); 320 List<int> bytes = unlinkedFile.readAsBytesSync();
304 bundle = new PackageBundle.fromBuffer(bytes); 321 bundle = new PackageBundle.fromBuffer(bytes);
305 unlinkedBundleMap[package] = bundle; 322 unlinkedBundleMap[package] = bundle;
306 return bundle; 323 return bundle;
307 } on FileSystemException { 324 } on FileSystemException {
308 // Ignore file system exceptions. 325 // Ignore file system exceptions.
309 } 326 }
310 } 327 }
311 // Schedule computation in the background. 328 // Schedule computation in the background.
312 if (package != null && seenPackages.add(package)) { 329 if (package != null && seenPackages.add(package)) {
313 if (packagesToComputeUnlinked.isEmpty) { 330 if (packagesToComputeUnlinked.isEmpty) {
314 _scheduleNextUnlinked(); 331 _scheduleNextUnlinked();
315 } 332 }
316 packagesToComputeUnlinked.add(package); 333 packagesToComputeUnlinked.add(package);
317 } 334 }
318 // The bundle is for available. 335 // The bundle is for available.
319 return null; 336 return null;
320 } 337 }
321 338
322 /** 339 /**
323 * Parse the given [source] into AST. 340 * Parse the given [source] into AST.
324 */ 341 */
325 CompilationUnit _parse(Source source) { 342 CompilationUnit _parse(Source source, bool strong) {
326 String code = source.contents.data; 343 String code = source.contents.data;
327 AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER; 344 AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
328 CharSequenceReader reader = new CharSequenceReader(code); 345 CharSequenceReader reader = new CharSequenceReader(code);
329 Scanner scanner = new Scanner(source, reader, errorListener); 346 Scanner scanner = new Scanner(source, reader, errorListener);
347 scanner.scanGenericMethodComments = strong;
330 Token token = scanner.tokenize(); 348 Token token = scanner.tokenize();
331 LineInfo lineInfo = new LineInfo(scanner.lineStarts); 349 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
332 Parser parser = new Parser(source, errorListener); 350 Parser parser = new Parser(source, errorListener);
351 parser.parseGenericMethodComments = strong;
333 CompilationUnit unit = parser.parseCompilationUnit(token); 352 CompilationUnit unit = parser.parseCompilationUnit(token);
334 unit.lineInfo = lineInfo; 353 unit.lineInfo = lineInfo;
335 return unit; 354 return unit;
336 } 355 }
337 356
338 /** 357 /**
339 * Schedule delayed computation of the next package unlinked bundle from the 358 * Schedule delayed computation of the next package unlinked bundle from the
340 * set of [packagesToComputeUnlinked]. We delay each computation because we 359 * set of [packagesToComputeUnlinked]. We delay each computation because we
341 * want operations in analysis server to proceed, and computing bundles of 360 * want operations in analysis server to proceed, and computing bundles of
342 * packages is a background task. 361 * packages is a background task.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 429
411 @override 430 @override
412 String toString() => package.toString(); 431 String toString() => package.toString();
413 } 432 }
414 433
415 /** 434 /**
416 * Specialization of [DependencyWalker] for linking packages. 435 * Specialization of [DependencyWalker] for linking packages.
417 */ 436 */
418 class _LinkedWalker extends DependencyWalker<_LinkedNode> { 437 class _LinkedWalker extends DependencyWalker<_LinkedNode> {
419 final SummaryDataStore store; 438 final SummaryDataStore store;
439 final bool strong;
420 440
421 _LinkedWalker(this.store); 441 _LinkedWalker(this.store, this.strong);
422 442
423 @override 443 @override
424 void evaluate(_LinkedNode v) { 444 void evaluate(_LinkedNode v) {
425 Set<String> libraryUris = v.unlinked.unlinkedUnitUris.toSet(); 445 Set<String> libraryUris = v.unlinked.unlinkedUnitUris.toSet();
426 Map<String, LinkedLibraryBuilder> map = link(libraryUris, (String absUri) { 446 Map<String, LinkedLibraryBuilder> map = link(libraryUris, (String absUri) {
427 LinkedLibrary dependencyLibrary = store.linkedMap[absUri]; 447 LinkedLibrary dependencyLibrary = store.linkedMap[absUri];
428 if (dependencyLibrary == null) { 448 if (dependencyLibrary == null) {
429 // TODO(scheglov) add test 449 // TODO(scheglov) add test
430 v.failed = true; 450 v.failed = true;
431 } 451 }
432 return dependencyLibrary; 452 return dependencyLibrary;
433 }, (String absUri) { 453 }, (String absUri) {
434 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri]; 454 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri];
435 if (unlinkedUnit == null) { 455 if (unlinkedUnit == null) {
436 // TODO(scheglov) add test 456 // TODO(scheglov) add test
437 v.failed = true; 457 v.failed = true;
438 } 458 }
439 return unlinkedUnit; 459 return unlinkedUnit;
440 }, false); 460 }, strong);
441 if (!v.failed) { 461 if (!v.failed) {
442 PackageBundleAssembler assembler = new PackageBundleAssembler(); 462 PackageBundleAssembler assembler = new PackageBundleAssembler();
443 map.forEach((uri, linkedLibrary) { 463 map.forEach((uri, linkedLibrary) {
444 assembler.addLinkedLibrary(uri, linkedLibrary); 464 assembler.addLinkedLibrary(uri, linkedLibrary);
445 }); 465 });
446 v.linkedBuilder = assembler.assemble(); 466 v.linkedBuilder = assembler.assemble();
447 store.addBundle(null, v.linkedBuilder); 467 store.addBundle(null, v.linkedBuilder);
448 } 468 }
449 } 469 }
450 470
451 @override 471 @override
452 void evaluateScc(List<_LinkedNode> scc) { 472 void evaluateScc(List<_LinkedNode> scc) {
453 print('evaluateScc: $scc'); 473 print('evaluateScc: $scc');
454 // TODO(scheglov): implement evaluateScc 474 // TODO(scheglov): implement evaluateScc
455 } 475 }
456 } 476 }
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