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

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

Issue 2808173002: Prioritize analysis of files that import the changed file, or have an error or warning. (Closed)
Patch Set: Use separate buckets for each file category. Created 3 years, 8 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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:collection'; 5 import 'dart:collection';
6 import 'dart:typed_data'; 6 import 'dart:typed_data';
7 7
8 import 'package:analyzer/file_system/file_system.dart'; 8 import 'package:analyzer/file_system/file_system.dart';
9 import 'package:analyzer/src/dart/analysis/byte_store.dart'; 9 import 'package:analyzer/src/dart/analysis/byte_store.dart';
10 import 'package:analyzer/src/dart/analysis/driver.dart'; 10 import 'package:analyzer/src/dart/analysis/driver.dart';
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 */ 52 */
53 final addedFiles = new LinkedHashSet<String>(); 53 final addedFiles = new LinkedHashSet<String>();
54 54
55 /** 55 /**
56 * The set of files were reported as changed through [changeFile] and not 56 * The set of files were reported as changed through [changeFile] and not
57 * checked for actual changes yet. 57 * checked for actual changes yet.
58 */ 58 */
59 final _changedFiles = new LinkedHashSet<String>(); 59 final _changedFiles = new LinkedHashSet<String>();
60 60
61 /** 61 /**
62 * The set of files that are currently scheduled for analysis. 62 * The set of files that are currently scheduled for analysis, which were
63 * reported as changed through [changeFile].
63 */ 64 */
64 final _pendingFiles = new LinkedHashSet<String>(); 65 var _pendingChangedFiles = new LinkedHashSet<String>();
66
67 /**
68 * The set of files that are currently scheduled for analysis, which directly
69 * import a changed file.
70 */
71 var _pendingImportFiles = new LinkedHashSet<String>();
72
73 /**
74 * The set of files that are currently scheduled for analysis, which have an
75 * error or a warning, which might be fixed by a changed file.
76 */
77 var _pendingErrorFiles = new LinkedHashSet<String>();
78
79 /**
80 * The set of files that are currently scheduled for analysis, and don't
81 * have any special relation with changed files.
82 */
83 var _pendingFiles = new LinkedHashSet<String>();
65 84
66 FileTracker( 85 FileTracker(
67 this.logger, 86 this.logger,
68 ByteStore byteStore, 87 ByteStore byteStore,
69 FileContentOverlay contentOverlay, 88 FileContentOverlay contentOverlay,
70 ResourceProvider resourceProvider, 89 ResourceProvider resourceProvider,
71 SourceFactory sourceFactory, 90 SourceFactory sourceFactory,
72 AnalysisOptions analysisOptions, 91 AnalysisOptions analysisOptions,
73 Uint32List salt, 92 Uint32List salt,
74 this._changeHook) 93 this._changeHook)
75 : fsState = new FileSystemState(logger, byteStore, contentOverlay, 94 : fsState = new FileSystemState(logger, byteStore, contentOverlay,
76 resourceProvider, sourceFactory, analysisOptions, salt); 95 resourceProvider, sourceFactory, analysisOptions, salt);
77 96
78 /** 97 /**
79 * Returns the path to exactly one that needs analysis. Throws a [StateError] 98 * Returns the path to exactly one that needs analysis. Throws a [StateError]
80 * if no files need analysis. 99 * if no files need analysis.
81 */ 100 */
82 String get anyPendingFile => _pendingFiles.first; 101 String get anyPendingFile {
102 if (_pendingChangedFiles.isNotEmpty) {
103 return _pendingChangedFiles.first;
104 }
105 if (_pendingImportFiles.isNotEmpty) {
106 return _pendingImportFiles.first;
107 }
108 if (_pendingErrorFiles.isNotEmpty) {
109 return _pendingErrorFiles.first;
110 }
111 return _pendingFiles.first;
112 }
83 113
84 /** 114 /**
85 * Returns a boolean indicating whether there are any files that have changed, 115 * Returns a boolean indicating whether there are any files that have changed,
86 * but for which the impact of the changes hasn't been measured. 116 * but for which the impact of the changes hasn't been measured.
87 */ 117 */
88 bool get hasChangedFiles => _changedFiles.isNotEmpty; 118 bool get hasChangedFiles => _changedFiles.isNotEmpty;
89 119
90 /** 120 /**
121 * Return `true` if there are changed files that need analysis.
122 */
123 bool get hasPendingChangedFiles => _pendingChangedFiles.isNotEmpty;
124
125 /**
126 * Return `true` if there are files that have an error or warning, and that
127 * need analysis.
128 */
129 bool get hasPendingErrorFiles => _pendingErrorFiles.isNotEmpty;
130
131 /**
91 * Returns a boolean indicating whether there are any files that need 132 * Returns a boolean indicating whether there are any files that need
92 * analysis. 133 * analysis.
93 */ 134 */
94 bool get hasPendingFiles => _pendingFiles.isNotEmpty; 135 bool get hasPendingFiles {
136 return hasPendingChangedFiles ||
137 hasPendingImportFiles ||
138 hasPendingErrorFiles ||
139 _pendingFiles.isNotEmpty;
140 }
141
142 /**
143 * Return `true` if there are files that directly import a changed file that
144 * need analysis.
145 */
146 bool get hasPendingImportFiles => _pendingImportFiles.isNotEmpty;
95 147
96 /** 148 /**
97 * Returns a count of how many files need analysis. 149 * Returns a count of how many files need analysis.
98 */ 150 */
99 int get numberOfPendingFiles => _pendingFiles.length; 151 int get numberOfPendingFiles {
152 return _pendingChangedFiles.length +
153 _pendingImportFiles.length +
154 _pendingErrorFiles.length +
155 _pendingFiles.length;
156 }
100 157
101 /** 158 /**
102 * Adds the given [path] to the set of "added files". 159 * Adds the given [path] to the set of "added files".
103 */ 160 */
104 void addFile(String path) { 161 void addFile(String path) {
105 addedFiles.add(path); 162 addedFiles.add(path);
106 _pendingFiles.add(path); 163 _pendingFiles.add(path);
107 _changeHook(); 164 _changeHook();
108 } 165 }
109 166
110 /** 167 /**
111 * Adds the given [paths] to the set of "added files". 168 * Adds the given [paths] to the set of "added files".
112 */ 169 */
113 void addFiles(Iterable<String> paths) { 170 void addFiles(Iterable<String> paths) {
114 addedFiles.addAll(paths); 171 addedFiles.addAll(paths);
115 _pendingFiles.addAll(paths); 172 _pendingFiles.addAll(paths);
116 _changeHook(); 173 _changeHook();
117 } 174 }
118 175
119 /** 176 /**
120 * Adds the given [path] to the set of "changed files". 177 * Adds the given [path] to the set of "changed files".
121 */ 178 */
122 void changeFile(String path) { 179 void changeFile(String path) {
123 _changedFiles.add(path); 180 _changedFiles.add(path);
124 if (addedFiles.contains(path)) { 181 if (addedFiles.contains(path)) {
125 _pendingFiles.add(path); 182 _pendingChangedFiles.add(path);
126 } 183 }
127 _changeHook(); 184 _changeHook();
128 } 185 }
129 186
130 /** 187 /**
131 * Removes the given [path] from the set of "pending files". 188 * Removes the given [path] from the set of "pending files".
132 * 189 *
133 * Should be called after the client has analyzed a file. 190 * Should be called after the client has analyzed a file.
134 */ 191 */
135 void fileWasAnalyzed(String path) { 192 void fileWasAnalyzed(String path) {
193 _pendingChangedFiles.remove(path);
194 _pendingImportFiles.remove(path);
195 _pendingErrorFiles.remove(path);
136 _pendingFiles.remove(path); 196 _pendingFiles.remove(path);
137 } 197 }
138 198
139 /** 199 /**
140 * Returns a boolean indicating whether the given [path] points to a file that 200 * Returns a boolean indicating whether the given [path] points to a file that
141 * requires analysis. 201 * requires analysis.
142 */ 202 */
143 bool isFilePending(String path) => _pendingFiles.contains(path); 203 bool isFilePending(String path) {
204 return _pendingChangedFiles.contains(path) ||
205 _pendingImportFiles.contains(path) ||
206 _pendingErrorFiles.contains(path) ||
207 _pendingFiles.contains(path);
208 }
144 209
145 /** 210 /**
146 * Removes the given [path] from the set of "added files". 211 * Removes the given [path] from the set of "added files".
147 */ 212 */
148 void removeFile(String path) { 213 void removeFile(String path) {
149 addedFiles.remove(path); 214 addedFiles.remove(path);
215 _pendingChangedFiles.remove(path);
216 _pendingImportFiles.remove(path);
217 _pendingErrorFiles.remove(path);
150 _pendingFiles.remove(path); 218 _pendingFiles.remove(path);
151 // TODO(paulberry): removing the path from [fsState] and re-analyzing all 219 // TODO(paulberry): removing the path from [fsState] and re-analyzing all
152 // files seems extreme. 220 // files seems extreme.
153 fsState.removeFile(path); 221 fsState.removeFile(path);
154 _pendingFiles.addAll(addedFiles); 222 _pendingFiles.addAll(addedFiles);
155 _changeHook(); 223 _changeHook();
156 } 224 }
157 225
158 /** 226 /**
159 * Verify the API signature for the file with the given [path], and decide 227 * Verify the API signature for the file with the given [path], and decide
160 * which linked libraries should be invalidated, and files reanalyzed. 228 * which linked libraries should be invalidated, and files reanalyzed.
161 */ 229 */
162 FileState verifyApiSignature(String path) { 230 FileState verifyApiSignature(String path) {
163 return logger.run('Verify API signature of $path', () { 231 return logger.run('Verify API signature of $path', () {
164 bool anyApiChanged = false; 232 bool anyApiChanged = false;
165 List<FileState> files = fsState.getFilesForPath(path); 233 List<FileState> files = fsState.getFilesForPath(path);
166 for (FileState file in files) { 234 for (FileState file in files) {
167 bool apiChanged = file.refresh(); 235 bool apiChanged = file.refresh();
168 if (apiChanged) { 236 if (apiChanged) {
169 anyApiChanged = true; 237 anyApiChanged = true;
170 } 238 }
171 } 239 }
172 if (anyApiChanged) { 240 if (anyApiChanged) {
173 logger.writeln('API signatures mismatch found for $path'); 241 logger.writeln('API signatures mismatch found for $path');
174 // TODO(scheglov) schedule analysis of only affected files 242 // TODO(scheglov) schedule analysis of only affected files
175 _pendingFiles.addAll(addedFiles); 243 var pendingChangedFiles = new LinkedHashSet<String>();
244 var pendingImportFiles = new LinkedHashSet<String>();
245 var pendingErrorFiles = new LinkedHashSet<String>();
246 var pendingFiles = new LinkedHashSet<String>();
247
248 // Add the changed file.
249 if (addedFiles.contains(path)) {
250 pendingChangedFiles.add(path);
251 }
252
253 // Add files that directly import the changed file.
254 for (String addedPath in addedFiles) {
255 FileState addedFile = fsState.getFileForPath(addedPath);
256 for (FileState changedFile in files) {
257 if (addedFile.importedFiles.contains(changedFile)) {
258 pendingImportFiles.add(addedPath);
259 }
260 }
261 }
262
263 // Add files with errors or warnings that might be fixed.
264 for (String addedPath in addedFiles) {
265 FileState addedFile = fsState.getFileForPath(addedPath);
266 if (addedFile.hasErrorOrWarning) {
267 pendingErrorFiles.add(addedPath);
268 }
269 }
270
271 // Add all previous pending files.
272 pendingChangedFiles.addAll(_pendingChangedFiles);
273 pendingImportFiles.addAll(_pendingImportFiles);
274 pendingErrorFiles.addAll(_pendingErrorFiles);
275 pendingFiles.addAll(_pendingFiles);
276
277 // Add all the rest.
278 pendingFiles.addAll(addedFiles);
279
280 // Replace pending files.
281 _pendingChangedFiles = pendingChangedFiles;
282 _pendingImportFiles = pendingImportFiles;
283 _pendingErrorFiles = pendingErrorFiles;
284 _pendingFiles = pendingFiles;
176 } 285 }
177 return files[0]; 286 return files[0];
178 }); 287 });
179 } 288 }
180 289
181 /** 290 /**
182 * If at least one file is in the "changed files" set, determines the impact 291 * If at least one file is in the "changed files" set, determines the impact
183 * of the change, updates the set of pending files, and returns `true`. 292 * of the change, updates the set of pending files, and returns `true`.
184 * 293 *
185 * If no files are in the "changed files" set, returns `false`. 294 * If no files are in the "changed files" set, returns `false`.
186 */ 295 */
187 bool verifyChangedFilesIfNeeded() { 296 bool verifyChangedFilesIfNeeded() {
188 // Verify all changed files one at a time. 297 // Verify all changed files one at a time.
189 if (_changedFiles.isNotEmpty) { 298 if (_changedFiles.isNotEmpty) {
190 String path = _changedFiles.first; 299 String path = _changedFiles.first;
191 _changedFiles.remove(path); 300 _changedFiles.remove(path);
192 // If the file has not been accessed yet, we either will eventually read 301 // If the file has not been accessed yet, we either will eventually read
193 // it later while analyzing one of the added files, or don't need it. 302 // it later while analyzing one of the added files, or don't need it.
194 if (fsState.knownFilePaths.contains(path)) { 303 if (fsState.knownFilePaths.contains(path)) {
195 verifyApiSignature(path); 304 verifyApiSignature(path);
196 } 305 }
197 return true; 306 return true;
198 } 307 }
199 return false; 308 return false;
200 } 309 }
201 } 310 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/analysis/file_state.dart ('k') | pkg/analyzer/test/src/dart/analysis/driver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698