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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 WorkOrder createWorkOrderForResult( | 117 WorkOrder createWorkOrderForResult( |
| 118 AnalysisTarget target, ResultDescriptor result) { | 118 AnalysisTarget target, ResultDescriptor result) { |
| 119 CacheEntry entry = context.getCacheEntry(target); | 119 CacheEntry entry = context.getCacheEntry(target); |
| 120 CacheState state = entry.getState(result); | 120 CacheState state = entry.getState(result); |
| 121 if (state == CacheState.VALID || | 121 if (state == CacheState.VALID || |
| 122 state == CacheState.ERROR || | 122 state == CacheState.ERROR || |
| 123 state == CacheState.IN_PROCESS) { | 123 state == CacheState.IN_PROCESS) { |
| 124 return null; | 124 return null; |
| 125 } | 125 } |
| 126 try { | 126 try { |
| 127 return new WorkOrder(taskManager, | 127 TaskDescriptor taskDescriptor = taskManager.findTask(target, result); |
| 128 new WorkItem(context, target, taskManager.findTask(target, result))); | 128 var memento = entry.getMemento(result); |
| 129 var workItem = new WorkItem(context, target, taskDescriptor, memento); | |
| 130 return new WorkOrder(taskManager, workItem); | |
| 129 } catch (exception, stackTrace) { | 131 } catch (exception, stackTrace) { |
| 130 throw new AnalysisException( | 132 throw new AnalysisException( |
| 131 'Could not create work order (target = $target; result = $result)', | 133 'Could not create work order (target = $target; result = $result)', |
| 132 new CaughtException(exception, stackTrace)); | 134 new CaughtException(exception, stackTrace)); |
| 133 } | 135 } |
| 134 } | 136 } |
| 135 | 137 |
| 136 /** | 138 /** |
| 137 * Create a work order that will produce the required analysis results for | 139 * Create a work order that will produce the required analysis results for |
| 138 * the given [target]. If [isPriority] is true, then the target is a priority | 140 * the given [target]. If [isPriority] is true, then the target is a priority |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 AnalysisTask task = item.buildTask(); | 210 AnalysisTask task = item.buildTask(); |
| 209 _onTaskStartedController.add(task); | 211 _onTaskStartedController.add(task); |
| 210 task.perform(); | 212 task.perform(); |
| 211 CacheEntry entry = context.getCacheEntry(task.target); | 213 CacheEntry entry = context.getCacheEntry(task.target); |
| 212 if (task.caughtException == null) { | 214 if (task.caughtException == null) { |
| 213 List<TargetedResult> dependedOn = item.inputTargetedResults.toList(); | 215 List<TargetedResult> dependedOn = item.inputTargetedResults.toList(); |
| 214 Map<ResultDescriptor, dynamic> outputs = task.outputs; | 216 Map<ResultDescriptor, dynamic> outputs = task.outputs; |
| 215 for (ResultDescriptor result in task.descriptor.results) { | 217 for (ResultDescriptor result in task.descriptor.results) { |
| 216 // TODO(brianwilkerson) We could check here that a value was produced | 218 // TODO(brianwilkerson) We could check here that a value was produced |
| 217 // and throw an exception if not (unless we want to allow null values). | 219 // and throw an exception if not (unless we want to allow null values). |
| 218 entry.setValue(result, outputs[result], dependedOn); | 220 entry.setValue(result, outputs[result], dependedOn, task.outputMemento); |
| 219 } | 221 } |
| 220 } else { | 222 } else { |
| 221 entry.setErrorState(task.caughtException, item.descriptor.results); | 223 entry.setErrorState(task.caughtException, item.descriptor.results); |
| 222 } | 224 } |
| 223 _onTaskCompletedController.add(task); | 225 _onTaskCompletedController.add(task); |
| 224 return task; | 226 return task; |
| 225 } | 227 } |
| 226 | 228 |
| 227 /** | 229 /** |
| 228 * Reset the state of the driver in response to a change in the state of one | 230 * Reset the state of the driver in response to a change in the state of one |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 * The target for which a task is to be performed. | 275 * The target for which a task is to be performed. |
| 274 */ | 276 */ |
| 275 final AnalysisTarget target; | 277 final AnalysisTarget target; |
| 276 | 278 |
| 277 /** | 279 /** |
| 278 * A description of the task to be performed. | 280 * A description of the task to be performed. |
| 279 */ | 281 */ |
| 280 final TaskDescriptor descriptor; | 282 final TaskDescriptor descriptor; |
| 281 | 283 |
| 282 /** | 284 /** |
| 285 * The optional data that the task associated with [target] last time. | |
| 286 * This data may help to compute outputs more efficiently. | |
| 287 */ | |
| 288 final memento; | |
|
Brian Wilkerson
2015/05/04 16:22:09
Should this be "inputMemento"?
| |
| 289 | |
| 290 /** | |
| 283 * An iterator used to iterate over the descriptors of the inputs to the task, | 291 * An iterator used to iterate over the descriptors of the inputs to the task, |
| 284 * or `null` if all of the inputs have been collected and the task can be | 292 * or `null` if all of the inputs have been collected and the task can be |
| 285 * created. | 293 * created. |
| 286 */ | 294 */ |
| 287 TaskInputBuilder builder; | 295 TaskInputBuilder builder; |
| 288 | 296 |
| 289 /** | 297 /** |
| 290 * The [TargetedResult]s outputs of this task depends on. | 298 * The [TargetedResult]s outputs of this task depends on. |
| 291 */ | 299 */ |
| 292 final HashSet<TargetedResult> inputTargetedResults = | 300 final HashSet<TargetedResult> inputTargetedResults = |
| 293 new HashSet<TargetedResult>(); | 301 new HashSet<TargetedResult>(); |
| 294 | 302 |
| 295 /** | 303 /** |
| 296 * The inputs to the task that have been computed. | 304 * The inputs to the task that have been computed. |
| 297 */ | 305 */ |
| 298 Map<String, dynamic> inputs; | 306 Map<String, dynamic> inputs; |
| 299 | 307 |
| 300 /** | 308 /** |
| 301 * The exception that was found while trying to populate the inputs. If this | 309 * The exception that was found while trying to populate the inputs. If this |
| 302 * field is non-`null`, then the task cannot be performed and all of the | 310 * field is non-`null`, then the task cannot be performed and all of the |
| 303 * results that this task would have computed need to be marked as being in | 311 * results that this task would have computed need to be marked as being in |
| 304 * ERROR with this exception. | 312 * ERROR with this exception. |
| 305 */ | 313 */ |
| 306 CaughtException exception = null; | 314 CaughtException exception = null; |
| 307 | 315 |
| 308 /** | 316 /** |
| 309 * Initialize a newly created work item to compute the inputs for the task | 317 * Initialize a newly created work item to compute the inputs for the task |
| 310 * described by the given descriptor. | 318 * described by the given descriptor. |
| 311 */ | 319 */ |
| 312 WorkItem(this.context, this.target, this.descriptor) { | 320 WorkItem(this.context, this.target, this.descriptor, this.memento) { |
| 313 AnalysisTarget actualTarget = identical( | 321 AnalysisTarget actualTarget = identical( |
| 314 target, AnalysisContextTarget.request) | 322 target, AnalysisContextTarget.request) |
| 315 ? new AnalysisContextTarget(context) | 323 ? new AnalysisContextTarget(context) |
| 316 : target; | 324 : target; |
| 317 Map<String, TaskInput> inputDescriptors = | 325 Map<String, TaskInput> inputDescriptors = |
| 318 descriptor.createTaskInputs(actualTarget); | 326 descriptor.createTaskInputs(actualTarget); |
| 319 builder = new TopLevelTaskInputBuilder(inputDescriptors); | 327 builder = new TopLevelTaskInputBuilder(inputDescriptors); |
| 320 if (!builder.moveNext()) { | 328 if (!builder.moveNext()) { |
| 321 builder = null; | 329 builder = null; |
| 322 } | 330 } |
| 323 inputs = new HashMap<String, dynamic>(); | 331 inputs = new HashMap<String, dynamic>(); |
| 324 } | 332 } |
| 325 | 333 |
| 326 /** | 334 /** |
| 327 * Build the task represented by this work item. | 335 * Build the task represented by this work item. |
| 328 */ | 336 */ |
| 329 AnalysisTask buildTask() { | 337 AnalysisTask buildTask() { |
| 330 if (builder != null) { | 338 if (builder != null) { |
| 331 throw new StateError("some inputs have not been computed"); | 339 throw new StateError("some inputs have not been computed"); |
| 332 } | 340 } |
| 333 return descriptor.createTask(context, target, inputs); | 341 return descriptor.createTask(context, target, inputs, memento); |
| 334 } | 342 } |
| 335 | 343 |
| 336 /** | 344 /** |
| 337 * Gather all of the inputs needed to perform the task. | 345 * Gather all of the inputs needed to perform the task. |
| 338 * | 346 * |
| 339 * If at least one of the inputs have not yet been computed, return a work | 347 * If at least one of the inputs have not yet been computed, return a work |
| 340 * item that can be used to generate that input to indicate that the caller | 348 * item that can be used to generate that input to indicate that the caller |
| 341 * should perform the returned item's task before returning to gathering | 349 * should perform the returned item's task before returning to gathering |
| 342 * inputs for this item's task. | 350 * inputs for this item's task. |
| 343 * | 351 * |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 368 // next iteration. It would be more efficient, in general, to push this | 376 // next iteration. It would be more efficient, in general, to push this |
| 369 // input onto a waiting list and proceed to the next input so that work | 377 // input onto a waiting list and proceed to the next input so that work |
| 370 // could proceed, but given that the only result that can currently be | 378 // could proceed, but given that the only result that can currently be |
| 371 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort | 379 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort |
| 372 // to implement the general solution at this point. | 380 // to implement the general solution at this point. |
| 373 // | 381 // |
| 374 } else if (inputState != CacheState.VALID) { | 382 } else if (inputState != CacheState.VALID) { |
| 375 try { | 383 try { |
| 376 TaskDescriptor descriptor = | 384 TaskDescriptor descriptor = |
| 377 taskManager.findTask(inputTarget, inputResult); | 385 taskManager.findTask(inputTarget, inputResult); |
| 378 return new WorkItem(context, inputTarget, descriptor); | 386 dynamic memento = inputEntry.getMemento(inputResult); |
| 387 return new WorkItem(context, inputTarget, descriptor, memento); | |
| 379 } on AnalysisException catch (exception, stackTrace) { | 388 } on AnalysisException catch (exception, stackTrace) { |
| 380 this.exception = new CaughtException(exception, stackTrace); | 389 this.exception = new CaughtException(exception, stackTrace); |
| 381 return null; | 390 return null; |
| 382 } | 391 } |
| 383 } | 392 } |
| 384 builder.currentValue = inputEntry.getValue(inputResult); | 393 builder.currentValue = inputEntry.getValue(inputResult); |
| 385 if (!builder.moveNext()) { | 394 if (!builder.moveNext()) { |
| 386 inputs = builder.inputValue; | 395 inputs = builder.inputValue; |
| 387 builder = null; | 396 builder = null; |
| 388 } | 397 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 TaskDescriptor descriptor = currentItem.descriptor; | 470 TaskDescriptor descriptor = currentItem.descriptor; |
| 462 AnalysisTarget target = currentItem.target; | 471 AnalysisTarget target = currentItem.target; |
| 463 for (WorkItem item in pendingItems) { | 472 for (WorkItem item in pendingItems) { |
| 464 if (item.descriptor == descriptor && item.target == target) { | 473 if (item.descriptor == descriptor && item.target == target) { |
| 465 return true; | 474 return true; |
| 466 } | 475 } |
| 467 } | 476 } |
| 468 return false; | 477 return false; |
| 469 } | 478 } |
| 470 } | 479 } |
| OLD | NEW |