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..78a135d8f6f920d02cd53550152390a1c29a056e 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 of a name. |
+ */ |
+ final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[]; |
+ |
+ /** |
* The mapping from the files for which the index was requested using |
* [getIndex] to the [Completer]s to report the result. |
*/ |
@@ -303,10 +309,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 (_topLevelNameDeclarationsTasks.isNotEmpty) { |
+ return AnalysisDriverPriority.interactive; |
} |
if (_priorityFiles.isNotEmpty) { |
for (String path in _priorityFiles) { |
@@ -438,6 +447,19 @@ class AnalysisDriver { |
} |
/** |
+ * Return a [Future] that completes with top-level declarations with the |
+ * given [name] in all known libraries. |
+ */ |
+ Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations( |
+ String name) { |
+ var task = new _TopLevelNameDeclarationsTask(this, name); |
+ _topLevelNameDeclarationsTasks.add(task); |
+ _statusSupport.transitionToAnalyzing(); |
+ _scheduler._notify(this); |
+ return task.completer.future; |
+ } |
+ |
+ /** |
* Return a [Future] that completes with a [ParseResult] for the file |
* with the given [path]. |
* |
@@ -813,6 +835,16 @@ class AnalysisDriver { |
return; |
} |
+ // Compute top-level declarations. |
+ if (_topLevelNameDeclarationsTasks.isNotEmpty) { |
+ _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first; |
+ bool isDone = await task.perform(); |
+ if (isDone) { |
+ _topLevelNameDeclarationsTasks.remove(task); |
+ } |
+ return; |
+ } |
+ |
// Analyze a priority file. |
if (_priorityFiles.isNotEmpty) { |
for (String path in _priorityFiles) { |
@@ -904,14 +936,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 +1346,56 @@ class _LibraryContext { |
final SummaryDataStore store; |
_LibraryContext(this.file, this.store); |
} |
+ |
+/** |
+ * Task that computes top-level declarations in all known libraries. |
Paul Berry
2016/12/02 17:56:37
Nit: Change to "Task that computes top-level decla
|
+ */ |
+class _TopLevelNameDeclarationsTask { |
+ final AnalysisDriver driver; |
+ final String name; |
+ final Completer<List<TopLevelDeclarationInSource>> completer = |
+ new Completer<List<TopLevelDeclarationInSource>>(); |
+ |
+ final List<TopLevelDeclarationInSource> libraryDeclarations = |
+ <TopLevelDeclarationInSource>[]; |
+ final Set<String> checkedFiles = new Set<String>(); |
+ final List<String> filesToCheck = <String>[]; |
+ |
+ _TopLevelNameDeclarationsTask(this.driver, this.name); |
+ |
+ /** |
+ * 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(); |
+ if (checkedFiles.add(path)) { |
+ FileState file = driver._fsState.getFileForPath(path); |
+ if (!file.isPart) { |
+ TopLevelDeclaration declaration = |
+ file.exportedTopLevelDeclarations[name]; |
+ if (declaration != null) { |
+ libraryDeclarations |
+ .add(new TopLevelDeclarationInSource(file.source, declaration)); |
+ } |
+ } |
+ } |
+ |
+ // We're not done yet. |
+ return false; |
+ } |
+} |