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 26 matching lines...) Expand all Loading... | |
| 37 * compute. | 37 * compute. |
| 38 */ | 38 */ |
| 39 final List<WorkManager> workManagers; | 39 final List<WorkManager> workManagers; |
| 40 | 40 |
| 41 /** | 41 /** |
| 42 * The context in which analysis is to be performed. | 42 * The context in which analysis is to be performed. |
| 43 */ | 43 */ |
| 44 final InternalAnalysisContext context; | 44 final InternalAnalysisContext context; |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * The alternative source of analysis results. | |
| 48 */ | |
| 49 ResultProvider resultProvider; | |
| 50 | |
| 51 /** | |
| 47 * The map of [ComputedResult] controllers. | 52 * The map of [ComputedResult] controllers. |
| 48 */ | 53 */ |
| 49 final Map<ResultDescriptor, StreamController<ComputedResult>> | 54 final Map<ResultDescriptor, StreamController<ComputedResult>> |
| 50 resultComputedControllers = | 55 resultComputedControllers = |
| 51 <ResultDescriptor, StreamController<ComputedResult>>{}; | 56 <ResultDescriptor, StreamController<ComputedResult>>{}; |
| 52 | 57 |
| 53 /** | 58 /** |
| 54 * The work order that was previously computed but that has not yet been | 59 * The work order that was previously computed but that has not yet been |
| 55 * completed. | 60 * completed. |
| 56 */ | 61 */ |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 AnalysisTarget target, ResultDescriptor result) { | 165 AnalysisTarget target, ResultDescriptor result) { |
| 161 CacheEntry entry = context.getCacheEntry(target); | 166 CacheEntry entry = context.getCacheEntry(target); |
| 162 CacheState state = entry.getState(result); | 167 CacheState state = entry.getState(result); |
| 163 if (state == CacheState.VALID || | 168 if (state == CacheState.VALID || |
| 164 state == CacheState.ERROR || | 169 state == CacheState.ERROR || |
| 165 state == CacheState.IN_PROCESS) { | 170 state == CacheState.IN_PROCESS) { |
| 166 return null; | 171 return null; |
| 167 } | 172 } |
| 168 TaskDescriptor taskDescriptor = taskManager.findTask(target, result); | 173 TaskDescriptor taskDescriptor = taskManager.findTask(target, result); |
| 169 try { | 174 try { |
| 170 WorkItem workItem = | 175 WorkItem workItem = new WorkItem( |
| 171 new WorkItem(context, target, taskDescriptor, result, 0, null); | 176 context, resultProvider, target, taskDescriptor, result, 0, null); |
| 172 return new WorkOrder(taskManager, workItem); | 177 return new WorkOrder(taskManager, workItem); |
| 173 } catch (exception, stackTrace) { | 178 } catch (exception, stackTrace) { |
| 174 throw new AnalysisException( | 179 throw new AnalysisException( |
| 175 'Could not create work order (target = $target; taskDescriptor = $task Descriptor; result = $result)', | 180 'Could not create work order (target = $target; taskDescriptor = $task Descriptor; result = $result)', |
| 176 new CaughtException(exception, stackTrace)); | 181 new CaughtException(exception, stackTrace)); |
| 177 } | 182 } |
| 178 } | 183 } |
| 179 | 184 |
| 180 /** | 185 /** |
| 181 * Create a work order that will produce the required analysis results for | 186 * Create a work order that will produce the required analysis results for |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 * Initialize a newly created exception to represent a failed attempt to | 502 * Initialize a newly created exception to represent a failed attempt to |
| 498 * perform the given [task] due to the given [dependencyCycle]. | 503 * perform the given [task] due to the given [dependencyCycle]. |
| 499 */ | 504 */ |
| 500 InfiniteTaskLoopException(AnalysisTask task, this.dependencyCycle, | 505 InfiniteTaskLoopException(AnalysisTask task, this.dependencyCycle, |
| 501 [this.cyclicPath]) | 506 [this.cyclicPath]) |
| 502 : super( | 507 : super( |
| 503 'Infinite loop while performing task ${task.descriptor.name} for ${t ask.target}'); | 508 'Infinite loop while performing task ${task.descriptor.name} for ${t ask.target}'); |
| 504 } | 509 } |
| 505 | 510 |
| 506 /** | 511 /** |
| 507 * Object used by CycleAwareDependencyWalker to report a single strongly | 512 * The object used by [WorkItem] to get values without using tasks. |
| 513 */ | |
| 514 abstract class ResultProvider { | |
| 515 /** | |
| 516 * [WorkItem] call this method when the [result] of the [entry] is | |
|
Paul Berry
2015/12/20 15:30:48
s/call/calls/
| |
| 517 * [CacheState.INVALID], so it is about to schedule its computation. | |
| 518 * | |
| 519 * If the provider knows how to provide the value, it sets the value into | |
| 520 * the [entry] with all required dependencies, and returns `true`. | |
| 521 * | |
| 522 * Otherwise, return `false` and the value will be computed. | |
|
Paul Berry
2015/12/20 15:30:48
Grammar seems a little funny here. How about:
"
| |
| 523 */ | |
| 524 bool provideResult(InternalAnalysisContext context, CacheEntry entry, | |
| 525 ResultDescriptor result); | |
| 526 } | |
| 527 | |
| 528 /** | |
| 529 * Object used by [CycleAwareDependencyWalker] to report a single strongly | |
| 508 * connected component of nodes. | 530 * connected component of nodes. |
| 509 */ | 531 */ |
| 510 class StronglyConnectedComponent<Node> { | 532 class StronglyConnectedComponent<Node> { |
| 511 /** | 533 /** |
| 512 * The nodes contained in the strongly connected component. | 534 * The nodes contained in the strongly connected component. |
| 513 */ | 535 */ |
| 514 final List<Node> nodes; | 536 final List<Node> nodes; |
| 515 | 537 |
| 516 /** | 538 /** |
| 517 * Indicates whether the strongly component contains any cycles. Note that | 539 * Indicates whether the strongly component contains any cycles. Note that |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 528 * A description of a single analysis task that can be performed to advance | 550 * A description of a single analysis task that can be performed to advance |
| 529 * analysis. | 551 * analysis. |
| 530 */ | 552 */ |
| 531 class WorkItem { | 553 class WorkItem { |
| 532 /** | 554 /** |
| 533 * The context in which the task will be performed. | 555 * The context in which the task will be performed. |
| 534 */ | 556 */ |
| 535 final InternalAnalysisContext context; | 557 final InternalAnalysisContext context; |
| 536 | 558 |
| 537 /** | 559 /** |
| 560 * The alternative source of analysis results. | |
| 561 */ | |
| 562 final ResultProvider resultProvider; | |
| 563 | |
| 564 /** | |
| 538 * The target for which a task is to be performed. | 565 * The target for which a task is to be performed. |
| 539 */ | 566 */ |
| 540 final AnalysisTarget target; | 567 final AnalysisTarget target; |
| 541 | 568 |
| 542 /** | 569 /** |
| 543 * A description of the task to be performed. | 570 * A description of the task to be performed. |
| 544 */ | 571 */ |
| 545 final TaskDescriptor descriptor; | 572 final TaskDescriptor descriptor; |
| 546 | 573 |
| 547 /** | 574 /** |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 * the set of [WorkItem]s contained in the cycle (if there are overlapping | 617 * the set of [WorkItem]s contained in the cycle (if there are overlapping |
| 591 * cycles, this is the set of all [WorkItem]s in the entire strongly | 618 * cycles, this is the set of all [WorkItem]s in the entire strongly |
| 592 * connected component). Otherwise, `null`. | 619 * connected component). Otherwise, `null`. |
| 593 */ | 620 */ |
| 594 List<WorkItem> dependencyCycle; | 621 List<WorkItem> dependencyCycle; |
| 595 | 622 |
| 596 /** | 623 /** |
| 597 * Initialize a newly created work item to compute the inputs for the task | 624 * Initialize a newly created work item to compute the inputs for the task |
| 598 * described by the given descriptor. | 625 * described by the given descriptor. |
| 599 */ | 626 */ |
| 600 WorkItem(this.context, this.target, this.descriptor, this.spawningResult, | 627 WorkItem(this.context, this.resultProvider, this.target, this.descriptor, |
| 601 this.level, this.workOrder) { | 628 this.spawningResult, this.level, this.workOrder) { |
| 602 AnalysisTarget actualTarget = | 629 AnalysisTarget actualTarget = |
| 603 identical(target, AnalysisContextTarget.request) | 630 identical(target, AnalysisContextTarget.request) |
| 604 ? new AnalysisContextTarget(context) | 631 ? new AnalysisContextTarget(context) |
| 605 : target; | 632 : target; |
| 606 // print('${'\t' * level}$spawningResult of $actualTarget'); | 633 // print('${'\t' * level}$spawningResult of $actualTarget'); |
| 607 Map<String, TaskInput> inputDescriptors = | 634 Map<String, TaskInput> inputDescriptors = |
| 608 descriptor.createTaskInputs(actualTarget); | 635 descriptor.createTaskInputs(actualTarget); |
| 609 builder = new TopLevelTaskInputBuilder(inputDescriptors); | 636 builder = new TopLevelTaskInputBuilder(inputDescriptors); |
| 610 if (!builder.moveNext()) { | 637 if (!builder.moveNext()) { |
| 611 builder = null; | 638 builder = null; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 695 // One possibility would be to return a WorkItem that would perform a | 722 // One possibility would be to return a WorkItem that would perform a |
| 696 // no-op task in order to cause us to come back to this work item on the | 723 // no-op task in order to cause us to come back to this work item on the |
| 697 // next iteration. It would be more efficient, in general, to push this | 724 // next iteration. It would be more efficient, in general, to push this |
| 698 // input onto a waiting list and proceed to the next input so that work | 725 // input onto a waiting list and proceed to the next input so that work |
| 699 // could proceed, but given that the only result that can currently be | 726 // could proceed, but given that the only result that can currently be |
| 700 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort | 727 // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort |
| 701 // to implement the general solution at this point. | 728 // to implement the general solution at this point. |
| 702 // | 729 // |
| 703 throw new UnimplementedError(); | 730 throw new UnimplementedError(); |
| 704 } else if (inputState != CacheState.VALID) { | 731 } else if (inputState != CacheState.VALID) { |
| 705 try { | 732 if (resultProvider != null && |
|
Brian Wilkerson
2015/12/21 17:01:44
I'm guessing that the null check will eventually b
| |
| 706 TaskDescriptor descriptor = | 733 resultProvider.provideResult(context, inputEntry, inputResult)) { |
| 707 taskManager.findTask(inputTarget, inputResult); | 734 inputState = CacheState.VALID; |
| 708 return new WorkItem(context, inputTarget, descriptor, inputResult, | 735 builder.currentValue = inputEntry.getValue(inputResult); |
| 709 level + 1, workOrder); | 736 } else { |
| 710 } on AnalysisException catch (exception, stackTrace) { | 737 try { |
| 711 this.exception = new CaughtException(exception, stackTrace); | 738 TaskDescriptor descriptor = |
| 712 return null; | 739 taskManager.findTask(inputTarget, inputResult); |
| 740 return new WorkItem(context, resultProvider, inputTarget, | |
| 741 descriptor, inputResult, level + 1, workOrder); | |
| 742 } on AnalysisException catch (exception, stackTrace) { | |
| 743 this.exception = new CaughtException(exception, stackTrace); | |
| 744 return null; | |
| 745 } | |
| 713 } | 746 } |
| 714 } else { | 747 } else { |
| 715 builder.currentValue = inputEntry.getValue(inputResult); | 748 builder.currentValue = inputEntry.getValue(inputResult); |
| 716 if (builder.flushOnAccess) { | 749 if (builder.flushOnAccess) { |
| 717 inputEntry.setState(inputResult, CacheState.FLUSHED); | 750 inputEntry.setState(inputResult, CacheState.FLUSHED); |
| 718 } | 751 } |
| 719 } | 752 } |
| 720 if (!builder.moveNext()) { | 753 if (!builder.moveNext()) { |
| 721 inputs = builder.inputValue; | 754 inputs = builder.inputValue; |
| 722 builder = null; | 755 builder = null; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 809 final TaskManager taskManager; | 842 final TaskManager taskManager; |
| 810 | 843 |
| 811 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode) | 844 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode) |
| 812 : super(startingNode); | 845 : super(startingNode); |
| 813 | 846 |
| 814 @override | 847 @override |
| 815 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) { | 848 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) { |
| 816 return node.gatherInputs(taskManager, skipInputs); | 849 return node.gatherInputs(taskManager, skipInputs); |
| 817 } | 850 } |
| 818 } | 851 } |
| OLD | NEW |