aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java74
1 files changed, 66 insertions, 8 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
index a9408ee754..485bfa8b6c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.packages;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
@@ -23,6 +24,7 @@ import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.Label.SyntaxException;
+import com.google.devtools.build.lib.syntax.StackTraceElement;
import java.util.Map;
import java.util.Set;
@@ -75,7 +77,8 @@ public class RuleFactory {
Map<String, Object> attributeValues,
EventHandler eventHandler,
FuncallExpression ast,
- Location location)
+ Location location,
+ ImmutableList<StackTraceElement> stackTrace)
throws InvalidRuleException, NameConflictException {
Preconditions.checkNotNull(ruleClass);
String ruleClassName = ruleClass.getName();
@@ -105,8 +108,9 @@ public class RuleFactory {
}
try {
- Rule rule = ruleClass.createRuleWithLabel(pkgBuilder, label, attributeValues,
- eventHandler, ast, location);
+ Rule rule = ruleClass.createRuleWithLabel(pkgBuilder, label,
+ addGeneratorAttributesForMacros(attributeValues, stackTrace), eventHandler, ast,
+ location);
return rule;
} catch (SyntaxException e) {
throw new RuleFactory.InvalidRuleException(ruleClass + " " + e.getMessage());
@@ -114,7 +118,22 @@ public class RuleFactory {
}
/**
- * Creates and returns a rule instance.
+ * Creates and returns a rule instance (without a stack trace).
+ */
+ static Rule createRule(
+ Package.Builder pkgBuilder,
+ RuleClass ruleClass,
+ Map<String, Object> attributeValues,
+ EventHandler eventHandler,
+ FuncallExpression ast,
+ Location location)
+ throws InvalidRuleException, NameConflictException {
+ return createRule(pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location,
+ ImmutableList.<StackTraceElement>of());
+ }
+
+ /**
+ * Creates a rule instance, adds it to the package and returns it.
*
* @param pkgBuilder the under-construction package to which the rule belongs
* @param ruleClass the class of the rule; this must not be null
@@ -126,6 +145,8 @@ public class RuleFactory {
* rule creation
* @param ast the abstract syntax tree of the rule expression (optional)
* @param location the location at which this rule was declared
+ * @param stackTrace the stack trace containing all functions that led to the creation of
+ * this rule (optional)
* @throws InvalidRuleException if the rule could not be constructed for any
* reason (e.g. no <code>name</code> attribute is defined)
* @throws NameConflictException
@@ -135,8 +156,11 @@ public class RuleFactory {
Map<String, Object> attributeValues,
EventHandler eventHandler,
FuncallExpression ast,
- Location location) throws InvalidRuleException, NameConflictException {
- Rule rule = createRule(pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location);
+ Location location,
+ ImmutableList<StackTraceElement> stackTrace)
+ throws InvalidRuleException, NameConflictException {
+ Rule rule = createRule(
+ pkgBuilder, ruleClass, attributeValues, eventHandler, ast, location, stackTrace);
pkgBuilder.addRule(rule);
return rule;
}
@@ -144,9 +168,11 @@ public class RuleFactory {
public static Rule createAndAddRule(PackageContext context,
RuleClass ruleClass,
Map<String, Object> attributeValues,
- FuncallExpression ast) throws InvalidRuleException, NameConflictException {
+ FuncallExpression ast,
+ ImmutableList<StackTraceElement> stackTrace)
+ throws InvalidRuleException, NameConflictException {
return createAndAddRule(context.pkgBuilder, ruleClass, attributeValues, context.eventHandler,
- ast, ast.getLocation());
+ ast, ast.getLocation(), stackTrace);
}
/**
@@ -158,4 +184,36 @@ public class RuleFactory {
super(message);
}
}
+
+ /**
+ * 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 Map<String, Object> addGeneratorAttributesForMacros(
+ Map<String, Object> args, ImmutableList<StackTraceElement> stackTrace) {
+ if (stackTrace.size() <= 2 || args.containsKey("generator_name")
+ || args.containsKey("generator_function")) {
+ // 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.
+ // The stack trace will always have at least two entries: one for the call to the rule and one
+ // for its implementation. Consequently, we check for size <= 2.
+ return args;
+ }
+
+ StackTraceElement generator = stackTrace.get(0);
+ ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
+ builder.putAll(args);
+ builder.put("generator_name", args.get("name"));
+ builder.put("generator_function", generator.getName());
+ builder.put("generator_location", Location.printPathAndLine(generator.getLocation()));
+
+ try {
+ return builder.build();
+ } catch (IllegalArgumentException ex) {
+ // Just to play it safe.
+ return args;
+ }
+ }
}