| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // BSD-style license that can be found in the LICENSE file. | 
|  | 4 | 
|  | 5 library analyzer.task.model; | 
|  | 6 | 
|  | 7 import 'dart:collection'; | 
|  | 8 | 
|  | 9 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; | 
|  | 10 import 'package:analyzer/src/generated/error.dart' show AnalysisError; | 
|  | 11 import 'package:analyzer/src/generated/java_engine.dart'; | 
|  | 12 import 'package:analyzer/src/generated/source.dart'; | 
|  | 13 import 'package:analyzer/src/generated/utilities_general.dart'; | 
|  | 14 import 'package:analyzer/src/task/driver.dart'; | 
|  | 15 import 'package:analyzer/src/task/model.dart'; | 
|  | 16 | 
|  | 17 /** | 
|  | 18  * A function that converts the given [key] and [value] into a [TaskInput]. | 
|  | 19  */ | 
|  | 20 typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value); | 
|  | 21 | 
|  | 22 /** | 
|  | 23  * A function that takes an analysis [context] and an analysis [target] and | 
|  | 24  * returns an analysis task. Such functions are passed to a [TaskDescriptor] to | 
|  | 25  * be used to create the described task. | 
|  | 26  */ | 
|  | 27 typedef AnalysisTask BuildTask(AnalysisContext context, AnalysisTarget target); | 
|  | 28 | 
|  | 29 /** | 
|  | 30  * A function that takes the target for which a task will produce results and | 
|  | 31  * returns a map from input names to descriptions of the analysis results needed | 
|  | 32  * by the task in order for the task to be performed. Such functions are passed | 
|  | 33  * to a [TaskDescriptor] to be used to determine the inputs needed by the task. | 
|  | 34  */ | 
|  | 35 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target); | 
|  | 36 | 
|  | 37 /** | 
|  | 38  * A function that converts an object of the type [B] into a [TaskInput]. | 
|  | 39  * This is used, for example, by a [ListTaskInput] to create task inputs | 
|  | 40  * for each value in a list of values. | 
|  | 41  */ | 
|  | 42 typedef TaskInput<E> UnaryFunction<B, E>(B object); | 
|  | 43 | 
|  | 44 /** | 
|  | 45  * An [AnalysisTarget] wrapper for an [AnalysisContext]. | 
|  | 46  */ | 
|  | 47 class AnalysisContextTarget implements AnalysisTarget { | 
|  | 48   static final AnalysisContextTarget request = new AnalysisContextTarget(null); | 
|  | 49 | 
|  | 50   final AnalysisContext context; | 
|  | 51 | 
|  | 52   AnalysisContextTarget(this.context); | 
|  | 53 | 
|  | 54   @override | 
|  | 55   Source get source => null; | 
|  | 56 } | 
|  | 57 | 
|  | 58 /** | 
|  | 59  * An object with which an analysis result can be associated. | 
|  | 60  * | 
|  | 61  * Clients are allowed to subtype this class when creating new kinds of targets. | 
|  | 62  * Instances of this type are used in hashed data structures, so subtypes are | 
|  | 63  * required to correctly implement [==] and [hashCode]. | 
|  | 64  */ | 
|  | 65 abstract class AnalysisTarget { | 
|  | 66   /** | 
|  | 67    * Return the source associated with this target, or `null` if this target is | 
|  | 68    * not associated with a source. | 
|  | 69    */ | 
|  | 70   Source get source; | 
|  | 71 } | 
|  | 72 | 
|  | 73 /** | 
|  | 74  * An object used to compute one or more analysis results associated with a | 
|  | 75  * single target. | 
|  | 76  * | 
|  | 77  * Clients are expected to extend this class when creating new tasks. | 
|  | 78  */ | 
|  | 79 abstract class AnalysisTask { | 
|  | 80   /** | 
|  | 81    * A table mapping the types of analysis tasks to the number of times each | 
|  | 82    * kind of task has been performed. | 
|  | 83    */ | 
|  | 84   static final Map<Type, int> countMap = new HashMap<Type, int>(); | 
|  | 85 | 
|  | 86   /** | 
|  | 87    * A table mapping the types of analysis tasks to stopwatches used to compute | 
|  | 88    * how much time was spent executing each kind of task. | 
|  | 89    */ | 
|  | 90   static final Map<Type, Stopwatch> stopwatchMap = | 
|  | 91       new HashMap<Type, Stopwatch>(); | 
|  | 92 | 
|  | 93   /** | 
|  | 94    * The context in which the task is to be performed. | 
|  | 95    */ | 
|  | 96   final AnalysisContext context; | 
|  | 97 | 
|  | 98   /** | 
|  | 99    * The target for which result values are being produced. | 
|  | 100    */ | 
|  | 101   final AnalysisTarget target; | 
|  | 102 | 
|  | 103   /** | 
|  | 104    * A table mapping input names to input values. | 
|  | 105    */ | 
|  | 106   Map<String, dynamic> inputs; | 
|  | 107 | 
|  | 108   /** | 
|  | 109    * A table mapping result descriptors whose values are produced by this task | 
|  | 110    * to the values that were produced. | 
|  | 111    */ | 
|  | 112   Map<ResultDescriptor, dynamic> outputs = | 
|  | 113       new HashMap<ResultDescriptor, dynamic>(); | 
|  | 114 | 
|  | 115   /** | 
|  | 116    * The exception that was thrown while performing this task, or `null` if the | 
|  | 117    * task completed successfully. | 
|  | 118    */ | 
|  | 119   CaughtException caughtException; | 
|  | 120 | 
|  | 121   /** | 
|  | 122    * If a dependency cycle was found while computing the inputs for the task, | 
|  | 123    * the set of [WorkItem]s contained in the cycle (if there are overlapping | 
|  | 124    * cycles, this is the set of all [WorkItem]s in the entire strongly | 
|  | 125    * connected component).  Otherwise, `null`. | 
|  | 126    */ | 
|  | 127   List<WorkItem> dependencyCycle; | 
|  | 128 | 
|  | 129   /** | 
|  | 130    * Initialize a newly created task to perform analysis within the given | 
|  | 131    * [context] in order to produce results for the given [target]. | 
|  | 132    */ | 
|  | 133   AnalysisTask(this.context, this.target); | 
|  | 134 | 
|  | 135   /** | 
|  | 136    * Return a textual description of this task. | 
|  | 137    */ | 
|  | 138   String get description; | 
|  | 139 | 
|  | 140   /** | 
|  | 141    * Return the descriptor that describes this task. | 
|  | 142    */ | 
|  | 143   TaskDescriptor get descriptor; | 
|  | 144 | 
|  | 145   /** | 
|  | 146    * Indicates whether the task is capable of handling dependency cycles.  A | 
|  | 147    * task that overrides this getter to return `true` must be prepared for the | 
|  | 148    * possibility that it will be invoked with a non-`null` value of | 
|  | 149    * [dependencyCycle], and with not all of its inputs computed. | 
|  | 150    */ | 
|  | 151   bool get handlesDependencyCycles => false; | 
|  | 152 | 
|  | 153   /** | 
|  | 154    * Return the value of the input with the given [name]. Throw an exception if | 
|  | 155    * the input value is not defined. | 
|  | 156    */ | 
|  | 157   Object getRequiredInput(String name) { | 
|  | 158     if (inputs == null || !inputs.containsKey(name)) { | 
|  | 159       throw new AnalysisException("Could not $description: missing $name"); | 
|  | 160     } | 
|  | 161     return inputs[name]; | 
|  | 162   } | 
|  | 163 | 
|  | 164   /** | 
|  | 165    * Return the source associated with the target. Throw an exception if | 
|  | 166    * the target is not associated with a source. | 
|  | 167    */ | 
|  | 168   Source getRequiredSource() { | 
|  | 169     Source source = target.source; | 
|  | 170     if (source == null) { | 
|  | 171       throw new AnalysisException("Could not $description: missing source"); | 
|  | 172     } | 
|  | 173     return source; | 
|  | 174   } | 
|  | 175 | 
|  | 176   /** | 
|  | 177    * Perform this analysis task, protected by an exception handler. | 
|  | 178    * | 
|  | 179    * This method should throw an [AnalysisException] if an exception occurs | 
|  | 180    * while performing the task. If other kinds of exceptions are thrown they | 
|  | 181    * will be wrapped in an [AnalysisException]. | 
|  | 182    * | 
|  | 183    * If no exception is thrown, this method must fully populate the [outputs] | 
|  | 184    * map (have a key/value pair for each result that this task is expected to | 
|  | 185    * produce). | 
|  | 186    */ | 
|  | 187   void internalPerform(); | 
|  | 188 | 
|  | 189   /** | 
|  | 190    * Perform this analysis task. When this method returns, either the [outputs] | 
|  | 191    * map should be fully populated (have a key/value pair for each result that | 
|  | 192    * this task is expected to produce) or the [caughtException] should be set. | 
|  | 193    * | 
|  | 194    * Clients should not override this method. | 
|  | 195    */ | 
|  | 196   void perform() { | 
|  | 197     try { | 
|  | 198       _safelyPerform(); | 
|  | 199     } on AnalysisException catch (exception, stackTrace) { | 
|  | 200       caughtException = new CaughtException(exception, stackTrace); | 
|  | 201       AnalysisEngine.instance.logger.logInformation( | 
|  | 202           "Task failed: ${description}", caughtException); | 
|  | 203     } | 
|  | 204   } | 
|  | 205 | 
|  | 206   @override | 
|  | 207   String toString() => description; | 
|  | 208 | 
|  | 209   /** | 
|  | 210    * Perform this analysis task, ensuring that all exceptions are wrapped in an | 
|  | 211    * [AnalysisException]. | 
|  | 212    * | 
|  | 213    * Clients should not override this method. | 
|  | 214    */ | 
|  | 215   void _safelyPerform() { | 
|  | 216     try { | 
|  | 217       // | 
|  | 218       // Report that this task is being performed. | 
|  | 219       // | 
|  | 220       String contextName = context.name; | 
|  | 221       if (contextName == null) { | 
|  | 222         contextName = 'unnamed'; | 
|  | 223       } | 
|  | 224       AnalysisEngine.instance.instrumentationService.logAnalysisTask( | 
|  | 225           contextName, this); | 
|  | 226       // | 
|  | 227       // Gather statistics on the performance of the task. | 
|  | 228       // | 
|  | 229       int count = countMap[runtimeType]; | 
|  | 230       countMap[runtimeType] = count == null ? 1 : count + 1; | 
|  | 231       Stopwatch stopwatch = stopwatchMap[runtimeType]; | 
|  | 232       if (stopwatch == null) { | 
|  | 233         stopwatch = new Stopwatch(); | 
|  | 234         stopwatchMap[runtimeType] = stopwatch; | 
|  | 235       } | 
|  | 236       stopwatch.start(); | 
|  | 237       // | 
|  | 238       // Actually perform the task. | 
|  | 239       // | 
|  | 240       try { | 
|  | 241         if (dependencyCycle != null && !handlesDependencyCycles) { | 
|  | 242           throw new InfiniteTaskLoopException(this, dependencyCycle); | 
|  | 243         } | 
|  | 244         internalPerform(); | 
|  | 245       } finally { | 
|  | 246         stopwatch.stop(); | 
|  | 247       } | 
|  | 248     } on AnalysisException { | 
|  | 249       rethrow; | 
|  | 250     } catch (exception, stackTrace) { | 
|  | 251       throw new AnalysisException( | 
|  | 252           'Unexpected exception while performing $description', | 
|  | 253           new CaughtException(exception, stackTrace)); | 
|  | 254     } | 
|  | 255   } | 
|  | 256 } | 
|  | 257 | 
|  | 258 /** | 
|  | 259  * A description of a [List]-based analysis result that can be computed by an | 
|  | 260  * [AnalysisTask]. | 
|  | 261  * | 
|  | 262  * Clients are not expected to subtype this class. | 
|  | 263  */ | 
|  | 264 abstract class ListResultDescriptor<E> implements ResultDescriptor<List<E>> { | 
|  | 265   /** | 
|  | 266    * Initialize a newly created analysis result to have the given [name] and | 
|  | 267    * [defaultValue]. If a [cachingPolicy] is provided, it will control how long | 
|  | 268    * values associated with this result will remain in the cache. | 
|  | 269    */ | 
|  | 270   factory ListResultDescriptor(String name, List<E> defaultValue, | 
|  | 271       {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl<E
     >; | 
|  | 272 | 
|  | 273   @override | 
|  | 274   ListTaskInput<E> of(AnalysisTarget target); | 
|  | 275 } | 
|  | 276 | 
|  | 277 /** | 
|  | 278  * A description of an input to an [AnalysisTask] that can be used to compute | 
|  | 279  * that input. | 
|  | 280  * | 
|  | 281  * Clients are not expected to subtype this class. | 
|  | 282  */ | 
|  | 283 abstract class ListTaskInput<E> extends TaskInput<List<E>> { | 
|  | 284   /** | 
|  | 285    * Return a task input that can be used to compute a list whose elements are | 
|  | 286    * the result of passing the elements of this input to the [mapper] function. | 
|  | 287    */ | 
|  | 288   ListTaskInput /*<V>*/ toList(UnaryFunction<E, dynamic /*<V>*/ > mapper); | 
|  | 289 | 
|  | 290   /** | 
|  | 291    * Return a task input that can be used to compute a list whose elements are | 
|  | 292    * [valueResult]'s associated with those elements. | 
|  | 293    */ | 
|  | 294   ListTaskInput /*<V>*/ toListOf(ResultDescriptor /*<V>*/ valueResult); | 
|  | 295 | 
|  | 296   /** | 
|  | 297    * Return a task input that can be used to compute a map whose keys are the | 
|  | 298    * elements of this input and whose values are the result of passing the | 
|  | 299    * corresponding key to the [mapper] function. | 
|  | 300    */ | 
|  | 301   MapTaskInput<E, dynamic /*V*/ > toMap( | 
|  | 302       UnaryFunction<E, dynamic /*<V>*/ > mapper); | 
|  | 303 | 
|  | 304   /** | 
|  | 305    * Return a task input that can be used to compute a map whose keys are the | 
|  | 306    * elements of this input and whose values are the [valueResult]'s associated | 
|  | 307    * with those elements. | 
|  | 308    */ | 
|  | 309   MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf( | 
|  | 310       ResultDescriptor /*<V>*/ valueResult); | 
|  | 311 } | 
|  | 312 | 
|  | 313 /** | 
|  | 314  * A description of an input with a [Map] based values. | 
|  | 315  * | 
|  | 316  * Clients are not expected to subtype this class. | 
|  | 317  */ | 
|  | 318 abstract class MapTaskInput<K, V> extends TaskInput<Map<K, V>> { | 
|  | 319   /** | 
|  | 320    * [V] must be a [List]. | 
|  | 321    * Return a task input that can be used to compute a list whose elements are | 
|  | 322    * the result of passing keys [K] and the corresponding elements of [V] to | 
|  | 323    * the [mapper] function. | 
|  | 324    */ | 
|  | 325   TaskInput<List /*<E>*/ > toFlattenList( | 
|  | 326       BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper); | 
|  | 327 } | 
|  | 328 | 
|  | 329 /** | 
|  | 330  * A policy object that can compute sizes of results and provide the maximum | 
|  | 331  * active and idle sizes that can be kept in the cache. | 
|  | 332  * | 
|  | 333  * All the [ResultDescriptor]s with the same [ResultCachingPolicy] instance | 
|  | 334  * share the same total size in a cache. | 
|  | 335  */ | 
|  | 336 abstract class ResultCachingPolicy<T> { | 
|  | 337   /** | 
|  | 338    * Return the maximum total size of results that can be kept in the cache | 
|  | 339    * while analysis is in progress. | 
|  | 340    */ | 
|  | 341   int get maxActiveSize; | 
|  | 342 | 
|  | 343   /** | 
|  | 344    * Return the maximum total size of results that can be kept in the cache | 
|  | 345    * while analysis is idle. | 
|  | 346    */ | 
|  | 347   int get maxIdleSize; | 
|  | 348 | 
|  | 349   /** | 
|  | 350    * Return the size of the given [object]. | 
|  | 351    */ | 
|  | 352   int measure(T object); | 
|  | 353 } | 
|  | 354 | 
|  | 355 /** | 
|  | 356  * A description of an analysis result that can be computed by an [AnalysisTask]
     . | 
|  | 357  * | 
|  | 358  * Clients are not expected to subtype this class. | 
|  | 359  */ | 
|  | 360 abstract class ResultDescriptor<V> { | 
|  | 361   /** | 
|  | 362    * Initialize a newly created analysis result to have the given [name] and | 
|  | 363    * [defaultValue]. | 
|  | 364    * | 
|  | 365    * The given [cachingPolicy] is used to limit the total size of results | 
|  | 366    * described by this descriptor. If no policy is specified, the results are | 
|  | 367    * never evicted from the cache, and removed only when they are invalidated. | 
|  | 368    */ | 
|  | 369   factory ResultDescriptor(String name, V defaultValue, | 
|  | 370       {ResultCachingPolicy<V> cachingPolicy}) = ResultDescriptorImpl; | 
|  | 371 | 
|  | 372   /** | 
|  | 373    * Return the caching policy for results described by this descriptor. | 
|  | 374    */ | 
|  | 375   ResultCachingPolicy<V> get cachingPolicy; | 
|  | 376 | 
|  | 377   /** | 
|  | 378    * Return the default value for results described by this descriptor. | 
|  | 379    */ | 
|  | 380   V get defaultValue; | 
|  | 381 | 
|  | 382   /** | 
|  | 383    * Return the name of this descriptor. | 
|  | 384    */ | 
|  | 385   String get name; | 
|  | 386 | 
|  | 387   /** | 
|  | 388    * Return a task input that can be used to compute this result for the given | 
|  | 389    * [target]. | 
|  | 390    */ | 
|  | 391   TaskInput<V> of(AnalysisTarget target); | 
|  | 392 } | 
|  | 393 | 
|  | 394 /** | 
|  | 395  * A specification of the given [result] for the given [target]. | 
|  | 396  * | 
|  | 397  * Clients are not expected to subtype this class. | 
|  | 398  */ | 
|  | 399 class TargetedResult { | 
|  | 400   /** | 
|  | 401    * An empty list of results. | 
|  | 402    */ | 
|  | 403   static final List<TargetedResult> EMPTY_LIST = const <TargetedResult>[]; | 
|  | 404 | 
|  | 405   /** | 
|  | 406    * The target with which the result is associated. | 
|  | 407    */ | 
|  | 408   final AnalysisTarget target; | 
|  | 409 | 
|  | 410   /** | 
|  | 411    * The result associated with the target. | 
|  | 412    */ | 
|  | 413   final ResultDescriptor result; | 
|  | 414 | 
|  | 415   /** | 
|  | 416    * Initialize a new targeted result. | 
|  | 417    */ | 
|  | 418   TargetedResult(this.target, this.result); | 
|  | 419 | 
|  | 420   @override | 
|  | 421   int get hashCode { | 
|  | 422     return JenkinsSmiHash.combine(target.hashCode, result.hashCode); | 
|  | 423   } | 
|  | 424 | 
|  | 425   @override | 
|  | 426   bool operator ==(other) { | 
|  | 427     return other is TargetedResult && | 
|  | 428         other.target == target && | 
|  | 429         other.result == result; | 
|  | 430   } | 
|  | 431 | 
|  | 432   @override | 
|  | 433   String toString() => '$result for $target'; | 
|  | 434 } | 
|  | 435 | 
|  | 436 /** | 
|  | 437  * A description of an [AnalysisTask]. | 
|  | 438  */ | 
|  | 439 abstract class TaskDescriptor { | 
|  | 440   /** | 
|  | 441    * Initialize a newly created task descriptor to have the given [name] and to | 
|  | 442    * describe a task that takes the inputs built using the given [inputBuilder], | 
|  | 443    * and produces the given [results]. The [buildTask] will be used to create | 
|  | 444    * the instance of [AnalysisTask] thusly described. | 
|  | 445    */ | 
|  | 446   factory TaskDescriptor(String name, BuildTask buildTask, | 
|  | 447       CreateTaskInputs inputBuilder, | 
|  | 448       List<ResultDescriptor> results) = TaskDescriptorImpl; | 
|  | 449 | 
|  | 450   /** | 
|  | 451    * Return the builder used to build the inputs to the task. | 
|  | 452    */ | 
|  | 453   CreateTaskInputs get createTaskInputs; | 
|  | 454 | 
|  | 455   /** | 
|  | 456    * Return the name of the task being described. | 
|  | 457    */ | 
|  | 458   String get name; | 
|  | 459 | 
|  | 460   /** | 
|  | 461    * Return a list of the analysis results that will be computed by this task. | 
|  | 462    */ | 
|  | 463   List<ResultDescriptor> get results; | 
|  | 464 | 
|  | 465   /** | 
|  | 466    * Create and return a task that is described by this descriptor that can be | 
|  | 467    * used to compute results based on the given [inputs]. | 
|  | 468    */ | 
|  | 469   AnalysisTask createTask(AnalysisContext context, AnalysisTarget target, | 
|  | 470       Map<String, dynamic> inputs); | 
|  | 471 } | 
|  | 472 | 
|  | 473 /** | 
|  | 474  * A description of an input to an [AnalysisTask] that can be used to compute | 
|  | 475  * that input. | 
|  | 476  * | 
|  | 477  * Clients are not expected to subtype this class. | 
|  | 478  */ | 
|  | 479 abstract class TaskInput<V> { | 
|  | 480   /** | 
|  | 481    * Create and return a builder that can be used to build this task input. | 
|  | 482    */ | 
|  | 483   TaskInputBuilder<V> createBuilder(); | 
|  | 484 | 
|  | 485   /** | 
|  | 486    * Return a task input that can be used to compute a list whose elements are | 
|  | 487    * the result of passing the result of this input to the [mapper] function. | 
|  | 488    */ | 
|  | 489   ListTaskInput /*<E>*/ mappedToList(List /*<E>*/ mapper(V value)); | 
|  | 490 } | 
|  | 491 | 
|  | 492 /** | 
|  | 493  * An object used to build the value associated with a single [TaskInput]. | 
|  | 494  * | 
|  | 495  * All builders work by requesting one or more results (each result being | 
|  | 496  * associated with a target). The interaction pattern is modeled after the class | 
|  | 497  * [Iterator], in which the method [moveNext] is invoked to move from one result | 
|  | 498  * request to the next. The getters [currentResult] and [currentTarget] are used | 
|  | 499  * to get the result and target of the current request. The value of the result | 
|  | 500  * must be supplied using the [currentValue] setter before [moveNext] can be | 
|  | 501  * invoked to move to the next request. When [moveNext] returns `false`, | 
|  | 502  * indicating that there are no more requests, the method [inputValue] can be | 
|  | 503  * used to access the value of the input that was built. | 
|  | 504  * | 
|  | 505  * Clients are not expected to subtype this class. | 
|  | 506  */ | 
|  | 507 abstract class TaskInputBuilder<V> { | 
|  | 508   /** | 
|  | 509    * Return the result that needs to be computed, or `null` if [moveNext] has | 
|  | 510    * not been invoked or if the last invocation of [moveNext] returned `false`. | 
|  | 511    */ | 
|  | 512   ResultDescriptor get currentResult; | 
|  | 513 | 
|  | 514   /** | 
|  | 515    * Return the target for which the result needs to be computed, or `null` if | 
|  | 516    * [moveNext] has not been invoked or if the last invocation of [moveNext] | 
|  | 517    * returned `false`. | 
|  | 518    */ | 
|  | 519   AnalysisTarget get currentTarget; | 
|  | 520 | 
|  | 521   /** | 
|  | 522    * Set the [value] that was computed for the current result. | 
|  | 523    * | 
|  | 524    * Throws a [StateError] if [moveNext] has not been invoked or if the last | 
|  | 525    * invocation of [moveNext] returned `false`. | 
|  | 526    */ | 
|  | 527   void set currentValue(Object value); | 
|  | 528 | 
|  | 529   /** | 
|  | 530    * Return the [value] that was computed by this builder. | 
|  | 531    * | 
|  | 532    * Throws a [StateError] if [moveNext] has not been invoked or if the last | 
|  | 533    * invocation of [moveNext] returned `true`. | 
|  | 534    * | 
|  | 535    * Returns `null` if no value could be computed due to a circular dependency. | 
|  | 536    */ | 
|  | 537   V get inputValue; | 
|  | 538 | 
|  | 539   /** | 
|  | 540    * Record that no value is available for the current result, due to a | 
|  | 541    * circular dependency. | 
|  | 542    * | 
|  | 543    * Throws a [StateError] if [moveNext] has not been invoked or if the last | 
|  | 544    * invocation of [moveNext] returned `false`. | 
|  | 545    */ | 
|  | 546   void currentValueNotAvailable(); | 
|  | 547 | 
|  | 548   /** | 
|  | 549    * Move to the next result that needs to be computed in order to build the | 
|  | 550    * inputs for a task. Return `true` if there is another result that needs to | 
|  | 551    * be computed, or `false` if the inputs have been computed. | 
|  | 552    * | 
|  | 553    * It is safe to invoke [moveNext] after it has returned `false`. In this case | 
|  | 554    * [moveNext] has no effect and will again return `false`. | 
|  | 555    * | 
|  | 556    * Throws a [StateError] if the value of the current result has not been | 
|  | 557    * provided using [currentValue]. | 
|  | 558    */ | 
|  | 559   bool moveNext(); | 
|  | 560 } | 
|  | 561 | 
|  | 562 /** | 
|  | 563  * [WorkManager]s are used to drive analysis. | 
|  | 564  * | 
|  | 565  * They know specific of the targets and results they care about, | 
|  | 566  * so they can request analysis results in optimal order. | 
|  | 567  */ | 
|  | 568 abstract class WorkManager { | 
|  | 569   /** | 
|  | 570    * Notifies the manager about changes in the explicit source list. | 
|  | 571    */ | 
|  | 572   void applyChange(List<Source> addedSources, List<Source> changedSources, | 
|  | 573       List<Source> removedSources); | 
|  | 574 | 
|  | 575   /** | 
|  | 576    * Notifies the managers that the given set of priority [targets] was set. | 
|  | 577    */ | 
|  | 578   void applyPriorityTargets(List<AnalysisTarget> targets); | 
|  | 579 | 
|  | 580   /** | 
|  | 581    * Return a list of all of the errors associated with the given [source]. | 
|  | 582    * The list of errors will be empty if the source is not known to the context | 
|  | 583    * or if there are no errors in the source. The errors contained in the list | 
|  | 584    * can be incomplete. | 
|  | 585    */ | 
|  | 586   List<AnalysisError> getErrors(Source source); | 
|  | 587 | 
|  | 588   /** | 
|  | 589    * Return the next [TargetedResult] that this work manager wants to be | 
|  | 590    * computed, or `null` if this manager doesn't need any new results. | 
|  | 591    */ | 
|  | 592   TargetedResult getNextResult(); | 
|  | 593 | 
|  | 594   /** | 
|  | 595    * Return the priority if the next work order this work manager want to be | 
|  | 596    * computed. The [AnalysisDriver] will perform the work order with | 
|  | 597    * the highest priority. | 
|  | 598    * | 
|  | 599    * Even if the returned value is [WorkOrderPriority.NONE], it still does not | 
|  | 600    * guarantee that [getNextResult] will return not `null`. | 
|  | 601    */ | 
|  | 602   WorkOrderPriority getNextResultPriority(); | 
|  | 603 | 
|  | 604   /** | 
|  | 605    * Notifies the manager about analysis options changes. | 
|  | 606    */ | 
|  | 607   void onAnalysisOptionsChanged(); | 
|  | 608 | 
|  | 609   /** | 
|  | 610    * Notifies the manager about [SourceFactory] changes. | 
|  | 611    */ | 
|  | 612   void onSourceFactoryChanged(); | 
|  | 613 | 
|  | 614   /** | 
|  | 615    * Notifies the manager that the given [outputs] were produced for | 
|  | 616    * the given [target]. | 
|  | 617    */ | 
|  | 618   void resultsComputed( | 
|  | 619       AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs); | 
|  | 620 } | 
|  | 621 | 
|  | 622 /** | 
|  | 623  * The priorities of work orders returned by [WorkManager]s. | 
|  | 624  * | 
|  | 625  * New priorities may be added with time, clients need to tolerate this. | 
|  | 626  */ | 
|  | 627 enum WorkOrderPriority { | 
|  | 628   /** | 
|  | 629    * Responding to an user's action. | 
|  | 630    */ | 
|  | 631   INTERACTIVE, | 
|  | 632 | 
|  | 633   /** | 
|  | 634    * Computing information for priority sources. | 
|  | 635    */ | 
|  | 636   PRIORITY, | 
|  | 637 | 
|  | 638   /** | 
|  | 639    * A work should be done, but without any special urgency. | 
|  | 640    */ | 
|  | 641   NORMAL, | 
|  | 642 | 
|  | 643   /** | 
|  | 644    * Nothing to do. | 
|  | 645    */ | 
|  | 646   NONE | 
|  | 647 } | 
| OLD | NEW | 
|---|