diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java index 2a8445a5035157..1e8a0ef29f5cf0 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java @@ -30,7 +30,7 @@ import com.google.devtools.build.lib.causes.Cause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; +import com.google.devtools.build.lib.skyframe.AspectValueKey; import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; import java.util.Collection; import javax.annotation.Nullable; @@ -40,7 +40,7 @@ * target cannot be completed because of an error in one of its dependencies. */ public class AnalysisFailureEvent implements BuildEvent { - @Nullable private final AspectKey failedAspect; + @Nullable private final AspectValueKey failedAspect; private final ConfiguredTargetKey failedTarget; private final BuildEventId configuration; private final NestedSet rootCauses; @@ -48,12 +48,12 @@ public class AnalysisFailureEvent implements BuildEvent { public AnalysisFailureEvent( ActionLookupKey failedTarget, BuildEventId configuration, NestedSet rootCauses) { Preconditions.checkArgument( - failedTarget instanceof ConfiguredTargetKey || failedTarget instanceof AspectKey); + failedTarget instanceof ConfiguredTargetKey || failedTarget instanceof AspectValueKey); if (failedTarget instanceof ConfiguredTargetKey) { this.failedAspect = null; this.failedTarget = (ConfiguredTargetKey) failedTarget; } else { - this.failedAspect = (AspectKey) failedTarget; + this.failedAspect = (AspectValueKey) failedTarget; this.failedTarget = failedAspect.getBaseConfiguredTargetKey(); } if (configuration != null) { @@ -65,7 +65,7 @@ public AnalysisFailureEvent( } public AnalysisFailureEvent( - AspectKey failedAspect, BuildEventId configuration, NestedSet rootCauses) { + AspectValueKey failedAspect, BuildEventId configuration, NestedSet rootCauses) { this.failedAspect = failedAspect; this.failedTarget = failedAspect.getBaseConfiguredTargetKey(); if (configuration != null) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index f835927ef56fa0..bec43a1036d6bf 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -55,12 +55,13 @@ import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.ExtendedEventHandler; import com.google.devtools.build.lib.packages.AspectClass; +import com.google.devtools.build.lib.packages.AspectDescriptor; +import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.NativeAspectClass; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.NoSuchTargetException; import com.google.devtools.build.lib.packages.Rule; -import com.google.devtools.build.lib.packages.StarlarkAspectClass; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.packages.TargetUtils; import com.google.devtools.build.lib.pkgcache.PackageManager; @@ -74,7 +75,6 @@ import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns.Code; import com.google.devtools.build.lib.skyframe.AspectValueKey; import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; -import com.google.devtools.build.lib.skyframe.AspectValueKey.TopLevelAspectsKey; import com.google.devtools.build.lib.skyframe.BuildConfigurationValue; import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; import com.google.devtools.build.lib.skyframe.CoverageReportValue; @@ -86,6 +86,7 @@ import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.RegexFilter; import com.google.devtools.build.skyframe.WalkableGraph; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -274,7 +275,10 @@ public AnalysisResult update( .map(TargetAndConfiguration::getConfiguredTargetKey) .collect(Collectors.toList()); - ImmutableList.Builder aspectClassesBuilder = ImmutableList.builder(); + Multimap, BuildConfiguration> aspectConfigurations = + ArrayListMultimap.create(); + + List aspectKeys = new ArrayList<>(); for (String aspect : aspects) { // Syntax: label%aspect int delimiterPosition = aspect.indexOf('%'); @@ -314,14 +318,38 @@ public AnalysisResult update( createFailureDetail(errorMessage, Analysis.Code.ASPECT_LABEL_SYNTAX_ERROR), e); } + String starlarkFunctionName = aspect.substring(delimiterPosition + 1); - aspectClassesBuilder.add(new StarlarkAspectClass(starlarkFileLabel, starlarkFunctionName)); + for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) { + aspectConfigurations.put( + Pair.of(targetSpec.getLabel(), aspect), targetSpec.getConfiguration()); + aspectKeys.add( + AspectValueKey.createStarlarkAspectKey( + targetSpec.getLabel(), + // For invoking top-level aspects, use the top-level configuration for both the + // aspect and the base target while the top-level configuration is untrimmed. + targetSpec.getConfiguration(), + targetSpec.getConfiguration(), + starlarkFileLabel, + starlarkFunctionName)); + } } else { final NativeAspectClass aspectFactoryClass = ruleClassProvider.getNativeAspectClassMap().get(aspect); if (aspectFactoryClass != null) { - aspectClassesBuilder.add(aspectFactoryClass); + for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) { + // For invoking top-level aspects, use the top-level configuration for both the + // aspect and the base target while the top-level configuration is untrimmed. + BuildConfiguration configuration = targetSpec.getConfiguration(); + aspectConfigurations.put(Pair.of(targetSpec.getLabel(), aspect), configuration); + aspectKeys.add( + AspectValueKey.createAspectKey( + targetSpec.getLabel(), + configuration, + new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY), + configuration)); + } } else { String errorMessage = "Aspect '" + aspect + "' is unknown"; throw new ViewCreationFailedException( @@ -330,25 +358,6 @@ public AnalysisResult update( } } - Multimap, BuildConfiguration> aspectConfigurations = - ArrayListMultimap.create(); - ImmutableList aspectClasses = aspectClassesBuilder.build(); - ImmutableList.Builder aspectsKeys = ImmutableList.builder(); - for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) { - BuildConfiguration configuration = targetSpec.getConfiguration(); - for (AspectClass aspectClass : aspectClasses) { - aspectConfigurations.put( - Pair.of(targetSpec.getLabel(), aspectClass.getName()), configuration); - } - // For invoking top-level aspects, use the top-level configuration for both the - // aspect and the base target while the top-level configuration is untrimmed. - if (!aspectClasses.isEmpty()) { - aspectsKeys.add( - AspectValueKey.createTopLevelAspectsKey( - aspectClasses, targetSpec.getLabel(), configuration)); - } - } - for (Pair target : aspectConfigurations.keys()) { eventBus.post( new AspectConfiguredEvent( @@ -373,7 +382,7 @@ public AnalysisResult update( skyframeBuildView.configureTargets( eventHandler, topLevelCtKeys, - aspectsKeys.build(), + aspectKeys, Suppliers.memoize(configurationLookupSupplier), topLevelOptions, eventBus, diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequestOptions.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequestOptions.java index c35d8dd2714ab6..5dcd7582242336 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequestOptions.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequestOptions.java @@ -297,18 +297,11 @@ public class BuildRequestOptions extends OptionsBase { effectTags = {OptionEffectTag.UNKNOWN}, allowMultiple = true, help = - "Comma-separated list of aspects to be applied to top-level targets. All aspects are" - + " applied to all top-level targets. If aspect some_aspect specifies" - + " required aspect providers via required_aspect_providers," - + " some_aspect will run after every aspect that was mentioned before it" - + " in the aspects list and whose advertised providers satisfy" - + " some_aspect required aspect providers. some_aspect will" - + " then have access to the values of those aspects' providers. Aspects that do not" - + " have such dependency will run independently on the top-level targets." - + "" - + " Aspects are specified in the form %, for example" - + " '//tools:my_def.bzl%my_aspect', where 'my_aspect' is a top-level value from a" - + " file tools/my_def.bzl") + "Comma-separated list of aspects to be applied to top-level targets. All aspects " + + "are applied to all top-level targets independently. Aspects are specified in " + + "the form %, " + + "for example '//tools:my_def.bzl%my_aspect', where 'my_aspect' is a top-level " + + "value from from a file tools/my_def.bzl") public List aspects; public BuildRequestOptions() throws OptionsParsingException {} diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspectClass.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspectClass.java index bf0b414e875cdf..2b9f2a3d8bfef6 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspectClass.java +++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkAspectClass.java @@ -64,9 +64,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(extensionLabel, exportedName); } - - @Override - public String toString() { - return getName(); - } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java index f97e08d746ac85..04c15bdca24dda 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.skyframe; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -29,15 +30,29 @@ import com.google.devtools.build.skyframe.SkyFunctionName; import javax.annotation.Nullable; -/** A wrapper class for sky keys needed to compute sky values for aspects. */ -public final class AspectValueKey { - - private AspectValueKey() {} +/** A base class for keys that have AspectValue as a Sky value. */ +public abstract class AspectValueKey implements ActionLookupKey { private static final Interner aspectKeyInterner = BlazeInterners.newWeakInterner(); - private static final Interner topLevelAspectsKeyInterner = + private static final Interner starlarkAspectKeyInterner = BlazeInterners.newWeakInterner(); + /** + * Gets the name of the aspect that would be returned by the corresponding value's {@code + * aspectValue.getAspect().getAspectClass().getName()}, if the value could be produced. + * + *

Only needed for reporting errors in BEP when the key's AspectValue fails evaluation. + */ + public abstract String getAspectName(); + + public abstract String getDescription(); + + @Nullable + abstract BuildConfigurationValue.Key getAspectConfigurationKey(); + + /** Returns the key for the base configured target for this aspect. */ + public abstract ConfiguredTargetKey getBaseConfiguredTargetKey(); + public static AspectKey createAspectKey( Label label, @Nullable BuildConfiguration baseConfiguration, @@ -72,48 +87,33 @@ public static AspectKey createAspectKey( aspectConfiguration == null ? null : BuildConfigurationValue.key(aspectConfiguration)); } - public static TopLevelAspectsKey createTopLevelAspectsKey( - ImmutableList topLevelAspectsClasses, + public static StarlarkAspectLoadingKey createStarlarkAspectKey( Label targetLabel, - @Nullable BuildConfiguration configuration) { - return TopLevelAspectsKey.createInternal( - topLevelAspectsClasses, + @Nullable BuildConfiguration aspectConfiguration, + @Nullable BuildConfiguration targetConfiguration, + Label starlarkFileLabel, + String starlarkExportName) { + return StarlarkAspectLoadingKey.createInternal( targetLabel, + aspectConfiguration == null ? null : BuildConfigurationValue.key(aspectConfiguration), ConfiguredTargetKey.builder() .setLabel(targetLabel) - .setConfiguration(configuration) - .build()); - } - - /** Common superclass for {@link AspectKey} and {@link TopLevelAspectsKey}. */ - public abstract static class AspectBaseKey implements ActionLookupKey { - private final ConfiguredTargetKey baseConfiguredTargetKey; - private final int hashCode; - - private AspectBaseKey(ConfiguredTargetKey baseConfiguredTargetKey, int hashCode) { - this.baseConfiguredTargetKey = baseConfiguredTargetKey; - this.hashCode = hashCode; - } - - /** Returns the key for the base configured target for this aspect. */ - public final ConfiguredTargetKey getBaseConfiguredTargetKey() { - return baseConfiguredTargetKey; - } - - @Override - public final int hashCode() { - return hashCode; - } + .setConfiguration(targetConfiguration) + .build(), + starlarkFileLabel, + starlarkExportName); } // Specific subtypes of aspect keys. /** Represents an aspect applied to a particular target. */ @AutoCodec - public static final class AspectKey extends AspectBaseKey { + public static final class AspectKey extends AspectValueKey { + private final ConfiguredTargetKey baseConfiguredTargetKey; private final ImmutableList baseKeys; @Nullable private final BuildConfigurationValue.Key aspectConfigurationKey; private final AspectDescriptor aspectDescriptor; + private final int hashCode; private AspectKey( ConfiguredTargetKey baseConfiguredTargetKey, @@ -121,10 +121,11 @@ private AspectKey( AspectDescriptor aspectDescriptor, @Nullable BuildConfigurationValue.Key aspectConfigurationKey, int hashCode) { - super(baseConfiguredTargetKey, hashCode); this.baseKeys = baseKeys; this.aspectConfigurationKey = aspectConfigurationKey; + this.baseConfiguredTargetKey = baseConfiguredTargetKey; this.aspectDescriptor = aspectDescriptor; + this.hashCode = hashCode; } @AutoCodec.VisibleForSerialization @@ -149,19 +150,14 @@ public SkyFunctionName functionName() { return SkyFunctions.ASPECT; } - /** - * Gets the name of the aspect that would be returned by the corresponding value's {@code - * aspectValue.getAspect().getAspectClass().getName()}, if the value could be produced. - * - *

Only needed for reporting errors in BEP when the key's AspectValue fails evaluation. - */ + @Override public String getAspectName() { return aspectDescriptor.getDescription(); } @Override public Label getLabel() { - return getBaseConfiguredTargetKey().getLabel(); + return baseConfiguredTargetKey.getLabel(); } public AspectClass getAspectClass() { @@ -191,9 +187,11 @@ ImmutableList getBaseKeys() { return baseKeys; } + @Override public String getDescription() { if (baseKeys.isEmpty()) { - return String.format("%s of %s", aspectDescriptor.getAspectClass().getName(), getLabel()); + return String.format("%s of %s", + aspectDescriptor.getAspectClass().getName(), getLabel()); } else { return String.format( "%s on top of %s", aspectDescriptor.getAspectClass().getName(), baseKeys); @@ -218,10 +216,22 @@ public String getDescription() { * base target's configuration. */ @Nullable + @Override BuildConfigurationValue.Key getAspectConfigurationKey() { return aspectConfigurationKey; } + /** Returns the key for the base configured target for this aspect. */ + @Override + public ConfiguredTargetKey getBaseConfiguredTargetKey() { + return baseConfiguredTargetKey; + } + + @Override + public int hashCode() { + return hashCode; + } + @Override public boolean equals(Object other) { if (this == other) { @@ -231,10 +241,10 @@ public boolean equals(Object other) { return false; } AspectKey that = (AspectKey) other; - return hashCode() == that.hashCode() + return hashCode == that.hashCode && Objects.equal(baseKeys, that.baseKeys) && Objects.equal(aspectConfigurationKey, that.aspectConfigurationKey) - && Objects.equal(getBaseConfiguredTargetKey(), that.getBaseConfiguredTargetKey()) + && Objects.equal(baseConfiguredTargetKey, that.baseConfiguredTargetKey) && Objects.equal(aspectDescriptor, that.aspectDescriptor); } @@ -257,7 +267,7 @@ public String toString() { + " " + aspectConfigurationKey + " " - + getBaseConfiguredTargetKey() + + baseConfiguredTargetKey + " " + aspectDescriptor.getParameters(); } @@ -271,7 +281,7 @@ AspectKey withLabel(Label label) { return createAspectKey( ConfiguredTargetKey.builder() .setLabel(label) - .setConfigurationKey(getBaseConfiguredTargetKey().getConfigurationKey()) + .setConfigurationKey(baseConfiguredTargetKey.getConfigurationKey()) .build(), newBaseKeys.build(), aspectDescriptor, @@ -279,43 +289,70 @@ AspectKey withLabel(Label label) { } } - /** The key for top level aspects specified by --aspects option on a top level target. */ + /** The key for a Starlark aspect. */ @AutoCodec - public static final class TopLevelAspectsKey extends AspectBaseKey { - private final ImmutableList topLevelAspectsClasses; + public static final class StarlarkAspectLoadingKey extends AspectValueKey { private final Label targetLabel; + private final BuildConfigurationValue.Key aspectConfigurationKey; + private final ConfiguredTargetKey baseConfiguredTargetKey; + private final Label starlarkFileLabel; + private final String starlarkValueName; + private final int hashCode; @AutoCodec.Instantiator @AutoCodec.VisibleForSerialization - static TopLevelAspectsKey createInternal( - ImmutableList topLevelAspectsClasses, + static StarlarkAspectLoadingKey createInternal( Label targetLabel, - ConfiguredTargetKey baseConfiguredTargetKey) { - return topLevelAspectsKeyInterner.intern( - new TopLevelAspectsKey( - topLevelAspectsClasses, + BuildConfigurationValue.Key aspectConfigurationKey, + ConfiguredTargetKey baseConfiguredTargetKey, + Label starlarkFileLabel, + String starlarkValueName) { + return starlarkAspectKeyInterner.intern( + new StarlarkAspectLoadingKey( targetLabel, + aspectConfigurationKey, baseConfiguredTargetKey, - Objects.hashCode(topLevelAspectsClasses, targetLabel, baseConfiguredTargetKey))); + starlarkFileLabel, + starlarkValueName, + Objects.hashCode( + targetLabel, + aspectConfigurationKey, + baseConfiguredTargetKey, + starlarkFileLabel, + starlarkValueName))); } - private TopLevelAspectsKey( - ImmutableList topLevelAspectsClasses, + private StarlarkAspectLoadingKey( Label targetLabel, + BuildConfigurationValue.Key aspectConfigurationKey, ConfiguredTargetKey baseConfiguredTargetKey, + Label starlarkFileLabel, + String starlarkValueName, int hashCode) { - super(baseConfiguredTargetKey, hashCode); - this.topLevelAspectsClasses = topLevelAspectsClasses; this.targetLabel = targetLabel; + this.aspectConfigurationKey = aspectConfigurationKey; + this.baseConfiguredTargetKey = baseConfiguredTargetKey; + this.starlarkFileLabel = starlarkFileLabel; + this.starlarkValueName = starlarkValueName; + this.hashCode = hashCode; } @Override public SkyFunctionName functionName() { - return SkyFunctions.TOP_LEVEL_ASPECTS; + return SkyFunctions.LOAD_STARLARK_ASPECT; + } + + String getStarlarkValueName() { + return starlarkValueName; } - ImmutableList getTopLevelAspectsClasses() { - return topLevelAspectsClasses; + Label getStarlarkFileLabel() { + return starlarkFileLabel; + } + + @Override + public String getAspectName() { + return String.format("%s%%%s", starlarkFileLabel, starlarkValueName); } @Override @@ -323,8 +360,27 @@ public Label getLabel() { return targetLabel; } - String getDescription() { - return topLevelAspectsClasses + " on " + getLabel(); + @Override + public String getDescription() { + // Starlark aspects are referred to on command line with % + return String.format("%s%%%s of %s", starlarkFileLabel, starlarkValueName, targetLabel); + } + + @Nullable + @Override + BuildConfigurationValue.Key getAspectConfigurationKey() { + return aspectConfigurationKey; + } + + /** Returns the key for the base configured target for this aspect. */ + @Override + public ConfiguredTargetKey getBaseConfiguredTargetKey() { + return baseConfiguredTargetKey; + } + + @Override + public int hashCode() { + return hashCode; } @Override @@ -332,14 +388,35 @@ public boolean equals(Object o) { if (o == this) { return true; } - if (!(o instanceof TopLevelAspectsKey)) { + if (!(o instanceof StarlarkAspectLoadingKey)) { return false; } - TopLevelAspectsKey that = (TopLevelAspectsKey) o; - return hashCode() == that.hashCode() + StarlarkAspectLoadingKey that = (StarlarkAspectLoadingKey) o; + return hashCode == that.hashCode && Objects.equal(targetLabel, that.targetLabel) - && Objects.equal(getBaseConfiguredTargetKey(), that.getBaseConfiguredTargetKey()) - && Objects.equal(topLevelAspectsClasses, that.topLevelAspectsClasses); + && Objects.equal(aspectConfigurationKey, that.aspectConfigurationKey) + && Objects.equal(baseConfiguredTargetKey, that.baseConfiguredTargetKey) + && Objects.equal(starlarkFileLabel, that.starlarkFileLabel) + && Objects.equal(starlarkValueName, that.starlarkValueName); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("targetLabel", targetLabel) + .add("aspectConfigurationKey", aspectConfigurationKey) + .add("baseConfiguredTargetKey", baseConfiguredTargetKey) + .add("starlarkFileLabel", starlarkFileLabel) + .add("starlarkValueName", starlarkValueName) + .toString(); + } + + AspectKey toAspectKey(AspectClass aspectClass) { + return AspectKey.createAspectKey( + baseConfiguredTargetKey, + ImmutableList.of(), + new AspectDescriptor(aspectClass, AspectParameters.EMPTY), + aspectConfigurationKey); } } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD index 9e9a99a75f456f..15222d2f0c452e 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD @@ -38,7 +38,6 @@ java_library( "ExternalFilesHelper.java", "ExternalPackageFunction.java", "FileStateFunction.java", - "LoadStarlarkAspectFunction.java", "LocalRepositoryLookupFunction.java", "NonRuleConfiguredTargetValue.java", "PackageFunction.java", diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/LoadStarlarkAspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/LoadStarlarkAspectFunction.java deleted file mode 100644 index 4d81910f6e500e..00000000000000 --- a/src/main/java/com/google/devtools/build/lib/skyframe/LoadStarlarkAspectFunction.java +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2021 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.skyframe; - -import com.google.common.base.Objects; -import com.google.common.collect.Interner; -import com.google.devtools.build.lib.causes.LabelCause; -import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.concurrent.BlazeInterners; -import com.google.devtools.build.lib.packages.StarlarkAspect; -import com.google.devtools.build.lib.packages.StarlarkAspectClass; -import com.google.devtools.build.lib.server.FailureDetails.Analysis; -import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code; -import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; -import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; -import com.google.devtools.build.lib.util.DetailedExitCode; -import com.google.devtools.build.skyframe.SkyFunction; -import com.google.devtools.build.skyframe.SkyFunctionException; -import com.google.devtools.build.skyframe.SkyFunctionName; -import com.google.devtools.build.skyframe.SkyKey; -import com.google.devtools.build.skyframe.SkyValue; -import javax.annotation.Nullable; - -/** - * SkyFunction to load aspects from Starlark extensions and return StarlarkAspect. - * - *

Used for loading top-level aspects. At top level, in {@link - * com.google.devtools.build.lib.analysis.BuildView}, we cannot invoke two SkyFunctions one after - * another, so BuildView calls this function to do the work. - */ -public class LoadStarlarkAspectFunction implements SkyFunction { - private static final Interner starlarkAspectLoadingKeyInterner = - BlazeInterners.newWeakInterner(); - - LoadStarlarkAspectFunction() {} - - @Nullable - @Override - public SkyValue compute(SkyKey skyKey, Environment env) - throws LoadStarlarkAspectFunctionException, InterruptedException { - StarlarkAspectLoadingKey aspectLoadingKey = (StarlarkAspectLoadingKey) skyKey.argument(); - - Label extensionLabel = aspectLoadingKey.getAspectClass().getExtensionLabel(); - String exportedName = aspectLoadingKey.getAspectClass().getExportedName(); - StarlarkAspect starlarkAspect; - try { - starlarkAspect = AspectFunction.loadStarlarkAspect(env, extensionLabel, exportedName); - if (starlarkAspect == null) { - return null; - } - if (!starlarkAspect.getParamAttributes().isEmpty()) { - String msg = - String.format( - "Cannot instantiate parameterized aspect %s at the top level.", - starlarkAspect.getName()); - throw new AspectCreationException( - msg, - new LabelCause( - extensionLabel, - createDetailedCode(msg, Code.PARAMETERIZED_TOP_LEVEL_ASPECT_INVALID))); - } - } catch (AspectCreationException e) { - throw new LoadStarlarkAspectFunctionException(e); - } - - return new StarlarkAspectLoadingValue(starlarkAspect); - } - - @Nullable - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - - private static DetailedExitCode createDetailedCode(String msg, Code code) { - return DetailedExitCode.of( - FailureDetail.newBuilder() - .setMessage(msg) - .setAnalysis(Analysis.newBuilder().setCode(code)) - .build()); - } - - /** Exceptions thrown from LoadStarlarkAspectFunction. */ - public static class LoadStarlarkAspectFunctionException extends SkyFunctionException { - public LoadStarlarkAspectFunctionException(AspectCreationException cause) { - super(cause, Transience.PERSISTENT); - } - } - - public static StarlarkAspectLoadingKey createStarlarkAspectLoadingKey( - StarlarkAspectClass aspectClass) { - return StarlarkAspectLoadingKey.createInternal(aspectClass); - } - - /** Skykey for loading Starlark aspect. */ - @AutoCodec - public static final class StarlarkAspectLoadingKey implements SkyKey { - private final StarlarkAspectClass aspectClass; - private final int hashCode; - - @AutoCodec.Instantiator - @AutoCodec.VisibleForSerialization - static StarlarkAspectLoadingKey createInternal(StarlarkAspectClass aspectClass) { - return starlarkAspectLoadingKeyInterner.intern( - new StarlarkAspectLoadingKey(aspectClass, java.util.Objects.hashCode(aspectClass))); - } - - private StarlarkAspectLoadingKey(StarlarkAspectClass aspectClass, int hashCode) { - this.aspectClass = aspectClass; - this.hashCode = hashCode; - } - - @Override - public SkyFunctionName functionName() { - return SkyFunctions.LOAD_STARLARK_ASPECT; - } - - StarlarkAspectClass getAspectClass() { - return aspectClass; - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof StarlarkAspectLoadingKey)) { - return false; - } - StarlarkAspectLoadingKey that = (StarlarkAspectLoadingKey) o; - return hashCode == that.hashCode && Objects.equal(aspectClass, that.aspectClass); - } - - @Override - public String toString() { - return aspectClass.toString(); - } - } - - /** SkyValue for {@code StarlarkAspectLoadingKey} holds the loaded {@code StarlarkAspect}. */ - public static class StarlarkAspectLoadingValue implements SkyValue { - private final StarlarkAspect starlarkAspect; - - public StarlarkAspectLoadingValue(StarlarkAspect starlarkAspect) { - this.starlarkAspect = starlarkAspect; - } - - public StarlarkAspect getAspect() { - return starlarkAspect; - } - } -} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java index 46443e4d3dc9a0..cb07796b366192 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java @@ -88,8 +88,6 @@ public final class SkyFunctions { public static final SkyFunctionName ASPECT = SkyFunctionName.createHermetic("ASPECT"); static final SkyFunctionName LOAD_STARLARK_ASPECT = SkyFunctionName.createHermetic("LOAD_STARLARK_ASPECT"); - static final SkyFunctionName TOP_LEVEL_ASPECTS = - SkyFunctionName.createHermetic("TOP_LEVEL_ASPECTS"); public static final SkyFunctionName TARGET_COMPLETION = SkyFunctionName.create( "TARGET_COMPLETION", ShareabilityOfValue.NEVER, FunctionHermeticity.HERMETIC); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java index 792dc66938e9e6..c7187624e27ecd 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java @@ -88,9 +88,7 @@ import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; import com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ConflictException; import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; -import com.google.devtools.build.lib.skyframe.AspectValueKey.TopLevelAspectsKey; import com.google.devtools.build.lib.skyframe.SkyframeExecutor.TopLevelActionConflictReport; -import com.google.devtools.build.lib.skyframe.ToplevelStarlarkAspectFunction.TopLevelAspectsValue; import com.google.devtools.build.lib.util.DetailedExitCode; import com.google.devtools.build.lib.util.OrderedSetMultimap; import com.google.devtools.build.lib.util.Pair; @@ -382,7 +380,7 @@ public void clearAnalysisCache( public SkyframeAnalysisResult configureTargets( ExtendedEventHandler eventHandler, List ctKeys, - ImmutableList topLevelAspectsKey, + List aspectKeys, Supplier> configurationLookupSupplier, TopLevelArtifactContext topLevelArtifactContextForConflictPruning, EventBus eventBus, @@ -399,7 +397,7 @@ public SkyframeAnalysisResult configureTargets( skyframeExecutor.configureTargets( eventHandler, ctKeys, - topLevelAspectsKey, + aspectKeys, keepGoing, numThreads, cpuHeavySkyKeysThreadPoolSize); @@ -407,33 +405,21 @@ public SkyframeAnalysisResult configureTargets( enableAnalysis(false); } - int numOfAspects = 0; - if (!topLevelAspectsKey.isEmpty()) { - numOfAspects = - topLevelAspectsKey.size() * topLevelAspectsKey.get(0).getTopLevelAspectsClasses().size(); - } - Map aspects = Maps.newHashMapWithExpectedSize(numOfAspects); + Map aspects = Maps.newHashMapWithExpectedSize(aspectKeys.size()); Root singleSourceRoot = skyframeExecutor.getForcedSingleSourceRootIfNoExecrootSymlinkCreation(); NestedSetBuilder packages = singleSourceRoot == null ? NestedSetBuilder.stableOrder() : null; - ImmutableList.Builder aspectKeysBuilder = ImmutableList.builder(); - - for (TopLevelAspectsKey key : topLevelAspectsKey) { - TopLevelAspectsValue value = (TopLevelAspectsValue) result.get(key); + for (AspectValueKey aspectKey : aspectKeys) { + AspectValue value = (AspectValue) result.get(aspectKey); if (value == null) { // Skip aspects that couldn't be applied to targets. continue; } - for (SkyValue val : value.getTopLevelAspectsValues()) { - AspectValue aspectValue = (AspectValue) val; - aspects.put(aspectValue.getKey(), aspectValue.getConfiguredAspect()); - if (packages != null) { - packages.addTransitive(aspectValue.getTransitivePackagesForPackageRootResolution()); - } - aspectKeysBuilder.add(aspectValue.getKey()); + aspects.put(value.getKey(), value.getConfiguredAspect()); + if (packages != null) { + packages.addTransitive(value.getTransitivePackagesForPackageRootResolution()); } } - ImmutableList aspectKeys = aspectKeysBuilder.build(); Collection cts = Lists.newArrayListWithCapacity(ctKeys.size()); for (ConfiguredTargetKey value : ctKeys) { @@ -575,7 +561,7 @@ public SkyframeAnalysisResult configureTargets( BuildConfigurationValue.Key configKey = ctKey instanceof ConfiguredTargetKey ? ((ConfiguredTargetKey) ctKey).getConfigurationKey() - : ((AspectKey) ctKey).getAspectConfigurationKey(); + : ((AspectValueKey) ctKey).getAspectConfigurationKey(); eventBus.post( new AnalysisFailureEvent( ctKey, @@ -611,9 +597,13 @@ public SkyframeAnalysisResult configureTargets( .collect(toImmutableList()); aspects = - aspects.entrySet().stream() - .filter(e -> topLevelActionConflictReport.isErrorFree(e.getKey())) - .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); + aspectKeys.stream() + .filter(topLevelActionConflictReport::isErrorFree) + .map(result::get) + .map(AspectValue.class::cast) + .collect( + ImmutableMap.toImmutableMap( + AspectValue::getKey, AspectValue::getConfiguredAspect)); } return new SkyframeAnalysisResult( @@ -755,15 +745,17 @@ static Pair processErrors( .reportCycles(errorInfo.getCycleInfo(), errorKey, eventHandler); Exception cause = errorInfo.getException(); Preconditions.checkState(cause != null || !errorInfo.getCycleInfo().isEmpty(), errorInfo); - if (errorKey.argument() instanceof TopLevelAspectsKey) { + + if (errorKey.argument() instanceof AspectValueKey) { // We skip Aspects in the keepGoing case; the failures should already have been reported to // the event handler. if (!keepGoing && noKeepGoingException == null) { - TopLevelAspectsKey aspectKey = (TopLevelAspectsKey) errorKey.argument(); + AspectValueKey aspectKey = (AspectValueKey) errorKey.argument(); failedAspectLabel = aspectKey.getBaseConfiguredTargetKey(); + String errorMsg = String.format( - "Analysis of aspects '%s' failed; build aborted", aspectKey.getDescription()); + "Analysis of aspect '%s' failed; build aborted", aspectKey.getDescription()); noKeepGoingException = createViewCreationFailedException(cause, errorMsg); } continue; @@ -784,7 +776,7 @@ static Pair processErrors( } Preconditions.checkState( errorKey.argument() instanceof ConfiguredTargetKey, - "expected '%s' to be a TopLevelAspectsKey or ConfiguredTargetKey", + "expected '%s' to be a AspectValueKey or ConfiguredTargetKey", errorKey.argument()); ConfiguredTargetKey label = (ConfiguredTargetKey) errorKey.argument(); Label topLevelLabel = label.getLabel(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 780cdceb756673..af7eb2756f4c7a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java @@ -162,7 +162,6 @@ import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns; import com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ConflictException; import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; -import com.google.devtools.build.lib.skyframe.AspectValueKey.TopLevelAspectsKey; import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.FileDirtinessChecker; import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction; import com.google.devtools.build.lib.skyframe.MetadataConsumerForMetrics.FilesMetricConsumer; @@ -575,8 +574,7 @@ private ImmutableMap skyFunctions() { new BuildViewProvider(), ruleClassProvider, shouldStoreTransitivePackagesInLoadingAndAnalysis())); - map.put(SkyFunctions.LOAD_STARLARK_ASPECT, new LoadStarlarkAspectFunction()); - map.put(SkyFunctions.TOP_LEVEL_ASPECTS, new ToplevelStarlarkAspectFunction()); + map.put(SkyFunctions.LOAD_STARLARK_ASPECT, new ToplevelStarlarkAspectFunction()); map.put(SkyFunctions.ACTION_LOOKUP_CONFLICT_FINDING, new ActionLookupConflictFindingFunction()); map.put( SkyFunctions.TOP_LEVEL_ACTION_LOOKUP_CONFLICT_FINDING, @@ -2334,7 +2332,7 @@ protected abstract void invalidateFilesUnderPathForTestingImpl( EvaluationResult configureTargets( ExtendedEventHandler eventHandler, List values, - ImmutableList aspectKeys, + List aspectKeys, boolean keepGoing, int numThreads, int cpuHeavySkyKeysThreadPoolSize) @@ -3071,7 +3069,7 @@ protected ExecutionFinishedEvent.Builder createExecutionFinishedEventInternal() } final AnalysisTraversalResult getActionLookupValuesInBuild( - List topLevelCtKeys, ImmutableList aspectKeys) + List topLevelCtKeys, List aspectKeys) throws InterruptedException { AnalysisTraversalResult result = new AnalysisTraversalResult(); if (!isAnalysisIncremental()) { @@ -3091,7 +3089,7 @@ final AnalysisTraversalResult getActionLookupValuesInBuild( for (ConfiguredTargetKey key : topLevelCtKeys) { findActionsRecursively(walkableGraph, key, seen, result); } - for (AspectKey key : aspectKeys) { + for (AspectValueKey key : aspectKeys) { findActionsRecursively(walkableGraph, key, seen, result); } return result; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCycleReporter.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCycleReporter.java index 693bde758f4f64..cf8f8285f1bb0b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCycleReporter.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCycleReporter.java @@ -39,7 +39,7 @@ class TargetCycleReporter extends AbstractLabelCycleReporter { Predicates.or( SkyFunctions.isSkyFunction(SkyFunctions.CONFIGURED_TARGET), SkyFunctions.isSkyFunction(SkyFunctions.ASPECT), - SkyFunctions.isSkyFunction(SkyFunctions.TOP_LEVEL_ASPECTS), + SkyFunctions.isSkyFunction(SkyFunctions.LOAD_STARLARK_ASPECT), SkyFunctions.isSkyFunction(TransitiveTargetKey.NAME), SkyFunctions.isSkyFunction(SkyFunctions.PREPARE_ANALYSIS_PHASE)); @@ -65,6 +65,8 @@ public String prettyPrint(SkyKey key) { return ((ConfiguredTargetKey) key.argument()).prettyPrint(); } else if (key instanceof AspectKey) { return ((AspectKey) key.argument()).prettyPrint(); + } else if (key instanceof AspectValueKey) { + return ((AspectValueKey) key).getDescription(); } else { return getLabel(key).toString(); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelStarlarkAspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelStarlarkAspectFunction.java index 5638d8e9c64a1f..a858e35e351abd 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelStarlarkAspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelStarlarkAspectFunction.java @@ -14,36 +14,22 @@ package com.google.devtools.build.lib.skyframe; -import com.google.common.collect.ImmutableList; -import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; -import com.google.devtools.build.lib.actions.ActionLookupValue; -import com.google.devtools.build.lib.analysis.AspectCollection; -import com.google.devtools.build.lib.analysis.AspectCollection.AspectCycleOnPathException; -import com.google.devtools.build.lib.events.Event; -import com.google.devtools.build.lib.packages.Aspect; -import com.google.devtools.build.lib.packages.AspectClass; -import com.google.devtools.build.lib.packages.AspectDescriptor; -import com.google.devtools.build.lib.packages.AspectsListBuilder; -import com.google.devtools.build.lib.packages.NativeAspectClass; +import com.google.devtools.build.lib.causes.LabelCause; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.StarlarkAspect; -import com.google.devtools.build.lib.packages.StarlarkAspectClass; -import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; -import com.google.devtools.build.lib.skyframe.AspectValueKey.TopLevelAspectsKey; -import com.google.devtools.build.lib.skyframe.LoadStarlarkAspectFunction.StarlarkAspectLoadingKey; -import com.google.devtools.build.lib.skyframe.LoadStarlarkAspectFunction.StarlarkAspectLoadingValue; +import com.google.devtools.build.lib.server.FailureDetails.Analysis; +import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code; +import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; +import com.google.devtools.build.lib.skyframe.AspectValueKey.StarlarkAspectLoadingKey; +import com.google.devtools.build.lib.util.DetailedExitCode; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; -import java.util.HashMap; -import java.util.Map; import javax.annotation.Nullable; -import net.starlark.java.eval.EvalException; /** - * SkyFunction to load top level aspects, build the dependency relation between them based on the - * providers they advertise and provide using {@link AspectCollection} and runs the obtained aspects - * path on the top level target. + * SkyFunction to load aspects from Starlark extensions and calculate their values. * *

Used for loading top-level aspects. At top level, in {@link * com.google.devtools.build.lib.analysis.BuildView}, we cannot invoke two SkyFunctions one after @@ -55,40 +41,34 @@ public class ToplevelStarlarkAspectFunction implements SkyFunction { @Nullable @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws TopLevelStarlarkAspectFunctionException, InterruptedException { - TopLevelAspectsKey topLevelAspectsKey = (TopLevelAspectsKey) skyKey.argument(); + throws LoadStarlarkAspectFunctionException, InterruptedException { + StarlarkAspectLoadingKey aspectLoadingKey = (StarlarkAspectLoadingKey) skyKey.argument(); + String starlarkValueName = aspectLoadingKey.getStarlarkValueName(); + Label starlarkFileLabel = aspectLoadingKey.getStarlarkFileLabel(); - ImmutableList topLevelAspects; + StarlarkAspect starlarkAspect; try { - topLevelAspects = getTopLevelAspects(env, topLevelAspectsKey.getTopLevelAspectsClasses()); - } catch (EvalException e) { - env.getListener().handle(Event.error(e.getMessage())); - throw new TopLevelStarlarkAspectFunctionException( - new AspectCreationException(e.getMessage(), topLevelAspectsKey.getLabel())); - } - - if (topLevelAspects == null) { - return null; // some aspects are not loaded - } - - AspectCollection aspectCollection; - try { - aspectCollection = AspectCollection.create(topLevelAspects); - } catch (AspectCycleOnPathException e) { - env.getListener().handle(Event.error(e.getMessage())); - throw new TopLevelStarlarkAspectFunctionException( - new AspectCreationException(e.getMessage(), topLevelAspectsKey.getLabel())); - } - - ImmutableList aspectKeys = - getTopLevelAspectsKeys(aspectCollection, topLevelAspectsKey.getBaseConfiguredTargetKey()); - - Map result = env.getValues(aspectKeys); - if (env.valuesMissing()) { - return null; // some aspects keys are not evaluated + starlarkAspect = AspectFunction.loadStarlarkAspect(env, starlarkFileLabel, starlarkValueName); + if (starlarkAspect == null) { + return null; + } + if (!starlarkAspect.getParamAttributes().isEmpty()) { + String msg = + String.format( + "Cannot instantiate parameterized aspect %s at the top level.", + starlarkAspect.getName()); + throw new AspectCreationException( + msg, + new LabelCause( + starlarkFileLabel, + createDetailedCode(msg, Code.PARAMETERIZED_TOP_LEVEL_ASPECT_INVALID))); + } + } catch (AspectCreationException e) { + throw new LoadStarlarkAspectFunctionException(e); } + SkyKey aspectKey = aspectLoadingKey.toAspectKey(starlarkAspect.getAspectClass()); - return new TopLevelAspectsValue(result); + return env.getValue(aspectKey); } @Nullable @@ -97,112 +77,18 @@ public String extractTag(SkyKey skyKey) { return null; } - @Nullable - private static ImmutableList getTopLevelAspects( - Environment env, ImmutableList topLevelAspectsClasses) - throws InterruptedException, EvalException { - AspectsListBuilder aspectsList = new AspectsListBuilder(); - - ImmutableList.Builder aspectLoadingKeys = ImmutableList.builder(); - for (AspectClass aspectClass : topLevelAspectsClasses) { - if (aspectClass instanceof StarlarkAspectClass) { - aspectLoadingKeys.add( - LoadStarlarkAspectFunction.createStarlarkAspectLoadingKey( - (StarlarkAspectClass) aspectClass)); - } - } - - Map loadedAspects = env.getValues(aspectLoadingKeys.build()); - if (env.valuesMissing()) { - return null; - } - - for (AspectClass aspectClass : topLevelAspectsClasses) { - if (aspectClass instanceof StarlarkAspectClass) { - StarlarkAspectLoadingValue aspectLoadingValue = - (StarlarkAspectLoadingValue) - loadedAspects.get( - LoadStarlarkAspectFunction.createStarlarkAspectLoadingKey( - (StarlarkAspectClass) aspectClass)); - StarlarkAspect starlarkAspect = aspectLoadingValue.getAspect(); - starlarkAspect.attachToAspectsList( - /** baseAspectName= */ - null, - aspectsList, - /** inheritedRequiredProviders= */ - ImmutableList.of(), - /** inheritedAttributeAspects= */ - ImmutableList.of()); - } else { - aspectsList.addAspect((NativeAspectClass) aspectClass); - } - } - - return aspectsList.buildAspects(); - } - - private static ImmutableList getTopLevelAspectsKeys( - AspectCollection aspectCollection, ConfiguredTargetKey topLevelTargetKey) { - Map result = new HashMap<>(); - for (AspectCollection.AspectDeps aspectDeps : aspectCollection.getUsedAspects()) { - buildAspectKey(aspectDeps, result, topLevelTargetKey); - } - return ImmutableList.copyOf(result.values()); - } - - private static AspectKey buildAspectKey( - AspectCollection.AspectDeps aspectDeps, - Map result, - ConfiguredTargetKey topLevelTargetKey) { - if (result.containsKey(aspectDeps.getAspect())) { - return result.get(aspectDeps.getAspect()); - } - - ImmutableList.Builder dependentAspects = ImmutableList.builder(); - for (AspectCollection.AspectDeps path : aspectDeps.getUsedAspects()) { - dependentAspects.add(buildAspectKey(path, result, topLevelTargetKey)); - } - - AspectKey aspectKey = - AspectValueKey.createAspectKey( - aspectDeps.getAspect(), - dependentAspects.build(), - topLevelTargetKey.getConfigurationKey(), - topLevelTargetKey); - result.put(aspectKey.getAspectDescriptor(), aspectKey); - return aspectKey; + private static DetailedExitCode createDetailedCode(String msg, Code code) { + return DetailedExitCode.of( + FailureDetail.newBuilder() + .setMessage(msg) + .setAnalysis(Analysis.newBuilder().setCode(code)) + .build()); } /** Exceptions thrown from ToplevelStarlarkAspectFunction. */ - public static class TopLevelStarlarkAspectFunctionException extends SkyFunctionException { - public TopLevelStarlarkAspectFunctionException(AspectCreationException cause) { + public static class LoadStarlarkAspectFunctionException extends SkyFunctionException { + public LoadStarlarkAspectFunctionException(AspectCreationException cause) { super(cause, Transience.PERSISTENT); } } - - /** - * SkyValue for {@code TopLevelAspectsKey} wraps a list of the {@code AspectValue} of the top - * level aspects applied on the same top level target. - */ - public static class TopLevelAspectsValue implements ActionLookupValue { - private final Map topLevelAspectsMap; - - public TopLevelAspectsValue(Map topLevelAspectsMap) { - this.topLevelAspectsMap = topLevelAspectsMap; - } - - public ImmutableList getTopLevelAspectsValues() { - return ImmutableList.copyOf(topLevelAspectsMap.values()); - } - - public SkyValue get(SkyKey skyKey) { - return topLevelAspectsMap.get(skyKey); - } - - @Override - public ImmutableList getActions() { - // return topLevelAspectsMap.values().stream(). - return ImmutableList.of(); - } - } } 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 e6e59298bc3152..e39c708f550115 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 @@ -875,25 +875,20 @@ public void aspectApplyingToSourceFilesIgnored() throws Exception { } @Test - public void duplicateAspectsFailed() throws Exception { + public void duplicateAspectsDeduped() throws Exception { AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles(); setRulesAndAspectsAvailableInTests(ImmutableList.of(aspectApplyingToFiles), ImmutableList.of()); pkg("a", "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])"); - reporter.removeHandler(failFastHandler); - AssertionError exception = - assertThrows( - AssertionError.class, - () -> - update( - new EventBus(), - defaultFlags(), - ImmutableList.of( - aspectApplyingToFiles.getName(), aspectApplyingToFiles.getName()), - "//a:x_deploy.jar")); - - assertThat(exception) - .hasMessageThat() - .containsMatch("Aspect AspectApplyingToFiles has already been added"); + AnalysisResult analysisResult = + update( + new EventBus(), + defaultFlags(), + ImmutableList.of(aspectApplyingToFiles.getName(), aspectApplyingToFiles.getName()), + "//a:x_deploy.jar"); + ConfiguredAspect aspect = Iterables.getOnlyElement(analysisResult.getAspectsMap().values()); + AspectApplyingToFiles.Provider provider = + aspect.getProvider(AspectApplyingToFiles.Provider.class); + assertThat(provider.getLabel()).isEqualTo(Label.parseAbsoluteUnchecked("//a:x_deploy.jar")); } @Test diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TargetCycleReporterTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/TargetCycleReporterTest.java index f491beac037b4e..17ec74063c813f 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/TargetCycleReporterTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/TargetCycleReporterTest.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.StarlarkAspectClass; import com.google.devtools.build.skyframe.CycleInfo; import com.google.devtools.build.skyframe.SkyKey; import org.junit.Test; @@ -71,12 +70,12 @@ public void loadingPhaseCycleWithDifferentTopLevelKeyTypes() throws Exception { + "target //foo:c"); SkyKey starlarkAspectKey = - AspectValueKey.createTopLevelAspectsKey( - ImmutableList.of( - new StarlarkAspectClass( - Label.parseAbsoluteUnchecked("//foo:b"), "my Starlark key")), + AspectValueKey.createStarlarkAspectKey( Label.parseAbsoluteUnchecked("//foo:a"), - targetConfig); + targetConfig, + targetConfig, + Label.parseAbsoluteUnchecked("//foo:b"), + "my Starlark key"); assertThat(cycleReporter.getAdditionalMessageAboutCycle(reporter, starlarkAspectKey, cycle)) .contains( "The cycle is caused by a visibility edge from //foo:b to the non-package_group " diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkDefinedAspectsTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkDefinedAspectsTest.java index 375e8a8b40caea..e74bb4d67e0ca2 100644 --- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkDefinedAspectsTest.java +++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkDefinedAspectsTest.java @@ -40,7 +40,6 @@ import com.google.devtools.build.lib.collect.nestedset.Depset; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.AspectDefinition; -import com.google.devtools.build.lib.packages.StarlarkAspectClass; import com.google.devtools.build.lib.packages.StarlarkProvider; import com.google.devtools.build.lib.packages.StructImpl; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; @@ -53,7 +52,6 @@ import com.google.devtools.build.lib.vfs.Path; import java.util.ArrayList; import java.util.List; -import java.util.Map; import net.starlark.java.eval.Sequence; import net.starlark.java.eval.Starlark; import net.starlark.java.eval.StarlarkInt; @@ -4197,1287 +4195,6 @@ public void testAspectRequiresAspect_withRequiredAspectProvidersNotFound() throw assertThat(aspectBResult).isEqualTo("aspect_b on target //test:dep_target cannot find prov_b"); } - /** - * --aspects = a3, a2, a1: aspect a1 requires provider a1p, aspect a2 requires provider a2p and - * provides a1p and aspect a3 provides a2p. The three aspects will propagate together but aspect - * a1 will only see a1p and aspect a2 will only see a2p. - */ - @Test - public void testTopLevelAspectOnAspect_stackOfAspects() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a2p = provider()", - "a1_result = provider()", - "a2_result = provider()", - "a3_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " if a2p in target:", - " result += ' and sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' and cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " result = 'aspect a2 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " if a2p in target:", - " result += ' and sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' and cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a2_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a2_result(value = complete_result), a1p(value = 'a1p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - " required_aspect_providers = [a2p],", - ")", - "", - "def _a3_impl(target, ctx):", - " result = 'aspect a3 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " if a2p in target:", - " result += ' and sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' and cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a3_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a3_result(value = complete_result), a2p(value = 'a2p_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['dep'],", - " provides = [a2p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a3 = getConfiguredAspect(configuredAspects, "a3"); - assertThat(a3).isNotNull(); - StarlarkProvider.Key a3Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a3_result"); - StructImpl a3ResultProvider = (StructImpl) a3.get(a3Result); - assertThat((Sequence) a3ResultProvider.getValue("value")) - .containsExactly( - "aspect a3 on target //test:dep_target cannot see a1p and cannot see a2p", - "aspect a3 on target //test:main cannot see a1p and cannot see a2p"); - - ConfiguredAspect a2 = getConfiguredAspect(configuredAspects, "a2"); - assertThat(a2).isNotNull(); - StarlarkProvider.Key a2Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a2_result"); - StructImpl a2ResultProvider = (StructImpl) a2.get(a2Result); - assertThat((Sequence) a2ResultProvider.getValue("value")) - .containsExactly( - "aspect a2 on target //test:dep_target cannot see a1p and sees a2p = a2p_val", - "aspect a2 on target //test:main cannot see a1p and sees a2p = a2p_val"); - - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a1p = a1p_val and cannot see a2p", - "aspect a1 on target //test:main sees a1p = a1p_val and cannot see a2p"); - } - - /** - * --aspects = a3, a2, a1: aspect a1 requires provider a1p, aspect a2 and aspect a3 provides a1p. - * This should fail because provider a1p is provided twice. - */ - @Test - public void testTopLevelAspectOnAspect_requiredProviderProvidedTwiceFailed() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a1p(value = 'a1p_a2_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _a3_impl(target, ctx):", - " return [a1p(value = 'a1p_a3_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - reporter.removeHandler(failFastHandler); - - // The call to `update` does not throw an exception when "--keep_going" is passed in the - // WithKeepGoing test suite. Otherwise, it throws ViewCreationFailedException. - if (keepGoing()) { - AnalysisResult result = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - assertThat(result.hasError()).isTrue(); - } else { - assertThrows( - ViewCreationFailedException.class, - () -> - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main")); - } - assertContainsEvent("ERROR /workspace/test/BUILD:2:12: Provider a1p provided twice"); - } - - /** - * --aspects = a3, a1, a2: aspect a1 requires provider a1p, aspect a2 and aspect a3 provide a1p. - * a1 should see the value provided by a3 because a3 is listed before a1. - */ - @Test - public void testTopLevelAspectOnAspect_requiredProviderProvidedTwicePassed() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a1p(value = 'a1p_a2_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _a3_impl(target, ctx):", - " return [a1p(value = 'a1p_a3_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a1", "test/defs.bzl%a2"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a1p = a1p_a3_val", - "aspect a1 on target //test:main sees a1p = a1p_a3_val"); - } - - @Test - public void testTopLevelAspectOnAspect_requiredProviderNotProvided() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a2p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a2p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update(ImmutableList.of("test/defs.bzl%a2", "test/defs.bzl%a1"), "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target cannot see a1p", - "aspect a1 on target //test:main cannot see a1p"); - } - - /** - * --aspects = a1, a2: aspect a1 requires provider a1p, aspect a2 provides a1p but it was listed - * after a1 so aspect a1 cannot see a1p value. - */ - @Test - public void testTopLevelAspectOnAspect_requiredProviderProvidedAfterTheAspect() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a1p(value = 'a1p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update(ImmutableList.of("test/defs.bzl%a1", "test/defs.bzl%a2"), "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target cannot see a1p", - "aspect a1 on target //test:main cannot see a1p"); - } - - /** - * --aspects = a2, a1: aspect a1 requires provider a1p, aspect a2 provides a1p. But aspect a2 - * propagates along different attr_aspects from a1 so a1 cannot get a1p on all dependency targets. - */ - @Test - public void testTopLevelAspectOnAspect_differentAttrAspects() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result += ctx.rule.attr.dep[a1_result].value", - " if ctx.rule.attr.extra_dep:", - " complete_result += ctx.rule.attr.extra_dep[a1_result].value", - " complete_result += [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep', 'extra_dep'],", - " required_aspect_providers = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a1p(value = 'a1p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " provides = [a1p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " 'extra_dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - " extra_dep = ':extra_dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")", - "simple_rule(", - " name = 'extra_dep_target',", - ")"); - - AnalysisResult analysisResult = - update(ImmutableList.of("test/defs.bzl%a2", "test/defs.bzl%a1"), "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a1p = a1p_val", - "aspect a1 on target //test:extra_dep_target cannot see a1p", - "aspect a1 on target //test:main sees a1p = a1p_val"); - } - - /** - * --aspects = a2, a1: aspect a1 requires provider a1p, aspect a2 provides a1p. But aspect a2 - * propagates along different required_providers from a1 so a1 cannot get a1p on all dependency - * targets. - */ - @Test - public void testTopLevelAspectOnAspect_differentRequiredRuleProviders() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a1_result = provider()", - "rule_prov_a = provider()", - "rule_prov_b = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " complete_result = []", - " if hasattr(ctx.rule.attr, 'deps'):", - " for dep in ctx.rule.attr.deps:", - " complete_result += dep[a1_result].value", - " complete_result += [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [a1p],", - " required_providers = [[rule_prov_a], [rule_prov_b]],", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a1p(value = 'a1p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a1p],", - " required_providers = [rule_prov_a],", - ")", - "", - "def _main_rule_impl(ctx):", - " return [rule_prov_a(), rule_prov_b()]", - "main_rule = rule(", - " implementation = _main_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - ")", - "", - "def _rule_with_prov_a_impl(ctx):", - " return [rule_prov_a()]", - "rule_with_prov_a = rule(", - " implementation = _rule_with_prov_a_impl,", - " provides = [rule_prov_a]", - ")", - "", - "def _rule_with_prov_b_impl(ctx):", - " return [rule_prov_b()]", - "rule_with_prov_b = rule(", - " implementation = _rule_with_prov_b_impl,", - " provides = [rule_prov_b]", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'main_rule', 'rule_with_prov_a', 'rule_with_prov_b')", - "main_rule(", - " name = 'main',", - " deps = [':target_with_prov_a', ':target_with_prov_b'],", - ")", - "rule_with_prov_a(", - " name = 'target_with_prov_a',", - ")", - "rule_with_prov_b(", - " name = 'target_with_prov_b',", - ")"); - - AnalysisResult analysisResult = - update(ImmutableList.of("test/defs.bzl%a2", "test/defs.bzl%a1"), "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:target_with_prov_a sees a1p = a1p_val", - "aspect a1 on target //test:target_with_prov_b cannot see a1p", - "aspect a1 on target //test:main sees a1p = a1p_val"); - } - - /** - * --aspects = a3, a2, a1: both aspects a1 and a2 require provider a3p, aspect a3 provides a3p. a1 - * and a2 should be able to read a3p. - */ - @Test - public void testTopLevelAspectOnAspect_providerRequiredByMultipleAspects() throws Exception { - scratch.file( - "test/defs.bzl", - "a3p = provider()", - "a1_result = provider()", - "a2_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a3p in target:", - " result += ' sees a3p = {}'.format(target[a3p].value)", - " else:", - " result += ' cannot see a3p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a1_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a3p]", - ")", - "", - "def _a2_impl(target, ctx):", - " result = 'aspect a2 on target {}'.format(target.label)", - " if a3p in target:", - " result += ' sees a3p = {}'.format(target[a3p].value)", - " else:", - " result += ' cannot see a3p'", - " complete_result = []", - " if ctx.rule.attr.dep:", - " complete_result = ctx.rule.attr.dep[a2_result].value + [result]", - " else:", - " complete_result = [result]", - " return [a2_result(value = complete_result)]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['dep'],", - " required_aspect_providers = [a3p]", - ")", - "", - "def _a3_impl(target, ctx):", - " return [a3p(value = 'a3p_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['dep'],", - " provides = [a3p],", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'dep': attr.label(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " dep = ':dep_target',", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a2 = getConfiguredAspect(configuredAspects, "a2"); - assertThat(a2).isNotNull(); - StarlarkProvider.Key a2Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a2_result"); - StructImpl a2ResultProvider = (StructImpl) a2.get(a2Result); - assertThat((Sequence) a2ResultProvider.getValue("value")) - .containsExactly( - "aspect a2 on target //test:dep_target sees a3p = a3p_val", - "aspect a2 on target //test:main sees a3p = a3p_val"); - - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a3p = a3p_val", - "aspect a1 on target //test:main sees a3p = a3p_val"); - } - - /** - * --aspects = a1, a2, a3: aspect a3 requires a1p and a2p, a1 provides a1p and a2 provides a2p. - * - *

top level target (main) has two dependencies t1 and t2. Aspects a1 and a3 can propagate to - * t1 and aspects a2 and a3 can propagate to t2. Both t1 and t2 have t0 as dependency, aspect a3 - * will run twice on t0 once with aspects path (a1, a3) and the other with (a2, a3). - */ - @Test - public void testTopLevelAspectOnAspect_diamondCase() throws Exception { - scratch.file( - "test/defs.bzl", - "a1p = provider()", - "a2p = provider()", - "a3_result = provider()", - "", - "r1p = provider()", - "r2p = provider()", - "", - "def _a1_impl(target, ctx):", - " return [a1p(value = 'a1p_val')]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_providers = [r1p],", - " provides = [a1p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " required_providers = [r2p],", - " provides = [a2p]", - ")", - "", - "def _a3_impl(target, ctx):", - " result = 'aspect a3 on target {}'.format(target.label)", - " if a1p in target:", - " result += ' sees a1p = {}'.format(target[a1p].value)", - " else:", - " result += ' cannot see a1p'", - " if a2p in target:", - " result += ' and sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' and cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a3_result].value)", - " complete_result.append(result)", - " return [a3_result(value = complete_result)]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [[a1p], [a2p]],", - ")", - "", - "def _r0_impl(ctx):", - " return [r1p(), r2p()]", - "r0 = rule(", - " implementation = _r0_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - " provides = [r1p, r2p]", - ")", - "def _r1_impl(ctx):", - " return [r1p()]", - "r1 = rule(", - " implementation = _r1_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - " provides = [r1p]", - ")", - "def _r2_impl(ctx):", - " return [r2p()]", - "r2 = rule(", - " implementation = _r2_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - " provides = [r2p]", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'r0', 'r1', 'r2')", - "r0(", - " name = 'main',", - " deps = [':t1', ':t2'],", - ")", - "r1(", - " name = 't1',", - " deps = [':t0'],", - ")", - "r2(", - " name = 't2',", - " deps = [':t0'],", - ")", - "r0(", - " name = 't0',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a1", "test/defs.bzl%a2", "test/defs.bzl%a3"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a3 = getConfiguredAspect(configuredAspects, "a3"); - assertThat(a3).isNotNull(); - StarlarkProvider.Key a3Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a3_result"); - StructImpl a3ResultProvider = (StructImpl) a3.get(a3Result); - assertThat((Sequence) a3ResultProvider.getValue("value")) - .containsExactly( - "aspect a3 on target //test:t0 sees a1p = a1p_val and cannot see a2p", - "aspect a3 on target //test:t0 cannot see a1p and sees a2p = a2p_val", - "aspect a3 on target //test:t1 sees a1p = a1p_val and cannot see a2p", - "aspect a3 on target //test:t2 cannot see a1p and sees a2p = a2p_val", - "aspect a3 on target //test:main sees a1p = a1p_val and sees a2p = a2p_val"); - } - - @Test - public void testTopLevelAspectOnAspect_duplicateAspectsFailed() throws Exception { - scratch.file( - "test/defs.bzl", - "a2p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a2p in target:", - " result += ' sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a1_result].value)", - " complete_result.append(result)", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [a2p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a2p]", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " deps = [':dep_target'],", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - reporter.removeHandler(failFastHandler); - - // The call to `update` does not throw an exception when "--keep_going" is passed in the - // WithKeepGoing test suite. Otherwise, it throws ViewCreationFailedException. - if (keepGoing()) { - AnalysisResult result = - update( - ImmutableList.of("test/defs.bzl%a1", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - assertThat(result.hasError()).isTrue(); - } else { - assertThrows( - ViewCreationFailedException.class, - () -> - update( - ImmutableList.of("test/defs.bzl%a1", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main")); - } - assertContainsEvent("aspect //test:defs.bzl%a1 added more than once"); - } - - /** - * --aspects = a1 requires provider a2p provided by aspect a2. a1 is applied on top level target - * `main` whose rule propagates aspect a2 to its `deps`. So a1 on `main` cannot see a2p but it can - * see a2p on `main` deps. - */ - @Test - public void testTopLevelAspectOnAspect_requiredAspectProviderOnlyAvailableOnDep() - throws Exception { - scratch.file( - "test/defs.bzl", - "a2p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a2p in target:", - " result += ' sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a1_result].value)", - " complete_result.append(result)", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [a2p]", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a2p]", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(aspects=[a2]),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " deps = [':dep_target'],", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = update(ImmutableList.of("test/defs.bzl%a1"), "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a2p = a2p_val", - "aspect a1 on target //test:main cannot see a2p"); - } - - @Test - public void testTopLevelAspectOnAspect_multipleTopLevelTargets() throws Exception { - scratch.file( - "test/defs.bzl", - "a2p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a2p in target:", - " result += ' sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' cannot see a2p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a1_result].value)", - " complete_result.append(result)", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [a2p],", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a2p]", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 't1',", - ")", - "simple_rule(", - " name = 't2',", - ")"); - - AnalysisResult analysisResult = - update(ImmutableList.of("test/defs.bzl%a2", "test/defs.bzl%a1"), "//test:t2", "//test:t1"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1Ont1 = getConfiguredAspect(configuredAspects, "a1", "t1"); - assertThat(a1Ont1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1Ont1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly("aspect a1 on target //test:t1 sees a2p = a2p_val"); - - ConfiguredAspect a1Ont2 = getConfiguredAspect(configuredAspects, "a1", "t2"); - assertThat(a1Ont2).isNotNull(); - a1ResultProvider = (StructImpl) a1Ont2.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly("aspect a1 on target //test:t2 sees a2p = a2p_val"); - } - - @Test - public void testTopLevelAspectOnAspect_multipleRequiredProviders() throws Exception { - scratch.file( - "test/defs.bzl", - "a2p = provider()", - "a3p = provider()", - "a1_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a2p in target:", - " result += ' sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' cannot see a2p'", - " if a3p in target:", - " result += ' and sees a3p = {}'.format(target[a3p].value)", - " else:", - " result += ' and cannot see a3p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a1_result].value)", - " complete_result.append(result)", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [[a2p], [a3p]],", - ")", - "", - "def _a2_impl(target, ctx):", - " return [a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a2p]", - ")", - "", - "def _a3_impl(target, ctx):", - " return [a3p(value = 'a3p_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['deps'],", - " provides = [a3p]", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " deps = [':dep_target'],", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a2p = a2p_val and sees a3p = a3p_val", - "aspect a1 on target //test:main sees a2p = a2p_val and sees a3p = a3p_val"); - } - - @Test - public void testTopLevelAspectOnAspect_multipleRequiredProviders2() throws Exception { - scratch.file( - "test/defs.bzl", - "a2p = provider()", - "a3p = provider()", - "a1_result = provider()", - "a2_result = provider()", - "", - "def _a1_impl(target, ctx):", - " result = 'aspect a1 on target {}'.format(target.label)", - " if a2p in target:", - " result += ' sees a2p = {}'.format(target[a2p].value)", - " else:", - " result += ' cannot see a2p'", - " if a3p in target:", - " result += ' and sees a3p = {}'.format(target[a3p].value)", - " else:", - " result += ' and cannot see a3p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a1_result].value)", - " complete_result.append(result)", - " return [a1_result(value = complete_result)]", - "a1 = aspect(", - " implementation = _a1_impl,", - " attr_aspects = ['deps'],", - " required_aspect_providers = [[a2p], [a3p]],", - ")", - "", - "def _a2_impl(target, ctx):", - " result = 'aspect a2 on target {}'.format(target.label)", - " if a3p in target:", - " result += ' sees a3p = {}'.format(target[a3p].value)", - " else:", - " result += ' cannot see a3p'", - " complete_result = []", - " if ctx.rule.attr.deps:", - " for dep in ctx.rule.attr.deps:", - " complete_result.extend(dep[a2_result].value)", - " complete_result.append(result)", - " return [a2_result(value = complete_result), a2p(value = 'a2p_val')]", - "a2 = aspect(", - " implementation = _a2_impl,", - " attr_aspects = ['deps'],", - " provides = [a2p],", - " required_aspect_providers = [a3p]", - ")", - "", - "def _a3_impl(target, ctx):", - " return [a3p(value = 'a3p_val')]", - "a3 = aspect(", - " implementation = _a3_impl,", - " attr_aspects = ['deps'],", - " provides = [a3p]", - ")", - "", - "def _simple_rule_impl(ctx):", - " pass", - "simple_rule = rule(", - " implementation = _simple_rule_impl,", - " attrs = {", - " 'deps': attr.label_list(),", - " },", - ")"); - scratch.file( - "test/BUILD", - "load('//test:defs.bzl', 'simple_rule')", - "simple_rule(", - " name = 'main',", - " deps = [':dep_target'],", - ")", - "simple_rule(", - " name = 'dep_target',", - ")"); - - AnalysisResult analysisResult = - update( - ImmutableList.of("test/defs.bzl%a3", "test/defs.bzl%a2", "test/defs.bzl%a1"), - "//test:main"); - - Map configuredAspects = analysisResult.getAspectsMap(); - ConfiguredAspect a1 = getConfiguredAspect(configuredAspects, "a1"); - assertThat(a1).isNotNull(); - StarlarkProvider.Key a1Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a1_result"); - StructImpl a1ResultProvider = (StructImpl) a1.get(a1Result); - assertThat((Sequence) a1ResultProvider.getValue("value")) - .containsExactly( - "aspect a1 on target //test:dep_target sees a2p = a2p_val and sees a3p = a3p_val", - "aspect a1 on target //test:main sees a2p = a2p_val and sees a3p = a3p_val"); - - ConfiguredAspect a2 = getConfiguredAspect(configuredAspects, "a2"); - assertThat(a2).isNotNull(); - StarlarkProvider.Key a2Result = - new StarlarkProvider.Key( - Label.parseAbsolute("//test:defs.bzl", ImmutableMap.of()), "a2_result"); - StructImpl a2ResultProvider = (StructImpl) a2.get(a2Result); - assertThat((Sequence) a2ResultProvider.getValue("value")) - .containsExactly( - "aspect a2 on target //test:dep_target sees a3p = a3p_val", - "aspect a2 on target //test:main sees a3p = a3p_val"); - } - - private ConfiguredAspect getConfiguredAspect( - Map aspectsMap, String aspectName) { - for (Map.Entry entry : aspectsMap.entrySet()) { - String aspectExportedName = - ((StarlarkAspectClass) entry.getKey().getAspectClass()).getExportedName(); - if (aspectExportedName.equals(aspectName)) { - return entry.getValue(); - } - } - return null; - } - - private ConfiguredAspect getConfiguredAspect( - Map aspectsMap, String aspectName, String targetName) { - for (Map.Entry entry : aspectsMap.entrySet()) { - String aspectExportedName = - ((StarlarkAspectClass) entry.getKey().getAspectClass()).getExportedName(); - String target = entry.getKey().getLabel().getName(); - if (aspectExportedName.equals(aspectName) && target.equals(targetName)) { - return entry.getValue(); - } - } - return null; - } - /** StarlarkAspectTest with "keep going" flag */ @RunWith(JUnit4.class) public static final class WithKeepGoing extends StarlarkDefinedAspectsTest {