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