// 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.

import 'dart:async';
import 'dart:collection';

import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/api/model.dart';
import 'package:analyzer/src/task/inputs.dart';
import 'package:analyzer/src/task/manager.dart';

final PerformanceTag analysisDriverProcessOutputs =
    _taskDriverTag.createChild('processOutputs');

final PerformanceTag workOrderMoveNextPerformanceTag =
    _taskDriverTag.createChild('workOrderMoveNext');

final PerformanceTag _taskDriverTag =
    PerformanceStatistics.analyzer.createChild('taskDriver');

/**
 * An object that is used to cause analysis to be performed until all of the
 * required analysis information has been computed.
 */
class AnalysisDriver {
  /**
   * The task manager used to figure out how to compute analysis results.
   */
  final TaskManager taskManager;

  /**
   * The list of [WorkManager] used to figure out which analysis results to
   * compute.
   */
  final List<WorkManager> workManagers;

  /**
   * The context in which analysis is to be performed.
   */
  final InternalAnalysisContext context;

  /**
   * The map of [ResultChangedEvent] controllers.
   */
  final Map<ResultDescriptor, StreamController<ResultChangedEvent>>
      resultComputedControllers =
      <ResultDescriptor, StreamController<ResultChangedEvent>>{};

  /**
   * The work order that was previously computed but that has not yet been
   * completed.
   */
  WorkOrder currentWorkOrder;

  /**
   * Indicates whether any tasks are currently being performed (or building
   * their inputs).  In debug builds, we use this to ensure that tasks don't
   * try to make use of the task manager in reentrant fashion.
   */
  bool isTaskRunning = false;

  /**
   * The controller that is notified when a task is started.
   */
  StreamController<AnalysisTask> _onTaskStartedController;

  /**
   * The controller that is notified when a task is complete.
   */
  StreamController<AnalysisTask> _onTaskCompletedController;

  /**
   * Initialize a newly created driver to use the tasks know to the given
   * [taskManager] to perform analysis in the given [context].
   */
  AnalysisDriver(this.taskManager, this.workManagers, this.context) {
    _onTaskStartedController = new StreamController.broadcast();
    _onTaskCompletedController = new StreamController.broadcast();
  }

  /**
   * The stream that is notified when a task is complete.
   */
  Stream<AnalysisTask> get onTaskCompleted => _onTaskCompletedController.stream;

  /**
   * The stream that is notified when a task is started.
   */
  Stream<AnalysisTask> get onTaskStarted => _onTaskStartedController.stream;

  /**
   * Perform work until the given [result] has been computed for the given
   * [target]. Return the last [AnalysisTask] that was performed.
   */
  AnalysisTask computeResult(AnalysisTarget target, ResultDescriptor result) {
    assert(!isTaskRunning);
    try {
      isTaskRunning = true;
      AnalysisTask task;
      while (true) {
        try {
          WorkOrder workOrder = createWorkOrderForResult(target, result);
          if (workOrder != null) {
            while (workOrder.moveNext()) {
              task = performWorkItem(workOrder.current);
            }
          }
          break;
        } on ModificationTimeMismatchError {
          // Cache inconsistency was detected and fixed by invalidating
          // corresponding results in cache. Computation must be restarted.
        }
      }
      return task;
    } finally {
      isTaskRunning = false;
    }
  }

  /**
   * Return the work order describing the work that should be getting worked on,
   * or `null` if there is currently no work to be done.
   */
  WorkOrder createNextWorkOrder() {
    while (true) {
      // Find the WorkManager with the highest priority.
      WorkOrderPriority highestPriority = null;
      WorkManager highestManager = null;
      for (WorkManager manager in workManagers) {
        WorkOrderPriority priority = manager.getNextResultPriority();
        if (highestPriority == null || highestPriority.index > priority.index) {
          highestPriority = priority;
          highestManager = manager;
        }
      }
      // Nothing to do.
      if (highestPriority == WorkOrderPriority.NONE) {
        return null;
      }
      // Create a new WorkOrder.
      TargetedResult request = highestManager.getNextResult();
//      print('request: $request');
      if (request != null) {
        WorkOrder workOrder =
            createWorkOrderForResult(request.target, request.result);
        if (workOrder != null) {
          return workOrder;
        }
      }
    }
  }

