| 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 |