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

Side by Side Diff: pkg/analyzer/lib/task/model.dart

Issue 1147853002: Properly handle circular references among constants in the task model. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 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.task.model; 5 library analyzer.task.model;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; 9 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
10 import 'package:analyzer/src/generated/java_engine.dart'; 10 import 'package:analyzer/src/generated/java_engine.dart';
11 import 'package:analyzer/src/generated/source.dart'; 11 import 'package:analyzer/src/generated/source.dart';
12 import 'package:analyzer/src/task/driver.dart';
12 import 'package:analyzer/src/task/model.dart'; 13 import 'package:analyzer/src/task/model.dart';
13 14
14 /** 15 /**
15 * A function that converts the given [key] and [value] into a [TaskInput]. 16 * A function that converts the given [key] and [value] into a [TaskInput].
16 */ 17 */
17 typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value); 18 typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value);
18 19
19 /** 20 /**
20 * A function that takes an analysis [context] and an analysis [target] and 21 * A function that takes an analysis [context] and an analysis [target] and
21 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to 22 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 Map<ResultDescriptor, dynamic> outputs = 110 Map<ResultDescriptor, dynamic> outputs =
110 new HashMap<ResultDescriptor, dynamic>(); 111 new HashMap<ResultDescriptor, dynamic>();
111 112
112 /** 113 /**
113 * The exception that was thrown while performing this task, or `null` if the 114 * The exception that was thrown while performing this task, or `null` if the
114 * task completed successfully. 115 * task completed successfully.
115 */ 116 */
116 CaughtException caughtException; 117 CaughtException caughtException;
117 118
118 /** 119 /**
120 * If a dependency cycle was found while computing the inputs for the task,
121 * the set of [WorkItem]s contained in the cycle (if there are overlapping
122 * cycles, this is the set of all [WorkItem]s in the entire strongly
123 * connected component). Otherwise, `null`.
124 */
125 List<WorkItem> dependencyCycle;
126
127 /**
119 * Initialize a newly created task to perform analysis within the given 128 * Initialize a newly created task to perform analysis within the given
120 * [context] in order to produce results for the given [target]. 129 * [context] in order to produce results for the given [target].
121 */ 130 */
122 AnalysisTask(this.context, this.target); 131 AnalysisTask(this.context, this.target);
123 132
124 /** 133 /**
125 * Return a textual description of this task. 134 * Return a textual description of this task.
126 */ 135 */
127 String get description; 136 String get description;
128 137
129 /** 138 /**
130 * Return the descriptor that describes this task. 139 * Return the descriptor that describes this task.
131 */ 140 */
132 TaskDescriptor get descriptor; 141 TaskDescriptor get descriptor;
133 142
134 /** 143 /**
144 * Indicates whether the task is capable of handling dependency cycles. A
145 * task that overrides this getter to return `true` must be prepared for the
146 * possibility that it will be invoked with a non-`null` value of
147 * [dependencyCycle], and with not all of its inputs computed.
148 */
149 bool get handlesDependencyCycles => false;
150
151 /**
135 * Return the value of the input with the given [name]. Throw an exception if 152 * Return the value of the input with the given [name]. Throw an exception if
136 * the input value is not defined. 153 * the input value is not defined.
137 */ 154 */
138 Object getRequiredInput(String name) { 155 Object getRequiredInput(String name) {
139 if (inputs == null || !inputs.containsKey(name)) { 156 if (inputs == null || !inputs.containsKey(name)) {
140 throw new AnalysisException("Could not $description: missing $name"); 157 throw new AnalysisException("Could not $description: missing $name");
141 } 158 }
142 return inputs[name]; 159 return inputs[name];
143 } 160 }
144 161
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 Stopwatch stopwatch = stopwatchMap[runtimeType]; 229 Stopwatch stopwatch = stopwatchMap[runtimeType];
213 if (stopwatch == null) { 230 if (stopwatch == null) {
214 stopwatch = new Stopwatch(); 231 stopwatch = new Stopwatch();
215 stopwatchMap[runtimeType] = stopwatch; 232 stopwatchMap[runtimeType] = stopwatch;
216 } 233 }
217 stopwatch.start(); 234 stopwatch.start();
218 // 235 //
219 // Actually perform the task. 236 // Actually perform the task.
220 // 237 //
221 try { 238 try {
239 if (dependencyCycle != null && !handlesDependencyCycles) {
240 throw new InfiniteTaskLoopException(this, dependencyCycle);
241 }
222 internalPerform(); 242 internalPerform();
223 } finally { 243 } finally {
224 stopwatch.stop(); 244 stopwatch.stop();
225 } 245 }
226 } on AnalysisException { 246 } on AnalysisException {
227 rethrow; 247 rethrow;
228 } catch (exception, stackTrace) { 248 } catch (exception, stackTrace) {
229 throw new AnalysisException( 249 throw new AnalysisException(
230 'Unexpected exception while performing $description', 250 'Unexpected exception while performing $description',
231 new CaughtException(exception, stackTrace)); 251 new CaughtException(exception, stackTrace));
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 * Throws a [StateError] if [moveNext] has not been invoked or if the last 474 * Throws a [StateError] if [moveNext] has not been invoked or if the last
455 * invocation of [moveNext] returned `false`. 475 * invocation of [moveNext] returned `false`.
456 */ 476 */
457 void set currentValue(Object value); 477 void set currentValue(Object value);
458 478
459 /** 479 /**
460 * Return the [value] that was computed by this builder. 480 * Return the [value] that was computed by this builder.
461 * 481 *
462 * Throws a [StateError] if [moveNext] has not been invoked or if the last 482 * Throws a [StateError] if [moveNext] has not been invoked or if the last
463 * invocation of [moveNext] returned `true`. 483 * invocation of [moveNext] returned `true`.
484 *
485 * Returns `null` if no value could be computed due to a circular dependency.
464 */ 486 */
465 V get inputValue; 487 V get inputValue;
466 488
467 /** 489 /**
490 * Record that no value is available for the current result, due to a
491 * circular dependency.
492 *
493 * Throws a [StateError] if [moveNext] has not been invoked or if the last
494 * invocation of [moveNext] returned `false`.
495 */
496 void currentValueNotAvailable();
497
498 /**
468 * Move to the next result that needs to be computed in order to build the 499 * Move to the next result that needs to be computed in order to build the
469 * inputs for a task. Return `true` if there is another result that needs to 500 * inputs for a task. Return `true` if there is another result that needs to
470 * be computed, or `false` if the inputs have been computed. 501 * be computed, or `false` if the inputs have been computed.
471 * 502 *
472 * It is safe to invoke [moveNext] after it has returned `false`. In this case 503 * It is safe to invoke [moveNext] after it has returned `false`. In this case
473 * [moveNext] has no effect and will again return `false`. 504 * [moveNext] has no effect and will again return `false`.
474 * 505 *
475 * Throws a [StateError] if the value of the current result has not been 506 * Throws a [StateError] if the value of the current result has not been
476 * provided using [currentValue]. 507 * provided using [currentValue].
477 */ 508 */
478 bool moveNext(); 509 bool moveNext();
479 } 510 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698