  /**
   * Create a work order that will produce the given [result] for the given
   * [target]. Return the work order that was created, or `null` if the result
   * has either already been computed or cannot be computed.
   */
  WorkOrder createWorkOrderForResult(
      AnalysisTarget target, ResultDescriptor result) {
    CacheEntry entry = context.getCacheEntry(target);
    CacheState state = entry.getState(result);
    if (state == CacheState.VALID ||
        state == CacheState.ERROR ||
        state == CacheState.IN_PROCESS) {
      return null;
    }
    if (context.aboutToComputeResult(entry, result)) {
      return null;
    }
    TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
    if (taskDescriptor == null) {
      return null;
    }
    try {
      WorkItem workItem =
          new WorkItem._(context, target, taskDescriptor, result, 0, null);
      return new WorkOrder(taskManager, workItem);
    } catch (exception, stackTrace) {
      throw new AnalysisException(
          'Could not create work order (target = $target; taskDescriptor = $taskDescriptor; result = $result)',
          new CaughtException(exception, stackTrace));
    }
  }

  /**
   * Create a work order that will produce the required analysis results for
   * the given [target]. If [isPriority] is true, then the target is a priority
   * target. Return the work order that was created, or `null` if there is no
   * further work that needs to be done for the given target.
   */
  WorkOrder createWorkOrderForTarget(AnalysisTarget target, bool isPriority) {
    for (ResultDescriptor result in taskManager.generalResults) {
      WorkOrder workOrder = createWorkOrderForResult(target, result);
      if (workOrder != null) {
        return workOrder;
      }
    }
    if (isPriority) {
      for (ResultDescriptor result in taskManager.priorityResults) {
        WorkOrder workOrder = createWorkOrderForResult(target, result);
        if (workOrder != null) {
          return workOrder;
        }
      }
    }
    return null;
  }

  /**
   * Return the stream that is notified when a new value for the given
   * [descriptor] is computed.
   */
  Stream<ResultChangedEvent> onResultComputed(ResultDescriptor descriptor) {
    return resultComputedControllers.putIfAbsent(descriptor, () {
      return new StreamController<ResultChangedEvent>.broadcast(sync: true);
    }).stream;
  }

  /**
   * Perform the next analysis task, and return `true` if there is more work to
   * be done in order to compute all of the required analysis information.
   */
  bool performAnalysisTask() {
    //
    // TODO(brianwilkerson) This implementation does not allow us to prioritize
    // work across contexts. What we need is a way for an external client to ask
    // to have all priority files analyzed for each context, then ask for normal
    // files to be analyzed. There are a couple of ways to do this.
    //
    // First, we could add a "bool priorityOnly" parameter to this method and
    // return null here when it is true.
    //
    // Second, we could add a concept of a priority order and (externally) run
    // through the priorities from highest to lowest. That would be a nice
    // generalization of the previous idea, but it isn't clear that we need the
    // generality.
    //
    // Third, we could move performAnalysisTask and createNextWorkOrder to an
    // object that knows about all sources in all contexts, so that instead of
    // the client choosing a context and telling it do to some work, the client
    // simply says "do some work", and the engine chooses the best thing to do
    // next regardless of what context it's in.
    //
    assert(!isTaskRunning);
    try {
      isTaskRunning = true;
      if (currentWorkOrder == null) {
        currentWorkOrder = createNextWorkOrder();
      } else if (currentWorkOrder.moveNext()) {
        try {
          performWorkItem(currentWorkOrder.current);
        } on ModificationTimeMismatchError {
          reset();
          return true;
        }
      } else {
        currentWorkOrder = createNextWorkOrder();
      }
      return currentWorkOrder != null;
    } finally {
      isTaskRunning = false;
    }
  }

