Add example test for requiring native aspect from a starlark defined aspect.

Starlark native aspects need to override the newly added `getDefaultParametersExtractor` from StarlarkAspect to be able to extract their parameters values from the base rule of the attribute in which they are required.

PiperOrigin-RevId: 381826763
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 9758e22..a3bd3fb 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -1191,7 +1191,7 @@
     }
 
     public Builder<TYPE> aspect(
-        NativeAspectClass nativeAspect,
+        StarlarkNativeAspect nativeAspect,
         String baseAspectName,
         ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> inheritedRequiredProviders,
         ImmutableList<String> inheritedAttributeAspects)
@@ -1206,7 +1206,7 @@
         NativeRuleAspect nativeRuleAspect =
             new NativeRuleAspect(
                 nativeAspect,
-                EMPTY_FUNCTION,
+                nativeAspect.getDefaultParametersExtractor(),
                 baseAspectName,
                 inheritedRequiredProviders,
                 inheritedAttributeAspects);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspect.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspect.java
index f3efc0a..d8f6fd1 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspect.java
@@ -14,6 +14,7 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.starlarkbuildapi.StarlarkAspectApi;
@@ -56,4 +57,7 @@
 
   /** Returns the name of this aspect. */
   String getName();
+
+  /** Returns a function to extract the aspect parameters values from its base rule. */
+  Function<Rule, AspectParameters> getDefaultParametersExtractor();
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkDefinedAspect.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkDefinedAspect.java
index 3b4397b..4562a99 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkDefinedAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkDefinedAspect.java
@@ -217,6 +217,7 @@
     return aspectClass != null;
   }
 
