Index: packages/analyzer/lib/task/model.dart |
diff --git a/analyzer/lib/task/model.dart b/packages/analyzer/lib/task/model.dart |
similarity index 77% |
rename from analyzer/lib/task/model.dart |
rename to packages/analyzer/lib/task/model.dart |
index 0a457661e8283f191e7ce78fd6e46a0ac4fd6bcf..9d949c308f836f0ec532fef3850f5e63d5bb39ff 100644 |
--- a/analyzer/lib/task/model.dart |
+++ b/packages/analyzer/lib/task/model.dart |
@@ -5,10 +5,13 @@ |
library analyzer.task.model; |
import 'dart:collection'; |
+import 'dart:developer'; |
import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; |
+import 'package:analyzer/src/generated/error.dart' show AnalysisError; |
import 'package:analyzer/src/generated/java_engine.dart'; |
import 'package:analyzer/src/generated/source.dart'; |
+import 'package:analyzer/src/generated/utilities_general.dart'; |
import 'package:analyzer/src/task/driver.dart'; |
import 'package:analyzer/src/task/model.dart'; |
@@ -82,6 +85,12 @@ abstract class AnalysisTask { |
static final Map<Type, int> countMap = new HashMap<Type, int>(); |
/** |
+ * A table mapping the types of analysis tasks to user tags used to collect |
+ * timing data for the Observatory. |
+ */ |
+ static Map<Type, UserTag> tagMap = new HashMap<Type, UserTag>(); |
+ |
+ /** |
* A table mapping the types of analysis tasks to stopwatches used to compute |
* how much time was spent executing each kind of task. |
*/ |
@@ -196,8 +205,8 @@ abstract class AnalysisTask { |
_safelyPerform(); |
} on AnalysisException catch (exception, stackTrace) { |
caughtException = new CaughtException(exception, stackTrace); |
- AnalysisEngine.instance.logger.logInformation( |
- "Task failed: ${description}", caughtException); |
+ AnalysisEngine.instance.logger |
+ .logInformation("Task failed: ${description}", caughtException); |
} |
} |
@@ -219,18 +228,22 @@ abstract class AnalysisTask { |
if (contextName == null) { |
contextName = 'unnamed'; |
} |
- AnalysisEngine.instance.instrumentationService.logAnalysisTask( |
- contextName, this); |
+ AnalysisEngine.instance.instrumentationService |
+ .logAnalysisTask(contextName, this); |
// |
// Gather statistics on the performance of the task. |
// |
int count = countMap[runtimeType]; |
countMap[runtimeType] = count == null ? 1 : count + 1; |
+// UserTag tag = tagMap.putIfAbsent( |
+// runtimeType, () => new UserTag(runtimeType.toString())); |
Stopwatch stopwatch = stopwatchMap[runtimeType]; |
if (stopwatch == null) { |
stopwatch = new Stopwatch(); |
stopwatchMap[runtimeType] = stopwatch; |
} |
+// UserTag previousTag = tag.makeCurrent(); |
+// try { |
stopwatch.start(); |
// |
// Actually perform the task. |
@@ -243,6 +256,9 @@ abstract class AnalysisTask { |
} finally { |
stopwatch.stop(); |
} |
+// } finally { |
+// previousTag.makeCurrent(); |
+// } |
} on AnalysisException { |
rethrow; |
} catch (exception, stackTrace) { |
@@ -266,10 +282,11 @@ abstract class ListResultDescriptor<E> implements ResultDescriptor<List<E>> { |
* values associated with this result will remain in the cache. |
*/ |
factory ListResultDescriptor(String name, List<E> defaultValue, |
- {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl<E>; |
+ {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl< |
+ E>; |
@override |
- ListTaskInput<E> of(AnalysisTarget target); |
+ ListTaskInput<E> of(AnalysisTarget target, {bool flushOnAccess: false}); |
} |
/** |
@@ -384,9 +401,52 @@ abstract class ResultDescriptor<V> { |
/** |
* Return a task input that can be used to compute this result for the given |
- * [target]. |
+ * [target]. If [flushOnAccess] is `true` then the value of this result that |
+ * is associated with the [target] will be flushed when it is accessed. |
*/ |
- TaskInput<V> of(AnalysisTarget target); |
+ TaskInput<V> of(AnalysisTarget target, {bool flushOnAccess: false}); |
+} |
+ |
+/** |
+ * A specification of the given [result] for the given [target]. |
+ * |
+ * Clients are not expected to subtype this class. |
+ */ |
+class TargetedResult { |
+ /** |
+ * An empty list of results. |
+ */ |
+ static final List<TargetedResult> EMPTY_LIST = const <TargetedResult>[]; |
+ |
+ /** |
+ * The target with which the result is associated. |
+ */ |
+ final AnalysisTarget target; |
+ |
+ /** |
+ * The result associated with the target. |
+ */ |
+ final ResultDescriptor result; |
+ |
+ /** |
+ * Initialize a new targeted result. |
+ */ |
+ TargetedResult(this.target, this.result); |
+ |
+ @override |
+ int get hashCode { |
+ return JenkinsSmiHash.combine(target.hashCode, result.hashCode); |
+ } |
+ |
+ @override |
+ bool operator ==(other) { |
+ return other is TargetedResult && |
+ other.target == target && |
+ other.result == result; |
+ } |
+ |
+ @override |
+ String toString() => '$result for $target'; |
} |
/** |
@@ -399,7 +459,9 @@ abstract class TaskDescriptor { |
* and produces the given [results]. The [buildTask] will be used to create |
* the instance of [AnalysisTask] thusly described. |
*/ |
- factory TaskDescriptor(String name, BuildTask buildTask, |
+ factory TaskDescriptor( |
+ String name, |
+ BuildTask buildTask, |
CreateTaskInputs inputBuilder, |
List<ResultDescriptor> results) = TaskDescriptorImpl; |
@@ -483,6 +545,12 @@ abstract class TaskInputBuilder<V> { |
void set currentValue(Object value); |
/** |
+ * Return `true` if the value accessed by this input builder should be flushed |
+ * from the cache at the time it is retrieved. |
+ */ |
+ bool get flushOnAccess; |
+ |
+ /** |
* Return the [value] that was computed by this builder. |
* |
* Throws a [StateError] if [moveNext] has not been invoked or if the last |
@@ -514,3 +582,95 @@ abstract class TaskInputBuilder<V> { |
*/ |
bool moveNext(); |
} |
+ |
+/** |
+ * [WorkManager]s are used to drive analysis. |
+ * |
+ * They know specific of the targets and results they care about, |
+ * so they can request analysis results in optimal order. |
+ */ |
+abstract class WorkManager { |
+ /** |
+ * Notifies the manager about changes in the explicit source list. |
+ */ |
+ void applyChange(List<Source> addedSources, List<Source> changedSources, |
+ List<Source> removedSources); |
+ |
+ /** |
+ * Notifies the managers that the given set of priority [targets] was set. |
+ */ |
+ void applyPriorityTargets(List<AnalysisTarget> targets); |
+ |
+ /** |
+ * Return a list of all of the errors associated with the given [source]. |
+ * The list of errors will be empty if the source is not known to the context |
+ * or if there are no errors in the source. The errors contained in the list |
+ * can be incomplete. |
+ */ |
+ List<AnalysisError> getErrors(Source source); |
+ |
+ /** |
+ * Return the next [TargetedResult] that this work manager wants to be |
+ * computed, or `null` if this manager doesn't need any new results. |
+ * |
+ * Note, that it is not guaranteed that this result will be computed, it is |
+ * up to the work manager to check whether the result is already computed |
+ * (for example during the next [getNextResult] invocation) or computation |
+ * of the same result should be requested again. |
+ */ |
+ 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 about analysis options changes. |
+ */ |
+ void onAnalysisOptionsChanged(); |
+ |
+ /** |
+ * Notifies the manager about [SourceFactory] changes. |
+ */ |
+ void onSourceFactoryChanged(); |
+ |
+ /** |
+ * 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. |
+ * |
+ * New priorities may be added with time, clients need to tolerate this. |
+ */ |
+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 |
+} |