  /**
   * Perform the given work item.
   * Return the performed [AnalysisTask].
   */
  AnalysisTask performWorkItem(WorkItem item) {
    if (item.exception != null) {
      // Mark all of the results that the task would have computed as being in
      // ERROR with the exception recorded on the work item.
      CacheEntry targetEntry = context.getCacheEntry(item.target);
      targetEntry.setErrorState(item.exception, item.descriptor.results);
      return null;
    }
    // Otherwise, perform the task.
    AnalysisTask task = item.buildTask();
    _onTaskStartedController.add(task);
    task.perform();
    analysisDriverProcessOutputs.makeCurrentWhile(() {
      AnalysisTarget target = task.target;
      CacheEntry entry = context.getCacheEntry(target);
      if (task.caughtException == null) {
        List<TargetedResult> dependedOn =
            context.analysisOptions.trackCacheDependencies
                ? item.inputTargetedResults.toList()
                : const <TargetedResult>[];
        Map<ResultDescriptor, dynamic> outputs = task.outputs;
        List<ResultDescriptor> results = task.descriptor.results;
        int resultLength = results.length;
        for (int i = 0; i < resultLength; i++) {
          ResultDescriptor result = results[i];
          // TODO(brianwilkerson) We could check here that a value was produced
          // and throw an exception if not (unless we want to allow null values).
          entry.setValue(result, outputs[result], dependedOn);
        }
        outputs.forEach((ResultDescriptor descriptor, value) {
          StreamController<ResultChangedEvent> controller =
              resultComputedControllers[descriptor];
          if (controller != null) {
            ResultChangedEvent event = new ResultChangedEvent(
                context, target, descriptor, value, true);
            controller.add(event);
          }
        });
        for (WorkManager manager in workManagers) {
          manager.resultsComputed(target, outputs);
        }
      } else {
        entry.setErrorState(task.caughtException, item.descriptor.results);
      }
    });
    _onTaskCompletedController.add(task);
    return task;
  }

  /**
   * Reset the state of the driver in response to a change in the state of one
   * or more analysis targets. This will cause any analysis that was currently
   * in process to be stopped and for analysis to resume based on the new state.
   */
  void reset() {
    currentWorkOrder = null;
  }
}

/**
 * Generic dependency walker suitable for use in the analysis task driver.
 * This class implements a variant of the path-based strong component algorithm
 * (described here: http://www.cs.colorado.edu/~hal/Papers/DFS/ipl.ps.gz), with
 * the following differences:
 *
 * - The algorithm is non-recursive so that it can be used in a coroutine
 *   fashion (each call to [getNextStronglyConnectedComponent] computes a
 *   single strongly connected component and then waits to be called again)
 *
 * - Instead of keeping a temporary array which maps nodes to their locations
 *   in the [path] array, we simply search the array when necessary.  This
 *   allows us to begin finding strongly connected components without having to
 *   know the size of the whole graph.
 *
 * - This algorithm does not compute all strongly connected components; only
 *   those reachable from the starting point which are as yet unevaluated.
 *
 * The algorithm, in essence, is to traverse the dependency graph in
 * depth-first fashion from a starting node.  If the path from the starting
 * node ever encounters the same node twice, then a cycle has been found, and
 * all the nodes comprising the cycle are (conceptually) contracted into a
 * single node.  The algorithm yields possibly-collapsed nodes in proper
 * topological sort order (all the dependencies of a node are yielded before,
 * or in the same contracted component as, the node itself).
 */
abstract class CycleAwareDependencyWalker<Node> {
  /**
   * The path through the dependency graph that is currently being considered,
   * with un-collapsed nodes.
   */
  final List<Node> _path;

  /**
   * For each node in [_path], a list of the unevaluated nodes which it is
   * already known to depend on.
   */
  final List<List<Node>> _provisionalDependencies;

  /**
   * Indices into [_path] of the nodes which begin a new strongly connected
   * component, in order.  The first index in [_contractedPath] is always 0.
   *
   * For all i < contractedPath.length - 1, at least one node in the strongly
   * connected component represented by [contractedPath[i]] depends directly
   * on at least one node in the strongly connected component represented by
   * [contractedPath[i+1]].
   */
  final List<int> _contractedPath;

  /**
   * Index into [_path] of the nodes which we are currently in the process of
   * querying for their dependencies.
   *
   * [currentIndices.last] always refers to a member of the last strongly
   * connected component indicated by [_contractedPath].
   */
  final List<int> _currentIndices;

