Enable aspect invocations to be matched by output filters.

Currently aspects have no tag, i.e., they don't get checked against output
filters at all. This changes aspects to have a tag of the same form as the
rule they are attached to (i.e., the label of the target).

Since the default output filters match on ^//package[:/], this should cover
most uses of the output filter, while still allowing for finer control for
those who crave it.

--
MOS_MIGRATED_REVID=133425215
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index 3f018d3..2037dbb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -97,7 +97,7 @@
     public void validate(
         RuleContext.Builder contextBuilder, ConfiguredTarget prerequisite, Attribute attribute) {
       validateDirectPrerequisiteForDeprecation(
-          contextBuilder, contextBuilder.getRule(), prerequisite);
+          contextBuilder, contextBuilder.getRule(), prerequisite, contextBuilder.forAspect());
     }
 
     /**
@@ -128,18 +128,22 @@
     /** Returns whether a deprecation warning should be printed for the prerequisite described. */
     private static boolean shouldEmitDeprecationWarningFor(
         String thisDeprecation, PackageIdentifier thisPackage,
-        String prerequisiteDeprecation, PackageIdentifier prerequisitePackage) {
+        String prerequisiteDeprecation, PackageIdentifier prerequisitePackage,
+        boolean forAspect) {
       // Don't report deprecation edges from javatests to java or within a package;
       // otherwise tests of deprecated code generate nuisance warnings.
-      // Don't report deprecation if the current target is also deprecated.
-      return (prerequisiteDeprecation != null
+      // Don't report deprecation if the current target is also deprecated,
+      // or if the current context is evaluating an aspect,
+      // as the base target would have already printed the deprecation warnings.
+      return (!forAspect
+          && prerequisiteDeprecation != null
           && !isSameLogicalPackage(thisPackage, prerequisitePackage)
           && thisDeprecation == null);
     }
 
     /** Checks if the given prerequisite is deprecated and prints a warning if so. */
     public static void validateDirectPrerequisiteForDeprecation(
-        RuleErrorConsumer errors, Rule rule, ConfiguredTarget prerequisite) {
+        RuleErrorConsumer errors, Rule rule, ConfiguredTarget prerequisite, boolean forAspect) {
       Target prerequisiteTarget = prerequisite.getTarget();
       Label prerequisiteLabel = prerequisiteTarget.getLabel();
       PackageIdentifier thatPackage = prerequisiteLabel.getPackageIdentifier();
@@ -152,7 +156,7 @@
         String thatDeprecation =
             NonconfigurableAttributeMapper.of(prerequisiteRule).get("deprecation", Type.STRING);
         if (shouldEmitDeprecationWarningFor(
-            thisDeprecation, thisPackage, thatDeprecation, thatPackage)) {
+            thisDeprecation, thisPackage, thatDeprecation, thatPackage, forAspect)) {
           errors.ruleWarning("target '" + rule.getLabel() +  "' depends on deprecated target '"
               + prerequisiteLabel + "': " + thatDeprecation);
         }
@@ -165,7 +169,7 @@
         String thatDeprecation =
             NonconfigurableAttributeMapper.of(generatingRule).get("deprecation", Type.STRING);
         if (shouldEmitDeprecationWarningFor(
-            thisDeprecation, thisPackage, thatDeprecation, thatPackage)) {
+            thisDeprecation, thisPackage, thatDeprecation, thatPackage, forAspect)) {
           errors.ruleWarning("target '" + rule.getLabel() + "' depends on the output file "
               + prerequisiteLabel + " of a deprecated rule " + generatingRule.getLabel()
               + "': " + thatDeprecation);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index b988b4d..f160424 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -1711,6 +1711,11 @@
       }
     }
 
+    /** Returns whether the context being constructed is for the evaluation of an aspect. */
+    public boolean forAspect() {
+      return aspectName != null;
+    }
+
     public Rule getRule() {
       return rule;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index 90b064a..755c246 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -183,7 +183,7 @@
         ConfiguredTarget prerequisite, Attribute attribute) {
       validateDirectPrerequisiteVisibility(context, prerequisite, attribute.getName());
       DeprecationValidator.validateDirectPrerequisiteForDeprecation(
-          context, context.getRule(), prerequisite);
+          context, context.getRule(), prerequisite, context.forAspect());
     }
 
     private void validateDirectPrerequisiteVisibility(
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index 4035242..ba84c5b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -376,10 +376,10 @@
         transitivePackages.build());
   }
 
