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:typed_data'; | 7 import 'dart:typed_data'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/error/error.dart'; | 10 import 'package:analyzer/error/error.dart'; |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 /** | 408 /** |
409 * TODO(scheglov) The existing [SummaryDataStore.addBundle] uses | 409 * TODO(scheglov) The existing [SummaryDataStore.addBundle] uses |
410 * [PackageBundle.unlinkedUnitUris] to add [PackageBundle.unlinkedUnits]. | 410 * [PackageBundle.unlinkedUnitUris] to add [PackageBundle.unlinkedUnits]. |
411 * But we store unlinked bundles with the hash of the file content. This | 411 * But we store unlinked bundles with the hash of the file content. This |
412 * means that when two files are the same, but have different URIs, we | 412 * means that when two files are the same, but have different URIs, we |
413 * add [UnlinkedUnit] with wrong URI. | 413 * add [UnlinkedUnit] with wrong URI. |
414 * | 414 * |
415 * We need to clean this up. | 415 * We need to clean this up. |
416 */ | 416 */ |
417 void _addToStoreUnlinked( | 417 void _addToStoreUnlinked( |
418 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { | 418 SummaryDataStore store, Uri uri, UnlinkedUnit unlinked) { |
419 store.unlinkedMap[uri] = unlinked; | 419 String uriStr = uri.toString(); |
| 420 store.unlinkedMap[uriStr] = unlinked; |
420 } | 421 } |
421 | 422 |
422 /** | 423 /** |
423 * Return the cached or newly computed analysis result of the file with the | 424 * Return the cached or newly computed analysis result of the file with the |
424 * given [path]. | 425 * given [path]. |
425 * | 426 * |
426 * The result will have the fully resolved unit and will always be newly | 427 * The result will have the fully resolved unit and will always be newly |
427 * compute only if [withUnit] is `true`. | 428 * compute only if [withUnit] is `true`. |
428 */ | 429 */ |
429 AnalysisResult _computeAnalysisResult(String path, {bool withUnit: false}) { | 430 AnalysisResult _computeAnalysisResult(String path, {bool withUnit: false}) { |
430 // If we don't need the fully resolved unit, check for the cached result. | 431 // If we don't need the fully resolved unit, check for the cached result. |
431 if (!withUnit) { | 432 if (!withUnit) { |
432 FileState file = _fsState.getFile(path); | 433 FileState file = _fsState.getFileForPath(path); |
433 // Prepare the key for the cached result. | 434 // Prepare the key for the cached result. |
434 String key = _getResolvedUnitKey(file); | 435 String key = _getResolvedUnitKey(file); |
435 if (key == null) { | 436 if (key == null) { |
436 _logger.run('Compute the dependency hash for $path', () { | 437 _logger.run('Compute the dependency hash for $path', () { |
437 _createLibraryContext(file); | 438 _createLibraryContext(file); |
438 key = _getResolvedUnitKey(file); | 439 key = _getResolvedUnitKey(file); |
439 }); | 440 }); |
440 } | 441 } |
441 // Check for the cached result. | 442 // Check for the cached result. |
442 AnalysisResult result = _getCachedAnalysisResult(file, key); | 443 AnalysisResult result = _getCachedAnalysisResult(file, key); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 | 528 |
528 String libraryUriStr = libraryUri.toString(); | 529 String libraryUriStr = libraryUri.toString(); |
529 _LibraryNode node = nodes[libraryUriStr]; | 530 _LibraryNode node = nodes[libraryUriStr]; |
530 if (node == null) { | 531 if (node == null) { |
531 node = new _LibraryNode(this, libraryFile, libraryUri); | 532 node = new _LibraryNode(this, libraryFile, libraryUri); |
532 nodes[libraryUriStr] = node; | 533 nodes[libraryUriStr] = node; |
533 | 534 |
534 // Append the defining unit. | 535 // Append the defining unit. |
535 { | 536 { |
536 UnlinkedUnit unlinked = libraryFile.unlinked; | 537 UnlinkedUnit unlinked = libraryFile.unlinked; |
537 _addToStoreUnlinked(store, libraryUriStr, unlinked); | 538 _addToStoreUnlinked(store, libraryFile.uri, unlinked); |
538 } | 539 } |
539 | 540 |
540 // Append parts. | 541 // Append parts. |
541 for (FileState part in libraryFile.partedFiles) { | 542 for (FileState part in libraryFile.partedFiles) { |
542 String partUriStr = part.uri.toString(); | |
543 UnlinkedUnit unlinked = part.unlinked; | 543 UnlinkedUnit unlinked = part.unlinked; |
544 _addToStoreUnlinked(store, partUriStr, unlinked); | 544 _addToStoreUnlinked(store, part.uri, unlinked); |
545 } | 545 } |
546 | 546 |
547 // Create nodes for referenced libraries. | 547 // Create nodes for referenced libraries. |
548 libraryFile.importedFiles.forEach(createLibraryNodes); | 548 libraryFile.importedFiles.forEach(createLibraryNodes); |
549 libraryFile.exportedFiles.forEach(createLibraryNodes); | 549 libraryFile.exportedFiles.forEach(createLibraryNodes); |
550 } | 550 } |
551 | 551 |
552 // Done with this node. | 552 // Done with this node. |
553 return node; | 553 return node; |
554 } | 554 } |
555 | 555 |
556 _LibraryNode libraryNode = _logger.run('Compute library nodes', () { | 556 _LibraryNode libraryNode = _logger.run('Compute library nodes', () { |
557 return createLibraryNodes(libraryFile); | 557 return createLibraryNodes(libraryFile); |
558 }); | 558 }); |
559 | 559 |
560 Set<String> libraryUrisToLink = new Set<String>(); | 560 Set<String> libraryUrisToLink = new Set<String>(); |
561 _logger.run('Load linked bundles', () { | 561 _logger.run('Load linked bundles', () { |
562 for (_LibraryNode node in nodes.values) { | 562 for (_LibraryNode node in nodes.values) { |
563 String key = '${node.dependencySignature}.linked'; | 563 String key = '${node.dependencySignature}.linked'; |
564 List<int> bytes = _byteStore.get(key); | 564 List<int> bytes = _byteStore.get(key); |
565 if (bytes != null) { | 565 if (bytes != null) { |
566 PackageBundle linked = new PackageBundle.fromBuffer(bytes); | 566 PackageBundle linked = new PackageBundle.fromBuffer(bytes); |
567 _addToStoreLinked( | 567 _addToStoreLinked( |
568 store, node.uri.toString(), linked.linkedLibraries.single); | 568 store, node.file.uri.toString(), linked.linkedLibraries.single); |
569 } else { | 569 } else { |
570 libraryUrisToLink.add(node.uri.toString()); | 570 libraryUrisToLink.add(node.uri.toString()); |
571 } | 571 } |
572 } | 572 } |
573 int numOfLoaded = nodes.length - libraryUrisToLink.length; | 573 int numOfLoaded = nodes.length - libraryUrisToLink.length; |
574 _logger.writeln('Loaded $numOfLoaded linked bundles.'); | 574 _logger.writeln('Loaded $numOfLoaded linked bundles.'); |
575 }); | 575 }); |
576 | 576 |
577 Map<String, LinkedLibraryBuilder> linkedLibraries = {}; | 577 Map<String, LinkedLibraryBuilder> linkedLibraries = {}; |
578 _logger.run('Link bundles', () { | 578 _logger.run('Link bundles', () { |
579 linkedLibraries = link(libraryUrisToLink, (String uri) { | 579 linkedLibraries = link(libraryUrisToLink, (String uri) { |
580 LinkedLibrary linkedLibrary = store.linkedMap[uri]; | 580 LinkedLibrary linkedLibrary = store.linkedMap[uri]; |
581 if (linkedLibrary == null) { | |
582 throw new StateError('No linked library for: $uri'); | |
583 } | |
584 return linkedLibrary; | 581 return linkedLibrary; |
585 }, (String uri) { | 582 }, (String uri) { |
586 UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri]; | 583 UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri]; |
587 if (unlinkedUnit == null) { | |
588 throw new StateError('No unlinked unit for: $uri'); | |
589 } | |
590 return unlinkedUnit; | 584 return unlinkedUnit; |
591 }, (_) => null, _analysisOptions.strongMode); | 585 }, (_) => null, _analysisOptions.strongMode); |
592 _logger.writeln('Linked ${linkedLibraries.length} bundles.'); | 586 _logger.writeln('Linked ${linkedLibraries.length} bundles.'); |
593 }); | 587 }); |
594 | 588 |
595 linkedLibraries.forEach((uri, linkedBuilder) { | 589 linkedLibraries.forEach((uri, linkedBuilder) { |
596 _LibraryNode node = nodes[uri]; | 590 _LibraryNode node = nodes[uri]; |
597 String key = '${node.dependencySignature}.linked'; | 591 String key = '${node.dependencySignature}.linked'; |
598 List<int> bytes; | 592 List<int> bytes; |
599 { | 593 { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 } | 675 } |
682 | 676 |
683 /** | 677 /** |
684 * Verify the API signature for the file with the given [path], and decide | 678 * Verify the API signature for the file with the given [path], and decide |
685 * which linked libraries should be invalidated, and files reanalyzed. | 679 * which linked libraries should be invalidated, and files reanalyzed. |
686 * | 680 * |
687 * TODO(scheglov) I see that adding a local var changes (full) API signature. | 681 * TODO(scheglov) I see that adding a local var changes (full) API signature. |
688 */ | 682 */ |
689 FileState _verifyApiSignature(String path) { | 683 FileState _verifyApiSignature(String path) { |
690 return _logger.run('Verify API signature of $path', () { | 684 return _logger.run('Verify API signature of $path', () { |
691 FileState file = _fsState.getFile(path); | 685 bool anyApiChanged = false; |
692 bool apiChanged = file.refresh(); | 686 List<FileState> files = _fsState.getFilesForPath(path); |
693 if (apiChanged) { | 687 for (FileState file in files) { |
| 688 bool apiChanged = file.refresh(); |
| 689 if (apiChanged) { |
| 690 anyApiChanged = true; |
| 691 } |
| 692 } |
| 693 if (anyApiChanged) { |
694 _logger.writeln('API signatures mismatch found for $path'); | 694 _logger.writeln('API signatures mismatch found for $path'); |
695 _dependencySignatureMap.clear(); | 695 _dependencySignatureMap.clear(); |
696 _filesToAnalyze.addAll(_explicitFiles); | 696 _filesToAnalyze.addAll(_explicitFiles); |
697 } | 697 } |
698 return file; | 698 return files[0]; |
699 }); | 699 }); |
700 } | 700 } |
701 | 701 |
702 /** | 702 /** |
703 * Returns a [Future] that completes after performing [times] pumpings of | 703 * Returns a [Future] that completes after performing [times] pumpings of |
704 * the event queue. | 704 * the event queue. |
705 */ | 705 */ |
706 static Future _pumpEventQueue(int times) { | 706 static Future _pumpEventQueue(int times) { |
707 if (times == 0) { | 707 if (times == 0) { |
708 return new Future.value(); | 708 return new Future.value(); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 /** | 954 /** |
955 * Complete the [signal] future if it is not completed yet. It is safe to | 955 * Complete the [signal] future if it is not completed yet. It is safe to |
956 * call this method multiple times, but the [signal] will complete only once. | 956 * call this method multiple times, but the [signal] will complete only once. |
957 */ | 957 */ |
958 void notify() { | 958 void notify() { |
959 if (!_completer.isCompleted) { | 959 if (!_completer.isCompleted) { |
960 _completer.complete(null); | 960 _completer.complete(null); |
961 } | 961 } |
962 } | 962 } |
963 } | 963 } |
OLD | NEW |