  /**
   * Begin walking dependencies starting at [startingNode].
   */
  CycleAwareDependencyWalker(Node startingNode)
      : _path = <Node>[startingNode],
        _provisionalDependencies = <List<Node>>[<Node>[]],
        _contractedPath = <int>[0],
        _currentIndices = <int>[0];

  /**
   * Determine the next unevaluated input for [node], skipping any inputs in
   * [skipInputs], and return it.  If [node] has no further inputs, return
   * `null`.
   */
  Node getNextInput(Node node, List<Node> skipInputs);

  /**
   * Determine the next strongly connected component in the graph, and return
   * it.  The client is expected to evaluate this component before calling
   * [getNextStronglyConnectedComponent] again.
   */
  StronglyConnectedComponent<Node> getNextStronglyConnectedComponent() {
    while (_currentIndices.isNotEmpty) {
      Node nextUnevaluatedInput = getNextInput(_path[_currentIndices.last],
          _provisionalDependencies[_currentIndices.last]);
      // If the assertion below fails, it indicates that [getNextInput] did not
      // skip an input that we asked it to skip.
      assert(!_provisionalDependencies[_currentIndices.last]
          .contains(nextUnevaluatedInput));
      if (nextUnevaluatedInput != null) {
        // TODO(paulberry): the call to _path.indexOf makes the algorithm
        // O(n^2) in the depth of the dependency graph.  If this becomes a
        // problem, consider maintaining a map from node to index.
        int previousIndex = _path.indexOf(nextUnevaluatedInput);
        if (previousIndex != -1) {
          // Update contractedPath to indicate that all nodes in the path
          // between previousIndex and currentIndex are part of the same
          // strongly connected component.
          while (_contractedPath.last > previousIndex) {
            _contractedPath.removeLast();
          }
          // Store nextUnevaluatedInput as a provisional dependency so that we
          // can move on to computing other dependencies.
          _provisionalDependencies[_currentIndices.last]
              .add(nextUnevaluatedInput);
          // And loop to move on to the node's next input.
          continue;
        } else {
          // This is a brand new input and there's no reason (yet) to believe
          // that it is in the same strongly connected component as any other
          // node, so push it onto the end of the path.
          int newIndex = _path.length;
          _path.add(nextUnevaluatedInput);
          _provisionalDependencies.add(<Node>[]);
          _contractedPath.add(newIndex);
          _currentIndices.add(newIndex);
          // And loop to move on to the new node's inputs.
          continue;
        }
      } else {
        // The node has no more inputs.  Figure out if there are any more nodes
        // in the current strongly connected component that need to have their
        // indices examined.
        _currentIndices.removeLast();
        if (_currentIndices.isEmpty ||
            _currentIndices.last < _contractedPath.last) {
          // No more nodes in the current strongly connected component need to
          // have their indices examined.  We can now yield this component to
          // the caller.
          List<Node> nodes = _path.sublist(_contractedPath.last);
          bool containsCycle = nodes.length > 1;
          if (!containsCycle) {
            if (_provisionalDependencies.last.isNotEmpty) {
              containsCycle = true;
            }
          }
          _path.length = _contractedPath.last;
          _provisionalDependencies.length = _contractedPath.last;
          _contractedPath.removeLast();
          return new StronglyConnectedComponent<Node>(nodes, containsCycle);
        } else {
          // At least one node in the current strongly connected component
          // still needs to have its inputs examined.  So loop and allow the
          // inputs to be examined.
          continue;
        }
      }
    }
    // No further strongly connected components found.
    return null;
  }
}

/**
 * A place to define the behaviors that need to be added to
 * [InternalAnalysisContext].
 */
abstract class ExtendedAnalysisContext implements InternalAnalysisContext {
  List<AnalysisTarget> get explicitTargets;
  List<AnalysisTarget> get priorityTargets;
  void set typeProvider(TypeProvider typeProvider);
  CacheEntry getCacheEntry(AnalysisTarget target);
}

