blob: 2e4fdb990f55690fab1471d6252f4b7d59ef0317 [file] [log] [blame]
/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.rules;
import com.facebook.buck.graph.AbstractBreadthFirstTraversal;
import com.facebook.buck.graph.DefaultDirectedAcyclicGraph;
import com.facebook.buck.graph.MutableDirectedGraph;
import com.facebook.buck.model.BuildTarget;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import javax.annotation.Nullable;
/**
* Represents the graph of {@link com.facebook.buck.rules.TargetNode}s constructed
* by parsing the build files.
*/
public class TargetGraph extends DefaultDirectedAcyclicGraph<TargetNode<?>> {
public static final TargetGraph EMPTY = new TargetGraph(
new MutableDirectedGraph<TargetNode<?>>());
private final ImmutableMap<BuildTarget, TargetNode<?>> targetsToNodes;
public TargetGraph(MutableDirectedGraph<TargetNode<?>> graph) {
super(graph);
ImmutableMap.Builder<BuildTarget, TargetNode<?>> builder = ImmutableMap.builder();
for (TargetNode<?> node : graph.getNodes()) {
builder.put(node.getBuildTarget(), node);
}
this.targetsToNodes = builder.build();
}
@Nullable
public TargetNode<?> get(BuildTarget target) {
return targetsToNodes.get(target);
}
public Function<BuildTarget, TargetNode<?>> get() {
return new Function<BuildTarget, TargetNode<?>>() {
@Override
public TargetNode<?> apply(BuildTarget input) {
return Preconditions.checkNotNull(get(input));
}
};
}
public Iterable<TargetNode<?>> getAll(Iterable<BuildTarget> targets) {
return Iterables.transform(
targets,
new Function<BuildTarget, TargetNode<?>>() {
@Override
public TargetNode<?> apply(BuildTarget input) {
return Preconditions.checkNotNull(get(input));
}
});
}
/**
* Get the subgraph of the the current graph containing the passed in roots and all of their
* transitive dependencies as nodes. Edges between the included nodes are preserved.
*
* @param roots An iterable containing the roots of the new subgraph.
* @return A subgraph of the current graph.
*/
public TargetGraph getSubgraph(Iterable<? extends TargetNode<?>> roots) {
final MutableDirectedGraph<TargetNode<?>> subgraph = new MutableDirectedGraph<>();
new AbstractBreadthFirstTraversal<TargetNode<?>>(roots) {
@Override
public ImmutableSet<TargetNode<?>> visit(TargetNode<?> node) {
subgraph.addNode(node);
ImmutableSet<TargetNode<?>> dependencies =
ImmutableSet.copyOf(getAll(node.getDeps()));
for (TargetNode<?> dependency : dependencies) {
subgraph.addEdge(node, dependency);
}
return dependencies;
}
}.start();
return new TargetGraph(subgraph);
}
}