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:convert'; | 7 import 'dart:convert'; |
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 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 } | 229 } |
230 | 230 |
231 // TODO(scheglov) analyze requested files | 231 // TODO(scheglov) analyze requested files |
232 | 232 |
233 // Analyze a priority file. | 233 // Analyze a priority file. |
234 if (_priorityFiles.isNotEmpty) { | 234 if (_priorityFiles.isNotEmpty) { |
235 bool analyzed = false; | 235 bool analyzed = false; |
236 for (String path in _priorityFiles) { | 236 for (String path in _priorityFiles) { |
237 if (_filesToAnalyze.remove(path)) { | 237 if (_filesToAnalyze.remove(path)) { |
238 _File file = _fileForPath(path); | 238 _File file = _fileForPath(path); |
239 AnalysisResult result = _computeAnalysisResult(file); | 239 AnalysisResult result = _computeAnalysisResult(file, true); |
240 yield result; | 240 yield result; |
241 break; | 241 break; |
242 } | 242 } |
243 } | 243 } |
244 // Repeat the processing loop. | 244 // Repeat the processing loop. |
245 if (analyzed) { | 245 if (analyzed) { |
246 _hasWork.notify(); | 246 _hasWork.notify(); |
247 continue; | 247 continue; |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 // Analyze a general file. | 251 // Analyze a general file. |
252 if (_filesToAnalyze.isNotEmpty) { | 252 if (_filesToAnalyze.isNotEmpty) { |
253 String path = _removeFirst(_filesToAnalyze); | 253 String path = _removeFirst(_filesToAnalyze); |
254 _File file = _fileForPath(path); | 254 _File file = _fileForPath(path); |
255 AnalysisResult result = _computeAnalysisResult(file); | 255 AnalysisResult result = _computeAnalysisResult(file, false); |
256 yield result; | 256 yield result; |
257 // Repeat the processing loop. | 257 // Repeat the processing loop. |
258 _hasWork.notify(); | 258 _hasWork.notify(); |
259 continue; | 259 continue; |
260 } | 260 } |
261 | 261 |
262 // There is nothing to do. | 262 // There is nothing to do. |
263 analysisSection.exit(); | 263 analysisSection.exit(); |
264 analysisSection = null; | 264 analysisSection = null; |
265 } | 265 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 * We need to clean this up. | 360 * We need to clean this up. |
361 */ | 361 */ |
362 void _addToStoreUnlinked( | 362 void _addToStoreUnlinked( |
363 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { | 363 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { |
364 store.unlinkedMap[uri] = unlinked; | 364 store.unlinkedMap[uri] = unlinked; |
365 } | 365 } |
366 | 366 |
367 /** | 367 /** |
368 * Compute the [AnalysisResult] for the [file]. | 368 * Compute the [AnalysisResult] for the [file]. |
369 */ | 369 */ |
370 AnalysisResult _computeAnalysisResult(_File file) { | 370 AnalysisResult _computeAnalysisResult(_File file, bool withUnit) { |
Brian Wilkerson
2016/10/26 18:32:11
Document 'withUnit'.
Also, consider making this a
scheglov
2016/10/26 18:48:41
Done.
| |
371 // If we don't need to the fully resolved unit, check for a cached result. | |
Brian Wilkerson
2016/10/26 18:32:11
"need to the" --> "need the"
scheglov
2016/10/26 18:48:41
Done.
| |
372 if (!withUnit) { | |
373 AnalysisResult result = _getCachedAnalysisResult(file); | |
374 if (result != null) { | |
375 return result; | |
376 } | |
377 } | |
378 | |
379 // We need the fully resolved unit, or the result is not cached. | |
371 return _logger.run('Compute analysis result for $file', () { | 380 return _logger.run('Compute analysis result for $file', () { |
372 _LibraryContext libraryContext = _createLibraryContext(file); | 381 _LibraryContext libraryContext = _createLibraryContext(file); |
382 | |
383 // We recomputed the dependency hash, and we might have a cached result. | |
384 if (!withUnit) { | |
385 AnalysisResult result = _getCachedAnalysisResult(file); | |
386 if (result != null) { | |
387 _logger.writeln('Return the cached analysis result.'); | |
388 return result; | |
389 } | |
390 } | |
391 | |
392 // Still no result, compute and store it. | |
373 AnalysisContext analysisContext = _createAnalysisContext(libraryContext); | 393 AnalysisContext analysisContext = _createAnalysisContext(libraryContext); |
374 try { | 394 try { |
375 analysisContext.setContents(file.source, file.content); | 395 analysisContext.setContents(file.source, file.content); |
376 // TODO(scheglov) Add support for parts. | 396 // TODO(scheglov) Add support for parts. |
377 CompilationUnit resolvedUnit = | 397 CompilationUnit resolvedUnit = |
378 analysisContext.resolveCompilationUnit2(file.source, file.source); | 398 analysisContext.resolveCompilationUnit2(file.source, file.source); |
379 List<AnalysisError> errors = analysisContext.computeErrors(file.source); | 399 List<AnalysisError> errors = analysisContext.computeErrors(file.source); |
400 | |
401 // Store the result into the cache. | |
402 { | |
403 List<int> bytes = new AnalysisDriverResolvedUnitBuilder( | |
404 errors: errors | |
405 .map((error) => new AnalysisDriverUnitErrorBuilder( | |
406 offset: error.offset, | |
407 length: error.length, | |
408 uniqueName: error.errorCode.uniqueName, | |
409 message: error.message, | |
410 correction: error.correction)) | |
411 .toList()) | |
412 .toBuffer(); | |
413 String key = _getResolvedUnitKey(file); | |
414 _byteStore.put(key, bytes); | |
415 } | |
416 | |
417 // Return the full result. | |
418 _logger.writeln('Computed new analysis result.'); | |
380 return new AnalysisResult(file.path, file.uri, file.content, | 419 return new AnalysisResult(file.path, file.uri, file.content, |
381 file.contentHash, resolvedUnit, errors); | 420 file.contentHash, resolvedUnit, errors); |
382 } finally { | 421 } finally { |
383 analysisContext.dispose(); | 422 analysisContext.dispose(); |
384 } | 423 } |
385 }); | 424 }); |
386 } | 425 } |
387 | 426 |
388 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) { | 427 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) { |
389 AnalysisContextImpl analysisContext = | 428 AnalysisContextImpl analysisContext = |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 * Return the [_File] for the given [path] in [_sourceFactory]. | 559 * Return the [_File] for the given [path] in [_sourceFactory]. |
521 */ | 560 */ |
522 _File _fileForPath(String path) { | 561 _File _fileForPath(String path) { |
523 Source fileSource = _resourceProvider.getFile(path).createSource(); | 562 Source fileSource = _resourceProvider.getFile(path).createSource(); |
524 Uri uri = _sourceFactory.restoreUri(fileSource); | 563 Uri uri = _sourceFactory.restoreUri(fileSource); |
525 Source source = _resourceProvider.getFile(path).createSource(uri); | 564 Source source = _resourceProvider.getFile(path).createSource(uri); |
526 return new _File.forResolution(this, source); | 565 return new _File.forResolution(this, source); |
527 } | 566 } |
528 | 567 |
529 /** | 568 /** |
569 * If we know the dependency signature for the [file], try to load the | |
570 * analysis result from the cache. Return `null` if not found. | |
571 */ | |
572 AnalysisResult _getCachedAnalysisResult(_File file) { | |
573 String key = _getResolvedUnitKey(file); | |
574 if (key != null) { | |
575 List<int> bytes = _byteStore.get(key); | |
576 if (bytes != null) { | |
577 var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes); | |
578 List<AnalysisError> errors = unit.errors | |
579 .map((error) => new AnalysisError.forValues( | |
580 file.source, | |
581 error.offset, | |
582 error.length, | |
583 ErrorCode.byUniqueName(error.uniqueName), | |
584 error.message, | |
585 error.correction)) | |
586 .toList(); | |
587 return new AnalysisResult( | |
588 file.path, file.uri, null, file.contentHash, null, errors); | |
589 } | |
590 } | |
591 return null; | |
592 } | |
593 | |
594 /** | |
595 * Return the key to store fully resolved results for the [file] into the | |
596 * cache. Return `null` if the dependency signature is not known yet. | |
597 */ | |
598 String _getResolvedUnitKey(_File file) { | |
599 String dependencyHash = _dependencySignatureMap[file.uri]; | |
600 if (dependencyHash != null) { | |
601 ApiSignature signature = new ApiSignature(); | |
602 signature.addString(dependencyHash); | |
603 signature.addString(file.contentHash); | |
604 return '${signature.toHex()}.resolved'; | |
605 } | |
606 return null; | |
607 } | |
608 | |
609 /** | |
530 * Verify the API signature for the file with the given [path], and decide | 610 * Verify the API signature for the file with the given [path], and decide |
531 * which linked libraries should be invalidated, and files reanalyzed. | 611 * which linked libraries should be invalidated, and files reanalyzed. |
532 * | 612 * |
533 * TODO(scheglov) I see that adding a local var changes (full) API signature. | 613 * TODO(scheglov) I see that adding a local var changes (full) API signature. |
534 */ | 614 */ |
535 void _verifyApiSignatureOfChangedFile(String path) { | 615 void _verifyApiSignatureOfChangedFile(String path) { |
536 _logger.run('Verify API signature of $path', () { | 616 _logger.run('Verify API signature of $path', () { |
537 String oldSignature = _fileApiSignatureMap[path]; | 617 String oldSignature = _fileApiSignatureMap[path]; |
538 // Compute the new API signature. | 618 // Compute the new API signature. |
539 // _File.forResolution() also updates the content hash in the cache. | 619 // _File.forResolution() also updates the content hash in the cache. |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 } | 1079 } |
1000 } | 1080 } |
1001 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | 1081 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { |
1002 referenced.exported.add(export.uri); | 1082 referenced.exported.add(export.uri); |
1003 } | 1083 } |
1004 return referenced; | 1084 return referenced; |
1005 } | 1085 } |
1006 | 1086 |
1007 _ReferencedUris._(); | 1087 _ReferencedUris._(); |
1008 } | 1088 } |
OLD | NEW |