Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: pkg/analyzer/lib/src/task/driver.dart

Issue 1311773005: Extension point for WorkManagerFactory(s). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Move classes as by review comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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';
11 import 'package:analyzer/src/generated/engine.dart' 11 import 'package:analyzer/src/generated/engine.dart'
12 hide AnalysisTask, AnalysisContextImpl; 12 hide AnalysisTask, AnalysisContextImpl, WorkManager;
13 import 'package:analyzer/src/generated/java_engine.dart'; 13 import 'package:analyzer/src/generated/java_engine.dart';
14 import 'package:analyzer/src/generated/resolver.dart'; 14 import 'package:analyzer/src/generated/resolver.dart';
15 import 'package:analyzer/src/generated/utilities_general.dart'; 15 import 'package:analyzer/src/generated/utilities_general.dart';
16 import 'package:analyzer/src/task/inputs.dart'; 16 import 'package:analyzer/src/task/inputs.dart';
17 import 'package:analyzer/src/task/manager.dart'; 17 import 'package:analyzer/src/task/manager.dart';
18 import 'package:analyzer/task/model.dart'; 18 import 'package:analyzer/task/model.dart';
19 19
20 final PerformanceTag workOrderMoveNextPerfTag = 20 final PerformanceTag workOrderMoveNextPerfTag =
21 new PerformanceTag('WorkOrder.moveNext'); 21 new PerformanceTag('WorkOrder.moveNext');
22 22
(...skipping 14 matching lines...) Expand all
37 final List<WorkManager> workManagers; 37 final List<WorkManager> workManagers;
38 38
39 /** 39 /**
40 * The context in which analysis is to be performed. 40 * The context in which analysis is to be performed.
41 */ 41 */
42 final InternalAnalysisContext context; 42 final InternalAnalysisContext context;
43 43
44 /** 44 /**
45 * The map of [ComputedResult] controllers. 45 * The map of [ComputedResult] controllers.
46 */ 46 */
47 final Map<ResultDescriptor, StreamController<ComputedResult>> resultComputedCo ntrollers = 47 final Map<ResultDescriptor,
48 StreamController<ComputedResult>> resultComputedControllers =
48 <ResultDescriptor, StreamController<ComputedResult>>{}; 49 <ResultDescriptor, StreamController<ComputedResult>>{};
49 50
50 /** 51 /**
51 * The work order that was previously computed but that has not yet been 52 * The work order that was previously computed but that has not yet been
52 * completed. 53 * completed.
53 */ 54 */
54 WorkOrder currentWorkOrder; 55 WorkOrder currentWorkOrder;
55 56
56 /** 57 /**
57 * Indicates whether any tasks are currently being performed (or building 58 * Indicates whether any tasks are currently being performed (or building
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 } 191 }
191 } 192 }
192 return null; 193 return null;
193 } 194 }
194 195
195 /** 196 /**
196 * Return the stream that is notified when a new value for the given 197 * Return the stream that is notified when a new value for the given
197 * [descriptor] is computed. 198 * [descriptor] is computed.
198 */ 199 */
199 Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) { 200 Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
200 return resultComputedControllers.putIfAbsent(descriptor, () => 201 return resultComputedControllers
201 new StreamController<ComputedResult>.broadcast(sync: true)).stream; 202 .putIfAbsent(descriptor,
203 () => new StreamController<ComputedResult>.broadcast(sync: true))
204 .stream;
202 } 205 }
203 206
204 /** 207 /**
205 * Perform the next analysis task, and return `true` if there is more work to 208 * Perform the next analysis task, and return `true` if there is more work to
206 * be done in order to compute all of the required analysis information. 209 * be done in order to compute all of the required analysis information.
207 */ 210 */
208 bool performAnalysisTask() { 211 bool performAnalysisTask() {
209 // 212 //
210 // TODO(brianwilkerson) This implementaiton does not allow us to prioritize 213 // TODO(brianwilkerson) This implementaiton does not allow us to prioritize
211 // work across contexts. What we need is a way for an external client to ask 214 // work across contexts. What we need is a way for an external client to ask
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 * the set of [WorkItem]s contained in the cycle (if there are overlapping 472 * the set of [WorkItem]s contained in the cycle (if there are overlapping
470 * cycles, this is the set of all [WorkItem]s in the entire strongly 473 * cycles, this is the set of all [WorkItem]s in the entire strongly
471 * connected component). Otherwise, `null`. 474 * connected component). Otherwise, `null`.
472 */ 475 */
473 final List<WorkItem> dependencyCycle; 476 final List<WorkItem> dependencyCycle;
474 477
475 /** 478 /**
476 * Initialize a newly created exception to represent a failed attempt to 479 * Initialize a newly created exception to represent a failed attempt to
477 * perform the given [task] due to the given [dependencyCycle]. 480 * perform the given [task] due to the given [dependencyCycle].
478 */ 481 */
479 InfiniteTaskLoopException(AnalysisTask task, this.dependencyCycle) : super( 482 InfiniteTaskLoopException(AnalysisTask task, this.dependencyCycle)
480 'Infinite loop while performing task ${task.descriptor.name} for ${tas k.target}'); 483 : super(
484 'Infinite loop while performing task ${task.descriptor.name} for ${t ask.target}');
481 } 485 }
482 486
483 /** 487 /**
484 * Object used by CycleAwareDependencyWalker to report a single strongly 488 * Object used by CycleAwareDependencyWalker to report a single strongly
485 * connected component of nodes. 489 * connected component of nodes.
486 */ 490 */
487 class StronglyConnectedComponent<Node> { 491 class StronglyConnectedComponent<Node> {
488 /** 492 /**
489 * The nodes contained in the strongly connected component. 493 * The nodes contained in the strongly connected component.
490 */ 494 */
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 * cycles, this is the set of all [WorkItem]s in the entire strongly 562 * cycles, this is the set of all [WorkItem]s in the entire strongly
559 * connected component). Otherwise, `null`. 563 * connected component). Otherwise, `null`.
560 */ 564 */
561 List<WorkItem> dependencyCycle; 565 List<WorkItem> dependencyCycle;
562 566
563 /** 567 /**
564 * Initialize a newly created work item to compute the inputs for the task 568 * Initialize a newly created work item to compute the inputs for the task
565 * described by the given descriptor. 569 * described by the given descriptor.
566 */ 570 */
567 WorkItem(this.context, this.target, this.descriptor, this.spawningResult) { 571 WorkItem(this.context, this.target, this.descriptor, this.spawningResult) {
568 AnalysisTarget actualTarget = identical( 572 AnalysisTarget actualTarget =
569 target, AnalysisContextTarget.request) 573 identical(target, AnalysisContextTarget.request)
570 ? new AnalysisContextTarget(context) 574 ? new AnalysisContextTarget(context)
571 : target; 575 : target;
572 Map<String, TaskInput> inputDescriptors = 576 Map<String, TaskInput> inputDescriptors =
573 descriptor.createTaskInputs(actualTarget); 577 descriptor.createTaskInputs(actualTarget);
574 builder = new TopLevelTaskInputBuilder(inputDescriptors); 578 builder = new TopLevelTaskInputBuilder(inputDescriptors);
575 if (!builder.moveNext()) { 579 if (!builder.moveNext()) {
576 builder = null; 580 builder = null;
577 } 581 }
578 inputs = new HashMap<String, dynamic>(); 582 inputs = new HashMap<String, dynamic>();
579 } 583 }
580 584
581 @override 585 @override
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 } 669 }
666 } 670 }
667 return null; 671 return null;
668 } 672 }
669 673
670 @override 674 @override
671 String toString() => 'Run $descriptor on $target'; 675 String toString() => 'Run $descriptor on $target';
672 } 676 }
673 677
674 /** 678 /**
675 * [AnalysisDriver] uses [WorkManager]s to select results to compute.
676 *
677 * They know specific of the targets and results they care about,
678 * so they can request analysis results in optimal order.
679 */
680 abstract class WorkManager {
681 /**
682 * Notifies the managers that the given set of priority [targets] was set.
683 */
684 void applyPriorityTargets(List<AnalysisTarget> targets);
685
686 /**
687 * Return the next [TargetedResult] that this work manager wants to be
688 * computed, or `null` if this manager doesn't need any new results.
689 */
690 TargetedResult getNextResult();
691
692 /**
693 * Return the priority if the next work order this work manager want to be
694 * computed. The [AnalysisDriver] will perform the work order with
695 * the highest priority.
696 *
697 * Even if the returned value is [WorkOrderPriority.NONE], it still does not
698 * guarantee that [getNextResult] will return not `null`.
699 */
700 WorkOrderPriority getNextResultPriority();
701
702 /**
703 * Notifies the manager that the given [outputs] were produced for
704 * the given [target].
705 */
706 void resultsComputed(
707 AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs);
708 }
709
710 /**
711 * A description of the work to be done to compute a desired analysis result. 679 * A description of the work to be done to compute a desired analysis result.
712 * The class implements a lazy depth-first traversal of the work item's input. 680 * The class implements a lazy depth-first traversal of the work item's input.
713 */ 681 */
714 class WorkOrder implements Iterator<WorkItem> { 682 class WorkOrder implements Iterator<WorkItem> {
715 /** 683 /**
716 * The dependency walker which is being used to determine what work to do 684 * The dependency walker which is being used to determine what work to do
717 * next. 685 * next.
718 */ 686 */
719 final _WorkOrderDependencyWalker _dependencyWalker; 687 final _WorkOrderDependencyWalker _dependencyWalker;
720 688
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 } else { 735 } else {
768 assert(currentItems.length == 1); 736 assert(currentItems.length == 1);
769 } 737 }
770 return true; 738 return true;
771 } 739 }
772 }); 740 });
773 } 741 }
774 } 742 }
775 743
776 /** 744 /**
777 * The priorities of work orders returned by [WorkManager]s.
778 */
779 enum WorkOrderPriority {
780 /**
781 * Responding to an user's action.
782 */
783 INTERACTIVE,
784
785 /**
786 * Computing information for priority sources.
787 */
788 PRIORITY,
789
790 /**
791 * A work should be done, but without any special urgency.
792 */
793 NORMAL,
794
795 /**
796 * Nothing to do.
797 */
798 NONE
799 }
800
801 /**
802 * Specilaization of [CycleAwareDependencyWalker] for use by [WorkOrder]. 745 * Specilaization of [CycleAwareDependencyWalker] for use by [WorkOrder].
803 */ 746 */
804 class _WorkOrderDependencyWalker extends CycleAwareDependencyWalker<WorkItem> { 747 class _WorkOrderDependencyWalker extends CycleAwareDependencyWalker<WorkItem> {
805 /** 748 /**
806 * The task manager used to build work items. 749 * The task manager used to build work items.
807 */ 750 */
808 final TaskManager taskManager; 751 final TaskManager taskManager;
809 752
810 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode) 753 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode)
811 : super(startingNode); 754 : super(startingNode);
812 755
813 @override 756 @override
814 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) { 757 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) {
815 return node.gatherInputs(taskManager, skipInputs); 758 return node.gatherInputs(taskManager, skipInputs);
816 } 759 }
817 } 760 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698