/**
 * An exception indicating that an attempt was made to perform a task on a
 * target while gathering the inputs to perform the same task for the same
 * target.
 */
class InfiniteTaskLoopException extends AnalysisException {
  /**
   * A concrete cyclic path of [TargetedResults] within the [dependencyCycle],
   * `null` if no such path exists.  All nodes in the path are in the
   * dependencyCycle, but the path is not guaranteed to cover the
   * entire cycle.
   */
  final List<TargetedResult> cyclicPath;

  /**
   * If a dependency cycle was found while computing the inputs for the task,
   * the set of [WorkItem]s contained in the cycle (if there are overlapping
   * cycles, this is the set of all [WorkItem]s in the entire strongly
   * connected component).  Otherwise, `null`.
   */
  final List<WorkItem> dependencyCycle;

  /**
   * Initialize a newly created exception to represent a failed attempt to
   * perform the given [task] due to the given [dependencyCycle].
   */
  InfiniteTaskLoopException(AnalysisTask task, List<WorkItem> dependencyCycle,
      [List<TargetedResult> cyclicPath])
      : this.dependencyCycle = dependencyCycle,
        this.cyclicPath = cyclicPath,
        super(_composeMessage(task, dependencyCycle, cyclicPath));

  /**
   * Compose an error message based on the data we have available.
   */
  static String _composeMessage(AnalysisTask task,
      List<WorkItem> dependencyCycle, List<TargetedResult> cyclicPath) {
    StringBuffer buffer = new StringBuffer();
    buffer.write('Infinite loop while performing task ');
    buffer.write(task.descriptor.name);
    buffer.write(' for ');
    buffer.writeln(task.target);
    buffer.writeln('  Dependency Cycle:');
    for (WorkItem item in dependencyCycle) {
      buffer.write('    ');
      buffer.writeln(item);
    }
    if (cyclicPath != null) {
      buffer.writeln('  Cyclic Path:');
      for (TargetedResult result in cyclicPath) {
        buffer.write('    ');
        buffer.writeln(result);
      }
    }
    return buffer.toString();
  }
}

/**
 * Object used by [CycleAwareDependencyWalker] to report a single strongly
 * connected component of nodes.
 */
class StronglyConnectedComponent<Node> {
  /**
   * The nodes contained in the strongly connected component.
   */
  final List<Node> nodes;

  /**
   * Indicates whether the strongly component contains any cycles.  Note that
   * if [nodes] has multiple elements, this will always be `true`.  However, if
   * [nodes] has exactly one element, this may be either `true` or `false`
   * depending on whether the node has a dependency on itself.
   */
  final bool containsCycle;

  StronglyConnectedComponent(this.nodes, this.containsCycle);
}

/**
 * A description of a single analysis task that can be performed to advance
 * analysis.
 */
class WorkItem {
  /**
   * The context in which the task will be performed.
   */
  final InternalAnalysisContext context;

  /**
   * The target for which a task is to be performed.
   */
  final AnalysisTarget target;

  /**
   * A description of the task to be performed.
   */
  final TaskDescriptor descriptor;

  /**
   * The [ResultDescriptor] which was led to this work item being spawned.
   */
  final ResultDescriptor spawningResult;

  /**
   * The level of this item in its [WorkOrder].
   */
  final int level;

  /**
   * The work order that this item is part of, may be `null`.
   */
  WorkOrder workOrder;

  /**
   * An iterator used to iterate over the descriptors of the inputs to the task,
   * or `null` if all of the inputs have been collected and the task can be
   * created.
   */
  TopLevelTaskInputBuilder builder;

  /**
   * The [TargetedResult]s outputs of this task depends on.
   */
  final HashSet<TargetedResult> inputTargetedResults =
      new HashSet<TargetedResult>();

  /**
   * The inputs to the task that have been computed.
   */
  Map<String, dynamic> inputs = const <String, dynamic>{};

  /**
   * The exception that was found while trying to populate the inputs. If this
   * field is non-`null`, then the task cannot be performed and all of the
   * results that this task would have computed need to be marked as being in
   * ERROR with this exception.
   */
  CaughtException exception = null;

