| // Copyright 2025 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.devtools.build.lib.starlark; |
| |
| import static com.google.common.collect.ImmutableList.toImmutableList; |
| import static com.google.common.truth.Truth.assertThat; |
| import static org.junit.Assert.assertThrows; |
| |
| import com.google.common.base.Splitter; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.devtools.build.lib.analysis.ConfiguredAspect; |
| import com.google.devtools.build.lib.analysis.ViewCreationFailedException; |
| import com.google.devtools.build.lib.analysis.util.AnalysisTestCase; |
| import com.google.devtools.build.lib.packages.AspectClass; |
| import com.google.devtools.build.lib.packages.StarlarkAspectClass; |
| import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey; |
| import java.util.Map; |
| import javax.annotation.Nullable; |
| import net.starlark.java.eval.Sequence; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests for Starlark aspects {@code propagation_predicate} function. */ |
| @RunWith(JUnit4.class) |
| public final class StarlarkAspectsPropagationPredicateTest extends AnalysisTestCase { |
| |
| private void createTestDefs(String propagationPredicate) throws Exception { |
| scratch.file( |
| "test/BUILD", |
| """ |
| load('//test:defs.bzl', 'rule_1') |
| rule_1(name = 'tool') |
| """); |
| scratch.file( |
| "test/defs.bzl", |
| String.format( |
| """ |
| AspectInfo = provider() |
| RuleInfo = provider() |
| |
| %s |
| |
| def _aspect_impl(target, ctx): |
| res = ['cmdline_aspect on ' + str(target.label)] |
| for dep in ctx.rule.attr.deps: |
| if AspectInfo in dep: |
| res.extend(dep[AspectInfo].res) |
| return [AspectInfo(res = res)] |
| |
| cmdline_aspect = aspect( |
| implementation = _aspect_impl, |
| propagation_predicate = _propagation_predicate, |
| attrs = { |
| 'allowed_pkg': attr.string(default = '*'), |
| 'ignored_tag': attr.string(default = ''), |
| 'allowed_rule_file': attr.string(default = '*'), |
| 'allowed_rule_name': attr.string(default = '*'), |
| '_tool': attr.label(default = Label('//test:tool'))}, |
| attr_aspects = ['deps'], |
| ) |
| |
| aspect_with_required_provider = aspect( |
| implementation = _aspect_impl, |
| required_providers = [RuleInfo], |
| propagation_predicate = _propagation_predicate, |
| attr_aspects = ['deps'], |
| ) |
| |
| def _rule_impl(ctx): |
| pass |
| |
| rule_1 = rule( |
| implementation = _rule_impl, |
| attrs = {'deps': attr.label_list()}, |
| ) |
| |
| rule_2 = rule( |
| implementation = _rule_impl, |
| attrs = {'deps': attr.label_list()}, |
| ) |
| |
| def _out_rule_impl(ctx): |
| if ctx.outputs.out: |
| ctx.actions.write(ctx.outputs.out, 'hi') |
| return [] |
| |
| out_rule = rule( |
| implementation = _out_rule_impl, |
| attrs = {'deps': attr.label_list(), 'out': attr.output()}, |
| ) |
| |
| def _rule_with_provider_impl(ctx): |
| return [RuleInfo()] |
| |
| rule_with_provider = rule( |
| implementation = _rule_with_provider_impl, |
| attrs = {'deps': attr.label_list()}, |
| provides = [RuleInfo], |
| ) |
| |
| aspect_on_rule = aspect( |
| implementation = _aspect_impl, |
| propagation_predicate = _propagation_predicate, |
| attr_aspects = ['deps'], |
| ) |
| |
| rule_with_aspect_on_deps = rule( |
| implementation = _rule_impl, |
| attrs = {'deps': attr.label_list(aspects = [aspect_on_rule])}, |
| ) |
| """, |
| propagationPredicate)); |
| } |
| |
| private void createTestPackages() throws Exception { |
| scratch.file( |
| "pkg1/BUILD", |
| """ |
| load('//test:defs.bzl', 'rule_1', 'rule_2', 'out_rule', 'rule_with_aspect_on_deps') |
| rule_1(name = 't1', deps = [':t2', '//pkg2:t2'], tags = ['no-aspect']) |
| rule_2(name = 't2', tags = ['another-tag']) |
| out_rule(name = 'target_with_output', out = 'my_out.txt', deps = [':t2']) |
| rule_with_aspect_on_deps(name = 'target_with_aspect_on_deps', deps = [':t2', '//pkg2:t2']) |
| alias(name = 'alias_1', actual = ':alias_2') |
| alias(name = 'alias_2', actual = ':actual') |
| rule_1(name = 'actual') |
| """); |
| scratch.file( |
| "pkg2/BUILD", |
| """ |
| load('//test:defs.bzl', 'rule_1', 'rule_2', 'rule_with_provider') |
| rule_2(name = 't1', deps = [':t2', '//pkg1:t2']) |
| rule_1(name = 't2', tags = ['no-aspect', 'another-tag']) |
| rule_with_provider(name = 'target_with_provider', deps = [':t2']) |
| """); |
| } |
| |
| @Test |
| public void propagationPredicateOnTargetPackage_aspectPropagatedToSatisfyingTargets() |
| throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| if ctx.attr.allowed_pkg != '*' and ctx.rule.label.package != ctx.attr.allowed_pkg: |
| return False |
| return True |
| """); |
| createTestPackages(); |
| |
| var analysisResult = |
| update( |
| ImmutableList.of("//test:defs.bzl%cmdline_aspect"), |
| ImmutableMap.of("allowed_pkg", "pkg1"), |
| "//pkg1:t1", |
| "//pkg2:t1"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%cmdline_aspect"); |
| // Only the keys to the targets that satisfy the aspect's propagation predicate are present. |
| assertThat(aspectKeys) |
| .containsExactly("cmdline_aspect on //pkg1:t1", "cmdline_aspect on //pkg1:t2"); |
| |
| var aspectResult = getAspectResult(analysisResult.getAspectsMap(), "cmdline_aspect"); |
| assertThat(aspectResult) |
| .containsExactly("cmdline_aspect on @@//pkg1:t1", "cmdline_aspect on @@//pkg1:t2"); |
| } |
| |
| @Test |
| public void propagationPredicateOnTargetTags_aspectPropagatedToSatisfyingTargets() |
| throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| if ctx.attr.ignored_tag != '' and ctx.attr.ignored_tag in ctx.rule.attr.tags.value: |
| return False |
| return True |
| """); |
| createTestPackages(); |
| |
| var analysisResult = |
| update( |
| ImmutableList.of("//test:defs.bzl%cmdline_aspect"), |
| ImmutableMap.of("ignored_tag", "no-aspect"), |
| "//pkg1:t1", |
| "//pkg2:t1"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%cmdline_aspect"); |
| // Only the keys to the targets that satisfy the aspect's propagation predicate are present. |
| assertThat(aspectKeys) |
| .containsExactly("cmdline_aspect on //pkg2:t1", "cmdline_aspect on //pkg1:t2"); |
| |
| var aspectResult = getAspectResult(analysisResult.getAspectsMap(), "cmdline_aspect"); |
| assertThat(aspectResult) |
| .containsExactly("cmdline_aspect on @@//pkg2:t1", "cmdline_aspect on @@//pkg1:t2"); |
| } |
| |
| @Test |
| public void propagationPredicateOnRuleKind_aspectPropagatedToSatisfyingTargets() |
| throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| qualified_kind = ctx.rule.qualified_kind |
| allowed_rule_file = ctx.attr.allowed_rule_file |
| allowed_rule_name = ctx.attr.allowed_rule_name |
| |
| if allowed_rule_file != '*' and qualified_kind.file_label != Label(allowed_rule_file): |
| return False |
| |
| if allowed_rule_name != '*' and qualified_kind.rule_name != allowed_rule_name: |
| return False |
| |
| return True |
| """); |
| createTestPackages(); |
| |
| var analysisResult = |
| update( |
| ImmutableList.of("//test:defs.bzl%cmdline_aspect"), |
| ImmutableMap.of( |
| "allowed_rule_file", "@@//test:defs.bzl", "allowed_rule_name", "rule_1"), |
| "//pkg1:t1", |
| "//pkg2:t1"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%cmdline_aspect"); |
| // Only the keys to the targets that satisfy the aspect's propagation predicate are present. |
| assertThat(aspectKeys) |
| .containsExactly("cmdline_aspect on //pkg1:t1", "cmdline_aspect on //pkg2:t2"); |
| |
| var aspectResult = getAspectResult(analysisResult.getAspectsMap(), "cmdline_aspect"); |
| assertThat(aspectResult) |
| .containsExactly("cmdline_aspect on @@//pkg1:t1", "cmdline_aspect on @@//pkg2:t2"); |
| } |
| |
| @Test |
| public void accessPrivateAspectAttribute_fails() throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| tool = ctx.attr._tool |
| return True |
| """); |
| createTestPackages(); |
| |
| reporter.removeHandler(failFastHandler); |
| assertThrows( |
| ViewCreationFailedException.class, |
| () -> update(ImmutableList.of("//test:defs.bzl%cmdline_aspect"), "//pkg1:t1")); |
| assertContainsEvent("'_tool' is not a public parameter of the aspect."); |
| } |
| |
| @Test |
| public void aspectOnOutputFile_propagationPredicateNotUsed() throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| return False |
| """); |
| createTestPackages(); |
| |
| var unused = update(ImmutableList.of("//test:defs.bzl%cmdline_aspect"), "//pkg1:my_out.txt"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%cmdline_aspect"); |
| // The propagation predicate is not used for output files, so the aspect key is created even if |
| // the propagation predicate is not satisfied. |
| assertThat(aspectKeys).containsExactly("cmdline_aspect on //pkg1:my_out.txt"); |
| } |
| |
| @Test |
| public void aspectPropagatedFromRule_propagationPredicateIsUsed() throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| if ctx.rule.label == Label('//pkg1:t2'): |
| return False |
| return True |
| """); |
| createTestPackages(); |
| |
| var unused = update("//pkg1:target_with_aspect_on_deps"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_on_rule"); |
| // The propagation predicate is used for the aspect_on_rule, so the aspect key is not created |
| // for //pkg1:t2. |
| assertThat(aspectKeys).containsExactly("aspect_on_rule on //pkg2:t2"); |
| } |
| |
| @Test |
| public void aspectOnAlias_propagationPredicateRunOnActualTarget() throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| if ctx.rule.qualified_kind.rule_name == 'rule_1': |
| return True |
| return False |
| """); |
| createTestPackages(); |
| |
| var unused = update(ImmutableList.of("//test:defs.bzl%cmdline_aspect"), "//pkg1:alias_1"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%cmdline_aspect"); |
| // The propagation predicate is evaluated on the actual target of the alias which in this case |
| // satisfies the predicate. |
| assertThat(aspectKeys) |
| .containsExactly( |
| "cmdline_aspect on //pkg1:alias_1", |
| "cmdline_aspect on //pkg1:alias_2", |
| "cmdline_aspect on //pkg1:actual"); |
| } |
| |
| @Test |
| public void requiredProviderSatisfied_propagationPredicateNotSatisfied_aspectNotPropagated() |
| throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| return False |
| """); |
| createTestPackages(); |
| |
| var unused = |
| update( |
| ImmutableList.of("//test:defs.bzl%aspect_with_required_provider"), |
| "//pkg2:target_with_provider"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_with_required_provider"); |
| // The propagation predicate is not satisfied, so the aspect is not propagated even though its |
| // required provider is satisfied. |
| assertThat(aspectKeys).isEmpty(); |
| } |
| |
| @Test |
| public void requiredProviderSatisfied_propagationPredicateSatisfied_aspectPropagated() |
| throws Exception { |
| createTestDefs( |
| """ |
| def _propagation_predicate(ctx): |
| return True |
| """); |
| createTestPackages(); |
| |
| var unused = |
| update( |
| ImmutableList.of("//test:defs.bzl%aspect_with_required_provider"), |
| "//pkg2:target_with_provider"); |
| |
| var aspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_with_required_provider"); |
| // The propagation predicate and the required provider are satisfied, so the aspect is |
| // propagated to the target. |
| assertThat(aspectKeys) |
| .containsExactly("aspect_with_required_provider on //pkg2:target_with_provider"); |
| } |
| |
| @Test |
| public void aspectOnAspect_eachPropagationPredicateEvaluatedSeparately() throws Exception { |
| scratch.file("test/BUILD"); |
| scratch.file( |
| "test/defs.bzl", |
| """ |
| CInfo = provider() |
| BInfo = provider() |
| AInfo = provider() |
| |
| def _aspect_a_propagation_predicate(ctx): |
| return True |
| |
| def _aspect_b_propagation_predicate(ctx): |
| if ctx.rule.label.package == 'pkg1': |
| return True |
| return False |
| |
| def _aspect_c_propagation_predicate(ctx): |
| return True |
| |
| def _aspect_a_impl(target, ctx): |
| res = 'aspect_a on %s' % target.label |
| if BInfo in target: |
| res += ' with BInfo' |
| if CInfo in target: |
| res += ' with CInfo' |
| |
| res_list = [res] |
| |
| for dep in ctx.rule.attr.deps: |
| if AInfo in dep: |
| res_list.extend(dep[AInfo].res) |
| |
| return [AInfo(res = res_list)] |
| |
| def _aspect_b_impl(target, ctx): |
| return [BInfo()] |
| |
| def _aspect_c_impl(target, ctx): |
| return [CInfo()] |
| |
| aspect_a = aspect( |
| implementation = _aspect_a_impl, |
| propagation_predicate = _aspect_a_propagation_predicate, |
| attr_aspects = ['deps'], |
| required_aspect_providers = [[BInfo], [CInfo]], |
| ) |
| |
| aspect_b = aspect( |
| implementation = _aspect_b_impl, |
| propagation_predicate = _aspect_b_propagation_predicate, |
| attr_aspects = ['deps'], |
| provides = [BInfo], |
| ) |
| |
| aspect_c = aspect( |
| implementation = _aspect_c_impl, |
| propagation_predicate = _aspect_c_propagation_predicate, |
| attr_aspects = ['deps'], |
| provides = [CInfo], |
| ) |
| |
| def _rule_impl(ctx): |
| pass |
| |
| my_rule = rule( |
| implementation = _rule_impl, |
| attrs = {'deps': attr.label_list()}, |
| ) |
| """); |
| scratch.file( |
| "pkg1/BUILD", |
| """ |
| load('//test:defs.bzl', 'my_rule') |
| my_rule(name = 't1', deps = [':t2', '//pkg2:t2']) |
| my_rule(name = 't2') |
| """); |
| scratch.file( |
| "pkg2/BUILD", |
| """ |
| load('//test:defs.bzl', 'my_rule') |
| my_rule(name = 't1', deps = [':t2']) |
| my_rule(name = 't2') |
| """); |
| |
| var analysisResult = |
| update( |
| ImmutableList.of( |
| "//test:defs.bzl%aspect_c", "//test:defs.bzl%aspect_b", "//test:defs.bzl%aspect_a"), |
| "//pkg1:t1", |
| "//pkg2:t1"); |
| |
| // The propagation predicate of each aspect is evaluated separately, then the aspect-on-aspect |
| // relation is created between the filtered aspects. |
| var aAspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_a"); |
| assertThat(aAspectKeys) |
| .containsExactly( |
| "aspect_a on //pkg1:t1 with base aspects: aspect_b,aspect_c", |
| "aspect_a on //pkg1:t2 with base aspects: aspect_b,aspect_c", |
| "aspect_a on //pkg2:t1 with base aspects: aspect_c", |
| "aspect_a on //pkg2:t2 with base aspects: aspect_c"); |
| |
| var bAspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_b"); |
| assertThat(bAspectKeys).containsExactly("aspect_b on //pkg1:t1", "aspect_b on //pkg1:t2"); |
| |
| var cAspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_c"); |
| assertThat(cAspectKeys) |
| .containsExactly( |
| "aspect_c on //pkg1:t1", |
| "aspect_c on //pkg1:t2", |
| "aspect_c on //pkg2:t1", |
| "aspect_c on //pkg2:t2"); |
| |
| var aspectAonPkg1T1 = |
| getAspectResult(analysisResult.getAspectsMap(), "aspect_a", "//pkg1:t1", "AInfo"); |
| assertThat(aspectAonPkg1T1) |
| .containsExactly( |
| "aspect_a on @@//pkg1:t1 with BInfo with CInfo", |
| "aspect_a on @@//pkg1:t2 with BInfo with CInfo", |
| "aspect_a on @@//pkg2:t2 with CInfo"); |
| |
| var aspectAonPkg2T1 = |
| getAspectResult(analysisResult.getAspectsMap(), "aspect_a", "//pkg2:t1", "AInfo"); |
| assertThat(aspectAonPkg2T1) |
| .containsExactly( |
| "aspect_a on @@//pkg2:t1 with CInfo", "aspect_a on @@//pkg2:t2 with CInfo"); |
| } |
| |
| @Test |
| public void requiredAspects_propagationPredicateOfRequiredAspectIsUsed() throws Exception { |
| scratch.file("test/BUILD"); |
| scratch.file( |
| "test/defs.bzl", |
| """ |
| AInfo = provider() |
| BInfo = provider() |
| |
| def _aspect_a_propagation_predicate(ctx): |
| return True |
| |
| def _aspect_b_propagation_predicate(ctx): |
| if ctx.rule.label.package == 'pkg1': |
| return True |
| return False |
| |
| def _aspect_a_impl(target, ctx): |
| res = 'aspect_a on %s' % target.label |
| if BInfo in target: |
| res += ' with BInfo' |
| else: |
| res += ' without BInfo' |
| |
| res_list = [res] |
| |
| for dep in ctx.rule.attr.deps: |
| if AInfo in dep: |
| res_list.extend(dep[AInfo].res) |
| |
| return [AInfo(res = res_list)] |
| |
| def _aspect_b_impl(target, ctx): |
| return [BInfo()] |
| |
| aspect_b = aspect( |
| implementation = _aspect_b_impl, |
| propagation_predicate = _aspect_b_propagation_predicate, |
| ) |
| |
| aspect_a = aspect( |
| implementation = _aspect_a_impl, |
| propagation_predicate = _aspect_a_propagation_predicate, |
| attr_aspects = ['deps'], |
| requires = [aspect_b], |
| ) |
| |
| def _rule_impl(ctx): |
| pass |
| |
| my_rule = rule( |
| implementation = _rule_impl, |
| attrs = {'deps': attr.label_list()}, |
| ) |
| """); |
| scratch.file( |
| "pkg1/BUILD", |
| """ |
| load('//test:defs.bzl', 'my_rule') |
| my_rule(name = 't1', deps = [':t2', '//pkg2:t2']) |
| my_rule(name = 't2') |
| """); |
| scratch.file( |
| "pkg2/BUILD", |
| """ |
| load('//test:defs.bzl', 'my_rule') |
| my_rule(name = 't1', deps = [':t2']) |
| my_rule(name = 't2') |
| """); |
| |
| var analysisResult = |
| update(ImmutableList.of("//test:defs.bzl%aspect_a"), "//pkg1:t1", "//pkg2:t1"); |
| |
| // The propagation predicate of both aspects is used. |
| var aAspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_a"); |
| assertThat(aAspectKeys) |
| .containsExactly( |
| "aspect_a on //pkg1:t1 with base aspects: aspect_b", |
| "aspect_a on //pkg1:t2 with base aspects: aspect_b", |
| "aspect_a on //pkg2:t1", |
| "aspect_a on //pkg2:t2"); |
| |
| var bAspectKeys = getFormattedAspectKeys("//test:defs.bzl%aspect_b"); |
| assertThat(bAspectKeys).containsExactly("aspect_b on //pkg1:t1", "aspect_b on //pkg1:t2"); |
| |
| var aspectAonPkg1T1 = |
| getAspectResult(analysisResult.getAspectsMap(), "aspect_a", "//pkg1:t1", "AInfo"); |
| assertThat(aspectAonPkg1T1) |
| .containsExactly( |
| "aspect_a on @@//pkg1:t1 with BInfo", |
| "aspect_a on @@//pkg1:t2 with BInfo", |
| "aspect_a on @@//pkg2:t2 without BInfo"); |
| var aspectAonPkg2T1 = |
| getAspectResult(analysisResult.getAspectsMap(), "aspect_a", "//pkg2:t1", "AInfo"); |
| assertThat(aspectAonPkg2T1) |
| .containsExactly( |
| "aspect_a on @@//pkg2:t1 without BInfo", "aspect_a on @@//pkg2:t2 without BInfo"); |
| } |
| |
| private String formatAspectKey(AspectKey aspectKey) { |
| if (aspectKey.getBaseKeys().isEmpty()) { |
| return Splitter.on("%").splitToList(aspectKey.getAspectClass().toString()).get(1) |
| + " on " |
| + aspectKey.getLabel(); |
| } |
| |
| String baseAspects = |
| String.join( |
| ",", |
| aspectKey.getBaseKeys().stream() |
| .map(k -> Splitter.on("%").splitToList(k.getAspectClass().toString()).get(1)) |
| .collect(toImmutableList())); |
| return Splitter.on("%").splitToList(aspectKey.getAspectClass().toString()).get(1) |
| + " on " |
| + aspectKey.getLabel() |
| + " with base aspects: " |
| + baseAspects; |
| } |
| |
| private ImmutableList<String> getFormattedAspectKeys(String aspectLabel) { |
| return skyframeExecutor.getEvaluator().getDoneValues().entrySet().stream() |
| .filter( |
| entry -> |
| entry.getKey() instanceof AspectKey |
| && ((AspectKey) entry.getKey()).getAspectClass().toString().equals(aspectLabel)) |
| .map(e -> formatAspectKey((AspectKey) e.getKey())) |
| .collect(toImmutableList()); |
| } |
| |
| private Sequence<?> getAspectResult( |
| Map<AspectKey, ConfiguredAspect> aspectsMap, String aspectName) throws Exception { |
| return getAspectResult(aspectsMap, aspectName, null, "AspectInfo"); |
| } |
| |
| @Nullable |
| private Sequence<?> getAspectResult( |
| Map<AspectKey, ConfiguredAspect> aspectsMap, |
| String aspectName, |
| String targetLabel, |
| String providerName) |
| throws Exception { |
| for (Map.Entry<AspectKey, ConfiguredAspect> entry : aspectsMap.entrySet()) { |
| AspectClass aspectClass = entry.getKey().getAspectClass(); |
| if (aspectClass instanceof StarlarkAspectClass starlarkAspectClass) { |
| String aspectExportedName = starlarkAspectClass.getExportedName(); |
| if (aspectExportedName.equals(aspectName) |
| && (targetLabel == null || entry.getKey().getLabel().toString().equals(targetLabel))) { |
| return getStarlarkProvider(entry.getValue(), "//test:defs.bzl", providerName) |
| .getValue("res", Sequence.class); |
| } |
| } |
| } |
| return null; |
| } |
| } |