-  @Nullable
   @Override
   public String extractTag(SkyKey skyKey) {
-    return null;
+    AspectKey aspectKey = (AspectKey) skyKey.argument();
+    return Label.print(aspectKey.getLabel());
   }
 
   /**
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index d29e332..9274b75 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -36,11 +36,13 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.vfs.ModifiedFileSet;
+import java.util.regex.Pattern;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -226,6 +228,47 @@
   }
 
   @Test
+  public void aspectDependenciesDontShowDeprecationWarnings() throws Exception {
+    setRulesAvailableInTests(
+        new TestAspects.BaseRule(), new TestAspects.ExtraAttributeAspectRule());
+
+    pkg("extra", "base(name='extra', deprecation='bad aspect')");
+
+    pkg("a",
+        "rule_with_extra_deps_aspect(name='a', foo=[':b'])",
+        "base(name='b')");
+
+    getConfiguredTarget("//a:a");
+    assertContainsEventWithFrequency("bad aspect", 0);
+  }
+
+  @Test
+  public void ruleDependencyDeprecationWarningsAbsentDuringAspectEvaluations() throws Exception {
+    setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.AspectRequiringRule());
+
+    pkg("a", "aspect(name='a', foo=['//b:b'])");
+    pkg("b", "aspect(name='b', bar=['//d:d'])");
+    pkg("d", "base(name='d', deprecation='bad rule')");
+
+    getConfiguredTarget("//a:a");
+    assertContainsEventWithFrequency("bad rule", 1);
+  }
+
+  @Test
+  public void aspectWarningsFilteredByOutputFiltersForAssociatedRules() throws Exception {
+    setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.WarningAspectRule());
+    pkg("a", "warning_aspect(name='a', foo=['//b:b', '//c:c'])");
+    pkg("b", "base(name='b')");
+    pkg("c", "base(name='c')");
+
+    reporter.setOutputFilter(RegexOutputFilter.forPattern(Pattern.compile("^//b:")));
+
+    getConfiguredTarget("//a:a");
+    assertContainsEventWithFrequency("Aspect warning on //b:b", 1);
+    assertContainsEventWithFrequency("Aspect warning on //c:c", 0);
+  }
+
+  @Test
   public void sameTargetInDifferentAttributes() throws Exception {
     setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.AspectRequiringRule(),
         new TestAspects.SimpleRule());
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
index 67b7f28..351ae38 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -293,6 +293,31 @@
           .build();
 
   /**
+   * An aspect that prints a warning.
+   */
+  public static class WarningAspect extends NativeAspectClass
+    implements ConfiguredAspectFactory {
+
+    @Override
+    public ConfiguredAspect create(
+        ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) {
+      ruleContext.ruleWarning("Aspect warning on " + base.getTarget().getLabel());
+      return new ConfiguredAspect.Builder("warning", ruleContext).build();
+    }
+
+    @Override
+    public AspectDefinition getDefinition(AspectParameters aspectParameters) {
+      return WARNING_ASPECT_DEFINITION;
+    }
+  }
+
+  public static final WarningAspect WARNING_ASPECT = new WarningAspect();
+  private static final AspectDefinition WARNING_ASPECT_DEFINITION =
+      new AspectDefinition.Builder("warning")
+      .attributeAspect("bar", WARNING_ASPECT)
+      .build();
+
+  /**
    * An aspect that raises an error.
    */
   public static class ErrorAspect extends NativeAspectClass
@@ -328,7 +353,7 @@
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("testonly", BOOLEAN).nonconfigurable("test").value(false))
-          .add(attr("deprecation", STRING).nonconfigurable("test"))
+          .add(attr("deprecation", STRING).nonconfigurable("test").value((String) null))
           .add(attr("tags", STRING_LIST))
           .add(attr("visibility", NODEP_LABEL_LIST).orderIndependent().cfg(HOST)
               .nonconfigurable("test"))
@@ -500,7 +525,30 @@
   }
 
   /**
-   * A rule that defines an {@link AspectRequiringProvider} on one of its attributes.
+   * A rule that defines a {@link WarningAspect} on one of its attributes.
+   */
+  public static class WarningAspectRule implements RuleDefinition {
+    @Override
+    public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+      return builder
+          .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+              .aspect(WARNING_ASPECT))
+          .add(attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+          .build();
+    }
+
+    @Override
+    public Metadata getMetadata() {
+      return RuleDefinition.Metadata.builder()
+          .name("warning_aspect")
+          .factoryClass(DummyRuleFactory.class)
+          .ancestors(BaseRule.class)
+          .build();
+    }
+  }
+
+  /**
+   * A rule that defines an {@link ErrorAspect} on one of its attributes.
    */
   public static class ErrorAspectRule implements RuleDefinition {
     @Override