diff options
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.java | 74 |
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; + } + } } |