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 fc48adc23a4110f7b2bbcf48776149e01a1575f1..78628d1b1945eaa193252e142e64d675ce8a0a2f 100644 |
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart |
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart |
@@ -17,6 +17,7 @@ import 'package:analyzer/src/dart/analysis/file_state.dart'; |
import 'package:analyzer/src/dart/analysis/index.dart'; |
import 'package:analyzer/src/dart/analysis/search.dart'; |
import 'package:analyzer/src/dart/analysis/status.dart'; |
+import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; |
import 'package:analyzer/src/generated/engine.dart' |
show AnalysisContext, AnalysisEngine, AnalysisOptions, ChangeSet; |
import 'package:analyzer/src/generated/source.dart'; |
@@ -157,6 +158,11 @@ class AnalysisDriver { |
final _referencingNameTasks = <_FilesReferencingNameTask>[]; |
/** |
+ * The list of tasks to compute top-level declarations. |
+ */ |
+ final _topLevelDeclarationsTasks = <_TopLevelLibraryDeclarationsTask>[]; |
+ |
+ /** |
* The mapping from the files for which the index was requested using |
* [getIndex] to the [Completer]s to report the result. |
*/ |
@@ -296,6 +302,18 @@ class AnalysisDriver { |
Stream<AnalysisStatus> get status => _statusSupport.stream; |
/** |
+ * Return a [Future] that completes with top-level declaration in all known |
+ * libraries. |
+ */ |
+ Future<List<TopLevelLibraryDeclarations>> get topLevelLibraryDeclarations { |
Paul Berry
2016/12/01 22:28:15
I'm concerned that this API forces the driver to c
scheglov
2016/12/02 17:19:12
That's a good idea.
Thank you.
We need to know ki
|
+ var task = new _TopLevelLibraryDeclarationsTask(this); |
+ _topLevelDeclarationsTasks.add(task); |
+ _statusSupport.transitionToAnalyzing(); |
+ _scheduler._notify(this); |
+ return task.completer.future; |
+ } |
+ |
+ /** |
* Return the priority of work that the driver needs to perform. |
*/ |
AnalysisDriverPriority get _workPriority { |
@@ -303,10 +321,13 @@ class AnalysisDriver { |
return AnalysisDriverPriority.interactive; |
} |
if (_referencingNameTasks.isNotEmpty) { |
- return AnalysisDriverPriority.referencingName; |
+ return AnalysisDriverPriority.interactive; |
} |
if (_indexRequestedFiles.isNotEmpty) { |
- return AnalysisDriverPriority.getIndex; |
+ return AnalysisDriverPriority.interactive; |
+ } |
+ if (_topLevelDeclarationsTasks.isNotEmpty) { |
+ return AnalysisDriverPriority.interactive; |
} |
if (_priorityFiles.isNotEmpty) { |
for (String path in _priorityFiles) { |
@@ -813,6 +834,16 @@ class AnalysisDriver { |
return; |
} |
+ // Compute top-level declarations. |
+ if (_topLevelDeclarationsTasks.isNotEmpty) { |
+ _TopLevelLibraryDeclarationsTask task = _topLevelDeclarationsTasks.first; |
+ bool isDone = await task.perform(); |
+ if (isDone) { |
+ _topLevelDeclarationsTasks.remove(task); |
+ } |
+ return; |
+ } |
+ |
// Analyze a priority file. |
if (_priorityFiles.isNotEmpty) { |
for (String path in _priorityFiles) { |
@@ -904,14 +935,7 @@ class AnalysisDriver { |
* of the list, the earlier the corresponding [AnalysisDriver] should be asked |
* to perform work. |
*/ |
-enum AnalysisDriverPriority { |
- nothing, |
- general, |
- priority, |
- referencingName, |
- getIndex, |
- interactive |
-} |
+enum AnalysisDriverPriority { nothing, general, priority, interactive } |
/** |
* Instances of this class schedule work in multiple [AnalysisDriver]s so that |
@@ -1321,3 +1345,50 @@ class _LibraryContext { |
final SummaryDataStore store; |
_LibraryContext(this.file, this.store); |
} |
+ |
+/** |
+ * Task that computes top-level declarations in all known libraries. |
+ */ |
+class _TopLevelLibraryDeclarationsTask { |
+ final AnalysisDriver driver; |
+ final Completer<List<TopLevelLibraryDeclarations>> completer = |
+ new Completer<List<TopLevelLibraryDeclarations>>(); |
+ |
+ final List<TopLevelLibraryDeclarations> libraryDeclarations = |
+ <TopLevelLibraryDeclarations>[]; |
+ final Set<String> checkedFiles = new Set<String>(); |
+ final List<String> filesToCheck = <String>[]; |
+ |
+ _TopLevelLibraryDeclarationsTask(this.driver); |
+ |
+ /** |
+ * Perform a single piece of work, and either complete the [completer] and |
+ * return `true` to indicate that the task is done, return `false` to indicate |
+ * that the task should continue to be run. |
+ */ |
+ Future<bool> perform() async { |
+ // Prepare files to check. |
+ if (filesToCheck.isEmpty) { |
+ filesToCheck.addAll(driver.addedFiles.difference(checkedFiles)); |
+ filesToCheck.addAll(driver.knownFiles.difference(checkedFiles)); |
+ } |
+ |
+ // If no more files to check, complete and done. |
+ if (filesToCheck.isEmpty) { |
+ completer.complete(libraryDeclarations); |
+ return true; |
+ } |
+ |
+ // Check the next file. |
+ String path = filesToCheck.removeLast(); |
+ FileState file = driver._fsState.getFileForPath(path); |
+ if (!file.isPart) { |
+ libraryDeclarations.add(new TopLevelLibraryDeclarations( |
+ file.source, file.exportedTopLevelDeclarations)); |
+ } |
+ checkedFiles.add(path); |
+ |
+ // We're not done yet. |
+ return false; |
+ } |
+} |