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

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

Issue 1539093002: ResultProvider - an alternative source of analysis results. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years 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
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/driver_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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';
(...skipping 26 matching lines...) Expand all
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/driver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698