Exemple #1
0
  /**
   * If the rule was created by a macro, this method sets the appropriate values for the attributes
   * generator_{name, function, location} and returns all attributes.
   *
   * <p>Otherwise, it returns the given attributes without any changes.
   */
  private static AttributesAndLocation generatorAttributesForMacros(
      BuildLangTypedAttributeValuesMap args,
      @Nullable Environment env,
      Location location,
      Label label) {
    // Returns the original arguments if a) there is only the rule itself on the stack
    // trace (=> no macro) or b) the attributes have already been set by Python pre-processing.
    if (env == null) {
      return new AttributesAndLocation(args, location);
    }
    boolean hasName = args.containsAttributeNamed("generator_name");
    boolean hasFunc = args.containsAttributeNamed("generator_function");
    // TODO(bazel-team): resolve cases in our code where hasName && !hasFunc, or hasFunc && !hasName
    if (hasName || hasFunc) {
      return new AttributesAndLocation(args, location);
    }
    Pair<FuncallExpression, BaseFunction> topCall = env.getTopCall();
    if (topCall == null || !(topCall.second instanceof UserDefinedFunction)) {
      return new AttributesAndLocation(args, location);
    }

    FuncallExpression generator = topCall.first;
    BaseFunction function = topCall.second;
    String name = generator.getNameArg();

    ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
    for (String attributeName : args.getAttributeNames()) {
      builder.put(attributeName, args.getAttributeValue(attributeName));
    }
    builder.put("generator_name", (name == null) ? args.getAttributeValue("name") : name);
    builder.put("generator_function", function.getName());

    if (generator.getLocation() != null) {
      location = generator.getLocation();
    }
    String relativePath = maybeGetRelativeLocation(location, label);
    if (relativePath != null) {
      builder.put("generator_location", relativePath);
    }

    try {
      return new AttributesAndLocation(
          new BuildLangTypedAttributeValuesMap(builder.build()), location);
    } catch (IllegalArgumentException ex) {
      // We just fall back to the default case and swallow any messages.
      return new AttributesAndLocation(args, location);
    }
  }
Exemple #2
0
  /**
   * Creates and returns a rule instance.
   *
   * <p>It is the caller's responsibility to add the rule to the package (the caller may choose not
   * to do so if, for example, the rule has errors).
   */
  static Rule createRule(
      Package.Builder pkgBuilder,
      RuleClass ruleClass,
      BuildLangTypedAttributeValuesMap attributeValues,
      EventHandler eventHandler,
      @Nullable FuncallExpression ast,
      Location location,
      @Nullable Environment env)
      throws InvalidRuleException, InterruptedException {
    Preconditions.checkNotNull(ruleClass);
    String ruleClassName = ruleClass.getName();
    Object nameObject = attributeValues.getAttributeValue("name");
    if (nameObject == null) {
      throw new InvalidRuleException(ruleClassName + " rule has no 'name' attribute");
    } else if (!(nameObject instanceof String)) {
      throw new InvalidRuleException(ruleClassName + " 'name' attribute must be a string");
    }
    String name = (String) nameObject;
    Label label;
    try {
      // Test that this would form a valid label name -- in particular, this
      // catches cases where Makefile variables $(foo) appear in "name".
      label = pkgBuilder.createLabel(name);
    } catch (LabelSyntaxException e) {
      throw new InvalidRuleException("illegal rule name: " + name + ": " + e.getMessage());
    }
    boolean inWorkspaceFile = pkgBuilder.isWorkspace();
    if (ruleClass.getWorkspaceOnly() && !inWorkspaceFile) {
      throw new RuleFactory.InvalidRuleException(
          ruleClass + " must be in the WORKSPACE file " + "(used by " + label + ")");
    } else if (!ruleClass.getWorkspaceOnly() && inWorkspaceFile) {
      throw new RuleFactory.InvalidRuleException(
          ruleClass + " cannot be in the WORKSPACE file " + "(used by " + label + ")");
    }

    AttributesAndLocation generator =
        generatorAttributesForMacros(attributeValues, env, location, label);
    try {
      return ruleClass.createRule(
          pkgBuilder,
          label,
          generator.attributes,
          eventHandler,
          ast,
          generator.location,
          new AttributeContainer(ruleClass));
    } catch (LabelSyntaxException e) {
      throw new RuleFactory.InvalidRuleException(ruleClass + " " + e.getMessage());
    }
  }