| 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.src.task.inputs; | 5 library analyzer.src.task.inputs; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/task/model.dart'; | 9 import 'package:analyzer/task/model.dart'; |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * A function that converts an arbitrary object into a [TaskInput]. This is | 12 * A function that converts an arbitrary object into a [TaskInput]. This is |
| 13 * used, for example, by a [ListBasedTaskInput] to create task inputs for each | 13 * used, for example, by a [ListBasedTaskInput] to create task inputs for each |
| 14 * value in a list of values. | 14 * value in a list of values. |
| 15 */ | 15 */ |
| 16 typedef TaskInput<E> GenerateTaskInputs<E>(Object object); | 16 typedef TaskInput<E> GenerateTaskInputs<E>(Object object); |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * An input to an [AnalysisTask] that is computed by the following steps. First | 19 * An input to an [AnalysisTask] that is computed by the following steps. First |
| 20 * another (base) task input is used to compute a [List]-valued result. An input | 20 * another (base) task input is used to compute a [List]-valued result. An input |
| 21 * generator function is then used to map each element of that list to a task | 21 * generator function is then used to map each element of that list to a task |
| 22 * input. Finally, each of the task inputs are used to access analysis results, | 22 * input. Finally, each of the task inputs are used to access analysis results, |
| 23 * and the list of the analysis results is used as the input to the task. | 23 * and the list of the analysis results is used as the input to the task. |
| 24 */ | 24 */ |
| 25 class ListBasedTaskInput<B, E> implements TaskInput<List<E>> { | 25 class ListBasedTaskInput<B, E> |
| 26 /** | 26 extends _CollectionBasedTaskInput<B, E, List<E>> { |
| 27 * The accessor used to access the list of elements being mapped. | |
| 28 */ | |
| 29 final TaskInput<B> baseAccessor; | |
| 30 | |
| 31 /** | |
| 32 * The function used to convert an element in the list returned by the | |
| 33 * [baseAccessor] to a task input. | |
| 34 */ | |
| 35 GenerateTaskInputs<E> generateTaskInputs; | |
| 36 | |
| 37 /** | 27 /** |
| 38 * Initialize a result accessor to use the given [baseAccessor] to access a | 28 * Initialize a result accessor to use the given [baseAccessor] to access a |
| 39 * list of values that can be passed to the given [generateTaskInputs] to gene
rate | 29 * list of values that can be passed to the given [generateTaskInputs] to |
| 40 * a list of task inputs that can be used to access the elements of the input | 30 * generate a list of task inputs that can be used to access the elements of |
| 41 * being accessed. | 31 * the input being accessed. |
| 42 */ | 32 */ |
| 43 ListBasedTaskInput(this.baseAccessor, this.generateTaskInputs); | 33 ListBasedTaskInput( |
| 34 TaskInput<List<B>> baseAccessor, GenerateTaskInputs<E> generateTaskInputs) |
| 35 : super(baseAccessor, generateTaskInputs); |
| 44 | 36 |
| 45 @override | 37 @override |
| 46 TaskInputBuilder<List<E>> createBuilder() => | 38 TaskInputBuilder<List<E>> createBuilder() => |
| 47 new ListBasedTaskInputBuilder<B, E>(this); | 39 new ListBasedTaskInputBuilder<B, E>(this); |
| 48 } | 40 } |
| 49 | 41 |
| 50 /** | 42 /** |
| 51 * A [TaskInputBuilder] used to build an input based on a [ListBasedTaskInput]. | 43 * A [TaskInputBuilder] used to build an input based on a [ListBasedTaskInput]. |
| 52 */ | 44 */ |
| 53 class ListBasedTaskInputBuilder<B, E> implements TaskInputBuilder<List<E>> { | 45 class ListBasedTaskInputBuilder<B, E> |
| 54 /** | 46 extends _CollectionBasedTaskInputBuilder<B, E, List<E>> { |
| 55 * The input being built. | |
| 56 */ | |
| 57 final ListBasedTaskInput<B, E> input; | |
| 58 | |
| 59 /** | |
| 60 * The builder used to build the current result. | |
| 61 */ | |
| 62 TaskInputBuilder currentBuilder; | |
| 63 | |
| 64 /** | |
| 65 * The list of values computed by the [input]'s base accessor. | |
| 66 */ | |
| 67 List _baseList = null; | |
| 68 | |
| 69 /** | |
| 70 * The index in the [_baseList] of the value for which a value is currently | |
| 71 * being built. | |
| 72 */ | |
| 73 int _baseListIndex = -1; | |
| 74 | |
| 75 /** | 47 /** |
| 76 * The list of values being built. | 48 * The list of values being built. |
| 77 */ | 49 */ |
| 78 List<E> _resultValue = null; | 50 List<E> _resultValue; |
| 79 | 51 |
| 80 /** | 52 /** |
| 81 * Initialize a newly created task input builder that computes the result | 53 * Initialize a newly created task input builder that computes the result |
| 82 * specified by the given [input]. | 54 * specified by the given [input]. |
| 83 */ | 55 */ |
| 84 ListBasedTaskInputBuilder(this.input); | 56 ListBasedTaskInputBuilder(ListBasedTaskInput<B, E> input) : super(input); |
| 85 | 57 |
| 86 @override | 58 @override |
| 87 ResultDescriptor get currentResult { | 59 void _addResultElement(B baseElement, E resultElement) { |
| 88 if (currentBuilder == null) { | 60 _resultValue.add(resultElement); |
| 89 return null; | |
| 90 } | |
| 91 return currentBuilder.currentResult; | |
| 92 } | 61 } |
| 93 | 62 |
| 94 @override | 63 @override |
| 95 AnalysisTarget get currentTarget { | 64 void _initResultValue() { |
| 96 if (currentBuilder == null) { | 65 _resultValue = <E>[]; |
| 97 return null; | 66 } |
| 98 } | 67 } |
| 99 return currentBuilder.currentTarget; | 68 |
| 69 /** |
| 70 * An input to an [AnalysisTask] that is computed by the following steps. First |
| 71 * another (base) task input is used to compute a [List]-valued result. An input |
| 72 * generator function is then used to map each element of that list to a task |
| 73 * input. Finally, each of the task inputs are used to access analysis results, |
| 74 * and the map of the base elements to the analysis results is used as the |
| 75 * input to the task. |
| 76 */ |
| 77 class MapBasedTaskInput<B, E> |
| 78 extends _CollectionBasedTaskInput<B, E, Map<B, E>> { |
| 79 /** |
| 80 * Initialize a result accessor to use the given [baseAccessor] to access a |
| 81 * list of values that can be passed to the given [generateTaskInputs] to |
| 82 * generate a list of task inputs that can be used to access the elements of |
| 83 * the input being accessed. |
| 84 */ |
| 85 MapBasedTaskInput( |
| 86 TaskInput<List<B>> baseAccessor, GenerateTaskInputs<E> generateTaskInputs) |
| 87 : super(baseAccessor, generateTaskInputs); |
| 88 |
| 89 @override |
| 90 TaskInputBuilder<Map<B, E>> createBuilder() => |
| 91 new MapBasedTaskInputBuilder<B, E>(this); |
| 92 } |
| 93 |
| 94 /** |
| 95 * A [TaskInputBuilder] used to build an input based on a [MapBasedTaskInput]. |
| 96 */ |
| 97 class MapBasedTaskInputBuilder<B, E> |
| 98 extends _CollectionBasedTaskInputBuilder<B, E, Map<B, E>> { |
| 99 /** |
| 100 * The map being built. |
| 101 */ |
| 102 Map<B, E> _resultValue; |
| 103 |
| 104 /** |
| 105 * Initialize a newly created task input builder that computes the result |
| 106 * specified by the given [input]. |
| 107 */ |
| 108 MapBasedTaskInputBuilder(MapBasedTaskInput<B, E> input) : super(input); |
| 109 |
| 110 @override |
| 111 void _addResultElement(B baseElement, E resultElement) { |
| 112 _resultValue[baseElement] = resultElement; |
| 100 } | 113 } |
| 101 | 114 |
| 102 @override | 115 @override |
| 103 void set currentValue(Object value) { | 116 void _initResultValue() { |
| 104 if (currentBuilder == null) { | 117 _resultValue = new HashMap<B, E>(); |
| 105 throw new StateError( | |
| 106 'Cannot set the result value when there is no current result'); | |
| 107 } | |
| 108 currentBuilder.currentValue = value; | |
| 109 } | |
| 110 | |
| 111 @override | |
| 112 List<E> get inputValue { | |
| 113 if (currentBuilder != null || _resultValue == null) { | |
| 114 throw new StateError('Result value has not been created'); | |
| 115 } | |
| 116 return _resultValue; | |
| 117 } | |
| 118 | |
| 119 @override | |
| 120 bool moveNext() { | |
| 121 if (currentBuilder == null) { | |
| 122 if (_resultValue == null) { | |
| 123 // This is the first time moveNext has been invoked, so start by | |
| 124 // computing the list of values from which the results will be derived. | |
| 125 currentBuilder = input.baseAccessor.createBuilder(); | |
| 126 return currentBuilder.moveNext(); | |
| 127 } else { | |
| 128 // We have already computed all of the results, so just return false. | |
| 129 return false; | |
| 130 } | |
| 131 } | |
| 132 if (currentBuilder.moveNext()) { | |
| 133 return true; | |
| 134 } | |
| 135 if (_resultValue == null) { | |
| 136 // We have finished computing the list of values from which the results | |
| 137 // will be derived. | |
| 138 _baseList = currentBuilder.inputValue; | |
| 139 _baseListIndex = 0; | |
| 140 _resultValue = <E>[]; | |
| 141 } else { | |
| 142 // We have finished computing one of the elements in the result list. | |
| 143 _resultValue.add(currentBuilder.inputValue); | |
| 144 _baseListIndex++; | |
| 145 } | |
| 146 if (_baseListIndex >= _baseList.length) { | |
| 147 currentBuilder = null; | |
| 148 return false; | |
| 149 } | |
| 150 currentBuilder = | |
| 151 input.generateTaskInputs(_baseList[_baseListIndex]).createBuilder(); | |
| 152 return currentBuilder.moveNext(); | |
| 153 } | 118 } |
| 154 } | 119 } |
| 155 | 120 |
| 156 /** | 121 /** |
| 157 * An input to an [AnalysisTask] that is computed by accessing a single result | 122 * An input to an [AnalysisTask] that is computed by accessing a single result |
| 158 * defined on a single target. | 123 * defined on a single target. |
| 159 */ | 124 */ |
| 160 class SimpleTaskInput<V> implements TaskInput<V> { | 125 class SimpleTaskInput<V> implements TaskInput<V> { |
| 161 /** | 126 /** |
| 162 * The target on which the result is defined. | 127 * The target on which the result is defined. |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 return false; | 335 return false; |
| 371 } | 336 } |
| 372 currentBuilder = inputDescriptors[_currentName].createBuilder(); | 337 currentBuilder = inputDescriptors[_currentName].createBuilder(); |
| 373 // NOTE: This assumes that every builder will require at least one result | 338 // NOTE: This assumes that every builder will require at least one result |
| 374 // value to be created. If that assumption is every broken, this method will | 339 // value to be created. If that assumption is every broken, this method will |
| 375 // need to be changed to advance until we find a builder that does require | 340 // need to be changed to advance until we find a builder that does require |
| 376 // a result to be computed (or run out of builders). | 341 // a result to be computed (or run out of builders). |
| 377 return currentBuilder.moveNext(); | 342 return currentBuilder.moveNext(); |
| 378 } | 343 } |
| 379 } | 344 } |
| 345 |
| 346 /** |
| 347 * An input to an [AnalysisTask] that is computed by the following steps. First |
| 348 * another (base) task input is used to compute a [List]-valued result. An input |
| 349 * generator function is then used to map each element of that list to a task |
| 350 * input. Finally, each of the task inputs are used to access analysis results, |
| 351 * and a collection of the analysis results is used as the input to the task. |
| 352 */ |
| 353 abstract class _CollectionBasedTaskInput<B, E, C> implements TaskInput<C> { |
| 354 /** |
| 355 * The accessor used to access the list of elements being mapped. |
| 356 */ |
| 357 final TaskInput<List<B>> baseAccessor; |
| 358 |
| 359 /** |
| 360 * The function used to convert an element in the list returned by the |
| 361 * [baseAccessor] to a task input. |
| 362 */ |
| 363 final GenerateTaskInputs<E> generateTaskInputs; |
| 364 |
| 365 /** |
| 366 * Initialize a result accessor to use the given [baseAccessor] to access a |
| 367 * list of values that can be passed to the given [generateTaskInputs] to |
| 368 * generate a list of task inputs that can be used to access the elements of |
| 369 * the input being accessed. |
| 370 */ |
| 371 _CollectionBasedTaskInput(this.baseAccessor, this.generateTaskInputs); |
| 372 } |
| 373 |
| 374 /** |
| 375 * A [TaskInputBuilder] used to build an [_CollectionBasedTaskInput]. |
| 376 */ |
| 377 abstract class _CollectionBasedTaskInputBuilder<B, E, C> |
| 378 implements TaskInputBuilder<C> { |
| 379 /** |
| 380 * The input being built. |
| 381 */ |
| 382 final _CollectionBasedTaskInput<B, E, C> input; |
| 383 |
| 384 /** |
| 385 * The builder used to build the current result. |
| 386 */ |
| 387 TaskInputBuilder currentBuilder; |
| 388 |
| 389 /** |
| 390 * The list of values computed by the [input]'s base accessor. |
| 391 */ |
| 392 List<B> _baseList = null; |
| 393 |
| 394 /** |
| 395 * The index in the [_baseList] of the value for which a value is currently |
| 396 * being built. |
| 397 */ |
| 398 int _baseListIndex = -1; |
| 399 |
| 400 /** |
| 401 * The element of the [_baseList] for which a value is currently being built. |
| 402 */ |
| 403 B _baseListElement; |
| 404 |
| 405 /** |
| 406 * Initialize a newly created task input builder that computes the result |
| 407 * specified by the given [input]. |
| 408 */ |
| 409 _CollectionBasedTaskInputBuilder(this.input); |
| 410 |
| 411 @override |
| 412 ResultDescriptor get currentResult { |
| 413 if (currentBuilder == null) { |
| 414 return null; |
| 415 } |
| 416 return currentBuilder.currentResult; |
| 417 } |
| 418 |
| 419 @override |
| 420 AnalysisTarget get currentTarget { |
| 421 if (currentBuilder == null) { |
| 422 return null; |
| 423 } |
| 424 return currentBuilder.currentTarget; |
| 425 } |
| 426 |
| 427 @override |
| 428 void set currentValue(Object value) { |
| 429 if (currentBuilder == null) { |
| 430 throw new StateError( |
| 431 'Cannot set the result value when there is no current result'); |
| 432 } |
| 433 currentBuilder.currentValue = value; |
| 434 } |
| 435 |
| 436 @override |
| 437 C get inputValue { |
| 438 if (currentBuilder != null || _resultValue == null) { |
| 439 throw new StateError('Result value has not been created'); |
| 440 } |
| 441 return _resultValue; |
| 442 } |
| 443 |
| 444 /** |
| 445 * The list of values being built. |
| 446 */ |
| 447 C get _resultValue; |
| 448 |
| 449 @override |
| 450 bool moveNext() { |
| 451 if (currentBuilder == null) { |
| 452 if (_resultValue == null) { |
| 453 // This is the first time moveNext has been invoked, so start by |
| 454 // computing the list of values from which the results will be derived. |
| 455 currentBuilder = input.baseAccessor.createBuilder(); |
| 456 return currentBuilder.moveNext(); |
| 457 } else { |
| 458 // We have already computed all of the results, so just return false. |
| 459 return false; |
| 460 } |
| 461 } |
| 462 if (currentBuilder.moveNext()) { |
| 463 return true; |
| 464 } |
| 465 if (_resultValue == null) { |
| 466 // We have finished computing the list of values from which the results |
| 467 // will be derived. |
| 468 _baseList = currentBuilder.inputValue; |
| 469 _baseListIndex = 0; |
| 470 _initResultValue(); |
| 471 } else { |
| 472 // We have finished computing one of the elements in the result list. |
| 473 _addResultElement(_baseListElement, currentBuilder.inputValue); |
| 474 _baseListIndex++; |
| 475 } |
| 476 if (_baseListIndex >= _baseList.length) { |
| 477 currentBuilder = null; |
| 478 return false; |
| 479 } |
| 480 _baseListElement = _baseList[_baseListIndex]; |
| 481 currentBuilder = input.generateTaskInputs(_baseListElement).createBuilder(); |
| 482 return currentBuilder.moveNext(); |
| 483 } |
| 484 |
| 485 void _addResultElement(B baseElement, E resultElement); |
| 486 void _initResultValue(); |
| 487 } |
| OLD | NEW |