Chromium Code Reviews| 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; |
| + } |
| +} |