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

Side by Side Diff: pkg/analyzer/lib/src/task/inputs.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.src.task.inputs;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/task/model.dart';
10
11 /**
12 * A function that converts an arbitrary object into a [TaskInput]. This is
13 * used, for example, by a [ListBasedTaskInput] to create task inputs for each
14 * value in a list of values.
15 */
16 typedef TaskInput<E> GenerateTaskInputs<E>(Object object);
17
18 /**
19 * An input to an [AnalysisTask] that is computed by the following steps. First
20 * another (base) task input is used to compute a [List]-valued result. An input
21 * generator function is then used to map each element of that list to a task
22 * input. Finally, each of the task inputs are used to access analysis results,
23 * and the list of the analysis results is used as the input to the task.
24 */
25 class ListBasedTaskInput<B, E> implements TaskInput<List<E>> {
26 /**
27 * The accessor used to access the list of elements being mapped.
28 */
29 final TaskInput<B> baseAccessor;
30
31 /**
32 * The function used to convert an element in the list returned by the
33 * [baseAccessor] to a task input.
34 */
35 GenerateTaskInputs<E> generateTaskInputs;
36
37 /**
38 * Initialize a result accessor to use the given [baseAccessor] to access a
39 * list of values that can be passed to the given [generateTaskInputs] to gene rate
40 * a list of task inputs that can be used to access the elements of the input
41 * being accessed.
42 */
43 ListBasedTaskInput(this.baseAccessor, this.generateTaskInputs);
44
45 @override
46 TaskInputBuilder<List<E>> createBuilder() =>
47 new ListBasedTaskInputBuilder<B, E>(this);
48 }
49
50 /**
51 * A [TaskInputBuilder] used to build an input based on a [ListBasedTaskInput].
52 */
53 class ListBasedTaskInputBuilder<B, E> implements TaskInputBuilder<List<E>> {
54 /**
55 * The input being built.
56 */
57 final ListBasedTaskInput<B, E> input;
58
59 /**
60 * The builder used to build the current result.
61 */
62 TaskInputBuilder currentBuilder;
63
64 /**
65 * The list of values computed by the [input]'s base accessor.
66 */
67 List _baseList = null;
68
69 /**
70 * The index in the [_baseList] of the value for which a value is currently
71 * being built.
72 */
73 int _baseListIndex = -1;
74
75 /**
76 * The list of values being built.
77 */
78 List<E> _resultValue = null;
79
80 /**
81 * Initialize a newly created task input builder that computes the result
82 * specified by the given [input].
83 */
84 ListBasedTaskInputBuilder(this.input);
85
86 @override
87 ResultDescriptor get currentResult {
88 if (currentBuilder == null) {
89 return null;
90 }
91 return currentBuilder.currentResult;
92 }
93
94 @override
95 AnalysisTarget get currentTarget {
96 if (currentBuilder == null) {
97 return null;
98 }
99 return currentBuilder.currentTarget;
100 }
101
102 @override
103 void set currentValue(Object value) {
104 if (currentBuilder == null) {
105 throw new StateError(
106 'Cannot set the result value when there is no current result');
107 }
108 currentBuilder.currentValue = value;
109 }
110
111 @override
112 List<E> get inputValue {
113 if (currentBuilder != null || _resultValue == null) {
114 throw new StateError('Result value has not been created');
115 }
116 return _resultValue;
117 }
118
119 @override
120 bool moveNext() {
121 if (currentBuilder == null) {
122 if (_resultValue == null) {
123 // This is the first time moveNext has been invoked, so start by
124 // computing the list of values from which the results will be derived.
125 currentBuilder = input.baseAccessor.createBuilder();
126 return currentBuilder.moveNext();
127 } else {
128 // We have already computed all of the results, so just return false.
129 return false;
130 }
131 }
132 if (currentBuilder.moveNext()) {
133 return true;
134 }
135 if (_resultValue == null) {
136 // We have finished computing the list of values from which the results
137 // will be derived.
138 _baseList = currentBuilder.inputValue;
139 _baseListIndex = 0;
140 _resultValue = <E>[];
141 } else {
142 // We have finished computing one of the elements in the result list.
143 _resultValue.add(currentBuilder.inputValue);
144 _baseListIndex++;
145 }
146 if (_baseListIndex >= _baseList.length) {
147 currentBuilder = null;
148 return false;
149 }
150 currentBuilder =
151 input.generateTaskInputs(_baseList[_baseListIndex]).createBuilder();
152 return currentBuilder.moveNext();
153 }
154 }
155
156 /**
157 * An input to an [AnalysisTask] that is computed by accessing a single result
158 * defined on a single target.
159 */
160 class SimpleTaskInput<V> implements TaskInput<V> {
161 /**
162 * The target on which the result is defined.
163 */
164 final AnalysisTarget target;
165
166 /**
167 * The result to be accessed.
168 */
169 final ResultDescriptor<V> result;
170
171 /**
172 * Initialize a newly created task input that computes the input by accessing
173 * the given [result] associated with the given [target].
174 */
175 SimpleTaskInput(this.target, this.result);
176
177 @override
178 TaskInputBuilder<V> createBuilder() => new SimpleTaskInputBuilder<V>(this);
179 }
180
181 /**
182 * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
183 */
184 class SimpleTaskInputBuilder<V> implements TaskInputBuilder<V> {
185 /**
186 * The state value indicating that the builder is positioned before the single result.
187 */
188 static const _BEFORE = -1;
189
190 /**
191 * The state value indicating that the builder is positioned at the single res ult.
192 */
193 static const _AT = 0;
194
195 /**
196 * The state value indicating that the builder is positioned before the single result.
scheglov 2015/01/21 14:50:47 "after the single result"
Brian Wilkerson 2015/01/26 04:54:51 Done
197 */
198 static const _AFTER = 1;
199
200 /**
201 * The input being built.
202 */
203 final SimpleTaskInput<V> input;
204
205 /**
206 * The value of the input being built.
207 */
208 V _resultValue = null;
209
210 /**
211 * The state of the builder.
212 */
213 int _state = _BEFORE;
214
215 /**
216 * A flag indicating whether the result value was explicitly set.
217 */
218 bool _resultSet = false;
219
220 /**
221 * Initialize a newly created task input builder that computes the result
222 * specified by the given [input].
223 */
224 SimpleTaskInputBuilder(this.input);
225
226 @override
227 ResultDescriptor get currentResult => _state == _AT ? input.result : null;
228
229 @override
230 AnalysisTarget get currentTarget => _state == _AT ? input.target : null;
231
232 @override
233 void set currentValue(Object value) {
234 if (_state != _AT) {
235 throw new StateError(
236 'Cannot set the result value when there is no current result');
237 }
238 _resultValue = value as V;
239 _resultSet = true;
240 }
241
242 @override
243 V get inputValue {
244 if (_state != _AFTER) {
245 throw new StateError('Result value has not been created');
246 }
247 return _resultValue;
248 }
249
250 @override
251 bool moveNext() {
252 if (_state == _BEFORE) {
253 _state = _AT;
254 return true;
255 } else {
256 if (!_resultSet) {
257 throw new StateError(
258 'The value of the current result must be set before moving to the ne xt result.');
259 }
260 _state = _AFTER;
261 return false;
262 }
263 }
264 }
265
266 /**
267 * A [TaskInputBuilder] used to build an input based on one or more other task
268 * inputs. The task inputs to be built are specified by a table mapping the name
269 * of the input to the task used to access the input's value.
270 */
271 class TopLevelTaskInputBuilder implements TaskInputBuilder<Map<String, Object>>
272 {
273 /**
274 * The descriptors describing the inputs to be built.
275 */
276 final Map<String, TaskInput> inputDescriptors;
277
278 /**
279 * The names of the inputs. There are the keys from the [inputDescriptors] in
280 * an indexable form.
281 */
282 List<String> inputNames;
283
284 /**
285 * The index of the input name associated with the current result and target.
286 */
287 int nameIndex = -1;
288
289 /**
290 * The builder used to build the current result.
291 */
292 TaskInputBuilder currentBuilder;
293
294 /**
295 * The inputs that are being or have been built. The map will be incomplete
296 * unless the method [moveNext] returns `false`.
297 */
298 final Map<String, Object> inputs = new HashMap<String, Object>();
299
300 /**
301 * Initialize a newly created task input builder to build the inputs described
302 * by the given [inputDescriptors].
303 */
304 TopLevelTaskInputBuilder(this.inputDescriptors) {
305 inputNames = inputDescriptors.keys.toList();
306 }
307
308 @override
309 ResultDescriptor get currentResult {
310 if (currentBuilder == null) {
311 return null;
312 }
313 return currentBuilder.currentResult;
314 }
315
316 @override
317 AnalysisTarget get currentTarget {
318 if (currentBuilder == null) {
319 return null;
320 }
321 return currentBuilder.currentTarget;
322 }
323
324 @override
325 void set currentValue(Object value) {
326 if (currentBuilder == null) {
327 throw new StateError(
328 'Cannot set the result value when there is no current result');
329 }
330 currentBuilder.currentValue = value;
331 }
332
333 @override
334 Map<String, Object> get inputValue {
335 if (nameIndex < inputNames.length) {
336 throw new StateError('Result value has not been created');
337 }
338 return inputs;
339 }
340
341 /**
342 * Assuming that there is a current input, return its name.
343 */
344 String get _currentName => inputNames[nameIndex];
345
346 @override
347 bool moveNext() {
348 if (nameIndex >= inputNames.length) {
349 // We have already computed all of the results, so just return false.
350 return false;
351 }
352 if (nameIndex < 0) {
353 // This is the first time moveNext has been invoked, so we just determine
354 // whether there are any results to be computed.
355 nameIndex = 0;
356 } else {
357 if (currentBuilder.moveNext()) {
358 // We are still working on building the value associated with the
359 // current name.
360 return true;
361 }
362 inputs[_currentName] = currentBuilder.inputValue;
363 nameIndex++;
364 }
365 if (nameIndex >= inputNames.length) {
366 // There is no next value, so we're done.
367 return false;
368 }
369 currentBuilder = inputDescriptors[_currentName].createBuilder();
370 // NOTE: This assumes that every builder will require at least one result
371 // value to be created. If that assumption is every broken, this method will
372 // need to be changed to advance until we find a builder that does require
373 // a result to be computed (or run out of builders).
374 return currentBuilder.moveNext();
375 }
376 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698