Chromium Code Reviews| 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 |