Index: pkg/analyzer/lib/src/task/driver.dart |
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart |
index 17149227675dfbc60c8db9427e19f6d0ddbb5ea1..58aa4af9466798f5913460d05e68724344da1c01 100644 |
--- a/pkg/analyzer/lib/src/task/driver.dart |
+++ b/pkg/analyzer/lib/src/task/driver.dart |
@@ -25,11 +25,11 @@ class AnalysisDriver { |
*/ |
final TaskManager taskManager; |
-// /** |
-// * The list of [WorkManager] used to figure out which analysis results to |
-// * compute. |
-// */ |
-// final List<WorkManager> workManagers; |
+ /** |
+ * The list of [WorkManager] used to figure out which analysis results to |
+ * compute. |
+ */ |
+ final List<WorkManager> workManagers; |
/** |
* The context in which analysis is to be performed. |
@@ -56,7 +56,7 @@ class AnalysisDriver { |
* Initialize a newly created driver to use the tasks know to the given |
* [taskManager] to perform analysis in the given [context]. |
*/ |
- AnalysisDriver(this.taskManager, this.context) { |
+ AnalysisDriver(this.taskManager, this.workManagers, this.context) { |
_onTaskStartedController = new StreamController.broadcast(); |
_onTaskCompletedController = new StreamController.broadcast(); |
} |
@@ -91,28 +91,31 @@ class AnalysisDriver { |
* or `null` if there is currently no work to be done. |
*/ |
WorkOrder createNextWorkOrder() { |
- // |
- // TODO(brianwilkerson) This is an inefficient implementation. We need to |
- // port over the concept of the WorkManager to manage the list of sources |
- // for which some work needs to be performed so that we do not waste time |
- // repeatedly looking at the same completed sources to see whether there is |
- // work that needs to be done. |
- // |
- for (AnalysisTarget target in context.priorityTargets) { |
- WorkOrder workOrder = createWorkOrderForTarget(target, true); |
- if (workOrder != null) { |
- return workOrder; |
+ while (true) { |
+ // Find the WorkManager with the highest priority. |
+ WorkOrderPriority highestPriority = null; |
+ WorkManager highestManager = null; |
+ for (WorkManager manager in workManagers) { |
+ WorkOrderPriority priority = manager.getNextResultPriority(); |
+ if (highestPriority == null || highestPriority.index > priority.index) { |
+ highestPriority = priority; |
+ highestManager = manager; |
+ } |
} |
- } |
- // TODO(brianwilkerson) Add a third priority, corresponding to |
- // AnalysisContextImpl._pendingFutureSources to support code completion. |
- for (AnalysisTarget target in context.explicitTargets) { |
- WorkOrder workOrder = createWorkOrderForTarget(target, false); |
- if (workOrder != null) { |
- return workOrder; |
+ // Nothing to do. |
+ if (highestPriority == WorkOrderPriority.NONE) { |
+ return null; |
+ } |
+ // Create a new WorkOrder. |
+ TargetedResult request = highestManager.getNextResult(); |
+ if (request != null) { |
+ WorkOrder workOrder = |
+ createWorkOrderForResult(request.target, request.result); |
+ if (workOrder != null) { |
+ return workOrder; |
+ } |
} |
} |
- return null; |
} |
/** |
@@ -224,6 +227,9 @@ class AnalysisDriver { |
// and throw an exception if not (unless we want to allow null values). |
entry.setValue(result, outputs[result], dependedOn); |
} |
+ for (WorkManager manager in workManagers) { |
+ manager.resultsComputed(task.target, outputs); |
+ } |
} else { |
entry.setErrorState(task.caughtException, item.descriptor.results); |
} |
@@ -402,6 +408,62 @@ class WorkItem { |
} |
/** |
+ * [AnalysisDriver] uses [WorkManager]s to select results to compute. |
+ * |
+ * They know specific of the targets and results they care about, |
+ * so they can request analysis results in optimal order. |
+ */ |
+abstract class WorkManager { |
+ /** |
+ * Return the next [TargetedResult] that this work manager wants to be |
+ * computed, or `null` if this manager doesn't need any new results. |
+ */ |
+ TargetedResult getNextResult(); |
+ |
+ /** |
+ * Return the priority if the next work order this work manager want to be |
+ * computed. The [AnalysisDriver] will perform the work order with |
+ * the highest priority. |
+ * |
+ * Even if the returned value is [WorkOrderPriority.NONE], it still does not |
+ * guarantee that [getNextResult] will return not `null`. |
+ */ |
+ WorkOrderPriority getNextResultPriority(); |
+ |
+ /** |
+ * Notifies the manager that the given [outputs] were produced for |
+ * the given [target]. |
+ */ |
+ void resultsComputed( |
+ AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs); |
+} |
+ |
+/** |
+ * The priorities of work orders returned by [WorkManager]s. |
+ */ |
+enum WorkOrderPriority { |
+ /** |
+ * Responding to an user's action. |
+ */ |
+ INTERACTIVE, |
+ |
+ /** |
+ * Computing information for priority sources. |
+ */ |
+ PRIORITY, |
+ |
+ /** |
+ * A work should be done, but without any special urgency. |
+ */ |
+ NORMAL, |
+ |
+ /** |
+ * Nothing to do. |
+ */ |
+ NONE |
+} |
+ |
+/** |
* A description of the work to be done to compute a desired analysis result. |
* The class implements a lazy depth-first traversal of the work item's input. |
*/ |
@@ -475,24 +537,3 @@ class WorkOrder implements Iterator<WorkItem> { |
return false; |
} |
} |
- |
-/** |
- * [AnalysisDriver] uses [WorkManager]s to select results to compute. |
- * |
- * They know specific of the targets and results they care about, |
- * so they can request analysis results in optimal order. |
- */ |
-abstract class WorkManager { |
- /** |
- * Return the next [TargetedResult] that this work manager wants to be |
- * computed, or `null` if this manager doesn't need any new results. |
- */ |
- TargetedResult getNextResult(); |
- |
- /** |
- * Notifies the manager that the given [outputs] were produced for |
- * the given [target]. |
- */ |
- void resultsComputed( |
- AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs); |
-} |