// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library analyzer.src.task.inputs;

import 'dart:collection';

import 'package:analyzer/task/model.dart';

/**
 * A function that converts an object of the type [B] into a [TaskInput].
 * This is used, for example, by a [ListToListTaskInput] to create task inputs
 * for each value in a list of values.
 */
typedef TaskInput<E> GenerateTaskInputs<B, E>(B object);

/**
 * A function that maps one [value] to another value.
 */
typedef R Mapper<P, R>(P value);

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class ConstantTaskInput<V> extends TaskInputImpl<V> {
  final V value;

  ConstantTaskInput(this.value);

  @override
  TaskInputBuilder<V> createBuilder() {
    return new ConstantTaskInputBuilder<V>(this);
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ConstantTaskInput].
 */
class ConstantTaskInputBuilder<V> implements TaskInputBuilder<V> {
  final ConstantTaskInput<V> input;

  ConstantTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult => null;

  @override
  AnalysisTarget get currentTarget => null;

  @override
  void set currentValue(Object value) {
    throw new StateError('Only supported after moveNext() returns true');
  }

  @override
  bool get flushOnAccess => false;

  @override
  V get inputValue => input.value;

  @override
  void currentValueNotAvailable() {
    throw new StateError('Only supported after moveNext() returns true');
  }

  @override
  bool moveNext() => false;
}

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class ListTaskInputImpl<E> extends SimpleTaskInput<List<E>>
    with ListTaskInputMixin<E>
    implements ListTaskInput<E> {
  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  ListTaskInputImpl(AnalysisTarget target, ResultDescriptor<List<E>> result)
      : super._unflushable(target, result);
}

/**
 * A mixin-ready implementation of [ListTaskInput].
 */
abstract class ListTaskInputMixin<E> implements ListTaskInput<E> {
  @override
  ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
      ListResultDescriptor/*<V>*/ subListResult) {
    return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
        this,
        (E element) =>
            subListResult.of(element as AnalysisTarget) as TaskInput/*<V>*/);
  }

  ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper) {
    return new ListToListTaskInput<E, dynamic/*=V*/ >(this, mapper);
  }

  ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
    return (this as ListTaskInput<AnalysisTarget>).toList(valueResult.of);
  }

  MapTaskInput<E, dynamic/*=V*/ > toMap/*<V>*/(
      UnaryFunction<E, dynamic/*=V*/ > mapper) {
    return new ListToMapTaskInput<E, dynamic/*=V*/ >(this, mapper);
  }

  MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
      ResultDescriptor/*<V>*/ valueResult) {
    return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and the list of the analysis results is used as the input to the task.
 */
class ListToFlattenListTaskInput<B, E>
    extends _ListToCollectionTaskInput<B, E, List<E>>
    with ListTaskInputMixin<E>
    implements ListTaskInput<E> {
  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  ListToFlattenListTaskInput(TaskInput<List<B>> baseAccessor,
      GenerateTaskInputs<B, E> generateTaskInputs)
      : super(baseAccessor, generateTaskInputs);

  @override
  TaskInputBuilder<List<E>> createBuilder() =>
      new ListToFlattenListTaskInputBuilder<B, E>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ListToFlattenListTaskInput].
 */
class ListToFlattenListTaskInputBuilder<B, E>
    extends _ListToCollectionTaskInputBuilder<B, E, List<E>> {
  /**
   * The list of values being built.
   */
  List<E> _resultValue;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ListToFlattenListTaskInputBuilder(ListToFlattenListTaskInput<B, E> input)
      : super(input);

  @override
  void _addResultElement(B baseElement, E resultElement) {
    _resultValue.addAll(resultElement as Iterable<E>);
  }

  @override
  void _initResultValue() {
    _resultValue = <E>[];
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and the list of the analysis results is used as the input to the task.
 */
class ListToListTaskInput<B, E>
    extends _ListToCollectionTaskInput<B, E, List<E>>
    with ListTaskInputMixin<E> {
  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  ListToListTaskInput(TaskInput<List<B>> baseAccessor,
      GenerateTaskInputs<B, E> generateTaskInputs)
      : super(baseAccessor, generateTaskInputs);

  @override
  TaskInputBuilder<List<E>> createBuilder() =>
      new ListToListTaskInputBuilder<B, E>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ListToListTaskInput].
 */
class ListToListTaskInputBuilder<B, E>
    extends _ListToCollectionTaskInputBuilder<B, E, List<E>> {
  /**
   * The list of values being built.
   */
  List<E> _resultValue;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ListToListTaskInputBuilder(ListToListTaskInput<B, E> input) : super(input);

  @override
  void _addResultElement(B baseElement, E resultElement) {
    _resultValue.add(resultElement);
  }

  @override
  void _initResultValue() {
    _resultValue = <E>[];
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and the map of the base elements to the analysis results is used as the
 * input to the task.
 */
class ListToMapTaskInput<B, E>
    extends _ListToCollectionTaskInput<B, E, Map<B, E>>
    with MapTaskInputMixin<B, E> {
  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  ListToMapTaskInput(TaskInput<List<B>> baseAccessor,
      GenerateTaskInputs<B, E> generateTaskInputs)
      : super(baseAccessor, generateTaskInputs);

  @override
  TaskInputBuilder<Map<B, E>> createBuilder() =>
      new ListToMapTaskInputBuilder<B, E>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ListToMapTaskInput].
 */
class ListToMapTaskInputBuilder<B, E>
    extends _ListToCollectionTaskInputBuilder<B, E, Map<B, E>> {
  /**
   * The map being built.
   */
  Map<B, E> _resultValue;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ListToMapTaskInputBuilder(ListToMapTaskInput<B, E> input) : super(input);

  @override
  void _addResultElement(B baseElement, E resultElement) {
    _resultValue[baseElement] = resultElement;
  }

  @override
  void _initResultValue() {
    _resultValue = new HashMap<B, E>();
  }
}

/**
 * A mixin-ready implementation of [MapTaskInput].
 */
abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
  TaskInput<List/*<E>*/ > toFlattenList/*<E>*/(
      BinaryFunction<K, dynamic /*element of V*/, dynamic/*=E*/ > mapper) {
    return new MapToFlattenListTaskInput<K, dynamic /*element of V*/,
        dynamic/*=E*/ >(this as MapTaskInput<K, List /*element of V*/ >, mapper);
  }
}

/**
 * A [TaskInput] that is computed by the following steps.
 *
 * First the [base] task input is used to compute a [Map]-valued result.
 * The values of the [Map] must be [List]s.
 *
 * The given [mapper] is used to transform each key / value pair of the [Map]
 * into task inputs.
 *
 * Finally, each of the task inputs are used to access analysis results,
 * and the list of the results is used as the input.
 */
class MapToFlattenListTaskInput<K, V, E> extends TaskInputImpl<List<E>> {
  final MapTaskInput<K, List<V>> base;
  final BinaryFunction<K, V, E> mapper;

  MapToFlattenListTaskInput(this.base, this.mapper);

  @override
  TaskInputBuilder<List<E>> createBuilder() {
    return new MapToFlattenListTaskInputBuilder<K, V, E>(base, mapper);
  }
}

/**
 * The [TaskInputBuilder] for [MapToFlattenListTaskInput].
 */
class MapToFlattenListTaskInputBuilder<K, V, E>
    implements TaskInputBuilder<List<E>> {
  final MapTaskInput<K, List<V>> base;
  final BinaryFunction<K, V, E> mapper;

  TaskInputBuilder currentBuilder;
  Map<K, List<V>> baseMap;
  Iterator<K> keyIterator;
  Iterator<V> valueIterator;

  final List<E> inputValue = <E>[];

  MapToFlattenListTaskInputBuilder(this.base, this.mapper) {
    currentBuilder = base.createBuilder();
  }

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    // Prepare base Map.
    if (baseMap == null) {
      if (currentBuilder.moveNext()) {
        return true;
      }
      baseMap = currentBuilder.inputValue as dynamic/*=Map<K, List<V>>*/;
      if (baseMap == null) {
        // No base map could be computed due to a circular dependency.  Use an
        // empty map so that no further results will be computed.
        baseMap = {};
      }
      keyIterator = baseMap.keys.iterator;
      // Done with this builder.
      currentBuilder = null;
    }
    // Prepare the next result value.
    if (currentBuilder != null) {
      if (currentBuilder.moveNext()) {
        return true;
      }
      // Add the result value for the current Map key/value.
      E resultValue = currentBuilder.inputValue as dynamic/*=E*/;
      if (resultValue != null) {
        inputValue.add(resultValue);
      }
      // Done with this builder.
      currentBuilder = null;
    }
    // Move to the next Map value.
    if (valueIterator != null && valueIterator.moveNext()) {
      K key = keyIterator.current;
      V value = valueIterator.current;
      currentBuilder = mapper(key, value).createBuilder();
      return moveNext();
    }
    // Move to the next Map key.
    if (keyIterator.moveNext()) {
      K key = keyIterator.current;
      valueIterator = baseMap[key].iterator;
      return moveNext();
    }
    // No more Map values/keys to transform.
    return false;
  }
}

/**
 * An input to an [AnalysisTask] that is computed by mapping the value of
 * another task input to a list of values.
 */
class ObjectToListTaskInput<E> extends TaskInputImpl<List<E>>
    with ListTaskInputMixin<E>
    implements ListTaskInput<E> {
  // TODO(brianwilkerson) Add another type parameter to this class that can be
  // used as the type of the keys of [mapper].
  /**
   * The input used to compute the value to be mapped.
   */
  final TaskInput baseInput;

  /**
   * The function used to map the value of the base input to the list of values.
   */
  final Mapper<Object, List<E>> mapper;

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [baseInput] associated with the given [mapper].
   */
  ObjectToListTaskInput(this.baseInput, this.mapper);

  @override
  TaskInputBuilder<List<E>> createBuilder() =>
      new ObjectToListTaskInputBuilder<E>(this);

  @override
  ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
      ListResultDescriptor/*<V>*/ subListResult) {
    return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
        this,
        (E element) =>
            subListResult.of(element as AnalysisTarget) as TaskInput/*<V>*/);
  }

  @override
  ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
    return new ListToListTaskInput<E, dynamic/*=V*/ >(
        this, (E element) => valueResult.of(element as AnalysisTarget));
  }

  @override
  MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
      ResultDescriptor/*<V>*/ valueResult) {
    return new ListToMapTaskInput<AnalysisTarget, dynamic/*=V*/ >(
        this as dynamic/*=TaskInput<List<AnalysisTarget>>*/, valueResult.of);
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
 */
class ObjectToListTaskInputBuilder<E> implements TaskInputBuilder<List<E>> {
  /**
   * The input being built.
   */
  final ObjectToListTaskInput<E> input;

  /**
   * The builder created by the input.
   */
  TaskInputBuilder builder;

  /**
   * The value of the input being built, or `null` if the value hasn't been set
   * yet or if no result is available ([currentValueNotAvailable] was called).
   */
  List<E> _inputValue = null;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ObjectToListTaskInputBuilder(this.input) {
    builder = input.baseInput.createBuilder();
  }

  @override
  ResultDescriptor get currentResult {
    if (builder == null) {
      return null;
    }
    return builder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (builder == null) {
      return null;
    }
    return builder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (builder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    builder.currentValue = value;
  }

  @override
  bool get flushOnAccess => builder.flushOnAccess;

  @override
  List<E> get inputValue {
    if (builder != null) {
      throw new StateError('Result value has not been created');
    }
    return _inputValue;
  }

  @override
  void currentValueNotAvailable() {
    if (builder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    builder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (builder == null) {
      return false;
    } else if (builder.moveNext()) {
      return true;
    } else {
      // This might not be the right semantics. If the value could not be
      // computed then we pass the resulting `null` in to the mapper function.
      // Unfortunately, we cannot tell the difference between a `null` that's
      // there because no value could be computed and a `null` that's there
      // because that's what *was* computed.
      _inputValue = input.mapper(builder.inputValue);
      builder = null;
      return false;
    }
  }
}

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class SimpleTaskInput<V> extends TaskInputImpl<V> {
  /**
   * The target on which the result is defined.
   */
  final AnalysisTarget target;

  /**
   * The result to be accessed.
   */
  final ResultDescriptor<V> result;

  /**
   * Return `true` if the value accessed by this input builder should be flushed
   * from the cache at the time it is retrieved.
   */
  final bool flushOnAccess;

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  SimpleTaskInput(this.target, this.result, {this.flushOnAccess: false});

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  SimpleTaskInput._unflushable(this.target, this.result)
      : flushOnAccess = false;

  @override
  TaskInputBuilder<V> createBuilder() => new SimpleTaskInputBuilder<V>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
 */
class SimpleTaskInputBuilder<V> implements TaskInputBuilder<V> {
  /**
   * The state value indicating that the builder is positioned before the single
   * result.
   */
  static const _BEFORE = -1;

  /**
   * The state value indicating that the builder is positioned at the single
   * result.
   */
  static const _AT = 0;

  /**
   * The state value indicating that the builder is positioned after the single
   * result.
   */
  static const _AFTER = 1;

  /**
   * The input being built.
   */
  final SimpleTaskInput<V> input;

  /**
   * The value of the input being built.  `null` if the value hasn't been set
   * yet, or if no result is available ([currentValueNotAvailable] was called).
   */
  V _resultValue = null;

  /**
   * The state of the builder.
   */
  int _state = _BEFORE;

  /**
   * A flag indicating whether the result value was explicitly set.
   */
  bool _resultSet = false;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  SimpleTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult => _state == _AT ? input.result : null;

  @override
  AnalysisTarget get currentTarget => _state == _AT ? input.target : null;

  @override
  void set currentValue(Object value) {
    if (_state != _AT) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    _resultValue = value as V;
    _resultSet = true;
  }

  @override
  bool get flushOnAccess => input.flushOnAccess;

  @override
  V get inputValue {
    if (_state != _AFTER) {
      throw new StateError('Result value has not been created');
    }
    return _resultValue;
  }

  @override
  void currentValueNotAvailable() {
    if (_state != _AT) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    _resultValue = null;
    _resultSet = true;
  }

  @override
  bool moveNext() {
    if (_state == _BEFORE) {
      _state = _AT;
      return true;
    } else {
      if (!_resultSet) {
        throw new StateError(
            'The value of the current result must be set before moving to the next result.');
      }
      _state = _AFTER;
      return false;
    }
  }
}

abstract class TaskInputImpl<V> implements TaskInput<V> {
  @override
  ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value)) {
    return new ObjectToListTaskInput(
        this, (Object element) => mapper(element as V));
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on one or more other task
 * inputs. The task inputs to be built are specified by a table mapping the name
 * of the input to the task used to access the input's value.
 */
class TopLevelTaskInputBuilder
    implements TaskInputBuilder<Map<String, Object>> {
  /**
   * The descriptors describing the inputs to be built.
   */
  final Map<String, TaskInput> inputDescriptors;

  /**
   * The names of the inputs. There are the keys from the [inputDescriptors] in
   * an indexable form.
   */
  List<String> inputNames;

  /**
   * The index of the input name associated with the current result and target.
   */
  int nameIndex = -1;

  /**
   * The builder used to build the current result.
   */
  TaskInputBuilder currentBuilder;

  /**
   * The inputs that are being or have been built. The map will be incomplete
   * unless the method [moveNext] returns `false`.
   */
  final Map<String, Object> inputs = new HashMap<String, Object>();

  /**
   * Initialize a newly created task input builder to build the inputs described
   * by the given [inputDescriptors].
   */
  TopLevelTaskInputBuilder(this.inputDescriptors) {
    inputNames = inputDescriptors.keys.toList();
  }

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  Map<String, Object> get inputValue {
    if (nameIndex < inputNames.length) {
      throw new StateError('Result value has not been created');
    }
    return inputs;
  }

  /**
   * Assuming that there is a current input, return its name.
   */
  String get _currentName => inputNames[nameIndex];

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (nameIndex >= inputNames.length) {
      // We have already computed all of the results, so just return false.
      return false;
    }
    if (nameIndex < 0) {
      // This is the first time moveNext has been invoked, so we just determine
      // whether there are any results to be computed.
      nameIndex = 0;
    } else {
      if (currentBuilder.moveNext()) {
        // We are still working on building the value associated with the
        // current name.
        return true;
      }
      if (currentBuilder.inputValue != null) {
        inputs[_currentName] = currentBuilder.inputValue;
      }
      nameIndex++;
    }
    if (nameIndex >= inputNames.length) {
      // There is no next value, so we're done.
      return false;
    }
    currentBuilder = inputDescriptors[_currentName].createBuilder();
    while (!currentBuilder.moveNext()) {
      if (currentBuilder.inputValue != null) {
        inputs[_currentName] = currentBuilder.inputValue;
      }
      nameIndex++;
      if (nameIndex >= inputNames.length) {
        // There is no next value, so we're done.
        return false;
      }
      currentBuilder = inputDescriptors[_currentName].createBuilder();
    }
    return true;
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and a collection of the analysis results is used as the input to the task.
 */
abstract class _ListToCollectionTaskInput<B, E, C> extends TaskInputImpl<C> {
  /**
   * The accessor used to access the list of elements being mapped.
   */
  final TaskInput<List<B>> baseAccessor;

  /**
   * The function used to convert an element in the list returned by the
   * [baseAccessor] to a task input.
   */
  final GenerateTaskInputs<B, E> generateTaskInputs;

  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  _ListToCollectionTaskInput(this.baseAccessor, this.generateTaskInputs);
}

/**
 * A [TaskInputBuilder] used to build an [_ListToCollectionTaskInput].
 */
abstract class _ListToCollectionTaskInputBuilder<B, E, C>
    implements TaskInputBuilder<C> {
  /**
   * The input being built.
   */
  final _ListToCollectionTaskInput<B, E, C> input;

  /**
   * The builder used to build the current result.
   */
  TaskInputBuilder currentBuilder;

  /**
   * The list of values computed by the [input]'s base accessor.
   */
  List<B> _baseList = null;

  /**
   * The index in the [_baseList] of the value for which a value is currently
   * being built.
   */
  int _baseListIndex = -1;

  /**
   * The element of the [_baseList] for which a value is currently being built.
   */
  B _baseListElement;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  _ListToCollectionTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  C get inputValue {
    if (currentBuilder != null || _resultValue == null) {
      throw new StateError('Result value has not been created');
    }
    return _resultValue;
  }

  /**
   * The list of values being built.
   */
  C get _resultValue;

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (currentBuilder == null) {
      if (_resultValue == null) {
        // This is the first time moveNext has been invoked, so start by
        // computing the list of values from which the results will be derived.
        currentBuilder = input.baseAccessor.createBuilder();
        return currentBuilder.moveNext();
      } else {
        // We have already computed all of the results, so just return false.
        return false;
      }
    }
    if (currentBuilder.moveNext()) {
      return true;
    }
    if (_resultValue == null) {
      // We have finished computing the list of values from which the results
      // will be derived.
      _baseList = currentBuilder.inputValue as dynamic/*=List<B>*/;
      if (_baseList == null) {
        // No base list could be computed due to a circular dependency.  Use an
        // empty list so that no further results will be computed.
        _baseList = [];
      }
      _baseListIndex = 0;
      _initResultValue();
    } else {
      // We have finished computing one of the elements in the result list.
      if (currentBuilder.inputValue != null) {
        _addResultElement(
            _baseListElement, currentBuilder.inputValue as dynamic/*=E*/);
      }
      _baseListIndex++;
    }
    if (_baseListIndex >= _baseList.length) {
      currentBuilder = null;
      return false;
    }
    _baseListElement = _baseList[_baseListIndex];
    currentBuilder = input.generateTaskInputs(_baseListElement).createBuilder();
    return currentBuilder.moveNext();
  }

  void _addResultElement(B baseElement, E resultElement);
  void _initResultValue();
}