  /**
   * If a dependency cycle was found while computing the inputs for the task,
   * the set of [WorkItem]s contained in the cycle (if there are overlapping
   * cycles, this is the set of all [WorkItem]s in the entire strongly
   * connected component).  Otherwise, `null`.
   */
  List<WorkItem> dependencyCycle;

  /**
   * Initialize a newly created work item to compute the inputs for the task
   * described by the given descriptor.
   */
  WorkItem._(this.context, this.target, this.descriptor, this.spawningResult,
      this.level, this.workOrder) {
    _checkInternalUseOfTaskModel();
    AnalysisTarget actualTarget =
        identical(target, AnalysisContextTarget.request)
            ? new AnalysisContextTarget(context)
            : target;
//    print('${'\t' * level}$spawningResult of $actualTarget');
    Map<String, TaskInput> inputDescriptors =
        descriptor.createTaskInputs(actualTarget);
    builder = new TopLevelTaskInputBuilder(inputDescriptors);
    if (!builder.moveNext()) {
      builder = null;
    }
  }

  @override
  int get hashCode =>
      JenkinsSmiHash.hash2(descriptor.hashCode, target.hashCode);

  @override
  bool operator ==(other) {
    if (other is WorkItem) {
      return this.descriptor == other.descriptor && this.target == other.target;
    } else {
      return false;
    }
  }

  /**
   * Build the task represented by this work item.
   */
  AnalysisTask buildTask() {
    if (builder != null) {
      throw new StateError("some inputs have not been computed");
    }
    AnalysisTask task = descriptor.createTask(context, target, inputs);
    task.dependencyCycle = dependencyCycle;
    return task;
  }

  /**
   * Gather all of the inputs needed to perform the task.
   *
   * If at least one of the inputs have not yet been computed, return a work
   * item that can be used to generate that input to indicate that the caller
   * should perform the returned item's task before returning to gathering
   * inputs for this item's task.
   *
   * If all of the inputs have been gathered, return `null` to indicate that the
   * client should build and perform the task. A value of `null` will also be
   * returned if some of the inputs cannot be computed and the task cannot be
   * performed. Callers can differentiate between these cases by checking the
   * [exception] field. If the field is `null`, then the task can be performed;
   * if the field is non-`null` then the task cannot be performed and all of the
   * tasks' results should be marked as being in ERROR.
   */
  WorkItem gatherInputs(TaskManager taskManager, List<WorkItem> skipInputs) {
    while (builder != null) {
      AnalysisTarget inputTarget = builder.currentTarget;
      ResultDescriptor inputResult = builder.currentResult;

      // TODO(scheglov) record information to debug
      // https://github.com/dart-lang/sdk/issues/24939
      if (inputTarget == null || inputResult == null) {
        try {
          String message =
              'Invalid input descriptor ($inputTarget, $inputResult) for $this';
          if (workOrder != null) {
            message += '\nPath:\n' + workOrder.workItems.join('|\n');
          }
          throw new AnalysisException(message);
        } catch (exception, stackTrace) {
          this.exception = new CaughtException(exception, stackTrace);
          AnalysisEngine.instance.logger
              .logError('Task failed: $this', this.exception);
        }
        return null;
      }

      inputTargetedResults.add(new TargetedResult(inputTarget, inputResult));
      CacheEntry inputEntry = context.getCacheEntry(inputTarget);
      CacheState inputState = inputEntry.getState(inputResult);
      if (inputState == CacheState.ERROR) {
        exception = inputEntry.exception;
        return null;
      } else if (inputState == CacheState.IN_PROCESS) {
        //
        // TODO(brianwilkerson) Implement this case.
        //
        // One possibility would be to return a WorkItem that would perform a
        // no-op task in order to cause us to come back to this work item on the
        // next iteration. It would be more efficient, in general, to push this
        // input onto a waiting list and proceed to the next input so that work
        // could proceed, but given that the only result that can currently be
        // IN_PROCESS is CONTENT, I don't know that it's worth the extra effort
        // to implement the general solution at this point.
        //
        throw new UnimplementedError();
      } else if (inputState != CacheState.VALID) {
        if (context.aboutToComputeResult(inputEntry, inputResult)) {
          inputState = CacheState.VALID;
          builder.currentValue = inputEntry.getValue(inputResult);
        } else {
          try {
            TaskDescriptor descriptor =
                taskManager.findTask(inputTarget, inputResult);
            if (descriptor == null) {
              throw new AnalysisException(
                  'Cannot find task to build $inputResult for $inputTarget');
            }
            if (skipInputs.any((WorkItem item) =>
                item.target == inputTarget && item.descriptor == descriptor)) {
              // This input is being skipped due to a circular dependency.  Tell
              // the builder that it's not available so we can move on to other
              // inputs.
              builder.currentValueNotAvailable();
            } else {
              return new WorkItem._(context, inputTarget, descriptor,
                  inputResult, level + 1, workOrder);
            }
          } on AnalysisException catch (exception, stackTrace) {
            this.exception = new CaughtException(exception, stackTrace);
            return null;
          } catch (exception, stackTrace) {
            this.exception = new CaughtException(exception, stackTrace);
            throw new AnalysisException(
                'Cannot create work order to build $inputResult for $inputTarget',
                this.exception);
          }
        }
      } else {
        builder.currentValue = inputEntry.getValue(inputResult);
        if (builder.flushOnAccess) {
          inputEntry.setState(inputResult, CacheState.FLUSHED);
        }
      }
      if (!builder.moveNext()) {
        inputs = builder.inputValue;
        builder = null;
      }
    }
    return null;
  }

