use of com.facebook.buck.autodeps.DepsForBuildFiles.DependencyType in project buck by facebook.
the class JavaDepsFinder method findDepsForBuildFiles.
private DepsForBuildFiles findDepsForBuildFiles(final TargetGraph graph, final DependencyInfo dependencyInfo, final Console console) {
// For the rules that expect to have their deps generated, look through all of their required
// symbols and try to find the build rule that provides each symbols. Store these build rules in
// the depsForBuildFiles data structure.
//
// Currently, we process each rule with autodeps=True on a single thread. See the class overview
// for DepsForBuildFiles about what it would take to do this work in a multi-threaded way.
DepsForBuildFiles depsForBuildFiles = new DepsForBuildFiles();
for (final TargetNode<?, ?> rule : dependencyInfo.rulesWithAutodeps) {
final Set<BuildTarget> providedDeps = dependencyInfo.rulesWithAutodepsToProvidedDeps.get(rule);
final Predicate<TargetNode<?, ?>> isVisibleDepNotAlreadyInProvidedDeps = provider -> provider.isVisibleTo(graph, rule) && !providedDeps.contains(provider.getBuildTarget());
final boolean isJavaTestRule = rule.getDescription() instanceof JavaTestDescription;
for (DependencyType type : DependencyType.values()) {
HashMultimap<TargetNode<?, ?>, String> ruleToSymbolsMap;
switch(type) {
case DEPS:
ruleToSymbolsMap = dependencyInfo.ruleToRequiredSymbols;
break;
case EXPORTED_DEPS:
ruleToSymbolsMap = dependencyInfo.ruleToExportedSymbols;
break;
default:
throw new IllegalStateException("Unrecognized type: " + type);
}
final DependencyType typeOfDepToAdd;
if (isJavaTestRule) {
// java_test rules do not honor exported_deps: add all dependencies to the ordinary deps.
typeOfDepToAdd = DependencyType.DEPS;
} else {
typeOfDepToAdd = type;
}
for (String requiredSymbol : ruleToSymbolsMap.get(rule)) {
BuildTarget provider = findProviderForSymbolFromBuckConfig(requiredSymbol);
if (provider != null) {
depsForBuildFiles.addDep(rule.getBuildTarget(), provider, typeOfDepToAdd);
continue;
}
Set<TargetNode<?, ?>> providers = dependencyInfo.symbolToProviders.get(requiredSymbol);
SortedSet<TargetNode<?, ?>> candidateProviders = providers.stream().filter(isVisibleDepNotAlreadyInProvidedDeps).collect(MoreCollectors.toImmutableSortedSet(Comparator.<TargetNode<?, ?>>naturalOrder()));
int numCandidates = candidateProviders.size();
if (numCandidates == 1) {
depsForBuildFiles.addDep(rule.getBuildTarget(), Iterables.getOnlyElement(candidateProviders).getBuildTarget(), typeOfDepToAdd);
} else if (numCandidates > 1) {
// Warn the user that there is an ambiguity. This could be very common with macros that
// generate multiple versions of a java_library() with the same sources.
// If numProviders is 0, then hopefully the dep is provided by something the user
// hardcoded in the BUCK file.
console.printErrorText(String.format("WARNING: Multiple providers for %s: %s. " + "Consider adding entry to .buckconfig to eliminate ambiguity:\n" + "[autodeps]\n" + "java-package-mappings = %s => %s", requiredSymbol, Joiner.on(", ").join(candidateProviders), requiredSymbol, Iterables.getFirst(candidateProviders, null)));
} else {
// If there aren't any candidates, then see if there is a visible rule that can provide
// the symbol via its exported_deps. We make this a secondary check because we prefer to
// depend on the rule that defines the symbol directly rather than one of possibly many
// rules that provides it via its exported_deps.
ImmutableSortedSet<TargetNode<?, ?>> newCandidates = providers.stream().flatMap(candidate -> dependencyInfo.ruleToRulesThatExportIt.get(candidate).stream()).filter(ruleThatExportsCandidate -> ruleThatExportsCandidate.isVisibleTo(graph, rule)).collect(MoreCollectors.toImmutableSortedSet(Comparator.<TargetNode<?, ?>>naturalOrder()));
int numNewCandidates = newCandidates.size();
if (numNewCandidates == 1) {
depsForBuildFiles.addDep(rule.getBuildTarget(), Iterables.getOnlyElement(newCandidates).getBuildTarget(), typeOfDepToAdd);
} else if (numNewCandidates > 1) {
console.printErrorText(String.format("WARNING: No providers found for '%s' for build rule %s, " + "but there are multiple rules that export a rule to provide %s: %s", requiredSymbol, rule.getBuildTarget(), requiredSymbol, Joiner.on(", ").join(newCandidates)));
}
// In the case that numNewCandidates is 0, we assume that the user is taking
// responsibility for declaring a provider for the symbol by hardcoding it in the deps.
}
}
}
}
return depsForBuildFiles;
}
Aggregations