| Index: pkg/analyzer/lib/src/dart/analysis/driver.dart
|
| diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
|
| index d96e63daa15ccad290dd73e509a663c6854690ff..01c66563862b88f6803bdd3c718ccc09c8cee0c5 100644
|
| --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
|
| +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
|
| @@ -158,9 +158,9 @@ class AnalysisDriver {
|
| final _dependencySignatureMap = <Uri, String>{};
|
|
|
| /**
|
| - * TODO(scheglov) document and improve
|
| + * The monitor that is signalled when there is work to do.
|
| */
|
| - final _hasWorkStreamController = new StreamController<String>();
|
| + final _Monitor _hasWork = new _Monitor();
|
|
|
| AnalysisDriver(this._logger, this._resourceProvider, this._byteStore,
|
| this._contentCache, this._sourceFactory, this._analysisOptions) {
|
| @@ -203,31 +203,36 @@ class AnalysisDriver {
|
| */
|
| Stream<AnalysisResult> get results async* {
|
| try {
|
| + PerformanceLogSection analysisSection = null;
|
| while (true) {
|
| // TODO(scheglov) implement state transitioning
|
| - await for (String why in _hasWorkStreamController.stream) {
|
| - _verifyUnlinkedSignatureOfChangedFiles();
|
| -
|
| - // Analyze the first file in the general queue.
|
| - if (_filesToAnalyze.isNotEmpty) {
|
| - PerformanceLogSection analysisSection =
|
| - _logger.enter('Analyze ${_filesToAnalyze.length} files');
|
| - try {
|
| - // TODO(scheglov) The loop is strange for now.
|
| - while (_filesToAnalyze.isNotEmpty) {
|
| - String path = _filesToAnalyze.first;
|
| - _filesToAnalyze.remove(path);
|
| - _File file = _fileForPath(path);
|
| - AnalysisResult result = _computeAnalysisResult(file);
|
| - yield result;
|
| - }
|
| - } finally {
|
| - analysisSection.exit();
|
| - }
|
| - }
|
| + await _hasWork.signal;
|
| +
|
| + if (analysisSection == null) {
|
| + analysisSection = _logger.enter('Analyzing');
|
| + }
|
| +
|
| + // TODO(scheglov) verify one file at a time
|
| + _verifyUnlinkedSignatureOfChangedFiles();
|
| +
|
| + // Analyze the first file in the general queue.
|
| + if (_filesToAnalyze.isNotEmpty) {
|
| + String path = _filesToAnalyze.first;
|
| + _filesToAnalyze.remove(path);
|
| + _File file = _fileForPath(path);
|
| + AnalysisResult result = _computeAnalysisResult(file);
|
| + yield result;
|
| + }
|
| +
|
| + // If there is work to do, notify the monitor.
|
| + if (_filesToAnalyze.isNotEmpty) {
|
| + _hasWork.notify();
|
| + } else {
|
| + analysisSection.exit();
|
| + analysisSection = null;
|
| }
|
| - // TODO(scheglov) implement
|
| }
|
| + // TODO(scheglov) implement
|
| } finally {
|
| print('The stream was cancelled.');
|
| }
|
| @@ -243,7 +248,7 @@ class AnalysisDriver {
|
| void addFile(String path) {
|
| _explicitFiles.add(path);
|
| _filesToAnalyze.add(path);
|
| - _hasWorkStreamController.add('do it!');
|
| + _hasWork.notify();
|
| }
|
|
|
| /**
|
| @@ -267,7 +272,7 @@ class AnalysisDriver {
|
| void changeFile(String path) {
|
| _filesToVerifyUnlinkedSignature.add(path);
|
| _filesToAnalyze.add(path);
|
| - _hasWorkStreamController.add('do it!');
|
| + _hasWork.notify();
|
| }
|
|
|
| /**
|
| @@ -289,7 +294,7 @@ class AnalysisDriver {
|
| _requestedFiles
|
| .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
|
| .add(completer);
|
| - _hasWorkStreamController.add(path);
|
| + _hasWork.notify();
|
| return completer.future;
|
| }
|
|
|
| @@ -942,6 +947,35 @@ class _LibraryNode {
|
| }
|
|
|
| /**
|
| + * [_Monitor] can be used to wait for a signal.
|
| + *
|
| + * Signals are not queued, the client will receive exactly one signal
|
| + * regardless of the number of [notify] invocations. The [signal] is reset
|
| + * after completion and will not complete until [notify] is called next time.
|
| + */
|
| +class _Monitor {
|
| + Completer<Null> _completer = new Completer<Null>();
|
| +
|
| + /**
|
| + * Return a [Future] that completes when [notify] is called at least once.
|
| + */
|
| + Future<Null> get signal async {
|
| + await _completer.future;
|
| + _completer = new Completer<Null>();
|
| + }
|
| +
|
| + /**
|
| + * Complete the [signal] future if it is not completed yet. It is safe to
|
| + * call this method multiple times, but the [signal] will complete only once.
|
| + */
|
| + void notify() {
|
| + if (!_completer.isCompleted) {
|
| + _completer.complete(true);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| * TODO(scheglov) document
|
| */
|
| class _ReferencedUris {
|
|
|