Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: pkg/analyzer/lib/task/model.dart

Issue 812733004: Initial task support (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library analyzer.task.model;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
10 import 'package:analyzer/src/generated/java_engine.dart';
11 import 'package:analyzer/src/generated/source.dart';
12 import 'package:analyzer/src/task/model.dart';
13
14 /**
15 * A function that takes an analysis [context] and an analysis [target] and
16 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to
17 * be used to create the described task.
18 */
19 typedef AnalysisTask BuildTask(AnalysisContext context, AnalysisTarget target);
Paul Berry 2015/01/20 23:34:53 Consider renaming to "TaskBuilder" so that the typ
20
21 /**
22 * A function that takes the target for which a task will produce results and
23 * returns a map from input names to descriptions of the analysis results needed
24 * by the task in order for the task to be performed. Such functions are passed
25 * to a [TaskDescriptor] to be used to determine the inputs needed by the task.
26 */
27 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target);
Paul Berry 2015/01/20 23:34:53 Similarly, consider renaming to "InputBuilder".
28
29 /**
30 * An object with which an analysis result can be associated.
31 *
32 * Clients are allowed to subtype this class when creating new kinds of targets.
33 * Instances of this type are used in hashed data structures, so subtypes are
34 * required to correctly implement [==] and [hashCode].
35 */
36 abstract class AnalysisTarget {
37 /**
38 * Return the source associated with this target, or `null` if this target is
39 * not associated with a source.
40 */
41 Source get source;
42 }
43
44 /**
45 * An object used to compute one or more analysis results associated with a
46 * single target.
47 *
48 * Clients are expected to extend this class when creating new tasks.
49 */
50 abstract class AnalysisTask {
51 /**
52 * A table mapping the types of analysis tasks to stopwatches used to compute
53 * how much time was spent executing each kind of task.
54 */
55 static final Map<Type, Stopwatch> stopwatchMap =
56 new HashMap<Type, Stopwatch>();
57
58 /**
59 * The context in which the task is to be performed.
60 */
61 final AnalysisContext context;
62
63 /**
64 * The target for which result values are being produced.
65 */
66 final AnalysisTarget target;
67
68 /**
69 * A table mapping input names to input values.
70 */
71 Map<String, dynamic> inputs;
72
73 /**
74 * A table mapping result descriptors whose values are produced by this task
75 * to the values that were produced.
76 */
77 Map<ResultDescriptor, dynamic> outputs =
78 new HashMap<ResultDescriptor, dynamic>();
79
80 /**
81 * The exception that was thrown while performing this task, or `null` if the
82 * task completed successfully.
83 */
84 CaughtException thrownException;
Paul Berry 2015/01/20 23:34:53 I'm not sure the word "thrown" adds any meaning he
Brian Wilkerson 2015/01/26 04:54:51 Done
85
86 /**
87 * Initialize a newly created task to perform analysis within the given
88 * [context] in order to produce results for the given [target].
89 */
90 AnalysisTask(this.context, this.target);
91
92 /**
93 * Return a textual description of this task.
94 */
95 String get description;
96
97 /**
98 * Return the source associated with this task's target, or `null` if the
99 * target is not associated with a source.
100 */
101 Source get source => target.source;
Paul Berry 2015/01/20 23:34:53 Consider removing this getter. It doesn't add a h
Brian Wilkerson 2015/01/26 04:54:51 Done
102
103 /**
104 * Perform this analysis task, protected by an exception handler.
105 *
106 * This method should throw an [AnalysisException] if an exception occurs
107 * while performing the task. If other kinds of exceptions are thrown they
108 * will be wrapped in an [AnalysisException].
109 *
110 * If no exception is thrown, this method must fully populate the [outputs]
111 * map (have a key/value pair for each result that this task is expected to
112 * produce).
113 */
114 void internalPerform();
115
116 /**
117 * Perform this analysis task. When this method returns, either the [outputs]
118 * map should be fully populated (have a key/value pair for each result that
119 * this task is expected to produce) or the [thrownException] should be set.
120 *
121 * Clients should not override this method.
122 */
123 void perform() {
124 try {
125 safelyPerform();
126 } on AnalysisException catch (exception, stackTrace) {
127 thrownException = new CaughtException(exception, stackTrace);
128 AnalysisEngine.instance.logger.logInformation(
129 "Task failed: ${description}",
130 thrownException);
131 }
132 }
133
134 /**
135 * Perform this analysis task, ensuring that all exceptions are wrapped in an
136 * [AnalysisException].
137 *
138 * Clients should not override this method.
139 */
140 void safelyPerform() {
Paul Berry 2015/01/20 23:34:53 Is this method ever meant to be called by clients,
Brian Wilkerson 2015/01/26 04:54:51 It also changes what is being measures by the stop
141 try {
142 Stopwatch stopwatch = stopwatchMap[runtimeType];
143 if (stopwatch == null) {
144 stopwatch = new Stopwatch();
145 stopwatchMap[runtimeType] = stopwatch;
146 }
147 stopwatch.start();
148 try {
149 internalPerform();
150 } finally {
151 stopwatch.stop();
152 }
153 } on AnalysisException catch (exception) {
154 rethrow;
155 } catch (exception, stackTrace) {
156 throw new AnalysisException(
157 'Unexpected exception while performing $description',
158 new CaughtException(exception, stackTrace));
159 }
160 }
161
162 @override
163 String toString() => description;
164 }
165
166 /**
167 * A [ResultDescriptor] that denotes an analysis result that is a union of
168 * one or more other results.
169 *
170 * Clients are not expected to subtype this class.
171 */
172 abstract class ContributionPoint<V> extends ResultDescriptor<V> {
Paul Berry 2015/01/20 23:34:53 As discussed in person, consider making Contributi
Brian Wilkerson 2015/01/26 04:54:51 I like the idea, but it leads to a type warning th
173 /**
174 * Initialize a newly created contribution point to have the given [name].
175 */
176 factory ContributionPoint(String name) = ContributionPointImpl;
177
178 /**
179 * Return a list containing the descriptors of the results that are unioned
180 * together to comprise the value of this result.
181 *
182 * Clients must not modify the returned list.
183 */
184 List<ResultDescriptor<V>> get contributors;
185 }
186
187 /**
188 * A description of an analysis result that can be computed by an [AnalysisTask] .
189 *
190 * Clients are not expected to subtype this class.
191 */
192 abstract class ResultDescriptor<V> {
193 /**
194 * Initialize a newly created analysis result to have the given [name]. If a
195 * contribution point is specified, then this result will contribute to it.
196 */
197 factory ResultDescriptor(String name, {ContributionPoint contributesTo}) =
198 ResultDescriptorImpl;
199
200 /**
201 * Return a task input that can be used to compute this result for the given
202 * [target].
203 */
204 TaskInput<V> inputFor(AnalysisTarget target);
205 }
206
207 /**
208 * A description of an [AnalysisTask].
209 */
210 abstract class TaskDescriptor {
211 /**
212 * Initialize a newly created task descriptor to have the given [name] and to
213 * describe a task that takes the inputs built using the given [inputBuilder],
214 * and produces the given [results]. The [buildTask] will be used to create
215 * the instance of [AnalysisTask] thusly described.
216 */
217 factory TaskDescriptor(String name, BuildTask buildTask,
218 CreateTaskInputs inputBuilder, List<ResultDescriptor> results) =
219 TaskDescriptorImpl;
220
221 /**
222 * Return the builder used to build the inputs to the task.
223 */
224 CreateTaskInputs get createTaskInputs;
225
226 /**
227 * Return a list of the analysis results that will be computed by this task.
228 */
229 List<ResultDescriptor> get results;
230
231 /**
232 * Create and return a task that is described by this descriptor that can be
233 * used to compute results based on the given [inputs].
234 */
235 AnalysisTask createTask(AnalysisContext context, AnalysisTarget target,
236 Map<String, dynamic> inputs);
237 }
238
239 /**
240 * A description of an input to an [AnalysisTask] that can be used to compute
241 * that input.
242 *
243 * Clients are not expected to subtype this class.
244 */
245 abstract class TaskInput<V> {
246 /**
247 * Create and return a builder that can be used to build this task input.
248 */
249 TaskInputBuilder<V> createBuilder();
250 }
251
252 /**
253 * An object used to build the value associated with a single [TaskInput].
254 *
255 * All builders work by requesting one or more results (each result being
256 * associated with a target). The interaction pattern is modeled after the class
257 * [Iterator], in which the method [moveNext] is invoked to move from one result
258 * request to the next. The getters [currentResult] and [currentTarget] are used
259 * to get the result and target of the current request. The value of the result
260 * must be supplied using the [currentValue] setter before [moveNext] can be
261 * invoked to move to the next request. When [moveNext] returns `false`,
262 * indicating that there are no more requests, the method [inputValue] can be
263 * used to access the value of the input that was built.
264 *
265 * Clients are not expected to subtype this class.
266 */
267 abstract class TaskInputBuilder<V> {
268 /**
269 * Return the result that needs to be computed, or `null` if [moveNext] has
270 * not been invoked or if the last invocation of [moveNext] returned `false`.
271 */
272 ResultDescriptor get currentResult;
273
274 /**
275 * Return the target for which the result needs to be computed, or `null` if
276 * [moveNext] has not been invoked or if the last invocation of [moveNext]
277 * returned `false`.
278 */
279 AnalysisTarget get currentTarget;
280
281 /**
282 * Set the [value] that was computed for the current result.
283 *
284 * Throws a [StateError] if [moveNext] has not been invoked or if the last
285 * invocation of [moveNext] returned `false`.
286 */
287 void set currentValue(Object value);
288
289 /**
290 * Return the [value] that was computed by this builder.
291 *
292 * Throws a [StateError] if [moveNext] has not been invoked or if the last
293 * invocation of [moveNext] returned `true`.
294 */
295 V get inputValue;
296
297 /**
298 * Move to the next result that needs to be computed in order to build the
299 * inputs for a task. Return `true` if there is another result that needs to
300 * be computed, or `false` if the inputs have been computed.
301 *
302 * It is safe to invoke [moveNext] after it has returned `false`. In this case
303 * [moveNext] has no effect and will again return `false`.
304 *
305 * Throws a [StateError] if the value of the current result has not been
306 * provided using [currentValue].
307 */
308 bool moveNext();
309 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698