OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer.src.task.driver; | 5 library analyzer.src.task.driver; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'package:analyzer/src/context/cache.dart'; | 10 import 'package:analyzer/src/context/cache.dart'; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 currentWorkOrder = createNextWorkOrder(); | 200 currentWorkOrder = createNextWorkOrder(); |
201 } | 201 } |
202 return currentWorkOrder != null; | 202 return currentWorkOrder != null; |
203 } | 203 } |
204 | 204 |
205 /** | 205 /** |
206 * Perform the given work item. | 206 * Perform the given work item. |
207 * Return the performed [AnalysisTask]. | 207 * Return the performed [AnalysisTask]. |
208 */ | 208 */ |
209 AnalysisTask performWorkItem(WorkItem item) { | 209 AnalysisTask performWorkItem(WorkItem item) { |
210 if (item.exception != null) { | 210 try { |
Paul Berry
2015/05/13 21:32:00
Note: it's not obvious from the diff, but the only
| |
211 // Mark all of the results that the task would have computed as being in | 211 assert(!taskManager.isTaskRunning); |
212 // ERROR with the exception recorded on the work item. | 212 taskManager.isTaskRunning = true; |
213 CacheEntry targetEntry = context.getCacheEntry(item.target); | 213 if (item.exception != null) { |
214 targetEntry.setErrorState(item.exception, item.descriptor.results); | 214 // Mark all of the results that the task would have computed as being in |
215 return null; | 215 // ERROR with the exception recorded on the work item. |
216 CacheEntry targetEntry = context.getCacheEntry(item.target); | |
217 targetEntry.setErrorState(item.exception, item.descriptor.results); | |
218 return null; | |
219 } | |
220 // Otherwise, perform the task. | |
221 AnalysisTask task = item.buildTask(); | |
222 _onTaskStartedController.add(task); | |
223 task.perform(); | |
224 CacheEntry entry = context.getCacheEntry(task.target); | |
225 if (task.caughtException == null) { | |
226 List<TargetedResult> dependedOn = item.inputTargetedResults.toList(); | |
227 Map<ResultDescriptor, dynamic> outputs = task.outputs; | |
228 for (ResultDescriptor result in task.descriptor.results) { | |
229 // TODO(brianwilkerson) We could check here that a value was produced | |
230 // and throw an exception if not (unless we want to allow null values) . | |
231 entry.setValue(result, outputs[result], dependedOn); | |
232 } | |
233 for (WorkManager manager in workManagers) { | |
234 manager.resultsComputed(task.target, outputs); | |
235 } | |
236 } else { | |
237 entry.setErrorState(task.caughtException, item.descriptor.results); | |
238 } | |
239 _onTaskCompletedController.add(task); | |
240 return task; | |
241 } finally { | |
242 taskManager.isTaskRunning = false; | |
216 } | 243 } |
217 // Otherwise, perform the task. | |
218 AnalysisTask task = item.buildTask(); | |
219 _onTaskStartedController.add(task); | |
220 task.perform(); | |
221 CacheEntry entry = context.getCacheEntry(task.target); | |
222 if (task.caughtException == null) { | |
223 List<TargetedResult> dependedOn = item.inputTargetedResults.toList(); | |
224 Map<ResultDescriptor, dynamic> outputs = task.outputs; | |
225 for (ResultDescriptor result in task.descriptor.results) { | |
226 // TODO(brianwilkerson) We could check here that a value was produced | |
227 // and throw an exception if not (unless we want to allow null values). | |
228 entry.setValue(result, outputs[result], dependedOn); | |
229 } | |
230 for (WorkManager manager in workManagers) { | |
231 manager.resultsComputed(task.target, outputs); | |
232 } | |
233 } else { | |
234 entry.setErrorState(task.caughtException, item.descriptor.results); | |
235 } | |
236 _onTaskCompletedController.add(task); | |
237 return task; | |
238 } | 244 } |
239 | 245 |
240 /** | 246 /** |
241 * Reset the state of the driver in response to a change in the state of one | 247 * Reset the state of the driver in response to a change in the state of one |
242 * or more analysis targets. This will cause any analysis that was currently | 248 * or more analysis targets. This will cause any analysis that was currently |
243 * in process to be stopped and for analysis to resume based on the new state. | 249 * in process to be stopped and for analysis to resume based on the new state. |
244 */ | 250 */ |
245 void reset() { | 251 void reset() { |
246 currentWorkOrder = null; | 252 currentWorkOrder = null; |
247 } | 253 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 * | 362 * |
357 * If all of the inputs have been gathered, return `null` to indicate that the | 363 * If all of the inputs have been gathered, return `null` to indicate that the |
358 * client should build and perform the task. A value of `null` will also be | 364 * client should build and perform the task. A value of `null` will also be |
359 * returned if some of the inputs cannot be computed and the task cannot be | 365 * returned if some of the inputs cannot be computed and the task cannot be |
360 * performed. Callers can differentiate between these cases by checking the | 366 * performed. Callers can differentiate between these cases by checking the |
361 * [exception] field. If the field is `null`, then the task can be performed; | 367 * [exception] field. If the field is `null`, then the task can be performed; |
362 * if the field is non-`null` then the task cannot be performed and all of the | 368 * if the field is non-`null` then the task cannot be performed and all of the |
363 * tasks' results should be marked as being in ERROR. | 369 * tasks' results should be marked as being in ERROR. |
364 */ | 370 */ |
365 WorkItem gatherInputs(TaskManager taskManager) { | 371 WorkItem gatherInputs(TaskManager taskManager) { |
366 while (builder != null) { | 372 try { |
367 AnalysisTarget inputTarget = builder.currentTarget; | 373 assert(!taskManager.isTaskRunning); |
368 ResultDescriptor inputResult = builder.currentResult; | 374 taskManager.isTaskRunning = true; |
369 inputTargetedResults.add(new TargetedResult(inputTarget, inputResult)); | 375 while (builder != null) { |
370 CacheEntry inputEntry = context.getCacheEntry(inputTarget); | 376 AnalysisTarget inputTarget = builder.currentTarget; |
371 CacheState inputState = inputEntry.getState(inputResult); | 377 ResultDescriptor inputResult = builder.currentResult; |
372 if (inputState == CacheState.ERROR) { | 378 inputTargetedResults.add(new TargetedResult(inputTarget, inputResult)); |
373 exception = inputEntry.exception; | 379 CacheEntry inputEntry = context.getCacheEntry(inputTarget); |
374 return null; | 380 CacheState inputState = inputEntry.getState(inputResult); |
375 } else if (inputState == CacheState.IN_PROCESS) { | 381 if (inputState == CacheState.ERROR) { |
376 // | 382 exception = inputEntry.exception; |
377 // TODO(brianwilkerson) Implement this case. | |
378 // | |
379 // One possibility would be to return a WorkItem that would perform a | |
380 // no-op task in order to cause us to come back to this work item on the | |
381 // next iteration. It would be more efficient, in general, to push this | |
382 // input onto a waiting list and proceed to the next input so that work | |
383 // could proceed, but given that the only result that can currently be | |
384 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort | |
385 // to implement the general solution at this point. | |
386 // | |
387 } else if (inputState != CacheState.VALID) { | |
388 try { | |
389 TaskDescriptor descriptor = | |
390 taskManager.findTask(inputTarget, inputResult); | |
391 return new WorkItem(context, inputTarget, descriptor); | |
392 } on AnalysisException catch (exception, stackTrace) { | |
393 this.exception = new CaughtException(exception, stackTrace); | |
394 return null; | 383 return null; |
384 } else if (inputState == CacheState.IN_PROCESS) { | |
385 // | |
386 // TODO(brianwilkerson) Implement this case. | |
387 // | |
388 // One possibility would be to return a WorkItem that would perform a | |
389 // no-op task in order to cause us to come back to this work item on t he | |
390 // next iteration. It would be more efficient, in general, to push thi s | |
391 // input onto a waiting list and proceed to the next input so that wor k | |
392 // could proceed, but given that the only result that can currently be | |
393 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effor t | |
394 // to implement the general solution at this point. | |
395 // | |
396 } else if (inputState != CacheState.VALID) { | |
397 try { | |
398 TaskDescriptor descriptor = | |
399 taskManager.findTask(inputTarget, inputResult); | |
400 return new WorkItem(context, inputTarget, descriptor); | |
401 } on AnalysisException catch (exception, stackTrace) { | |
402 this.exception = new CaughtException(exception, stackTrace); | |
403 return null; | |
404 } | |
405 } | |
406 builder.currentValue = inputEntry.getValue(inputResult); | |
407 if (!builder.moveNext()) { | |
408 inputs = builder.inputValue; | |
409 builder = null; | |
395 } | 410 } |
396 } | 411 } |
397 builder.currentValue = inputEntry.getValue(inputResult); | 412 return null; |
398 if (!builder.moveNext()) { | 413 } finally { |
399 inputs = builder.inputValue; | 414 taskManager.isTaskRunning = false; |
400 builder = null; | |
401 } | |
402 } | 415 } |
403 return null; | |
404 } | 416 } |
405 | 417 |
406 @override | 418 @override |
407 String toString() => 'Run $descriptor on $target'; | 419 String toString() => 'Run $descriptor on $target'; |
408 } | 420 } |
409 | 421 |
410 /** | 422 /** |
411 * [AnalysisDriver] uses [WorkManager]s to select results to compute. | 423 * [AnalysisDriver] uses [WorkManager]s to select results to compute. |
412 * | 424 * |
413 * They know specific of the targets and results they care about, | 425 * They know specific of the targets and results they care about, |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 TaskDescriptor descriptor = currentItem.descriptor; | 547 TaskDescriptor descriptor = currentItem.descriptor; |
536 AnalysisTarget target = currentItem.target; | 548 AnalysisTarget target = currentItem.target; |
537 for (WorkItem item in pendingItems) { | 549 for (WorkItem item in pendingItems) { |
538 if (item.descriptor == descriptor && item.target == target) { | 550 if (item.descriptor == descriptor && item.target == target) { |
539 return true; | 551 return true; |
540 } | 552 } |
541 } | 553 } |
542 return false; | 554 return false; |
543 } | 555 } |
544 } | 556 } |
OLD | NEW |