private void collectTransitiveClosure( PackageProviderForConfigurations packageProvider, Set<Label> reachableLabels, Label from) throws NoSuchThingException { if (!reachableLabels.add(from)) { return; } Target fromTarget = packageProvider.getTarget(from); if (fromTarget instanceof Rule) { Rule rule = (Rule) fromTarget; if (rule.getRuleClassObject().hasAttr("srcs", BuildType.LABEL_LIST)) { // TODO(bazel-team): refine this. This visits "srcs" reachable under *any* configuration, // not necessarily the configuration actually applied to the rule. We should correlate the // two. However, doing so requires faithfully reflecting the configuration transitions that // might happen as we traverse the dependency chain. // TODO(bazel-team): Why don't we use AbstractAttributeMapper#visitLabels() here? for (List<Label> labelsForConfiguration : AggregatingAttributeMapper.of(rule).visitAttribute("srcs", BuildType.LABEL_LIST)) { for (Label label : labelsForConfiguration) { collectTransitiveClosure( packageProvider, reachableLabels, from.resolveRepositoryRelative(label)); } } } if (rule.getRuleClass().equals("bind")) { Label actual = AggregatingAttributeMapper.of(rule).get("actual", BuildType.LABEL); if (actual != null) { collectTransitiveClosure(packageProvider, reachableLabels, actual); } } } }
/** Adds the given rule to the stack trace of the exception (if there is one). */ private static void addRuleToStackTrace(EvalException ex, Rule rule, BaseFunction ruleImpl) { if (ex instanceof EvalExceptionWithStackTrace) { ((EvalExceptionWithStackTrace) ex) .registerPhantomFuncall( String.format("%s(name = '%s')", rule.getRuleClass(), rule.getName()), rule.getLocation(), ruleImpl); } }
/** * Uses a remote repository name to fetch the corresponding Rule describing how to get it. This * should be called from {@link SkyFunction#compute} functions, which should return null if this * returns null. If {@code ruleClassName} is set, the rule found must have a matching rule class * name. */ @Nullable public static Rule getRule( RepositoryName repositoryName, @Nullable String ruleClassName, Environment env) throws RepositoryFunctionException { ExternalPackage externalPackage = getExternalPackage(env); if (externalPackage == null) { return null; } Rule rule = externalPackage.getRepositoryInfo(repositoryName); if (rule == null) { throw new RepositoryFunctionException( new BuildFileContainsErrorsException( ExternalPackage.PACKAGE_IDENTIFIER, "The repository named '" + repositoryName + "' could not be resolved"), Transience.PERSISTENT); } Preconditions.checkState( ruleClassName == null || rule.getRuleClass().equals(ruleClassName), "Got %s, was expecting a %s", rule, ruleClassName); return rule; }