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

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/driver.dart

Issue 2757753002: Migrate DDC to the new analysis driver.
Patch Set: Created 3 years, 9 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
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:typed_data'; 7 import 'dart:typed_data';
8 8
9 import 'package:analyzer/context/declared_variables.dart'; 9 import 'package:analyzer/context/declared_variables.dart';
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
11 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; 11 import 'package:analyzer/dart/element/element.dart'
12 show CompilationUnitElement, LibraryElement;
12 import 'package:analyzer/error/error.dart'; 13 import 'package:analyzer/error/error.dart';
13 import 'package:analyzer/error/listener.dart'; 14 import 'package:analyzer/error/listener.dart';
14 import 'package:analyzer/exception/exception.dart'; 15 import 'package:analyzer/exception/exception.dart';
15 import 'package:analyzer/file_system/file_system.dart'; 16 import 'package:analyzer/file_system/file_system.dart';
16 import 'package:analyzer/src/dart/analysis/byte_store.dart'; 17 import 'package:analyzer/src/dart/analysis/byte_store.dart';
17 import 'package:analyzer/src/dart/analysis/file_state.dart'; 18 import 'package:analyzer/src/dart/analysis/file_state.dart';
18 import 'package:analyzer/src/dart/analysis/file_tracker.dart'; 19 import 'package:analyzer/src/dart/analysis/file_tracker.dart';
19 import 'package:analyzer/src/dart/analysis/index.dart'; 20 import 'package:analyzer/src/dart/analysis/index.dart';
20 import 'package:analyzer/src/dart/analysis/library_analyzer.dart'; 21 import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
21 import 'package:analyzer/src/dart/analysis/library_context.dart'; 22 import 'package:analyzer/src/dart/analysis/library_context.dart';
22 import 'package:analyzer/src/dart/analysis/search.dart'; 23 import 'package:analyzer/src/dart/analysis/search.dart';
23 import 'package:analyzer/src/dart/analysis/status.dart'; 24 import 'package:analyzer/src/dart/analysis/status.dart';
24 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; 25 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
25 import 'package:analyzer/src/generated/engine.dart' 26 import 'package:analyzer/src/generated/engine.dart'
26 show AnalysisContext, AnalysisEngine, AnalysisOptions; 27 show AnalysisContext, AnalysisEngine, AnalysisOptions;
27 import 'package:analyzer/src/generated/source.dart'; 28 import 'package:analyzer/src/generated/source.dart';
28 import 'package:analyzer/src/services/lint.dart'; 29 import 'package:analyzer/src/services/lint.dart';
29 import 'package:analyzer/src/summary/api_signature.dart'; 30 import 'package:analyzer/src/summary/api_signature.dart';
30 import 'package:analyzer/src/summary/format.dart'; 31 import 'package:analyzer/src/summary/format.dart';
31 import 'package:analyzer/src/summary/idl.dart'; 32 import 'package:analyzer/src/summary/idl.dart';
33 import 'package:analyzer/src/summary/package_bundle_reader.dart';
32 import 'package:meta/meta.dart'; 34 import 'package:meta/meta.dart';
33 35
34 /** 36 /**
35 * This class computes [AnalysisResult]s for Dart files. 37 * This class computes [AnalysisResult]s for Dart files.
36 * 38 *
37 * Let the set of "explicitly analyzed files" denote the set of paths that have 39 * Let the set of "explicitly analyzed files" denote the set of paths that have
38 * been passed to [addFile] but not subsequently passed to [removeFile]. Let 40 * been passed to [addFile] but not subsequently passed to [removeFile]. Let
39 * the "current analysis results" denote the map from the set of explicitly 41 * the "current analysis results" denote the map from the set of explicitly
40 * analyzed files to the most recent [AnalysisResult] delivered to [results] 42 * analyzed files to the most recent [AnalysisResult] delivered to [results]
41 * for each file. Let the "current file state" represent a map from file path 43 * for each file. Let the "current file state" represent a map from file path
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 final ResourceProvider _resourceProvider; 104 final ResourceProvider _resourceProvider;
103 105
104 /** 106 /**
105 * The byte storage to get and put serialized data. 107 * The byte storage to get and put serialized data.
106 * 108 *
107 * It can be shared with other [AnalysisDriver]s. 109 * It can be shared with other [AnalysisDriver]s.
108 */ 110 */
109 final ByteStore _byteStore; 111 final ByteStore _byteStore;
110 112
111 /** 113 /**
114 * TODO(scheglov) document
115 */
116 final SummaryDataStore externalSummaries;
117
118 /**
112 * This [ContentCache] is consulted for a file content before reading 119 * This [ContentCache] is consulted for a file content before reading
113 * the content from the file. 120 * the content from the file.
114 */ 121 */
115 final FileContentOverlay _contentOverlay; 122 final FileContentOverlay _contentOverlay;
116 123
117 /** 124 /**
118 * The analysis options to analyze with. 125 * The analysis options to analyze with.
119 */ 126 */
120 AnalysisOptions _analysisOptions; 127 AnalysisOptions _analysisOptions;
121 128
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 */ 236 */
230 Search _search; 237 Search _search;
231 238
232 AnalysisDriverTestView _testView; 239 AnalysisDriverTestView _testView;
233 240
234 /** 241 /**
235 * The [FileTracker] used by this driver. 242 * The [FileTracker] used by this driver.
236 */ 243 */
237 FileTracker _fileTracker; 244 FileTracker _fileTracker;
238 245
246 final _cachedResults = {};
247
239 /** 248 /**
240 * Create a new instance of [AnalysisDriver]. 249 * Create a new instance of [AnalysisDriver].
241 * 250 *
242 * The given [SourceFactory] is cloned to ensure that it does not contain a 251 * The given [SourceFactory] is cloned to ensure that it does not contain a
243 * reference to a [AnalysisContext] in which it could have been used. 252 * reference to a [AnalysisContext] in which it could have been used.
244 */ 253 */
245 AnalysisDriver( 254 AnalysisDriver(
246 this._scheduler, 255 this._scheduler,
247 PerformanceLog logger, 256 PerformanceLog logger,
248 this._resourceProvider, 257 this._resourceProvider,
249 this._byteStore, 258 this._byteStore,
250 this._contentOverlay, 259 this._contentOverlay,
251 this.name, 260 this.name,
252 SourceFactory sourceFactory, 261 SourceFactory sourceFactory,
253 this._analysisOptions, 262 this._analysisOptions,
254 {PackageBundle sdkBundle, 263 {PackageBundle sdkBundle,
255 this.analyzeWithoutTasks: true}) 264 this.analyzeWithoutTasks: true,
265 SummaryDataStore externalSummaries})
256 : _logger = logger, 266 : _logger = logger,
257 _sourceFactory = sourceFactory.clone(), 267 _sourceFactory = sourceFactory.clone(),
258 _sdkBundle = sdkBundle { 268 _sdkBundle = sdkBundle,
269 externalSummaries = externalSummaries {
259 _testView = new AnalysisDriverTestView(this); 270 _testView = new AnalysisDriverTestView(this);
260 _createFileTracker(logger); 271 _createFileTracker(logger);
261 _scheduler.add(this); 272 _scheduler.add(this);
262 _search = new Search(this); 273 _search = new Search(this);
263 } 274 }
264 275
265 /** 276 /**
266 * Return the set of files explicitly added to analysis using [addFile]. 277 * Return the set of files explicitly added to analysis using [addFile].
267 */ 278 */
268 Set<String> get addedFiles => _fileTracker.addedFiles; 279 Set<String> get addedFiles => _fileTracker.addedFiles;
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 return new Future.value(); 548 return new Future.value();
538 } 549 }
539 var completer = new Completer<AnalysisDriverUnitIndex>(); 550 var completer = new Completer<AnalysisDriverUnitIndex>();
540 _indexRequestedFiles 551 _indexRequestedFiles
541 .putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex>>[]) 552 .putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex>>[])
542 .add(completer); 553 .add(completer);
543 _scheduler.notify(this); 554 _scheduler.notify(this);
544 return completer.future; 555 return completer.future;
545 } 556 }
546 557
558 ApiSignature getResolvedUnitKeyByPath(String path) {
559 ApiSignature signature = getUnitKeyByPath(path);
560 var file = fsState.getFileForPath(path);
561 signature.addString(file.contentHash);
562 return signature;
563 }
564
547 /** 565 /**
548 * Return a [Future] that completes with a [AnalysisResult] for the Dart 566 * Return a [Future] that completes with a [AnalysisResult] for the Dart
549 * file with the given [path]. If the file is not a Dart file or cannot 567 * file with the given [path]. If the file is not a Dart file or cannot
550 * be analyzed, the [Future] completes with `null`. 568 * be analyzed, the [Future] completes with `null`.
551 * 569 *
552 * The [path] must be absolute and normalized. 570 * The [path] must be absolute and normalized.
553 * 571 *
554 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 572 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
555 * 573 *
556 * If the driver has the cached analysis result for the file, it is returned. 574 * If the driver has the cached analysis result for the file, it is returned.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 return new Future.value(); 658 return new Future.value();
641 } 659 }
642 var completer = new Completer<String>(); 660 var completer = new Completer<String>();
643 _unitElementSignatureRequests 661 _unitElementSignatureRequests
644 .putIfAbsent(path, () => <Completer<String>>[]) 662 .putIfAbsent(path, () => <Completer<String>>[])
645 .add(completer); 663 .add(completer);
646 _scheduler.notify(this); 664 _scheduler.notify(this);
647 return completer.future; 665 return completer.future;
648 } 666 }
649 667
668 ApiSignature getUnitKeyByPath(String path) {
669 var file = fsState.getFileForPath(path);
670 ApiSignature signature = new ApiSignature();
671 signature.addUint32List(_salt);
672 signature.addString(file.transitiveSignature);
673 return signature;
674 }
675
650 /** 676 /**
651 * Return a [Future] that completes with a [ParseResult] for the file 677 * Return a [Future] that completes with a [ParseResult] for the file
652 * with the given [path]. 678 * with the given [path].
653 * 679 *
654 * The [path] must be absolute and normalized. 680 * The [path] must be absolute and normalized.
655 * 681 *
656 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 682 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
657 * 683 *
658 * The parsing is performed in the method itself, and the result is not 684 * The parsing is performed in the method itself, and the result is not
659 * produced through the [results] stream (just because it is not a fully 685 * produced through the [results] stream (just because it is not a fully
660 * resolved unit). 686 * resolved unit).
661 */ 687 */
662 Future<ParseResult> parseFile(String path) async { 688 Future<ParseResult> parseFile(String path) async {
663 FileState file = _fileTracker.verifyApiSignature(path); 689 FileState file = _fileTracker.verifyApiSignature(path);
664 RecordingErrorListener listener = new RecordingErrorListener(); 690 RecordingErrorListener listener = new RecordingErrorListener();
665 CompilationUnit unit = file.parse(listener); 691 CompilationUnit unit = file.parse(listener);
666 return new ParseResult(file.path, file.uri, file.content, file.contentHash, 692 return new ParseResult(file.path, file.uri, file.content, file.contentHash,
667 unit.lineInfo, unit, listener.errors); 693 unit.lineInfo, unit, listener.errors);
668 } 694 }
669 695
670 /** 696 /**
697 * Perform a single chunk of work and produce [results].
698 */
699 Future<Null> performWork() async {
700 if (_fileTracker.verifyChangedFilesIfNeeded()) {
701 return;
702 }
703
704 // Analyze a requested file.
705 if (_requestedFiles.isNotEmpty) {
706 String path = _requestedFiles.keys.first;
707 try {
708 AnalysisResult result = _computeAnalysisResult(path, withUnit: true);
709 // If a part without a library, delay its analysis.
710 if (result == null) {
711 _requestedParts
712 .putIfAbsent(path, () => [])
713 .addAll(_requestedFiles.remove(path));
714 return;
715 }
716 // Notify the completers.
717 _requestedFiles.remove(path).forEach((completer) {
718 completer.complete(result);
719 });
720 // Remove from to be analyzed and produce it now.
721 _fileTracker.fileWasAnalyzed(path);
722 _resultController.add(result);
723 } catch (exception, stackTrace) {
724 _fileTracker.fileWasAnalyzed(path);
725 _requestedFiles.remove(path).forEach((completer) {
726 completer.completeError(exception, stackTrace);
727 });
728 }
729 return;
730 }
731
732 // Process an index request.
733 if (_indexRequestedFiles.isNotEmpty) {
734 String path = _indexRequestedFiles.keys.first;
735 AnalysisDriverUnitIndex index = _computeIndex(path);
736 _indexRequestedFiles.remove(path).forEach((completer) {
737 completer.complete(index);
738 });
739 return;
740 }
741
742 // Process a unit element key request.
743 if (_unitElementSignatureRequests.isNotEmpty) {
744 String path = _unitElementSignatureRequests.keys.first;
745 String signature = _computeUnitElementSignature(path);
746 _unitElementSignatureRequests.remove(path).forEach((completer) {
747 completer.complete(signature);
748 });
749 return;
750 }
751
752 // Process a unit element request.
753 if (_unitElementRequestedFiles.isNotEmpty) {
754 String path = _unitElementRequestedFiles.keys.first;
755 UnitElementResult result = _computeUnitElement(path);
756 _unitElementRequestedFiles.remove(path).forEach((completer) {
757 completer.complete(result);
758 });
759 return;
760 }
761
762 // Compute files defining a name.
763 if (_definingClassMemberNameTasks.isNotEmpty) {
764 _FilesDefiningClassMemberNameTask task =
765 _definingClassMemberNameTasks.first;
766 bool isDone = await task.perform();
767 if (isDone) {
768 _definingClassMemberNameTasks.remove(task);
769 }
770 return;
771 }
772
773 // Compute files referencing a name.
774 if (_referencingNameTasks.isNotEmpty) {
775 _FilesReferencingNameTask task = _referencingNameTasks.first;
776 bool isDone = await task.perform();
777 if (isDone) {
778 _referencingNameTasks.remove(task);
779 }
780 return;
781 }
782
783 // Compute top-level declarations.
784 if (_topLevelNameDeclarationsTasks.isNotEmpty) {
785 _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
786 bool isDone = await task.perform();
787 if (isDone) {
788 _topLevelNameDeclarationsTasks.remove(task);
789 }
790 return;
791 }
792
793 // Analyze a priority file.
794 if (_priorityFiles.isNotEmpty) {
795 for (String path in _priorityFiles) {
796 if (_fileTracker.isFilePending(path)) {
797 try {
798 AnalysisResult result =
799 _computeAnalysisResult(path, withUnit: true);
800 if (result == null) {
801 _partsToAnalyze.add(path);
802 } else {
803 _resultController.add(result);
804 }
805 } catch (exception, stackTrace) {
806 _reportException(path, exception, stackTrace);
807 } finally {
808 _fileTracker.fileWasAnalyzed(path);
809 }
810 return;
811 }
812 }
813 }
814
815 // Analyze a general file.
816 if (_fileTracker.hasPendingFiles) {
817 String path = _fileTracker.anyPendingFile;
818 try {
819 AnalysisResult result = _computeAnalysisResult(path,
820 withUnit: false, skipIfSameSignature: true);
821 if (result == null) {
822 _partsToAnalyze.add(path);
823 } else if (result == AnalysisResult._UNCHANGED) {
824 // We found that the set of errors is the same as we produced the
825 // last time, so we don't need to produce it again now.
826 } else {
827 _resultController.add(result);
828 _lastProducedSignatures[result.path] = result._signature;
829 }
830 } catch (exception, stackTrace) {
831 _reportException(path, exception, stackTrace);
832 } finally {
833 _fileTracker.fileWasAnalyzed(path);
834 }
835 return;
836 }
837
838 // Analyze a requested part file.
839 if (_requestedParts.isNotEmpty) {
840 String path = _requestedParts.keys.first;
841 try {
842 AnalysisResult result = _computeAnalysisResult(path,
843 withUnit: true, asIsIfPartWithoutLibrary: true);
844 // Notify the completers.
845 _requestedParts.remove(path).forEach((completer) {
846 completer.complete(result);
847 });
848 // Remove from to be analyzed and produce it now.
849 _partsToAnalyze.remove(path);
850 _resultController.add(result);
851 } catch (exception, stackTrace) {
852 _partsToAnalyze.remove(path);
853 _requestedParts.remove(path).forEach((completer) {
854 completer.completeError(exception, stackTrace);
855 });
856 }
857 return;
858 }
859
860 // Analyze a general part.
861 if (_partsToAnalyze.isNotEmpty) {
862 String path = _partsToAnalyze.first;
863 _partsToAnalyze.remove(path);
864 try {
865 AnalysisResult result = _computeAnalysisResult(path,
866 withUnit: _priorityFiles.contains(path),
867 asIsIfPartWithoutLibrary: true);
868 _resultController.add(result);
869 } catch (exception, stackTrace) {
870 _reportException(path, exception, stackTrace);
871 }
872 return;
873 }
874 }
875
876 /**
671 * Remove the file with the given [path] from the list of files to analyze. 877 * Remove the file with the given [path] from the list of files to analyze.
672 * 878 *
673 * The [path] must be absolute and normalized. 879 * The [path] must be absolute and normalized.
674 * 880 *
675 * The results of analysis of the file might still be produced by the 881 * The results of analysis of the file might still be produced by the
676 * [results] stream. The driver will try to stop producing these results, 882 * [results] stream. The driver will try to stop producing these results,
677 * but does not guarantee this. 883 * but does not guarantee this.
678 */ 884 */
679 void removeFile(String path) { 885 void removeFile(String path) {
680 _fileTracker.removeFile(path); 886 _fileTracker.removeFile(path);
681 _priorityResults.clear(); 887 _priorityResults.clear();
682 } 888 }
683 889
684 /** 890 /**
891 * TODO(scheglov) document
892 */
893 Future<LibraryElement> resynthesizeLibrary(String uri) async {
894 if (externalSummaries.hasUnlinkedUnit(uri)) {
895 return LibraryContext.resynthesizeLibrary(analysisOptions,
896 declaredVariables, sourceFactory, externalSummaries, uri);
897 }
898 Source source = sourceFactory.resolveUri(null, uri);
899 var unitResult = await getUnitElement(source.fullName);
900 return unitResult.element.library;
901 }
902
903 /**
685 * Handles a notification from the [FileTracker] that there has been a change 904 * Handles a notification from the [FileTracker] that there has been a change
686 * of state. 905 * of state.
687 */ 906 */
688 void _changeHook() { 907 void _changeHook() {
689 _priorityResults.clear(); 908 _priorityResults.clear();
690 _scheduler.notify(this); 909 _scheduler.notify(this);
691 } 910 }
692 911
693 /** 912 /**
694 * Return the cached or newly computed analysis result of the file with the 913 * Return the cached or newly computed analysis result of the file with the
695 * given [path]. 914 * given [path].
696 * 915 *
697 * The result will have the fully resolved unit and will always be newly 916 * The result will have the fully resolved unit and will always be newly
698 * compute only if [withUnit] is `true`. 917 * compute only if [withUnit] is `true`.
699 * 918 *
700 * Return `null` if the file is a part of an unknown library, so cannot be 919 * Return `null` if the file is a part of an unknown library, so cannot be
701 * analyzed yet. But [asIsIfPartWithoutLibrary] is `true`, then the file is 920 * analyzed yet. But [asIsIfPartWithoutLibrary] is `true`, then the file is
702 * analyzed anyway, even without a library. 921 * analyzed anyway, even without a library.
703 * 922 *
704 * Return [AnalysisResult._UNCHANGED] if [skipIfSameSignature] is `true` and 923 * Return [AnalysisResult._UNCHANGED] if [skipIfSameSignature] is `true` and
705 * the resolved signature of the file in its library is the same as the one 924 * the resolved signature of the file in its library is the same as the one
706 * that was the most recently produced to the client. 925 * that was the most recently produced to the client.
707 */ 926 */
708 AnalysisResult _computeAnalysisResult(String path, 927 AnalysisResult _computeAnalysisResult(String path,
709 {bool withUnit: false, 928 {bool withUnit: false,
710 bool asIsIfPartWithoutLibrary: false, 929 bool asIsIfPartWithoutLibrary: false,
711 bool skipIfSameSignature: false}) { 930 bool skipIfSameSignature: false}) {
712 FileState file = _fileTracker.fsState.getFileForPath(path); 931 FileState file = _fileTracker.fsState.getFileForPath(path);
713 932
933 {
934 UnitAnalysisResult unitResult = _cachedResults[file];
935 if (unitResult != null) {
936 return new AnalysisResult(
937 this,
938 sourceFactory,
939 path,
940 file.uri,
941 file.exists,
942 file.content,
943 file.contentHash,
944 file.lineInfo,
945 null,
946 unitResult.unit,
947 unitResult.errors,
948 null);
949 }
950 }
951
714 // Prepare the library - the file itself, or the known library. 952 // Prepare the library - the file itself, or the known library.
715 FileState library = file.isPart ? file.library : file; 953 FileState library = file.isPart ? file.library : file;
716 if (library == null) { 954 if (library == null) {
717 if (asIsIfPartWithoutLibrary) { 955 if (asIsIfPartWithoutLibrary) {
718 library = file; 956 library = file;
719 } else { 957 } else {
720 return null; 958 return null;
721 } 959 }
722 } 960 }
723 961
(...skipping 26 matching lines...) Expand all
750 List<int> bytes; 988 List<int> bytes;
751 if (analyzeWithoutTasks) { 989 if (analyzeWithoutTasks) {
752 LibraryAnalyzer analyzer = new LibraryAnalyzer( 990 LibraryAnalyzer analyzer = new LibraryAnalyzer(
753 analysisOptions, 991 analysisOptions,
754 declaredVariables, 992 declaredVariables,
755 sourceFactory, 993 sourceFactory,
756 _fileTracker.fsState, 994 _fileTracker.fsState,
757 libraryContext.store, 995 libraryContext.store,
758 library); 996 library);
759 Map<FileState, UnitAnalysisResult> results = analyzer.analyze(); 997 Map<FileState, UnitAnalysisResult> results = analyzer.analyze();
998 _cachedResults.addAll(results);
760 for (FileState unitFile in results.keys) { 999 for (FileState unitFile in results.keys) {
761 UnitAnalysisResult unitResult = results[unitFile]; 1000 UnitAnalysisResult unitResult = results[unitFile];
762 List<int> unitBytes = 1001 List<int> unitBytes =
763 _serializeResolvedUnit(unitResult.unit, unitResult.errors); 1002 _serializeResolvedUnit(unitResult.unit, unitResult.errors);
764 String unitSignature = 1003 String unitSignature =
765 _getResolvedUnitSignature(library, unitFile); 1004 _getResolvedUnitSignature(library, unitFile);
766 String unitKey = _getResolvedUnitKey(unitSignature); 1005 String unitKey = _getResolvedUnitKey(unitSignature);
767 _byteStore.put(unitKey, unitBytes); 1006 _byteStore.put(unitKey, unitBytes);
768 if (unitFile == file) { 1007 if (unitFile == file) {
769 bytes = unitBytes; 1008 bytes = unitBytes;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 } 1042 }
804 1043
805 AnalysisDriverUnitIndex _computeIndex(String path) { 1044 AnalysisDriverUnitIndex _computeIndex(String path) {
806 AnalysisResult analysisResult = _computeAnalysisResult(path, 1045 AnalysisResult analysisResult = _computeAnalysisResult(path,
807 withUnit: false, asIsIfPartWithoutLibrary: true); 1046 withUnit: false, asIsIfPartWithoutLibrary: true);
808 return analysisResult._index; 1047 return analysisResult._index;
809 } 1048 }
810 1049
811 UnitElementResult _computeUnitElement(String path) { 1050 UnitElementResult _computeUnitElement(String path) {
812 FileState file = _fileTracker.fsState.getFileForPath(path); 1051 FileState file = _fileTracker.fsState.getFileForPath(path);
1052 if (path.startsWith('dart:')) {
1053 file = _fileTracker.fsState.getFileForUri(Uri.parse(path));
1054 }
813 FileState library = file.library ?? file; 1055 FileState library = file.library ?? file;
814 1056
815 // Create the AnalysisContext to resynthesize elements in. 1057 // Create the AnalysisContext to resynthesize elements in.
816 LibraryContext libraryContext = _createLibraryContext(library); 1058 LibraryContext libraryContext = _createLibraryContext(library);
817 1059
818 // Resynthesize the CompilationUnitElement in the context. 1060 // Resynthesize the CompilationUnitElement in the context.
819 try { 1061 try {
820 CompilationUnitElement element = 1062 CompilationUnitElement element =
821 libraryContext.computeUnitElement(library.source, file.source); 1063 libraryContext.computeUnitElement(library.source, file.source);
822 String signature = library.transitiveSignature; 1064 String signature = library.transitiveSignature;
(...skipping 10 matching lines...) Expand all
833 } 1075 }
834 1076
835 /** 1077 /**
836 * Creates a new [FileTracker] object and stores it in [_fileTracker]. 1078 * Creates a new [FileTracker] object and stores it in [_fileTracker].
837 * 1079 *
838 * This is used both on initial construction and whenever the configuration 1080 * This is used both on initial construction and whenever the configuration
839 * changes. 1081 * changes.
840 */ 1082 */
841 void _createFileTracker(PerformanceLog logger) { 1083 void _createFileTracker(PerformanceLog logger) {
842 _fillSalt(); 1084 _fillSalt();
843 _fileTracker = new FileTracker(logger, _byteStore, _contentOverlay, 1085 _fileTracker = new FileTracker(
844 _resourceProvider, sourceFactory, _analysisOptions, _salt, _changeHook); 1086 logger,
1087 _byteStore,
1088 _contentOverlay,
1089 _resourceProvider,
1090 sourceFactory,
1091 _analysisOptions,
1092 _salt,
1093 externalSummaries,
1094 _changeHook);
845 } 1095 }
846 1096
847 /** 1097 /**
848 * Return the context in which the [library] should be analyzed. 1098 * Return the context in which the [library] should be analyzed.
849 */ 1099 */
850 LibraryContext _createLibraryContext(FileState library) => 1100 LibraryContext _createLibraryContext(FileState library) =>
851 new LibraryContext.forSingleLibrary( 1101 new LibraryContext.forSingleLibrary(
852 library, 1102 library,
853 _logger, 1103 _logger,
854 _sdkBundle, 1104 _sdkBundle,
855 _byteStore, 1105 _byteStore,
856 _analysisOptions, 1106 _analysisOptions,
857 declaredVariables, 1107 declaredVariables,
858 _sourceFactory, 1108 _sourceFactory,
1109 externalSummaries,
859 _fileTracker); 1110 _fileTracker);
860 1111
861 /** 1112 /**
862 * Fill [_salt] with data. 1113 * Fill [_salt] with data.
863 */ 1114 */
864 void _fillSalt() { 1115 void _fillSalt() {
865 _salt[0] = DATA_VERSION; 1116 _salt[0] = DATA_VERSION;
866 List<int> crossContextOptions = _analysisOptions.signature; 1117 List<int> crossContextOptions = _analysisOptions.signature;
867 assert(crossContextOptions.length == AnalysisOptions.signatureLength); 1118 assert(crossContextOptions.length == AnalysisOptions.signatureLength);
868 for (int i = 0; i < crossContextOptions.length; i++) { 1119 for (int i = 0; i < crossContextOptions.length; i++) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 * in the [library], e.g. element model, errors, index, etc. 1177 * in the [library], e.g. element model, errors, index, etc.
927 */ 1178 */
928 String _getResolvedUnitSignature(FileState library, FileState file) { 1179 String _getResolvedUnitSignature(FileState library, FileState file) {
929 ApiSignature signature = new ApiSignature(); 1180 ApiSignature signature = new ApiSignature();
930 signature.addUint32List(_salt); 1181 signature.addUint32List(_salt);
931 signature.addString(library.transitiveSignature); 1182 signature.addString(library.transitiveSignature);
932 signature.addString(file.contentHash); 1183 signature.addString(file.contentHash);
933 return signature.toHex(); 1184 return signature.toHex();
934 } 1185 }
935 1186
936 ApiSignature getUnitKeyByPath(String path) {
937 var file = fsState.getFileForPath(path);
938 ApiSignature signature = new ApiSignature();
939 signature.addUint32List(_salt);
940 signature.addString(file.transitiveSignature);
941 return signature;
942 }
943
944 ApiSignature getResolvedUnitKeyByPath(String path) {
945 ApiSignature signature = getUnitKeyByPath(path);
946 var file = fsState.getFileForPath(path);
947 signature.addString(file.contentHash);
948 return signature;
949 }
950
951 /** 1187 /**
952 * Return the lint code with the given [errorName], or `null` if there is no 1188 * Return the lint code with the given [errorName], or `null` if there is no
953 * lint registered with that name or the lint is not enabled in the analysis 1189 * lint registered with that name or the lint is not enabled in the analysis
954 * options. 1190 * options.
955 */ 1191 */
956 ErrorCode _lintCodeByUniqueName(String errorName) { 1192 ErrorCode _lintCodeByUniqueName(String errorName) {
957 if (errorName.startsWith('_LintCode.')) { 1193 if (errorName.startsWith('_LintCode.')) {
958 String lintName = errorName.substring(10); 1194 String lintName = errorName.substring(10);
959 List<Linter> lintRules = _analysisOptions.lintRules; 1195 List<Linter> lintRules = _analysisOptions.lintRules;
960 for (Linter linter in lintRules) { 1196 for (Linter linter in lintRules) {
961 if (linter.name == lintName) { 1197 if (linter.name == lintName) {
962 return linter.lintCode; 1198 return linter.lintCode;
963 } 1199 }
964 } 1200 }
965 } 1201 }
966 return null; 1202 return null;
967 } 1203 }
968 1204
969 /**
970 * Perform a single chunk of work and produce [results].
971 */
972 Future<Null> performWork() async {
973 if (_fileTracker.verifyChangedFilesIfNeeded()) {
974 return;
975 }
976
977 // Analyze a requested file.
978 if (_requestedFiles.isNotEmpty) {
979 String path = _requestedFiles.keys.first;
980 try {
981 AnalysisResult result = _computeAnalysisResult(path, withUnit: true);
982 // If a part without a library, delay its analysis.
983 if (result == null) {
984 _requestedParts
985 .putIfAbsent(path, () => [])
986 .addAll(_requestedFiles.remove(path));
987 return;
988 }
989 // Notify the completers.
990 _requestedFiles.remove(path).forEach((completer) {
991 completer.complete(result);
992 });
993 // Remove from to be analyzed and produce it now.
994 _fileTracker.fileWasAnalyzed(path);
995 _resultController.add(result);
996 } catch (exception, stackTrace) {
997 _fileTracker.fileWasAnalyzed(path);
998 _requestedFiles.remove(path).forEach((completer) {
999 completer.completeError(exception, stackTrace);
1000 });
1001 }
1002 return;
1003 }
1004
1005 // Process an index request.
1006 if (_indexRequestedFiles.isNotEmpty) {
1007 String path = _indexRequestedFiles.keys.first;
1008 AnalysisDriverUnitIndex index = _computeIndex(path);
1009 _indexRequestedFiles.remove(path).forEach((completer) {
1010 completer.complete(index);
1011 });
1012 return;
1013 }
1014
1015 // Process a unit element key request.
1016 if (_unitElementSignatureRequests.isNotEmpty) {
1017 String path = _unitElementSignatureRequests.keys.first;
1018 String signature = _computeUnitElementSignature(path);
1019 _unitElementSignatureRequests.remove(path).forEach((completer) {
1020 completer.complete(signature);
1021 });
1022 return;
1023 }
1024
1025 // Process a unit element request.
1026 if (_unitElementRequestedFiles.isNotEmpty) {
1027 String path = _unitElementRequestedFiles.keys.first;
1028 UnitElementResult result = _computeUnitElement(path);
1029 _unitElementRequestedFiles.remove(path).forEach((completer) {
1030 completer.complete(result);
1031 });
1032 return;
1033 }
1034
1035 // Compute files defining a name.
1036 if (_definingClassMemberNameTasks.isNotEmpty) {
1037 _FilesDefiningClassMemberNameTask task =
1038 _definingClassMemberNameTasks.first;
1039 bool isDone = await task.perform();
1040 if (isDone) {
1041 _definingClassMemberNameTasks.remove(task);
1042 }
1043 return;
1044 }
1045
1046 // Compute files referencing a name.
1047 if (_referencingNameTasks.isNotEmpty) {
1048 _FilesReferencingNameTask task = _referencingNameTasks.first;
1049 bool isDone = await task.perform();
1050 if (isDone) {
1051 _referencingNameTasks.remove(task);
1052 }
1053 return;
1054 }
1055
1056 // Compute top-level declarations.
1057 if (_topLevelNameDeclarationsTasks.isNotEmpty) {
1058 _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
1059 bool isDone = await task.perform();
1060 if (isDone) {
1061 _topLevelNameDeclarationsTasks.remove(task);
1062 }
1063 return;
1064 }
1065
1066 // Analyze a priority file.
1067 if (_priorityFiles.isNotEmpty) {
1068 for (String path in _priorityFiles) {
1069 if (_fileTracker.isFilePending(path)) {
1070 try {
1071 AnalysisResult result =
1072 _computeAnalysisResult(path, withUnit: true);
1073 if (result == null) {
1074 _partsToAnalyze.add(path);
1075 } else {
1076 _resultController.add(result);
1077 }
1078 } catch (exception, stackTrace) {
1079 _reportException(path, exception, stackTrace);
1080 } finally {
1081 _fileTracker.fileWasAnalyzed(path);
1082 }
1083 return;
1084 }
1085 }
1086 }
1087
1088 // Analyze a general file.
1089 if (_fileTracker.hasPendingFiles) {
1090 String path = _fileTracker.anyPendingFile;
1091 try {
1092 AnalysisResult result = _computeAnalysisResult(path,
1093 withUnit: false, skipIfSameSignature: true);
1094 if (result == null) {
1095 _partsToAnalyze.add(path);
1096 } else if (result == AnalysisResult._UNCHANGED) {
1097 // We found that the set of errors is the same as we produced the
1098 // last time, so we don't need to produce it again now.
1099 } else {
1100 _resultController.add(result);
1101 _lastProducedSignatures[result.path] = result._signature;
1102 }
1103 } catch (exception, stackTrace) {
1104 _reportException(path, exception, stackTrace);
1105 } finally {
1106 _fileTracker.fileWasAnalyzed(path);
1107 }
1108 return;
1109 }
1110
1111 // Analyze a requested part file.
1112 if (_requestedParts.isNotEmpty) {
1113 String path = _requestedParts.keys.first;
1114 try {
1115 AnalysisResult result = _computeAnalysisResult(path,
1116 withUnit: true, asIsIfPartWithoutLibrary: true);
1117 // Notify the completers.
1118 _requestedParts.remove(path).forEach((completer) {
1119 completer.complete(result);
1120 });
1121 // Remove from to be analyzed and produce it now.
1122 _partsToAnalyze.remove(path);
1123 _resultController.add(result);
1124 } catch (exception, stackTrace) {
1125 _partsToAnalyze.remove(path);
1126 _requestedParts.remove(path).forEach((completer) {
1127 completer.completeError(exception, stackTrace);
1128 });
1129 }
1130 return;
1131 }
1132
1133 // Analyze a general part.
1134 if (_partsToAnalyze.isNotEmpty) {
1135 String path = _partsToAnalyze.first;
1136 _partsToAnalyze.remove(path);
1137 try {
1138 AnalysisResult result = _computeAnalysisResult(path,
1139 withUnit: _priorityFiles.contains(path),
1140 asIsIfPartWithoutLibrary: true);
1141 _resultController.add(result);
1142 } catch (exception, stackTrace) {
1143 _reportException(path, exception, stackTrace);
1144 }
1145 return;
1146 }
1147 }
1148
1149 void _reportException(String path, exception, StackTrace stackTrace) { 1205 void _reportException(String path, exception, StackTrace stackTrace) {
1150 String contextKey = null; 1206 String contextKey = null;
1151 if (exception is _ExceptionState) { 1207 if (exception is _ExceptionState) {
1152 var state = exception as _ExceptionState; 1208 var state = exception as _ExceptionState;
1153 exception = state.exception; 1209 exception = state.exception;
1154 stackTrace = state.stackTrace; 1210 stackTrace = state.stackTrace;
1155 contextKey = state.contextKey; 1211 contextKey = state.contextKey;
1156 } 1212 }
1157 CaughtException caught = new CaughtException(exception, stackTrace); 1213 CaughtException caught = new CaughtException(exception, stackTrace);
1158 _exceptionController.add(new ExceptionResult(path, caught, contextKey)); 1214 _exceptionController.add(new ExceptionResult(path, caught, contextKey));
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 bool get _hasFilesToAnalyze { 1353 bool get _hasFilesToAnalyze {
1298 for (AnalysisDriverGeneric driver in _drivers) { 1354 for (AnalysisDriverGeneric driver in _drivers) {
1299 if (driver.hasFilesToAnalyze) { 1355 if (driver.hasFilesToAnalyze) {
1300 return true; 1356 return true;
1301 } 1357 }
1302 } 1358 }
1303 return false; 1359 return false;
1304 } 1360 }
1305 1361
1306 /** 1362 /**
1363 * Add the given [driver] and schedule it to perform its work.
1364 */
1365 void add(AnalysisDriverGeneric driver) {
1366 _drivers.add(driver);
1367 _hasWork.notify();
1368 }
1369
1370 /**
1307 * Notify that there is a change to the [driver], it it might need to 1371 * Notify that there is a change to the [driver], it it might need to
1308 * perform some work. 1372 * perform some work.
1309 */ 1373 */
1310 void notify(AnalysisDriverGeneric driver) { 1374 void notify(AnalysisDriverGeneric driver) {
1311 _hasWork.notify(); 1375 _hasWork.notify();
1312 _statusSupport.preTransitionToAnalyzing(); 1376 _statusSupport.preTransitionToAnalyzing();
1313 } 1377 }
1314 1378
1315 /** 1379 /**
1316 * Start the scheduler, so that any [AnalysisDriver] created before or 1380 * Start the scheduler, so that any [AnalysisDriver] created before or
1317 * after will be asked to perform work. 1381 * after will be asked to perform work.
1318 */ 1382 */
1319 void start() { 1383 void start() {
1320 if (_started) { 1384 if (_started) {
1321 throw new StateError('The scheduler has already been started.'); 1385 throw new StateError('The scheduler has already been started.');
1322 } 1386 }
1323 _started = true; 1387 _started = true;
1324 _run(); 1388 _run();
1325 } 1389 }
1326 1390
1327 /** 1391 /**
1328 * Return a future that will be completed the next time the status is idle. 1392 * Return a future that will be completed the next time the status is idle.
1329 * 1393 *
1330 * If the status is currently idle, the returned future will be signaled 1394 * If the status is currently idle, the returned future will be signaled
1331 * immediately. 1395 * immediately.
1332 */ 1396 */
1333 Future<Null> waitForIdle() => _statusSupport.waitForIdle(); 1397 Future<Null> waitForIdle() => _statusSupport.waitForIdle();
1334 1398
1335 /** 1399 /**
1336 * Add the given [driver] and schedule it to perform its work.
1337 */
1338 void add(AnalysisDriverGeneric driver) {
1339 _drivers.add(driver);
1340 _hasWork.notify();
1341 }
1342
1343 /**
1344 * Remove the given [driver] from the scheduler, so that it will not be 1400 * Remove the given [driver] from the scheduler, so that it will not be
1345 * asked to perform any new work. 1401 * asked to perform any new work.
1346 */ 1402 */
1347 void _remove(AnalysisDriverGeneric driver) { 1403 void _remove(AnalysisDriverGeneric driver) {
1348 _drivers.remove(driver); 1404 _drivers.remove(driver);
1349 _hasWork.notify(); 1405 _hasWork.notify();
1350 } 1406 }
1351 1407
1352 /** 1408 /**
1353 * Run infinitely analysis cycle, selecting the drivers with the highest 1409 * Run infinitely analysis cycle, selecting the drivers with the highest
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
1928 libraryDeclarations.add(new TopLevelDeclarationInSource( 1984 libraryDeclarations.add(new TopLevelDeclarationInSource(
1929 file.source, declaration, isExported)); 1985 file.source, declaration, isExported));
1930 } 1986 }
1931 } 1987 }
1932 } 1988 }
1933 1989
1934 // We're not done yet. 1990 // We're not done yet.
1935 return false; 1991 return false;
1936 } 1992 }
1937 } 1993 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/dart/analysis/file_state.dart » ('j') | pkg/dev_compiler/lib/src/compiler/compiler.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698