コード例 #1
0
ファイル: RdepsFunction.java プロジェクト: Nethesh/bazel
  /**
   * Compute the transitive closure of the universe, then breadth-first search from the argument
   * towards the universe while staying within the transitive closure.
   */
  @Override
  public <T> Set<T> eval(QueryEnvironment<T> env, QueryExpression expression, List<Argument> args)
      throws QueryException {
    Set<T> universeValue = args.get(0).getExpression().eval(env);
    Set<T> argumentValue = args.get(1).getExpression().eval(env);
    int depthBound = args.size() > 2 ? args.get(2).getInteger() : Integer.MAX_VALUE;

    env.buildTransitiveClosure(expression, universeValue, Integer.MAX_VALUE);

    Set<T> visited = new LinkedHashSet<>();
    Set<T> reachableFromUniverse = env.getTransitiveClosure(universeValue);
    Collection<T> current = argumentValue;

    // We need to iterate depthBound + 1 times.
    for (int i = 0; i <= depthBound; i++) {
      List<T> next = new ArrayList<>();
      for (T node : current) {
        if (!reachableFromUniverse.contains(node)) {
          // Traversed outside the transitive closure of the universe.
          continue;
        }

        if (!visited.add(node)) {
          // Already visited; if we see a node in a later round, then we don't need to visit it
          // again, because the depth at which we see it at must be greater than or equal to the
          // last visit.
          continue;
        }

        next.addAll(env.getReverseDeps(node));
      }
      if (next.isEmpty()) {
        // Exit when there are no more nodes to visit.
        break;
      }
      current = next;
    }

    return visited;
  }