+  @Override
   public Function<Rule, AspectParameters> getDefaultParametersExtractor() {
     return rule -> {
       AttributeMap ruleAttrs = RawAttributeMapper.of(rule);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeAspect.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeAspect.java
index 14cf33e..f1b2f1b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeAspect.java
@@ -14,13 +14,18 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import net.starlark.java.eval.EvalException;
 import net.starlark.java.eval.Printer;
 
 /** A natively-defined aspect that is may be referenced by Starlark attribute definitions. */
 public abstract class StarlarkNativeAspect extends NativeAspectClass implements StarlarkAspect {
+  @AutoCodec @AutoCodec.VisibleForSerialization
+  static final Function<Rule, AspectParameters> EMPTY_FUNCTION = input -> AspectParameters.EMPTY;
+
   @Override
   public void repr(Printer printer) {
     printer.append("<native aspect>");
@@ -45,4 +50,9 @@
   public ImmutableSet<String> getParamAttributes() {
     return ImmutableSet.of();
   }
+
+  @Override
+  public Function<Rule, AspectParameters> getDefaultParametersExtractor() {
+    return EMPTY_FUNCTION;
+  }
 }
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 4add5da..b6c77cf 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
@@ -201,7 +201,12 @@
     if (key.getAspectClass() instanceof NativeAspectClass) {
       NativeAspectClass nativeAspectClass = (NativeAspectClass) key.getAspectClass();
       aspectFactory = (ConfiguredAspectFactory) nativeAspectClass;
-      aspect = Aspect.forNative(nativeAspectClass, key.getParameters());
+      aspect =
+          Aspect.forNative(
+              nativeAspectClass,
+              key.getParameters(),
+              key.getInheritedRequiredProviders(),
+              key.getInheritedAttributeAspects());
     } else if (key.getAspectClass() instanceof StarlarkAspectClass) {
       StarlarkAspectClass starlarkAspectClass = (StarlarkAspectClass) key.getAspectClass();
       StarlarkDefinedAspect starlarkAspect;
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 7c357e3..56d26fc 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
@@ -46,18 +46,23 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet;
 import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
 import com.google.devtools.build.lib.packages.Attribute.LabelListLateBoundDefault;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.BuildType;
 import com.google.devtools.build.lib.packages.NativeAspectClass;
+import com.google.devtools.build.lib.packages.RawAttributeMapper;
 import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.StarlarkNativeAspect;
 import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.rules.java.JavaConfiguration;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
 import com.google.devtools.build.lib.util.FileTypeSet;
+import java.io.Serializable;
 import java.util.List;
+import javax.annotation.Nullable;
 
 /**
  * Various rule and aspect classes that aid in testing the aspect machinery.
@@ -251,14 +256,38 @@
   public static final SimpleAspect SIMPLE_ASPECT = new SimpleAspect();
   public static final FooProviderAspect FOO_PROVIDER_ASPECT = new FooProviderAspect();
   public static final BarProviderAspect BAR_PROVIDER_ASPECT = new BarProviderAspect();
+  public static final SimpleStarlarkNativeAspect SIMPLE_STARLARK_NATIVE_ASPECT =
+      new SimpleStarlarkNativeAspect();
+  public static final ParametrizedAspectWithProvider
+      PARAMETRIZED_STARLARK_NATIVE_ASPECT_WITH_PROVIDER = new ParametrizedAspectWithProvider();
 
   private static final AspectDefinition SIMPLE_ASPECT_DEFINITION =
       new AspectDefinition.Builder(SIMPLE_ASPECT).build();
-
   private static final AspectDefinition FOO_PROVIDER_ASPECT_DEFINITION =
       new AspectDefinition.Builder(FOO_PROVIDER_ASPECT).build();
   private static final AspectDefinition BAR_PROVIDER_ASPECT_DEFINITION =
       new AspectDefinition.Builder(BAR_PROVIDER_ASPECT).build();
+  private static final AspectDefinition SIMPLE_STARLARK_NATIVE_ASPECT_DEFINITION =
+      new AspectDefinition.Builder(SIMPLE_STARLARK_NATIVE_ASPECT).build();
+
+  /** Simple StarlarkNativeAspect */
+  public static class SimpleStarlarkNativeAspect extends StarlarkNativeAspect
+      implements ConfiguredAspectFactory {
+    @Override
+    public AspectDefinition getDefinition(AspectParameters aspectParameters) {
+      return SIMPLE_STARLARK_NATIVE_ASPECT_DEFINITION;
+    }
+
+    @Override
+    public ConfiguredAspect create(
+        ConfiguredTargetAndData ctadBase,
+        RuleContext ruleContext,
+        AspectParameters parameters,
+        String toolsRepository)
+        throws ActionConflictException, InterruptedException {
+      return new ConfiguredAspect.Builder(ruleContext).addProvider(new FooProvider()).build();
+    }
+  }
 
   /**
    * A very simple aspect.
@@ -458,6 +487,49 @@
   }
 
   /**
+   * An aspect that has a definition depending on parameters provided by originating rule and
+   * advertises a simple provider.
+   */
+  public static class ParametrizedAspectWithProvider extends StarlarkNativeAspect
+      implements ConfiguredAspectFactory {
+
+    @Override
+    public AspectDefinition getDefinition(AspectParameters aspectParameters) {
+      AspectDefinition.Builder builder =
+          new AspectDefinition.Builder(PARAMETRIZED_STARLARK_NATIVE_ASPECT_WITH_PROVIDER);
+      ImmutableCollection<String> aspectAttr = aspectParameters.getAttribute("aspect_attr");
+      if (aspectAttr != null) {
+        builder.add(
+            attr("aspect_attr", Type.STRING)
+                .allowedValues(new AllowedValueSet("v1", "v2"))
+                .value(aspectAttr.iterator().next()));
+      }
+      return builder.build();
+    }
+
+    @Override
+    public ConfiguredAspect create(
+        ConfiguredTargetAndData ctadBase,
+        RuleContext ruleContext,
+        AspectParameters parameters,
+        String toolsRepository)
+        throws ActionConflictException, InterruptedException {
+      return new ConfiguredAspect.Builder(ruleContext).addProvider(new FooProvider()).build();
+    }
+
+    @Override
+    public Function<Rule, AspectParameters> getDefaultParametersExtractor() {
+      return (Function<Rule, AspectParameters> & Serializable)
+          (@Nullable Rule rule) -> {
+            AttributeMap attributes = RawAttributeMapper.of(rule);
+            return new AspectParameters.Builder()
+                .addAttribute("aspect_attr", attributes.get("aspect_attr", Type.STRING))
+                .build();
+          };
+    }
+  }
+
+  /**
    * An aspect that has a definition depending on parameters provided by originating rule.
    */
   public static class ParametrizedDefinitionAspect extends NativeAspectClass
diff --git a/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java b/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
index e83c387..e6e8483 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/AttributeTest.java
@@ -344,13 +344,13 @@
     Attribute attr =
         attr("x", LABEL)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_1",
                 /** inheritedRequiredProviders= */
                 ImmutableList.of(),
                 inheritedAttributeAspects1)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_2",
                 /** inheritedRequiredProviders= */
                 ImmutableList.of(),
@@ -375,13 +375,13 @@
     Attribute attr =
         attr("x", LABEL)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_1",
                 inheritedRequiredProviders1,
                 /** inheritedAttributeAspects= */
                 ImmutableList.of())
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_2",
                 inheritedRequiredProviders2,
                 /** inheritedAttributeAspects= */
@@ -417,9 +417,9 @@
 
     Attribute attr =
         attr("x", LABEL)
-            .aspect(TestAspects.SIMPLE_ASPECT)
+            .aspect(TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect",
                 /** inheritedRequiredProviders = */
                 ImmutableList.of(),
@@ -441,9 +441,9 @@
 
     Attribute attr =
         attr("x", LABEL)
-            .aspect(TestAspects.SIMPLE_ASPECT)
+            .aspect(TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect",
                 inheritedRequiredProviders,
                 /** inheritedAttributeAspects= */
@@ -480,15 +480,15 @@
 
     Attribute attr =
         attr("x", LABEL)
-            .aspect(TestAspects.SIMPLE_ASPECT)
+            .aspect(TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_1",
                 /** inheritedRequiredProviders = */
                 ImmutableList.of(),
                 inheritedAttributeAspects1)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_2",
                 /** inheritedRequiredProviders = */
                 ImmutableList.of(),
@@ -511,15 +511,15 @@
 
     Attribute attr =
         attr("x", LABEL)
-            .aspect(TestAspects.SIMPLE_ASPECT)
+            .aspect(TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT)
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_1",
                 inheritedRequiredProviders1,
                 /** inheritedAttributeAspects= */
                 ImmutableList.of())
             .aspect(
-                TestAspects.SIMPLE_ASPECT,
+                TestAspects.SIMPLE_STARLARK_NATIVE_ASPECT,
                 "base_aspect_2",
                 inheritedRequiredProviders2,
                 /** inheritedAttributeAspects= */
diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java
index bcb0381..fa20580 100644
--- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java
@@ -22,12 +22,14 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
 import com.google.devtools.build.lib.analysis.starlark.StarlarkAttrModule;
 import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleClassFunctions.StarlarkRuleFunction;
 import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.analysis.util.TestAspects;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.collect.nestedset.Depset;
 import com.google.devtools.build.lib.events.Event;
@@ -57,6 +59,7 @@
 import com.google.devtools.build.lib.skyframe.BzlLoadFunction;
 import com.google.devtools.build.lib.starlark.util.BazelEvaluationTestCase;
 import com.google.devtools.build.lib.testutil.MoreAsserts;
+import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
 import com.google.devtools.build.lib.util.FileTypeSet;
 import java.util.Arrays;
 import java.util.List;
@@ -95,6 +98,16 @@
     ev.setSemantics(options); // for StarlarkThread
   }
 
+  @Override
+  protected ConfiguredRuleClassProvider createRuleClassProvider() {
+    ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder();
+    TestRuleClassProvider.addStandardRules(builder);
+    builder.addStarlarkAccessibleTopLevels(
+        "parametrized_native_aspect",
+        TestAspects.PARAMETRIZED_STARLARK_NATIVE_ASPECT_WITH_PROVIDER);
+    return builder.build();
+  }
+
   @org.junit.Rule public ExpectedException thrown = ExpectedException.none();
 
   @Before
@@ -3025,4 +3038,109 @@
     ev.assertContainsError(
         "Error in unexported rule: Invalid rule class hasn't been exported by a bzl file");
   }
+
+  @Test
+  public void testAttrWithAspectRequiringAspects_requiredNativeAspect_getsParamsFromFromBaseRules()
+      throws Exception {
+    setBuildLanguageOptions("--experimental_required_aspects=true");
+    scratch.file(
+        "lib.bzl",
+        "rule_prov = provider()",
+        "def _impl(target, ctx):",
+        "   pass",
+        "aspect_a = aspect(implementation = _impl,",
+        "                  requires = [parametrized_native_aspect],",
+        "                  attr_aspects = ['deps'],",
+        "                  required_providers = [rule_prov])",
+        "def impl(ctx):",
+        "   return None",
+        "my_rule = rule(impl,",
+        "               attrs={'deps': attr.label_list(aspects = [aspect_a]),",
+        "                      'aspect_attr': attr.string()})");
+    scratch.file(
+        "BUILD", "load(':lib.bzl', 'my_rule')", "my_rule(name = 'main', aspect_attr = 'v1')");
+
+    RuleContext ruleContext = createRuleContext("//:main").getRuleContext();
+
+    Rule rule = ruleContext.getRule();
+    Attribute attr = rule.getRuleClassObject().getAttributeByName("deps");
+    ImmutableList<Aspect> aspects = attr.getAspects(rule);
+    Aspect requiredNativeAspect = aspects.get(0);
+    assertThat(requiredNativeAspect.getAspectClass().getName())
+        .isEqualTo("ParametrizedAspectWithProvider");
+    assertThat(
+            requiredNativeAspect
+                .getDefinition()
+                .getAttributes()
+                .get("aspect_attr")
+                .getDefaultValueUnchecked())
+        .isEqualTo("v1");
+  }
+
+  @Test
+  public void testAttrWithAspectRequiringAspects_requiredNativeAspect_inheritsAttrAspects()
+      throws Exception {
+    setBuildLanguageOptions("--experimental_required_aspects=true");
+    scratch.file(
+        "lib.bzl",
+        "rule_prov = provider()",
+        "def _impl(target, ctx):",
+        "   pass",
+        "aspect_a = aspect(implementation = _impl,",
+        "                  requires = [parametrized_native_aspect],",
+        "                  attr_aspects = ['deps'],",
+        "                  required_providers = [rule_prov])",
+        "def impl(ctx):",
+        "   return None",
+        "my_rule = rule(impl,",
+        "               attrs={'deps': attr.label_list(aspects = [aspect_a]),",
+        "                      'aspect_attr': attr.string()})");
+    scratch.file(
+        "BUILD", "load(':lib.bzl', 'my_rule')", "my_rule(name = 'main', aspect_attr = 'v1')");
+
+    RuleContext ruleContext = createRuleContext("//:main").getRuleContext();
+
+    Rule rule = ruleContext.getRule();
+    Attribute attr = rule.getRuleClassObject().getAttributeByName("deps");
+    ImmutableList<Aspect> aspects = attr.getAspects(rule);
+    Aspect requiredNativeAspect = aspects.get(0);
+    assertThat(requiredNativeAspect.getAspectClass().getName())
+        .isEqualTo("ParametrizedAspectWithProvider");
+    assertThat(requiredNativeAspect.getDescriptor().getInheritedAttributeAspects())
+        .containsExactly("deps");
+  }
+
+  @Test
+  public void testAttrWithAspectRequiringAspects_requiredNativeAspect_inheritsRequiredProviders()
+      throws Exception {
+    setBuildLanguageOptions("--experimental_required_aspects=true");
+    scratch.file(
+        "lib.bzl",
+        "rule_prov = provider()",
+        "def _impl(target, ctx):",
+        "   pass",
+        "aspect_a = aspect(implementation = _impl,",
+        "                  requires = [parametrized_native_aspect],",
+        "                  attr_aspects = ['deps'],",
+        "                  required_providers = [rule_prov])",
+        "def impl(ctx):",
+        "   return None",
+        "my_rule = rule(impl,",
+        "               attrs={'deps': attr.label_list(aspects = [aspect_a]),",
+        "                      'aspect_attr': attr.string()})");
+    scratch.file(
+        "BUILD", "load(':lib.bzl', 'my_rule')", "my_rule(name = 'main', aspect_attr = 'v1')");
+
+    RuleContext ruleContext = createRuleContext("//:main").getRuleContext();
+
+    Rule rule = ruleContext.getRule();
+    Attribute attr = rule.getRuleClassObject().getAttributeByName("deps");
+    ImmutableList<Aspect> aspects = attr.getAspects(rule);
+    Aspect requiredNativeAspect = aspects.get(0);
+    assertThat(requiredNativeAspect.getAspectClass().getName())
+        .isEqualTo("ParametrizedAspectWithProvider");
+    assertThat(
+            requiredNativeAspect.getDescriptor().getInheritedRequiredProviders().getDescription())
+        .isEqualTo("'rule_prov'");
+  }
 }