| 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.task.model; | 5 library analyzer.task.model; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:developer'; | 8 import 'dart:developer'; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; | 10 import 'package:analyzer/error/error.dart' show AnalysisError; |
| 11 import 'package:analyzer/src/generated/error.dart' show AnalysisError; | 11 import 'package:analyzer/exception/exception.dart'; |
| 12 import 'package:analyzer/src/generated/java_engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 13 import 'package:analyzer/src/generated/source.dart'; | 13 import 'package:analyzer/src/generated/source.dart'; |
| 14 import 'package:analyzer/src/generated/utilities_general.dart'; | 14 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 15 import 'package:analyzer/src/task/driver.dart'; | 15 import 'package:analyzer/src/task/driver.dart'; |
| 16 import 'package:analyzer/src/task/model.dart'; | 16 import 'package:analyzer/src/task/model.dart'; |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * A function that converts the given [key] and [value] into a [TaskInput]. | 19 * A function that converts the given [key] and [value] into a [TaskInput]. |
| 20 */ | 20 */ |
| 21 typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value); | 21 typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value); |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * A function that takes an analysis [context] and an analysis [target] and | 24 * A function that takes an analysis [context] and an analysis [target] and |
| 25 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to | 25 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to |
| 26 * be used to create the described task. | 26 * be used to create the described task. |
| 27 */ | 27 */ |
| 28 typedef AnalysisTask BuildTask(AnalysisContext context, AnalysisTarget target); | 28 typedef AnalysisTask BuildTask(AnalysisContext context, AnalysisTarget target); |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * A function that takes the target for which a task will produce results and | 31 * A function that takes the target for which a task will produce results and |
| 32 * returns a map from input names to descriptions of the analysis results needed | 32 * returns a map from input names to descriptions of the analysis results needed |
| 33 * by the task in order for the task to be performed. Such functions are passed | 33 * by the task in order for the task to be performed. Such functions are passed |
| 34 * to a [TaskDescriptor] to be used to determine the inputs needed by the task. | 34 * to a [TaskDescriptor] to be used to determine the inputs needed by the task. |
| 35 */ | 35 */ |
| 36 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target); | 36 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target); |
| 37 | 37 |
| 38 /** | 38 /** |
| 39 * A function that takes the target for which a task will produce results and |
| 40 * returns an indication of how suitable the task is for the target. Such |
| 41 * functions are passed to a [TaskDescriptor] to be used to determine their |
| 42 * suitability for computing results. |
| 43 */ |
| 44 typedef TaskSuitability SuitabilityFor(AnalysisTarget target); |
| 45 |
| 46 /** |
| 39 * A function that converts an object of the type [B] into a [TaskInput]. | 47 * A function that converts an object of the type [B] into a [TaskInput]. |
| 40 * This is used, for example, by a [ListTaskInput] to create task inputs | 48 * This is used, for example, by a [ListTaskInput] to create task inputs |
| 41 * for each value in a list of values. | 49 * for each value in a list of values. |
| 42 */ | 50 */ |
| 43 typedef TaskInput<E> UnaryFunction<B, E>(B object); | 51 typedef TaskInput<E> UnaryFunction<B, E>(B object); |
| 44 | 52 |
| 45 /** | 53 /** |
| 46 * An [AnalysisTarget] wrapper for an [AnalysisContext]. | 54 * An [AnalysisTarget] wrapper for an [AnalysisContext]. |
| 47 */ | 55 */ |
| 48 class AnalysisContextTarget implements AnalysisTarget { | 56 class AnalysisContextTarget implements AnalysisTarget { |
| 49 static final AnalysisContextTarget request = new AnalysisContextTarget(null); | 57 static final AnalysisContextTarget request = new AnalysisContextTarget(null); |
| 50 | 58 |
| 51 final AnalysisContext context; | 59 final AnalysisContext context; |
| 52 | 60 |
| 53 AnalysisContextTarget(this.context); | 61 AnalysisContextTarget(this.context); |
| 54 | 62 |
| 55 @override | 63 @override |
| 64 Source get librarySource => null; |
| 65 |
| 66 @override |
| 56 Source get source => null; | 67 Source get source => null; |
| 57 } | 68 } |
| 58 | 69 |
| 59 /** | 70 /** |
| 60 * An object with which an analysis result can be associated. | 71 * An object with which an analysis result can be associated. |
| 61 * | 72 * |
| 62 * Clients may implement this class when creating new kinds of targets. | 73 * Clients may implement this class when creating new kinds of targets. |
| 63 * Instances of this type are used in hashed data structures, so subtypes are | 74 * Instances of this type are used in hashed data structures, so subtypes are |
| 64 * required to correctly implement [==] and [hashCode]. | 75 * required to correctly implement [==] and [hashCode]. |
| 65 */ | 76 */ |
| 66 abstract class AnalysisTarget { | 77 abstract class AnalysisTarget { |
| 67 /** | 78 /** |
| 79 * If this target is associated with a library, return the source of the |
| 80 * library's defining compilation unit; otherwise return `null`. |
| 81 */ |
| 82 Source get librarySource; |
| 83 |
| 84 /** |
| 68 * Return the source associated with this target, or `null` if this target is | 85 * Return the source associated with this target, or `null` if this target is |
| 69 * not associated with a source. | 86 * not associated with a source. |
| 70 */ | 87 */ |
| 71 Source get source; | 88 Source get source; |
| 72 } | 89 } |
| 73 | 90 |
| 74 /** | 91 /** |
| 75 * An object used to compute one or more analysis results associated with a | 92 * An object used to compute one or more analysis results associated with a |
| 76 * single target. | 93 * single target. |
| 77 * | 94 * |
| 78 * Clients must extend this class when creating new tasks. | 95 * Clients must extend this class when creating new tasks. |
| 79 */ | 96 */ |
| 80 abstract class AnalysisTask { | 97 abstract class AnalysisTask { |
| 81 /** | 98 /** |
| 99 * A queue storing the last 10 task descriptions for diagnostic purposes. |
| 100 */ |
| 101 static final LimitedQueue<String> LAST_TASKS = new LimitedQueue<String>(10); |
| 102 |
| 103 /** |
| 82 * A table mapping the types of analysis tasks to the number of times each | 104 * A table mapping the types of analysis tasks to the number of times each |
| 83 * kind of task has been performed. | 105 * kind of task has been performed. |
| 84 */ | 106 */ |
| 85 static final Map<Type, int> countMap = new HashMap<Type, int>(); | 107 static final Map<Type, int> countMap = new HashMap<Type, int>(); |
| 86 | 108 |
| 87 /** | 109 /** |
| 88 * A table mapping the types of analysis tasks to user tags used to collect | 110 * A table mapping the types of analysis tasks to user tags used to collect |
| 89 * timing data for the Observatory. | 111 * timing data for the Observatory. |
| 90 */ | 112 */ |
| 91 static Map<Type, UserTag> tagMap = new HashMap<Type, UserTag>(); | 113 static Map<Type, UserTag> tagMap = new HashMap<Type, UserTag>(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 | 173 |
| 152 /** | 174 /** |
| 153 * Indicates whether the task is capable of handling dependency cycles. A | 175 * Indicates whether the task is capable of handling dependency cycles. A |
| 154 * task that overrides this getter to return `true` must be prepared for the | 176 * task that overrides this getter to return `true` must be prepared for the |
| 155 * possibility that it will be invoked with a non-`null` value of | 177 * possibility that it will be invoked with a non-`null` value of |
| 156 * [dependencyCycle], and with not all of its inputs computed. | 178 * [dependencyCycle], and with not all of its inputs computed. |
| 157 */ | 179 */ |
| 158 bool get handlesDependencyCycles => false; | 180 bool get handlesDependencyCycles => false; |
| 159 | 181 |
| 160 /** | 182 /** |
| 183 * Return the value of the input with the given [name], or `null` if the input |
| 184 * value is not defined. |
| 185 */ |
| 186 Object getOptionalInput(String name) { |
| 187 if (inputs == null || !inputs.containsKey(name)) { |
| 188 return null; |
| 189 } |
| 190 return inputs[name]; |
| 191 } |
| 192 |
| 193 /** |
| 161 * Return the value of the input with the given [name]. Throw an exception if | 194 * Return the value of the input with the given [name]. Throw an exception if |
| 162 * the input value is not defined. | 195 * the input value is not defined. |
| 163 */ | 196 */ |
| 164 Object getRequiredInput(String name) { | 197 Object/*=E*/ getRequiredInput/*<E>*/(String name) { |
| 165 if (inputs == null || !inputs.containsKey(name)) { | 198 if (inputs == null || !inputs.containsKey(name)) { |
| 166 throw new AnalysisException("Could not $description: missing $name"); | 199 throw new AnalysisException("Could not $description: missing $name"); |
| 167 } | 200 } |
| 168 return inputs[name]; | 201 return inputs[name] as Object/*=E*/; |
| 169 } | 202 } |
| 170 | 203 |
| 171 /** | 204 /** |
| 172 * Return the source associated with the target. Throw an exception if | 205 * Return the source associated with the target. Throw an exception if |
| 173 * the target is not associated with a source. | 206 * the target is not associated with a source. |
| 174 */ | 207 */ |
| 175 Source getRequiredSource() { | 208 Source getRequiredSource() { |
| 176 Source source = target.source; | 209 Source source = target.source; |
| 177 if (source == null) { | 210 if (source == null) { |
| 178 throw new AnalysisException("Could not $description: missing source"); | 211 throw new AnalysisException("Could not $description: missing source"); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 199 * this task is expected to produce) or the [caughtException] should be set. | 232 * this task is expected to produce) or the [caughtException] should be set. |
| 200 * | 233 * |
| 201 * Clients may not override this method. | 234 * Clients may not override this method. |
| 202 */ | 235 */ |
| 203 void perform() { | 236 void perform() { |
| 204 try { | 237 try { |
| 205 _safelyPerform(); | 238 _safelyPerform(); |
| 206 } on AnalysisException catch (exception, stackTrace) { | 239 } on AnalysisException catch (exception, stackTrace) { |
| 207 caughtException = new CaughtException(exception, stackTrace); | 240 caughtException = new CaughtException(exception, stackTrace); |
| 208 AnalysisEngine.instance.logger | 241 AnalysisEngine.instance.logger |
| 209 .logInformation("Task failed: ${description}", caughtException); | 242 .logError("Task failed: $description", caughtException); |
| 210 } | 243 } |
| 211 } | 244 } |
| 212 | 245 |
| 213 @override | 246 @override |
| 214 String toString() => description; | 247 String toString() => description; |
| 215 | 248 |
| 216 /** | 249 /** |
| 250 * Given a strongly connected component, find and return a list of |
| 251 * [TargetedResult]s that describes a cyclic path within the cycle. Returns |
| 252 * null if no cyclic path is found. |
| 253 */ |
| 254 List<TargetedResult> _findCyclicPath(List<WorkItem> cycle) { |
| 255 WorkItem findInCycle(AnalysisTarget target, ResultDescriptor descriptor) { |
| 256 for (WorkItem item in cycle) { |
| 257 if (target == item.target && descriptor == item.spawningResult) { |
| 258 return item; |
| 259 } |
| 260 } |
| 261 return null; |
| 262 } |
| 263 |
| 264 HashSet<WorkItem> active = new HashSet<WorkItem>(); |
| 265 List<TargetedResult> path = null; |
| 266 bool traverse(WorkItem item) { |
| 267 if (!active.add(item)) { |
| 268 // We've found a cycle |
| 269 path = <TargetedResult>[]; |
| 270 return true; |
| 271 } |
| 272 for (TargetedResult result in item.inputTargetedResults) { |
| 273 WorkItem item = findInCycle(result.target, result.result); |
| 274 // Ignore edges that leave the cycle. |
| 275 if (item != null) { |
| 276 if (traverse(item)) { |
| 277 // This edge is in a cycle (or leads to a cycle) so add it to the |
| 278 // path |
| 279 path.add(result); |
| 280 return true; |
| 281 } |
| 282 } |
| 283 } |
| 284 // There was no cycle. |
| 285 return false; |
| 286 } |
| 287 |
| 288 if (cycle.length > 0) { |
| 289 traverse(cycle[0]); |
| 290 } |
| 291 return path; |
| 292 } |
| 293 |
| 294 /** |
| 217 * Perform this analysis task, ensuring that all exceptions are wrapped in an | 295 * Perform this analysis task, ensuring that all exceptions are wrapped in an |
| 218 * [AnalysisException]. | 296 * [AnalysisException]. |
| 219 * | 297 * |
| 220 * Clients may not override this method. | 298 * Clients may not override this method. |
| 221 */ | 299 */ |
| 222 void _safelyPerform() { | 300 void _safelyPerform() { |
| 223 try { | 301 try { |
| 224 // | 302 // |
| 303 // Store task description for diagnostics. |
| 304 // |
| 305 LAST_TASKS.add(description); |
| 306 |
| 307 // |
| 225 // Report that this task is being performed. | 308 // Report that this task is being performed. |
| 226 // | 309 // |
| 227 String contextName = context.name; | 310 String contextName = context.name; |
| 228 if (contextName == null) { | 311 if (contextName == null) { |
| 229 contextName = 'unnamed'; | 312 contextName = 'unnamed'; |
| 230 } | 313 } |
| 231 AnalysisEngine.instance.instrumentationService | 314 AnalysisEngine.instance.instrumentationService |
| 232 .logAnalysisTask(contextName, this); | 315 .logAnalysisTask(contextName, this); |
| 233 // | 316 // |
| 234 // Gather statistics on the performance of the task. | 317 // Gather statistics on the performance of the task. |
| 235 // | 318 // |
| 236 int count = countMap[runtimeType]; | 319 int count = countMap[runtimeType]; |
| 237 countMap[runtimeType] = count == null ? 1 : count + 1; | 320 countMap[runtimeType] = count == null ? 1 : count + 1; |
| 238 // UserTag tag = tagMap.putIfAbsent( | 321 // UserTag tag = tagMap.putIfAbsent( |
| 239 // runtimeType, () => new UserTag(runtimeType.toString())); | 322 // runtimeType, () => new UserTag(runtimeType.toString())); |
| 240 Stopwatch stopwatch = stopwatchMap[runtimeType]; | 323 Stopwatch stopwatch = stopwatchMap[runtimeType]; |
| 241 if (stopwatch == null) { | 324 if (stopwatch == null) { |
| 242 stopwatch = new Stopwatch(); | 325 stopwatch = new Stopwatch(); |
| 243 stopwatchMap[runtimeType] = stopwatch; | 326 stopwatchMap[runtimeType] = stopwatch; |
| 244 } | 327 } |
| 245 // UserTag previousTag = tag.makeCurrent(); | 328 // UserTag previousTag = tag.makeCurrent(); |
| 246 // try { | 329 // try { |
| 247 stopwatch.start(); | 330 stopwatch.start(); |
| 248 // | 331 // |
| 249 // Actually perform the task. | 332 // Actually perform the task. |
| 250 // | 333 // |
| 251 try { | 334 try { |
| 252 if (dependencyCycle != null && !handlesDependencyCycles) { | 335 if (dependencyCycle != null && !handlesDependencyCycles) { |
| 253 throw new InfiniteTaskLoopException(this, dependencyCycle); | 336 throw new InfiniteTaskLoopException( |
| 337 this, dependencyCycle, _findCyclicPath(dependencyCycle)); |
| 254 } | 338 } |
| 255 internalPerform(); | 339 internalPerform(); |
| 256 } finally { | 340 } finally { |
| 257 stopwatch.stop(); | 341 stopwatch.stop(); |
| 258 } | 342 } |
| 259 // } finally { | 343 // } finally { |
| 260 // previousTag.makeCurrent(); | 344 // previousTag.makeCurrent(); |
| 261 // } | 345 // } |
| 262 } on AnalysisException { | 346 } on AnalysisException { |
| 263 rethrow; | 347 rethrow; |
| 348 } on ModificationTimeMismatchError { |
| 349 rethrow; |
| 264 } catch (exception, stackTrace) { | 350 } catch (exception, stackTrace) { |
| 265 throw new AnalysisException( | 351 throw new AnalysisException( |
| 266 'Unexpected exception while performing $description', | 352 'Unexpected exception while performing $description', |
| 267 new CaughtException(exception, stackTrace)); | 353 new CaughtException(exception, stackTrace)); |
| 268 } | 354 } |
| 269 } | 355 } |
| 270 } | 356 } |
| 271 | 357 |
| 272 /** | 358 /** |
| 273 * A description of a [List]-based analysis result that can be computed by an | 359 * A description of a [List]-based analysis result that can be computed by an |
| 274 * [AnalysisTask]. | 360 * [AnalysisTask]. |
| 275 * | 361 * |
| 276 * Clients may not extend, implement or mix-in this class. | 362 * Clients may not extend, implement or mix-in this class. |
| 277 */ | 363 */ |
| 278 abstract class ListResultDescriptor<E> implements ResultDescriptor<List<E>> { | 364 abstract class ListResultDescriptor<E> implements ResultDescriptor<List<E>> { |
| 279 /** | 365 /** |
| 280 * Initialize a newly created analysis result to have the given [name] and | 366 * Initialize a newly created analysis result to have the given [name] and |
| 281 * [defaultValue]. If a [cachingPolicy] is provided, it will control how long | 367 * [defaultValue]. If a [cachingPolicy] is provided, it will control how long |
| 282 * values associated with this result will remain in the cache. | 368 * values associated with this result will remain in the cache. |
| 283 */ | 369 */ |
| 284 factory ListResultDescriptor(String name, List<E> defaultValue, | 370 factory ListResultDescriptor(String name, List<E> defaultValue, |
| 285 {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl< | 371 {ResultCachingPolicy<List<E>> cachingPolicy}) = |
| 286 E>; | 372 ListResultDescriptorImpl<E>; |
| 287 | 373 |
| 288 @override | 374 @override |
| 289 ListTaskInput<E> of(AnalysisTarget target, {bool flushOnAccess: false}); | 375 ListTaskInput<E> of(AnalysisTarget target, {bool flushOnAccess: false}); |
| 290 } | 376 } |
| 291 | 377 |
| 292 /** | 378 /** |
| 293 * A description of an input to an [AnalysisTask] that can be used to compute | 379 * A description of an input to an [AnalysisTask] that can be used to compute |
| 294 * that input. | 380 * that input. |
| 295 * | 381 * |
| 296 * Clients may not extend, implement or mix-in this class. | 382 * Clients may not extend, implement or mix-in this class. |
| 297 */ | 383 */ |
| 298 abstract class ListTaskInput<E> extends TaskInput<List<E>> { | 384 abstract class ListTaskInput<E> implements TaskInput<List<E>> { |
| 385 /** |
| 386 * Return a task input that can be used to compute a flatten list whose |
| 387 * elements are combined [subListResult]'s associated with those elements. |
| 388 */ |
| 389 ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/( |
| 390 ListResultDescriptor/*<V>*/ subListResult); |
| 391 |
| 299 /** | 392 /** |
| 300 * Return a task input that can be used to compute a list whose elements are | 393 * Return a task input that can be used to compute a list whose elements are |
| 301 * the result of passing the elements of this input to the [mapper] function. | 394 * the result of passing the elements of this input to the [mapper] function. |
| 302 */ | 395 */ |
| 303 ListTaskInput /*<V>*/ toList(UnaryFunction<E, dynamic /*<V>*/ > mapper); | 396 ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper); |
| 304 | 397 |
| 305 /** | 398 /** |
| 306 * Return a task input that can be used to compute a list whose elements are | 399 * Return a task input that can be used to compute a list whose elements are |
| 307 * [valueResult]'s associated with those elements. | 400 * [valueResult]'s associated with those elements. |
| 308 */ | 401 */ |
| 309 ListTaskInput /*<V>*/ toListOf(ResultDescriptor /*<V>*/ valueResult); | 402 ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult); |
| 310 | 403 |
| 311 /** | 404 /** |
| 312 * Return a task input that can be used to compute a map whose keys are the | 405 * Return a task input that can be used to compute a map whose keys are the |
| 313 * elements of this input and whose values are the result of passing the | 406 * elements of this input and whose values are the result of passing the |
| 314 * corresponding key to the [mapper] function. | 407 * corresponding key to the [mapper] function. |
| 315 */ | 408 */ |
| 316 MapTaskInput<E, dynamic /*V*/ > toMap( | 409 MapTaskInput<E, dynamic/*=V*/ > toMap/*<V>*/( |
| 317 UnaryFunction<E, dynamic /*<V>*/ > mapper); | 410 UnaryFunction<E, dynamic/*=V*/ > mapper); |
| 318 | 411 |
| 319 /** | 412 /** |
| 320 * Return a task input that can be used to compute a map whose keys are the | 413 * Return a task input that can be used to compute a map whose keys are the |
| 321 * elements of this input and whose values are the [valueResult]'s associated | 414 * elements of this input and whose values are the [valueResult]'s associated |
| 322 * with those elements. | 415 * with those elements. |
| 323 */ | 416 */ |
| 324 MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf( | 417 MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/( |
| 325 ResultDescriptor /*<V>*/ valueResult); | 418 ResultDescriptor/*<V>*/ valueResult); |
| 326 } | 419 } |
| 327 | 420 |
| 328 /** | 421 /** |
| 329 * A description of an input with a [Map] based values. | 422 * A description of an input with a [Map] based values. |
| 330 * | 423 * |
| 331 * Clients may not extend, implement or mix-in this class. | 424 * Clients may not extend, implement or mix-in this class. |
| 332 */ | 425 */ |
| 333 abstract class MapTaskInput<K, V> extends TaskInput<Map<K, V>> { | 426 abstract class MapTaskInput<K, V> implements TaskInput<Map<K, V>> { |
| 334 /** | 427 /** |
| 335 * [V] must be a [List]. | 428 * [V] must be a [List]. |
| 336 * Return a task input that can be used to compute a list whose elements are | 429 * Return a task input that can be used to compute a list whose elements are |
| 337 * the result of passing keys [K] and the corresponding elements of [V] to | 430 * the result of passing keys [K] and the corresponding elements of [V] to |
| 338 * the [mapper] function. | 431 * the [mapper] function. |
| 339 */ | 432 */ |
| 340 TaskInput<List /*<E>*/ > toFlattenList( | 433 TaskInput<List/*<E>*/ > toFlattenList/*<E>*/( |
| 341 BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper); | 434 BinaryFunction<K, dynamic /*element of V*/, dynamic/*=E*/ > mapper); |
| 342 } | 435 } |
| 343 | 436 |
| 344 /** | 437 /** |
| 438 * Instances of this class are thrown when a task detects that the modification |
| 439 * time of a cache entry is not the same as the actual modification time. This |
| 440 * means that any analysis results based on the content of the target cannot be |
| 441 * used anymore and must be invalidated. |
| 442 */ |
| 443 class ModificationTimeMismatchError { |
| 444 final Source source; |
| 445 |
| 446 ModificationTimeMismatchError(this.source); |
| 447 } |
| 448 |
| 449 /** |
| 345 * A policy object that can compute sizes of results and provide the maximum | 450 * A policy object that can compute sizes of results and provide the maximum |
| 346 * active and idle sizes that can be kept in the cache. | 451 * active and idle sizes that can be kept in the cache. |
| 347 * | 452 * |
| 348 * All the [ResultDescriptor]s with the same [ResultCachingPolicy] instance | 453 * All the [ResultDescriptor]s with the same [ResultCachingPolicy] instance |
| 349 * share the same total size in a cache. | 454 * share the same total size in a cache. |
| 350 * | 455 * |
| 351 * Clients may implement this class when implementing plugins. | 456 * Clients may implement this class when implementing plugins. |
| 352 */ | 457 */ |
| 353 abstract class ResultCachingPolicy<T> { | 458 abstract class ResultCachingPolicy<T> { |
| 354 /** | 459 /** |
| (...skipping 14 matching lines...) Expand all Loading... |
| 369 int measure(T object); | 474 int measure(T object); |
| 370 } | 475 } |
| 371 | 476 |
| 372 /** | 477 /** |
| 373 * A description of an analysis result that can be computed by an [AnalysisTask]
. | 478 * A description of an analysis result that can be computed by an [AnalysisTask]
. |
| 374 * | 479 * |
| 375 * Clients may not extend, implement or mix-in this class. | 480 * Clients may not extend, implement or mix-in this class. |
| 376 */ | 481 */ |
| 377 abstract class ResultDescriptor<V> { | 482 abstract class ResultDescriptor<V> { |
| 378 /** | 483 /** |
| 484 * A comparator that can be used to sort result descriptors by their name. |
| 485 */ |
| 486 static final Comparator<ResultDescriptor> SORT_BY_NAME = |
| 487 (ResultDescriptor first, ResultDescriptor second) => |
| 488 first.name.compareTo(second.name); |
| 489 |
| 490 /** |
| 379 * Initialize a newly created analysis result to have the given [name] and | 491 * Initialize a newly created analysis result to have the given [name] and |
| 380 * [defaultValue]. | 492 * [defaultValue]. |
| 381 * | 493 * |
| 382 * The given [cachingPolicy] is used to limit the total size of results | 494 * The given [cachingPolicy] is used to limit the total size of results |
| 383 * described by this descriptor. If no policy is specified, the results are | 495 * described by this descriptor. If no policy is specified, the results are |
| 384 * never evicted from the cache, and removed only when they are invalidated. | 496 * never evicted from the cache, and removed only when they are invalidated. |
| 385 */ | 497 */ |
| 386 factory ResultDescriptor(String name, V defaultValue, | 498 factory ResultDescriptor(String name, V defaultValue, |
| 387 {ResultCachingPolicy<V> cachingPolicy}) = ResultDescriptorImpl; | 499 {ResultCachingPolicy<V> cachingPolicy}) = ResultDescriptorImpl<V>; |
| 388 | 500 |
| 389 /** | 501 /** |
| 390 * Return the caching policy for results described by this descriptor. | 502 * Return the caching policy for results described by this descriptor. |
| 391 */ | 503 */ |
| 392 ResultCachingPolicy<V> get cachingPolicy; | 504 ResultCachingPolicy<V> get cachingPolicy; |
| 393 | 505 |
| 394 /** | 506 /** |
| 395 * Return the default value for results described by this descriptor. | 507 * Return the default value for results described by this descriptor. |
| 396 */ | 508 */ |
| 397 V get defaultValue; | 509 V get defaultValue; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 | 565 |
| 454 /** | 566 /** |
| 455 * A description of an [AnalysisTask]. | 567 * A description of an [AnalysisTask]. |
| 456 * | 568 * |
| 457 * Clients may not extend, implement or mix-in this class. | 569 * Clients may not extend, implement or mix-in this class. |
| 458 */ | 570 */ |
| 459 abstract class TaskDescriptor { | 571 abstract class TaskDescriptor { |
| 460 /** | 572 /** |
| 461 * Initialize a newly created task descriptor to have the given [name] and to | 573 * Initialize a newly created task descriptor to have the given [name] and to |
| 462 * describe a task that takes the inputs built using the given [inputBuilder], | 574 * describe a task that takes the inputs built using the given [inputBuilder], |
| 463 * and produces the given [results]. The [buildTask] will be used to create | 575 * and produces the given [results]. The [buildTask] function will be used to |
| 464 * the instance of [AnalysisTask] thusly described. | 576 * create the instance of [AnalysisTask] being described. If provided, the |
| 577 * [isAppropriateFor] function will be used to determine whether the task can |
| 578 * be used on a specific target. |
| 465 */ | 579 */ |
| 466 factory TaskDescriptor( | 580 factory TaskDescriptor(String name, BuildTask buildTask, |
| 467 String name, | 581 CreateTaskInputs inputBuilder, List<ResultDescriptor> results, |
| 468 BuildTask buildTask, | 582 {SuitabilityFor suitabilityFor}) = TaskDescriptorImpl; |
| 469 CreateTaskInputs inputBuilder, | |
| 470 List<ResultDescriptor> results) = TaskDescriptorImpl; | |
| 471 | 583 |
| 472 /** | 584 /** |
| 473 * Return the builder used to build the inputs to the task. | 585 * Return the builder used to build the inputs to the task. |
| 474 */ | 586 */ |
| 475 CreateTaskInputs get createTaskInputs; | 587 CreateTaskInputs get createTaskInputs; |
| 476 | 588 |
| 477 /** | 589 /** |
| 478 * Return the name of the task being described. | 590 * Return the name of the task being described. |
| 479 */ | 591 */ |
| 480 String get name; | 592 String get name; |
| 481 | 593 |
| 482 /** | 594 /** |
| 483 * Return a list of the analysis results that will be computed by this task. | 595 * Return a list of the analysis results that will be computed by this task. |
| 484 */ | 596 */ |
| 485 List<ResultDescriptor> get results; | 597 List<ResultDescriptor> get results; |
| 486 | 598 |
| 487 /** | 599 /** |
| 488 * Create and return a task that is described by this descriptor that can be | 600 * Create and return a task that is described by this descriptor that can be |
| 489 * used to compute results based on the given [inputs]. | 601 * used to compute results based on the given [inputs]. |
| 490 */ | 602 */ |
| 491 AnalysisTask createTask(AnalysisContext context, AnalysisTarget target, | 603 AnalysisTask createTask(AnalysisContext context, AnalysisTarget target, |
| 492 Map<String, dynamic> inputs); | 604 Map<String, dynamic> inputs); |
| 605 |
| 606 /** |
| 607 * Return an indication of how suitable this task is for the given [target]. |
| 608 */ |
| 609 TaskSuitability suitabilityFor(AnalysisTarget target); |
| 493 } | 610 } |
| 494 | 611 |
| 495 /** | 612 /** |
| 496 * A description of an input to an [AnalysisTask] that can be used to compute | 613 * A description of an input to an [AnalysisTask] that can be used to compute |
| 497 * that input. | 614 * that input. |
| 498 * | 615 * |
| 499 * Clients may not extend, implement or mix-in this class. | 616 * Clients may not extend, implement or mix-in this class. |
| 500 */ | 617 */ |
| 501 abstract class TaskInput<V> { | 618 abstract class TaskInput<V> { |
| 502 /** | 619 /** |
| 503 * Create and return a builder that can be used to build this task input. | 620 * Create and return a builder that can be used to build this task input. |
| 504 */ | 621 */ |
| 505 TaskInputBuilder<V> createBuilder(); | 622 TaskInputBuilder<V> createBuilder(); |
| 506 | 623 |
| 507 /** | 624 /** |
| 508 * Return a task input that can be used to compute a list whose elements are | 625 * Return a task input that can be used to compute a list whose elements are |
| 509 * the result of passing the result of this input to the [mapper] function. | 626 * the result of passing the result of this input to the [mapper] function. |
| 510 */ | 627 */ |
| 511 ListTaskInput /*<E>*/ mappedToList(List /*<E>*/ mapper(V value)); | 628 ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value)); |
| 512 } | 629 } |
| 513 | 630 |
| 514 /** | 631 /** |
| 515 * An object used to build the value associated with a single [TaskInput]. | 632 * An object used to build the value associated with a single [TaskInput]. |
| 516 * | 633 * |
| 517 * All builders work by requesting one or more results (each result being | 634 * All builders work by requesting one or more results (each result being |
| 518 * associated with a target). The interaction pattern is modeled after the class | 635 * associated with a target). The interaction pattern is modeled after the class |
| 519 * [Iterator], in which the method [moveNext] is invoked to move from one result | 636 * [Iterator], in which the method [moveNext] is invoked to move from one result |
| 520 * request to the next. The getters [currentResult] and [currentTarget] are used | 637 * request to the next. The getters [currentResult] and [currentTarget] are used |
| 521 * to get the result and target of the current request. The value of the result | 638 * to get the result and target of the current request. The value of the result |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 * It is safe to invoke [moveNext] after it has returned `false`. In this case | 698 * It is safe to invoke [moveNext] after it has returned `false`. In this case |
| 582 * [moveNext] has no effect and will again return `false`. | 699 * [moveNext] has no effect and will again return `false`. |
| 583 * | 700 * |
| 584 * Throws a [StateError] if the value of the current result has not been | 701 * Throws a [StateError] if the value of the current result has not been |
| 585 * provided using [currentValue]. | 702 * provided using [currentValue]. |
| 586 */ | 703 */ |
| 587 bool moveNext(); | 704 bool moveNext(); |
| 588 } | 705 } |
| 589 | 706 |
| 590 /** | 707 /** |
| 708 * An indication of how suitable a task is for a given target. |
| 709 */ |
| 710 enum TaskSuitability { NONE, LOWEST, HIGHEST } |
| 711 |
| 712 /** |
| 591 * [WorkManager]s are used to drive analysis. | 713 * [WorkManager]s are used to drive analysis. |
| 592 * | 714 * |
| 593 * They know specific of the targets and results they care about, | 715 * They know specific of the targets and results they care about, |
| 594 * so they can request analysis results in optimal order. | 716 * so they can request analysis results in optimal order. |
| 595 * | 717 * |
| 596 * Clients may implement this class when implementing plugins. | 718 * Clients may implement this class when implementing plugins. |
| 597 */ | 719 */ |
| 598 abstract class WorkManager { | 720 abstract class WorkManager { |
| 599 /** | 721 /** |
| 600 * Notifies the manager about changes in the explicit source list. | 722 * Notifies the manager about changes in the explicit source list. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 /** | 795 /** |
| 674 * A work should be done, but without any special urgency. | 796 * A work should be done, but without any special urgency. |
| 675 */ | 797 */ |
| 676 NORMAL, | 798 NORMAL, |
| 677 | 799 |
| 678 /** | 800 /** |
| 679 * Nothing to do. | 801 * Nothing to do. |
| 680 */ | 802 */ |
| 681 NONE | 803 NONE |
| 682 } | 804 } |
| OLD | NEW |