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);
   }
 }
Esempio n. 3
0
 /**
  * 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;
 }