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

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: 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 179
179 // Done. 180 // Done.
180 return linkedPackages; 181 return linkedPackages;
181 } 182 }
182 183
183 /** 184 /**
184 * Return all available unlinked [PackageBundle]s for the given [context], 185 * Return all available unlinked [PackageBundle]s for the given [context],
185 * maybe an empty map, but not `null`. 186 * maybe an empty map, but not `null`.
186 */ 187 */
187 Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) { 188 Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) {
189 bool strongMode = context.analysisOptions.strongMode;
188 Map<PubPackage, PackageBundle> unlinkedBundles = 190 Map<PubPackage, PackageBundle> unlinkedBundles =
189 new HashMap<PubPackage, PackageBundle>(); 191 new HashMap<PubPackage, PackageBundle>();
190 Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap; 192 Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap;
191 if (packageMap != null) { 193 if (packageMap != null) {
192 packageMap.forEach((String packageName, List<Folder> libFolders) { 194 packageMap.forEach((String packageName, List<Folder> libFolders) {
193 if (libFolders.length == 1) { 195 if (libFolders.length == 1) {
194 Folder libFolder = libFolders.first; 196 Folder libFolder = libFolders.first;
195 if (isPathInPubCache(pathContext, libFolder.path)) { 197 if (isPathInPubCache(pathContext, libFolder.path)) {
196 PubPackage package = new PubPackage(packageName, libFolder); 198 PubPackage package = new PubPackage(packageName, libFolder);
197 PackageBundle unlinkedBundle = _getUnlinkedOrSchedule(package); 199 PackageBundle unlinkedBundle =
200 _getUnlinkedOrSchedule(package, strongMode);
198 if (unlinkedBundle != null) { 201 if (unlinkedBundle != null) {
199 unlinkedBundles[package] = unlinkedBundle; 202 unlinkedBundles[package] = unlinkedBundle;
200 } 203 }
201 } 204 }
202 } 205 }
203 }); 206 });
204 } 207 }
205 return unlinkedBundles; 208 return unlinkedBundles;
206 } 209 }
207 210
208 /** 211 /**
209 * Compute unlinked bundle for a package from [packagesToComputeUnlinked], 212 * Compute unlinked bundle for a package from [packagesToComputeUnlinked],
210 * and schedule delayed computation for the next package, if any. 213 * and schedule delayed computation for the next package, if any.
211 */ 214 */
212 void _computeNextUnlinked() { 215 void _computeNextUnlinked() {
213 if (packagesToComputeUnlinked.isNotEmpty) { 216 if (packagesToComputeUnlinked.isNotEmpty) {
214 PubPackage package = packagesToComputeUnlinked.first; 217 PubPackage package = packagesToComputeUnlinked.first;
215 _computeUnlinked(package); 218 _computeUnlinked(package, false);
219 _computeUnlinked(package, true);
216 packagesToComputeUnlinked.remove(package); 220 packagesToComputeUnlinked.remove(package);
217 _scheduleNextUnlinked(); 221 _scheduleNextUnlinked();
218 } else { 222 } else {
219 if (_onUnlinkedCompleteCompleter != null) { 223 if (_onUnlinkedCompleteCompleter != null) {
220 _onUnlinkedCompleteCompleter.complete(true); 224 _onUnlinkedCompleteCompleter.complete(true);
221 _onUnlinkedCompleteCompleter = null; 225 _onUnlinkedCompleteCompleter = null;
222 } 226 }
223 } 227 }
224 } 228 }
225 229
226 /** 230 /**
227 * Compute the unlinked bundle for the package with the given path, put 231 * Compute the unlinked bundle for the package with the given path, put
228 * it in the [unlinkedBundleMap] and store into the [resourceProvider]. 232 * it in the [unlinkedBundleMap] and store into the [resourceProvider].
229 * 233 *
230 * TODO(scheglov) Consider moving into separate isolate(s). 234 * TODO(scheglov) Consider moving into separate isolate(s).
231 */ 235 */
232 void _computeUnlinked(PubPackage package) { 236 void _computeUnlinked(PubPackage package, bool strongMode) {
233 Folder libFolder = package.libFolder; 237 Folder libFolder = package.libFolder;
234 String libPath = libFolder.path + pathContext.separator; 238 String libPath = libFolder.path + pathContext.separator;
235 PackageBundleAssembler assembler = new PackageBundleAssembler(); 239 PackageBundleAssembler assembler = new PackageBundleAssembler();
236 240
237 /** 241 /**
238 * Return the `package` [Uri] for the given [path] in the `lib` folder 242 * Return the `package` [Uri] for the given [path] in the `lib` folder
239 * of the current package. 243 * of the current package.
240 */ 244 */
241 Uri getUri(String path) { 245 Uri getUri(String path) {
242 String pathInLib = path.substring(libPath.length); 246 String pathInLib = path.substring(libPath.length);
243 String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib)); 247 String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
244 String uriStr = 'package:${package.name}/$uriPath'; 248 String uriStr = 'package:${package.name}/$uriPath';
245 return FastUri.parse(uriStr); 249 return FastUri.parse(uriStr);
246 } 250 }
247 251
248 /** 252 /**
249 * If the given [file] is a Dart file, add its unlinked unit. 253 * If the given [file] is a Dart file, add its unlinked unit.
250 */ 254 */
251 void addDartFile(File file) { 255 void addDartFile(File file) {
252 String path = file.path; 256 String path = file.path;
253 if (AnalysisEngine.isDartFileName(path)) { 257 if (AnalysisEngine.isDartFileName(path)) {
254 Uri uri = getUri(path); 258 Uri uri = getUri(path);
255 Source source = file.createSource(uri); 259 Source source = file.createSource(uri);
256 CompilationUnit unit = _parse(source); 260 CompilationUnit unit = _parse(source, strongMode);
257 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); 261 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
258 assembler.addUnlinkedUnit(source, unlinkedUnit); 262 assembler.addUnlinkedUnit(source, unlinkedUnit);
259 } 263 }
260 } 264 }
261 265
262 /** 266 /**
263 * Visit the [folder] recursively. 267 * Visit the [folder] recursively.
264 */ 268 */
265 void addDartFiles(Folder folder) { 269 void addDartFiles(Folder folder) {
266 List<Resource> children = folder.getChildren(); 270 List<Resource> children = folder.getChildren();
267 for (Resource child in children) { 271 for (Resource child in children) {
268 if (child is File) { 272 if (child is File) {
269 addDartFile(child); 273 addDartFile(child);
270 } 274 }
271 } 275 }
272 for (Resource child in children) { 276 for (Resource child in children) {
273 if (child is Folder) { 277 if (child is Folder) {
274 addDartFiles(child); 278 addDartFiles(child);
275 } 279 }
276 } 280 }
277 } 281 }
278 282
279 try { 283 try {
280 addDartFiles(libFolder); 284 addDartFiles(libFolder);
281 List<int> bytes = assembler.assemble().toBuffer(); 285 List<int> bytes = assembler.assemble().toBuffer();
282 _writeAtomic(package.folder, UNLINKED_BUNDLE_FILE_NAME, bytes); 286 String fileName = _getUnlinkedName(strongMode);
287 _writeAtomic(package.folder, fileName, bytes);
283 } on FileSystemException { 288 } on FileSystemException {
284 // Ignore file system exceptions. 289 // Ignore file system exceptions.
285 } 290 }
286 } 291 }
287 292
288 /** 293 /**
294 * Return the name of the file for an unlinked bundle, in strong or spec mode.
295 */
296 String _getUnlinkedName(bool strongMode) {
297 if (strongMode) {
298 return UNLINKED_NAME;
299 } else {
300 return UNLINKED_SPEC_NAME;
301 }
302 }
303
304 /**
289 * Return the unlinked [PackageBundle] for the given [package]. If the bundle 305 * Return the unlinked [PackageBundle] for the given [package]. If the bundle
290 * has not been compute yet, return `null` and schedule its computation. 306 * has not been compute yet, return `null` and schedule its computation.
291 */ 307 */
292 PackageBundle _getUnlinkedOrSchedule(PubPackage package) { 308 PackageBundle _getUnlinkedOrSchedule(PubPackage package, bool strongMode) {
293 // Try to find in the cache. 309 // Try to find in the cache.
294 PackageBundle bundle = unlinkedBundleMap[package]; 310 PackageBundle bundle = unlinkedBundleMap[package];
295 if (bundle != null) { 311 if (bundle != null) {
296 return bundle; 312 return bundle;
297 } 313 }
298 // Try to read from the file system. 314 // Try to read from the file system.
299 File unlinkedFile = 315 String fileName = _getUnlinkedName(strongMode);
300 package.folder.getChildAssumingFile(UNLINKED_BUNDLE_FILE_NAME); 316 File unlinkedFile = package.folder.getChildAssumingFile(fileName);
301 if (unlinkedFile.exists) { 317 if (unlinkedFile.exists) {
302 try { 318 try {
303 List<int> bytes = unlinkedFile.readAsBytesSync(); 319 List<int> bytes = unlinkedFile.readAsBytesSync();
304 bundle = new PackageBundle.fromBuffer(bytes); 320 bundle = new PackageBundle.fromBuffer(bytes);
305 unlinkedBundleMap[package] = bundle; 321 unlinkedBundleMap[package] = bundle;
306 return bundle; 322 return bundle;
307 } on FileSystemException { 323 } on FileSystemException {
308 // Ignore file system exceptions. 324 // Ignore file system exceptions.
309 } 325 }
310 } 326 }
311 // Schedule computation in the background. 327 // Schedule computation in the background.
312 if (package != null && seenPackages.add(package)) { 328 if (package != null && seenPackages.add(package)) {
313 if (packagesToComputeUnlinked.isEmpty) { 329 if (packagesToComputeUnlinked.isEmpty) {
314 _scheduleNextUnlinked(); 330 _scheduleNextUnlinked();
315 } 331 }
316 packagesToComputeUnlinked.add(package); 332 packagesToComputeUnlinked.add(package);
317 } 333 }
318 // The bundle is for available. 334 // The bundle is for available.
319 return null; 335 return null;
320 } 336 }
321 337
322 /** 338 /**
323 * Parse the given [source] into AST. 339 * Parse the given [source] into AST.
324 */ 340 */
325 CompilationUnit _parse(Source source) { 341 CompilationUnit _parse(Source source, bool strongMode) {
326 String code = source.contents.data; 342 String code = source.contents.data;
327 AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER; 343 AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
328 CharSequenceReader reader = new CharSequenceReader(code); 344 CharSequenceReader reader = new CharSequenceReader(code);
329 Scanner scanner = new Scanner(source, reader, errorListener); 345 Scanner scanner = new Scanner(source, reader, errorListener);
346 scanner.scanGenericMethodComments = strongMode;
330 Token token = scanner.tokenize(); 347 Token token = scanner.tokenize();
331 LineInfo lineInfo = new LineInfo(scanner.lineStarts); 348 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
332 Parser parser = new Parser(source, errorListener); 349 Parser parser = new Parser(source, errorListener);
350 parser.parseGenericMethodComments = strongMode;
333 CompilationUnit unit = parser.parseCompilationUnit(token); 351 CompilationUnit unit = parser.parseCompilationUnit(token);
334 unit.lineInfo = lineInfo; 352 unit.lineInfo = lineInfo;
335 return unit; 353 return unit;
336 } 354 }
337 355
338 /** 356 /**
339 * Schedule delayed computation of the next package unlinked bundle from the 357 * Schedule delayed computation of the next package unlinked bundle from the
340 * set of [packagesToComputeUnlinked]. We delay each computation because we 358 * set of [packagesToComputeUnlinked]. We delay each computation because we
341 * want operations in analysis server to proceed, and computing bundles of 359 * want operations in analysis server to proceed, and computing bundles of
342 * packages is a background task. 360 * packages is a background task.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 v.failed = true; 448 v.failed = true;
431 } 449 }
432 return dependencyLibrary; 450 return dependencyLibrary;
433 }, (String absUri) { 451 }, (String absUri) {
434 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri]; 452 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri];
435 if (unlinkedUnit == null) { 453 if (unlinkedUnit == null) {
436 // TODO(scheglov) add test 454 // TODO(scheglov) add test
437 v.failed = true; 455 v.failed = true;
438 } 456 }
439 return unlinkedUnit; 457 return unlinkedUnit;
440 }, false); 458 }, false);
Paul Berry 2016/08/10 21:34:42 Need to pass true when linking in strong mode.
scheglov 2016/08/10 21:41:37 Done.
441 if (!v.failed) { 459 if (!v.failed) {
442 PackageBundleAssembler assembler = new PackageBundleAssembler(); 460 PackageBundleAssembler assembler = new PackageBundleAssembler();
443 map.forEach((uri, linkedLibrary) { 461 map.forEach((uri, linkedLibrary) {
444 assembler.addLinkedLibrary(uri, linkedLibrary); 462 assembler.addLinkedLibrary(uri, linkedLibrary);
445 }); 463 });
446 v.linkedBuilder = assembler.assemble(); 464 v.linkedBuilder = assembler.assemble();
447 store.addBundle(null, v.linkedBuilder); 465 store.addBundle(null, v.linkedBuilder);
448 } 466 }
449 } 467 }
450 468
451 @override 469 @override
452 void evaluateScc(List<_LinkedNode> scc) { 470 void evaluateScc(List<_LinkedNode> scc) {
453 print('evaluateScc: $scc'); 471 print('evaluateScc: $scc');
454 // TODO(scheglov): implement evaluateScc 472 // TODO(scheglov): implement evaluateScc
455 } 473 }
456 } 474 }
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