in src/com/facebook/buck/command/Project.java [727:834]
private void walkRuleAndAdd(
final BuildRule rule,
final boolean isForTests,
final LinkedHashSet<DependentModule> dependencies,
@Nullable final BuildRule srcTarget) {
final String basePathForRule = rule.getBuildTarget().getBasePath();
new AbstractDependencyVisitor(rule, true /* excludeRoot */) {
private final LinkedHashSet<DependentModule> librariesToAdd = Sets.newLinkedHashSet();
private final LinkedHashSet<DependentModule> modulesToAdd = Sets.newLinkedHashSet();
@Override
public ImmutableSet<BuildRule> visit(BuildRule dep) {
ImmutableSet<BuildRule> depsToVisit;
if (rule.getProperties().is(PACKAGING) ||
dep instanceof AndroidResourceRule ||
dep == rule) {
depsToVisit = dep.getDeps();
} else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) {
depsToVisit = ((ExportDependencies)dep).getExportedDeps();
} else {
depsToVisit = ImmutableSet.of();
}
// Special Case: If we are traversing the test_target and we encounter a library rule in the
// same package that is not the src_target, then we should traverse the deps. Consider the
// following build file:
//
// android_library(
// name = 'lib',
// srcs = glob(['*.java'], excludes = ['*Test.java']),
// deps = [
// # LOTS OF DEPS
// ],
// )
//
// java_test(
// name = 'test',
// srcs = glob(['*Test.java']),
// deps = [
// ':lib',
// # MOAR DEPS
// ],
// )
//
// project_config(
// test_target = ':test',
// )
//
// Note that the only source folder for this IntelliJ module is the current directory. Thus,
// the current directory should be treated as a source folder with test sources, but it
// should contain the union of :lib and :test's deps as dependent modules.
if (isForTests
&& depsToVisit.isEmpty()
&& dep.getBuildTarget().getBasePath().equals(basePathForRule)
&& !dep.equals(srcTarget)) {
depsToVisit = dep.getDeps();
}
DependentModule dependentModule;
if (dep instanceof PrebuiltJarRule) {
libraryJars.add((PrebuiltJarRule) dep);
String libraryName = getIntellijNameForRule(dep);
dependentModule = DependentModule.newLibrary(dep.getBuildTarget(), libraryName);
} else if (dep instanceof NdkLibrary) {
String moduleName = getIntellijNameForRule(dep);
dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName);
} else if (dep.getFullyQualifiedName().startsWith(ANDROID_GEN_BUILD_TARGET_PREFIX)) {
return depsToVisit;
} else if (dep instanceof JavaLibraryRule || dep instanceof AndroidResourceRule) {
String moduleName = getIntellijNameForRule(dep);
dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName);
} else {
return depsToVisit;
}
if (isForTests) {
dependentModule.scope = "TEST";
} else {
// If the dependentModule has already been added in the "TEST" scope, then it should be
// removed and then re-added using the current (compile) scope.
String currentScope = dependentModule.scope;
dependentModule.scope = "TEST";
if (dependencies.contains(dependentModule)) {
dependencies.remove(dependentModule);
}
dependentModule.scope = currentScope;
}
// Slate the module for addition to the dependencies collection. Modules are added to
// dependencies collection once the traversal is complete in the onComplete() method.
if (dependentModule.isLibrary()) {
librariesToAdd.add(dependentModule);
} else {
modulesToAdd.add(dependentModule);
}
return depsToVisit;
}
@Override
protected void onComplete() {
dependencies.addAll(librariesToAdd);
dependencies.addAll(modulesToAdd);
}
}.start();
}