  @override
  String toString() => 'Run $descriptor on $target';

  static void _checkInternalUseOfTaskModel() {
    if (!StackTrace.current.toString().contains('/analyzer/test/')) {
      throw new StateError(
          'The analyzer task model is no longer supported.  Please use the AnalysisSession API.');
    }
  }
}

/**
 * A description of the work to be done to compute a desired analysis result.
 * The class implements a lazy depth-first traversal of the work item's input.
 */
class WorkOrder implements Iterator<WorkItem> {
  /**
   * The dependency walker which is being used to determine what work to do
   * next.
   */
  final _WorkOrderDependencyWalker _dependencyWalker;

  /**
   * The strongly connected component most recently returned by
   * [_dependencyWalker], minus any [WorkItem]s that the iterator has already
   * moved past.
   *
   * Null if the [_dependencyWalker] hasn't been used yet.
   */
  List<WorkItem> currentItems;

  /**
   * Initialize a newly created work order to compute the result described by
   * the given work item.
   */
  WorkOrder(TaskManager taskManager, WorkItem item)
      : _dependencyWalker = new _WorkOrderDependencyWalker(taskManager, item) {
    item.workOrder = this;
  }

  @override
  WorkItem get current {
    if (currentItems == null) {
      return null;
    } else {
      return currentItems.last;
    }
  }

  List<WorkItem> get workItems => _dependencyWalker._path;

  @override
  bool moveNext() {
    return workOrderMoveNextPerformanceTag.makeCurrentWhile(() {
      if (currentItems != null && currentItems.length > 1) {
        // Yield more items.
        currentItems.removeLast();
        return true;
      } else {
        // Get a new strongly connected component.
        StronglyConnectedComponent<WorkItem> nextStronglyConnectedComponent =
            _dependencyWalker.getNextStronglyConnectedComponent();
        if (nextStronglyConnectedComponent == null) {
          currentItems = null;
          return false;
        }
        currentItems = nextStronglyConnectedComponent.nodes;
        if (nextStronglyConnectedComponent.containsCycle) {
          // A cycle has been found.
          for (WorkItem item in currentItems) {
            item.dependencyCycle = currentItems.toList();
          }
        } else {
          assert(currentItems.length == 1);
        }
        return true;
      }
    });
  }
}

/**
 * Specialization of [CycleAwareDependencyWalker] for use by [WorkOrder].
 */
class _WorkOrderDependencyWalker extends CycleAwareDependencyWalker<WorkItem> {
  /**
   * The task manager used to build work items.
   */
  final TaskManager taskManager;

  _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode)
      : super(startingNode);

  @override
  WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) {
    return node.gatherInputs(taskManager, skipInputs);
  }
}
