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

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

Issue 2450143003: Add the 'status' stream and transitions. (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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:convert'; 7 import 'dart:convert';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 /** 159 /**
160 * Mapping from library URIs to the dependency signature of the library. 160 * Mapping from library URIs to the dependency signature of the library.
161 */ 161 */
162 final _dependencySignatureMap = <Uri, String>{}; 162 final _dependencySignatureMap = <Uri, String>{};
163 163
164 /** 164 /**
165 * The monitor that is signalled when there is work to do. 165 * The monitor that is signalled when there is work to do.
166 */ 166 */
167 final _Monitor _hasWork = new _Monitor(); 167 final _Monitor _hasWork = new _Monitor();
168 168
169 /**
170 * The controller for the [status] stream.
171 */
172 final _statusController = new StreamController<AnalysisStatus>();
173
174 /**
175 * The last status sent to the [status] stream.
176 */
177 AnalysisStatus _currentStatus = AnalysisStatus.IDLE;
178
169 AnalysisDriver(this._logger, this._resourceProvider, this._byteStore, 179 AnalysisDriver(this._logger, this._resourceProvider, this._byteStore,
170 this._contentCache, this._sourceFactory, this._analysisOptions) { 180 this._contentCache, this._sourceFactory, this._analysisOptions) {
171 _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle(); 181 _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle();
172 } 182 }
173 183
174 /** 184 /**
175 * Set the list of files that the driver should try to analyze sooner. 185 * Set the list of files that the driver should try to analyze sooner.
176 * 186 *
177 * Every path in the list must be absolute and normalized. 187 * Every path in the list must be absolute and normalized.
178 * 188 *
179 * The driver will produce the results through the [results] stream. The 189 * The driver will produce the results through the [results] stream. The
180 * exact order in which results are produced is not defined, neither 190 * exact order in which results are produced is not defined, neither
181 * between priority files, nor between priority and non-priority files. 191 * between priority files, nor between priority and non-priority files.
182 */ 192 */
183 void set priorityFiles(List<String> priorityPaths) { 193 void set priorityFiles(List<String> priorityPaths) {
184 _priorityFiles.clear(); 194 _priorityFiles.clear();
185 _priorityFiles.addAll(priorityPaths); 195 _priorityFiles.addAll(priorityPaths);
196 _transitionToAnalyzing();
186 _hasWork.notify(); 197 _hasWork.notify();
187 } 198 }
188 199
189 /** 200 /**
190 * Return the [Stream] that produces [AnalysisResult]s for added files. 201 * Return the [Stream] that produces [AnalysisResult]s for added files.
191 * 202 *
192 * Analysis starts when the client starts listening to the stream, and stops 203 * Analysis starts when the client starts listening to the stream, and stops
193 * when the client cancels the subscription. 204 * when the client cancels the subscription.
194 * 205 *
195 * When the client starts listening, the analysis state transitions to 206 * When the client starts listening, the analysis state transitions to
(...skipping 11 matching lines...) Expand all
207 * 218 *
208 * Results might be produced even for files that have never been added 219 * Results might be produced even for files that have never been added
209 * using [addFile], for example when [getResult] was called for a file. 220 * using [addFile], for example when [getResult] was called for a file.
210 */ 221 */
211 Stream<AnalysisResult> get results async* { 222 Stream<AnalysisResult> get results async* {
212 try { 223 try {
213 PerformanceLogSection analysisSection = null; 224 PerformanceLogSection analysisSection = null;
214 while (true) { 225 while (true) {
215 await _hasWork.signal; 226 await _hasWork.signal;
216 227
217 // TODO(scheglov) implement state transitioning
218 if (analysisSection == null) { 228 if (analysisSection == null) {
219 analysisSection = _logger.enter('Analyzing'); 229 analysisSection = _logger.enter('Analyzing');
220 } 230 }
221 231
222 // Verify all changed files one at a time. 232 // Verify all changed files one at a time.
223 if (_changedFiles.isNotEmpty) { 233 if (_changedFiles.isNotEmpty) {
224 String path = _removeFirst(_changedFiles); 234 String path = _removeFirst(_changedFiles);
225 _verifyApiSignatureOfChangedFile(path); 235 _verifyApiSignatureOfChangedFile(path);
226 // Repeat the processing loop. 236 // Repeat the processing loop.
227 _hasWork.notify(); 237 _hasWork.notify();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 AnalysisResult result = _computeAnalysisResult(path, withUnit: false); 275 AnalysisResult result = _computeAnalysisResult(path, withUnit: false);
266 yield result; 276 yield result;
267 // Repeat the processing loop. 277 // Repeat the processing loop.
268 _hasWork.notify(); 278 _hasWork.notify();
269 continue; 279 continue;
270 } 280 }
271 281
272 // There is nothing to do. 282 // There is nothing to do.
273 analysisSection.exit(); 283 analysisSection.exit();
274 analysisSection = null; 284 analysisSection = null;
285 _transitionToIdle();
275 } 286 }
276 } finally { 287 } finally {
277 print('The stream was cancelled.'); 288 print('The stream was cancelled.');
278 } 289 }
279 } 290 }
280 291
281 /** 292 /**
293 * Return the stream that produces [AnalysisStatus] events.
294 */
295 Stream<AnalysisStatus> get status => _statusController.stream;
296
297 /**
282 * Add the file with the given [path] to the set of files to analyze. 298 * Add the file with the given [path] to the set of files to analyze.
283 * 299 *
284 * The [path] must be absolute and normalized. 300 * The [path] must be absolute and normalized.
285 * 301 *
286 * The results of analysis are eventually produced by the [results] stream. 302 * The results of analysis are eventually produced by the [results] stream.
287 */ 303 */
288 void addFile(String path) { 304 void addFile(String path) {
289 _explicitFiles.add(path); 305 _explicitFiles.add(path);
290 _filesToAnalyze.add(path); 306 _filesToAnalyze.add(path);
307 _transitionToAnalyzing();
291 _hasWork.notify(); 308 _hasWork.notify();
292 } 309 }
293 310
294 /** 311 /**
295 * The file with the given [path] might have changed - updated, added or 312 * The file with the given [path] might have changed - updated, added or
296 * removed. Or not, we don't know. Or it might have, but then changed back. 313 * removed. Or not, we don't know. Or it might have, but then changed back.
297 * 314 *
298 * The [path] must be absolute and normalized. 315 * The [path] must be absolute and normalized.
299 * 316 *
300 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 317 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
301 * 318 *
302 * Causes the analysis state to transition to "analyzing" (if it is not in 319 * Causes the analysis state to transition to "analyzing" (if it is not in
303 * that state already). Schedules the file contents for [path] to be read 320 * that state already). Schedules the file contents for [path] to be read
304 * into the current file state prior to the next time the analysis state 321 * into the current file state prior to the next time the analysis state
305 * transitions to "idle". 322 * transitions to "idle".
306 * 323 *
307 * Invocation of this method will not prevent a [Future] returned from 324 * Invocation of this method will not prevent a [Future] returned from
308 * [getResult] from completing with a result, but the result is not 325 * [getResult] from completing with a result, but the result is not
309 * guaranteed to be consistent with the new current file state after this 326 * guaranteed to be consistent with the new current file state after this
310 * [changeFile] invocation. 327 * [changeFile] invocation.
311 */ 328 */
312 void changeFile(String path) { 329 void changeFile(String path) {
313 _changedFiles.add(path); 330 _changedFiles.add(path);
314 _filesToAnalyze.add(path); 331 _filesToAnalyze.add(path);
332 _transitionToAnalyzing();
315 _hasWork.notify(); 333 _hasWork.notify();
316 } 334 }
317 335
318 /** 336 /**
319 * Return the [Future] that completes with a [AnalysisResult] for the file 337 * Return the [Future] that completes with a [AnalysisResult] for the file
320 * with the given [path]. 338 * with the given [path].
321 * 339 *
322 * The [path] must be absolute and normalized. 340 * The [path] must be absolute and normalized.
323 * 341 *
324 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 342 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
325 * 343 *
326 * Causes the analysis state to transition to "analyzing" (if it is not in 344 * Causes the analysis state to transition to "analyzing" (if it is not in
327 * that state already), the driver will read the file and produce the analysis 345 * that state already), the driver will read the file and produce the analysis
328 * result for it, which is consistent with the current file state (including 346 * result for it, which is consistent with the current file state (including
329 * the new state of the file), prior to the next time the analysis state 347 * the new state of the file), prior to the next time the analysis state
330 * transitions to "idle". 348 * transitions to "idle".
331 */ 349 */
332 Future<AnalysisResult> getResult(String path) { 350 Future<AnalysisResult> getResult(String path) {
333 var completer = new Completer<AnalysisResult>(); 351 var completer = new Completer<AnalysisResult>();
334 _requestedFiles 352 _requestedFiles
335 .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) 353 .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
336 .add(completer); 354 .add(completer);
355 _transitionToAnalyzing();
337 _hasWork.notify(); 356 _hasWork.notify();
338 return completer.future; 357 return completer.future;
339 } 358 }
340 359
341 /** 360 /**
342 * Remove the file with the given [path] from the list of files to analyze. 361 * Remove the file with the given [path] from the list of files to analyze.
343 * 362 *
344 * The [path] must be absolute and normalized. 363 * The [path] must be absolute and normalized.
345 * 364 *
346 * The results of analysis of the file might still be produced by the 365 * The results of analysis of the file might still be produced by the
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 /** 632 /**
614 * Return the [Source] for the given [path] in [_sourceFactory]. 633 * Return the [Source] for the given [path] in [_sourceFactory].
615 */ 634 */
616 Source _sourceForPath(String path) { 635 Source _sourceForPath(String path) {
617 Source fileSource = _resourceProvider.getFile(path).createSource(); 636 Source fileSource = _resourceProvider.getFile(path).createSource();
618 Uri uri = _sourceFactory.restoreUri(fileSource); 637 Uri uri = _sourceFactory.restoreUri(fileSource);
619 return _resourceProvider.getFile(path).createSource(uri); 638 return _resourceProvider.getFile(path).createSource(uri);
620 } 639 }
621 640
622 /** 641 /**
642 * Send a notifications to the [status] stream that the driver started
643 * analyzing.
644 */
645 void _transitionToAnalyzing() {
646 if (_currentStatus != AnalysisStatus.ANALYZING) {
647 _currentStatus = AnalysisStatus.ANALYZING;
648 _statusController.add(AnalysisStatus.ANALYZING);
649 }
650 }
651
652 /**
653 * Send a notifications to the [status] stream that the driver is idle.
654 */
655 void _transitionToIdle() {
656 if (_currentStatus != AnalysisStatus.IDLE) {
657 _currentStatus = AnalysisStatus.IDLE;
658 _statusController.add(AnalysisStatus.IDLE);
659 }
660 }
661
662 /**
623 * Verify the API signature for the file with the given [path], and decide 663 * Verify the API signature for the file with the given [path], and decide
624 * which linked libraries should be invalidated, and files reanalyzed. 664 * which linked libraries should be invalidated, and files reanalyzed.
625 * 665 *
626 * TODO(scheglov) I see that adding a local var changes (full) API signature. 666 * TODO(scheglov) I see that adding a local var changes (full) API signature.
627 */ 667 */
628 void _verifyApiSignatureOfChangedFile(String path) { 668 void _verifyApiSignatureOfChangedFile(String path) {
629 _logger.run('Verify API signature of $path', () { 669 _logger.run('Verify API signature of $path', () {
630 String oldSignature = _fileApiSignatureMap[path]; 670 String oldSignature = _fileApiSignatureMap[path];
631 // Compute the new API signature. 671 // Compute the new API signature.
632 // _File.forResolution() also updates the content hash in the cache. 672 // _File.forResolution() also updates the content hash in the cache.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 /** 737 /**
698 * The full list of computed analysis errors, both syntactic and semantic. 738 * The full list of computed analysis errors, both syntactic and semantic.
699 */ 739 */
700 final List<AnalysisError> errors; 740 final List<AnalysisError> errors;
701 741
702 AnalysisResult(this.path, this.uri, this.content, this.contentHash, this.unit, 742 AnalysisResult(this.path, this.uri, this.content, this.contentHash, this.unit,
703 this.errors); 743 this.errors);
704 } 744 }
705 745
706 /** 746 /**
747 * The status of [AnalysisDriver]
748 */
749 class AnalysisStatus {
750 static const IDLE = const AnalysisStatus._(false);
751 static const ANALYZING = const AnalysisStatus._(true);
752
753 final bool _analyzing;
754
755 const AnalysisStatus._(this._analyzing);
756
757 /**
758 * Return `true` is the driver is analyzing.
759 */
760 bool get isAnalyzing => _analyzing;
761
762 /**
763 * Return `true` is the driver is idle.
764 */
765 bool get isIdle => !_analyzing;
766 }
767
768 /**
707 * This class is used to gather and print performance information. 769 * This class is used to gather and print performance information.
708 */ 770 */
709 class PerformanceLog { 771 class PerformanceLog {
710 final StringSink sink; 772 final StringSink sink;
711 int _level = 0; 773 int _level = 0;
712 774
713 PerformanceLog(this.sink); 775 PerformanceLog(this.sink);
714 776
715 /** 777 /**
716 * Enter a new execution section, which starts at one point of code, runs 778 * Enter a new execution section, which starts at one point of code, runs
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 } 1174 }
1113 } 1175 }
1114 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { 1176 for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
1115 referenced.exported.add(export.uri); 1177 referenced.exported.add(export.uri);
1116 } 1178 }
1117 return referenced; 1179 return referenced;
1118 } 1180 }
1119 1181
1120 _ReferencedUris._(); 1182 _ReferencedUris._();
1121 } 1183 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698