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 library analyzer_cli.src.incremental_analyzer; | 5 library analyzer_cli.src.incremental_analyzer; |
6 | 6 |
7 import 'dart:io' as io; | 7 import 'dart:io' as io; |
8 | 8 |
9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
10 import 'package:analyzer/file_system/physical_file_system.dart'; | 10 import 'package:analyzer/file_system/physical_file_system.dart'; |
11 import 'package:analyzer/src/context/cache.dart'; | 11 import 'package:analyzer/src/context/cache.dart'; |
12 import 'package:analyzer/src/context/context.dart'; | 12 import 'package:analyzer/src/context/context.dart'; |
13 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
14 import 'package:analyzer/src/generated/error.dart'; | 14 import 'package:analyzer/src/generated/error.dart'; |
15 import 'package:analyzer/src/generated/sdk.dart'; | 15 import 'package:analyzer/src/generated/sdk.dart'; |
16 import 'package:analyzer/src/generated/sdk_io.dart'; | 16 import 'package:analyzer/src/generated/sdk_io.dart'; |
17 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
18 import 'package:analyzer/src/summary/incremental_cache.dart'; | 18 import 'package:analyzer/src/summary/incremental_cache.dart'; |
19 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 19 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
20 import 'package:analyzer/src/task/dart.dart'; | 20 import 'package:analyzer/src/task/dart.dart'; |
21 import 'package:analyzer/task/dart.dart'; | 21 import 'package:analyzer/task/dart.dart'; |
| 22 import 'package:analyzer/task/general.dart'; |
22 import 'package:analyzer/task/model.dart'; | 23 import 'package:analyzer/task/model.dart'; |
23 import 'package:analyzer_cli/src/options.dart'; | 24 import 'package:analyzer_cli/src/options.dart'; |
24 | 25 |
25 /** | 26 /** |
26 * If the given [options] enables incremental analysis and [context] and Dart | 27 * If the given [options] enables incremental analysis and [context] and Dart |
27 * SDK implementations support incremental analysis, configure it for the | 28 * SDK implementations support incremental analysis, configure it for the |
28 * given [context] and return the handle to work with it. | 29 * given [context] and return the handle to work with it. |
29 */ | 30 */ |
30 IncrementalAnalysisSession configureIncrementalAnalysis( | 31 IncrementalAnalysisSession configureIncrementalAnalysis( |
31 CommandLineOptions options, AnalysisContext context) { | 32 CommandLineOptions options, AnalysisContext context) { |
32 String cachePath = options.incrementalCachePath; | 33 String cachePath = options.incrementalCachePath; |
33 DartSdk sdk = context.sourceFactory.dartSdk; | 34 DartSdk sdk = context.sourceFactory.dartSdk; |
34 // If supported implementations, configure for incremental analysis. | 35 // If supported implementations, configure for incremental analysis. |
35 if (cachePath != null && | 36 if (cachePath != null && |
36 context is InternalAnalysisContext && | 37 context is InternalAnalysisContext && |
37 sdk is DirectoryBasedDartSdk) { | 38 sdk is DirectoryBasedDartSdk) { |
38 context.typeProvider = sdk.context.typeProvider; | 39 context.typeProvider = sdk.context.typeProvider; |
39 // Set the result provide from the cache. | 40 // Set the result provide from the cache. |
40 CacheStorage storage = new FolderCacheStorage( | 41 CacheStorage storage = new FolderCacheStorage( |
41 PhysicalResourceProvider.INSTANCE.getFolder(cachePath), | 42 PhysicalResourceProvider.INSTANCE.getFolder(cachePath), |
42 '${io.pid}.temp'); | 43 '${io.pid}.temp'); |
43 List<int> configSalt = <int>[ | 44 List<int> configSalt = <int>[ |
44 context.analysisOptions.encodeCrossContextOptions() | 45 context.analysisOptions.encodeCrossContextOptions() |
45 ]; | 46 ]; |
46 IncrementalCache cache = new IncrementalCache(storage, context, configSalt); | 47 IncrementalCache cache = new IncrementalCache(storage, context, configSalt); |
47 context.resultProvider = new _CacheBasedResultProvider(context, cache); | 48 context.resultProvider = new _CacheBasedResultProvider(context, cache); |
48 // Listen for new libraries to put into the cache. | 49 // Listen for new libraries to put into the cache. |
49 _IncrementalAnalysisSession session = | 50 _IncrementalAnalysisSession session = |
50 new _IncrementalAnalysisSession(options, cache, context); | 51 new _IncrementalAnalysisSession(options, context, cache); |
51 context | 52 context |
52 .onResultChanged(LIBRARY_ELEMENT1) | 53 .onResultChanged(LIBRARY_ELEMENT1) |
53 .listen((ResultChangedEvent event) { | 54 .listen((ResultChangedEvent event) { |
54 if (event.wasComputed) { | 55 if (event.wasComputed) { |
55 session.librarySources.add(event.target.source); | 56 session.newLibrarySources.add(event.target.source); |
56 } | 57 } |
57 }); | 58 }); |
58 return session; | 59 return session; |
59 } | 60 } |
60 // Incremental analysis cannot be used. | 61 // Incremental analysis cannot be used. |
61 return null; | 62 return null; |
62 } | 63 } |
63 | 64 |
64 /** | 65 /** |
65 * Interface that is exposed to the clients of incremental analysis. | 66 * Interface that is exposed to the clients of incremental analysis. |
66 */ | 67 */ |
67 abstract class IncrementalAnalysisSession { | 68 abstract class IncrementalAnalysisSession { |
68 /** | 69 /** |
69 * Finish tasks required after incremental analysis - save results into the | 70 * Finish tasks required after incremental analysis - save results into the |
70 * cache, evict old results, etc. | 71 * cache, evict old results, etc. |
71 */ | 72 */ |
72 void finish(); | 73 void finish(); |
| 74 |
| 75 /** |
| 76 * Sets the set of [Source]s analyzed in the context, both explicit and |
| 77 * implicit, for which errors might be requested. This set is used to compute |
| 78 * containing libraries for every source in the context. |
| 79 */ |
| 80 void setAnalyzedSources(Iterable<Source> sources); |
73 } | 81 } |
74 | 82 |
75 /** | 83 /** |
76 * The [ResultProvider] that provides results from [IncrementalCache]. | 84 * The [ResultProvider] that provides results from [IncrementalCache]. |
77 */ | 85 */ |
78 class _CacheBasedResultProvider extends ResynthesizerResultProvider { | 86 class _CacheBasedResultProvider extends ResynthesizerResultProvider { |
79 final IncrementalCache cache; | 87 final IncrementalCache cache; |
80 | 88 |
81 final Set<Source> sourcesWithSummaries = new Set<Source>(); | 89 final Set<Source> sourcesWithSummaries = new Set<Source>(); |
82 final Set<Source> sourcesWithoutSummaries = new Set<Source>(); | 90 final Set<Source> sourcesWithoutSummaries = new Set<Source>(); |
83 final Set<String> addedLibraryBundleIds = new Set<String>(); | 91 final Set<String> addedLibraryBundleIds = new Set<String>(); |
84 | 92 |
85 _CacheBasedResultProvider(InternalAnalysisContext context, this.cache) | 93 _CacheBasedResultProvider(InternalAnalysisContext context, this.cache) |
86 : super(context, new SummaryDataStore(<String>[])) { | 94 : super(context, new SummaryDataStore(<String>[])) { |
87 AnalysisContext sdkContext = context.sourceFactory.dartSdk.context; | 95 AnalysisContext sdkContext = context.sourceFactory.dartSdk.context; |
88 createResynthesizer(sdkContext, sdkContext.typeProvider); | 96 createResynthesizer(sdkContext, sdkContext.typeProvider); |
89 } | 97 } |
90 | 98 |
91 @override | 99 @override |
92 bool compute(CacheEntry entry, ResultDescriptor result) { | 100 bool compute(CacheEntry entry, ResultDescriptor result) { |
93 AnalysisTarget target = entry.target; | 101 AnalysisTarget target = entry.target; |
94 // TODO(scheglov) remove the check after finishing optimizations. | |
95 if (target.source != null && | |
96 target.source.fullName | |
97 .endsWith('analysis_server/lib/src/computer/computer_hover.dart')) { | |
98 return false; | |
99 } | |
100 // Source based results. | 102 // Source based results. |
101 if (target is Source) { | 103 if (target is Source) { |
| 104 if (result == SOURCE_KIND) { |
| 105 SourceKind kind = cache.getSourceKind(target); |
| 106 if (kind != null) { |
| 107 entry.setValue(result, kind, TargetedResult.EMPTY_LIST); |
| 108 return true; |
| 109 } else { |
| 110 return false; |
| 111 } |
| 112 } |
102 if (result == INCLUDED_PARTS) { | 113 if (result == INCLUDED_PARTS) { |
103 List<Source> parts = cache.getLibraryParts(target); | 114 List<Source> parts = cache.getLibraryParts(target); |
104 if (parts != null) { | 115 if (parts != null) { |
105 entry.setValue(result, parts, TargetedResult.EMPTY_LIST); | 116 entry.setValue(result, parts, TargetedResult.EMPTY_LIST); |
106 return true; | 117 return true; |
107 } else { | 118 } else { |
108 return false; | 119 return false; |
109 } | 120 } |
110 } | 121 } |
111 if (result == DART_ERRORS) { | 122 if (result == DART_ERRORS) { |
112 // TODO(scheglov) provide actual errors | 123 List<Source> librarySources = context.getLibrariesContaining(target); |
113 entry.setValue(result, <AnalysisError>[], TargetedResult.EMPTY_LIST); | 124 List<List<AnalysisError>> errorList = <List<AnalysisError>>[]; |
| 125 for (Source librarySource in librarySources) { |
| 126 List<AnalysisError> errors = |
| 127 cache.getSourceErrorsInLibrary(librarySource, target); |
| 128 if (errors == null) { |
| 129 return false; |
| 130 } |
| 131 errorList.add(errors); |
| 132 } |
| 133 List<AnalysisError> mergedErrors = AnalysisError.mergeLists(errorList); |
| 134 entry.setValue(result, mergedErrors, TargetedResult.EMPTY_LIST); |
114 return true; | 135 return true; |
115 } | 136 } |
116 } | 137 } |
117 return super.compute(entry, result); | 138 return super.compute(entry, result); |
118 } | 139 } |
119 | 140 |
120 @override | 141 @override |
121 bool hasResultsForSource(Source source) { | 142 bool hasResultsForSource(Source source) { |
122 // Check cache states. | 143 // Check cache states. |
123 if (sourcesWithSummaries.contains(source)) { | 144 if (sourcesWithSummaries.contains(source)) { |
(...skipping 14 matching lines...) Expand all Loading... |
138 if (addedLibraryBundleIds.add(bundleWithId.id)) { | 159 if (addedLibraryBundleIds.add(bundleWithId.id)) { |
139 addBundle(null, bundleWithId.bundle); | 160 addBundle(null, bundleWithId.bundle); |
140 } | 161 } |
141 } | 162 } |
142 return true; | 163 return true; |
143 } | 164 } |
144 } | 165 } |
145 | 166 |
146 class _IncrementalAnalysisSession implements IncrementalAnalysisSession { | 167 class _IncrementalAnalysisSession implements IncrementalAnalysisSession { |
147 final CommandLineOptions commandLineOptions; | 168 final CommandLineOptions commandLineOptions; |
| 169 final AnalysisContext context; |
148 final IncrementalCache cache; | 170 final IncrementalCache cache; |
149 final AnalysisContext context; | |
150 | 171 |
151 final Set<Source> librarySources = new Set<Source>(); | 172 final Set<Source> newLibrarySources = new Set<Source>(); |
152 | 173 |
153 _IncrementalAnalysisSession( | 174 _IncrementalAnalysisSession( |
154 this.commandLineOptions, this.cache, this.context); | 175 this.commandLineOptions, this.context, this.cache); |
155 | 176 |
156 @override | 177 @override |
157 void finish() { | 178 void finish() { |
158 // Finish computing new libraries and put them into the cache. | 179 // Finish computing new libraries and put them into the cache. |
159 for (Source librarySource in librarySources) { | 180 for (Source librarySource in newLibrarySources) { |
160 if (!commandLineOptions.machineFormat) { | 181 if (!commandLineOptions.machineFormat) { |
161 print('Compute library element for $librarySource'); | 182 print('Compute library element for $librarySource'); |
162 } | 183 } |
163 LibraryElement libraryElement = | 184 _putLibrary(librarySource); |
164 context.computeResult(librarySource, LIBRARY_ELEMENT); | 185 } |
165 // TODO(scheglov) compute and store errors | 186 } |
166 // context.computeResult(librarySource, DART_ERRORS); | 187 |
167 try { | 188 @override |
168 cache.putLibrary(libraryElement); | 189 void setAnalyzedSources(Iterable<Source> sources) { |
169 } catch (e) {} | 190 for (Source source in sources) { |
| 191 SourceKind kind = context.computeKindOf(source); |
| 192 if (kind == SourceKind.LIBRARY) { |
| 193 context.computeResult(source, LINE_INFO); |
| 194 context.computeResult(source, INCLUDED_PARTS); |
| 195 } |
| 196 } |
| 197 } |
| 198 |
| 199 void _putLibrary(Source librarySource) { |
| 200 LibraryElement libraryElement = |
| 201 context.computeResult(librarySource, LIBRARY_ELEMENT); |
| 202 try { |
| 203 cache.putLibrary(libraryElement); |
| 204 } catch (e) { |
| 205 return; |
| 206 } |
| 207 // Write errors for the library units. |
| 208 for (CompilationUnitElement unit in libraryElement.units) { |
| 209 Source unitSource = unit.source; |
| 210 List<AnalysisError> errors = context.computeResult( |
| 211 new LibrarySpecificUnit(librarySource, unitSource), |
| 212 LIBRARY_UNIT_ERRORS); |
| 213 cache.putSourceErrorsInLibrary(librarySource, unitSource, errors); |
170 } | 214 } |
171 } | 215 } |
172 } | 216 } |
OLD | NEW |