Reduce parameters in `RuleContext` and its builder in favor of using enclosing objects `AnalysisEnvironment` and `ConfiguredRuleClassProvider`.
Inspired by `TODO(bazel-team): I get the feeling we could delete much of the boilerplate by replacing some of these fields with a RuleClassProvider -- both in the builder and in the RuleContext itself.` (written by brandjon@). I'm working on a change that will need yet another `ConfiguredRuleClassProvider` field in `RuleContext`, so this will be helpful.
Reduce `RuleContext.Builder` constructor parameters to only those that are needed up-front.
PiperOrigin-RevId: 401338523
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index fe2e141..8f1baf4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.analysis;
-import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.devtools.build.lib.packages.ExecGroup.DEFAULT_EXEC_GROUP_NAME;
@@ -51,11 +50,9 @@
import com.google.devtools.build.lib.analysis.config.ConfigConditions;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.analysis.config.Fragment;
-import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.analysis.config.FragmentCollection;
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
-import com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics;
import com.google.devtools.build.lib.analysis.constraints.RuleContextConstraintSemantics;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
@@ -66,7 +63,6 @@
import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.packages.Attribute;
@@ -131,10 +127,6 @@
public final class RuleContext extends TargetContext
implements ActionConstructionContext, ActionRegistry, RuleErrorConsumer, AutoCloseable {
- public boolean isAllowTagsPropagation() {
- return starlarkSemantics.getBool(BuildLanguageOptions.EXPERIMENTAL_ALLOW_TAGS_PROPAGATION);
- }
-
/** Custom dependency validation logic. */
public interface PrerequisiteValidator {
/**
@@ -168,11 +160,10 @@
private final String ruleClassNameForLogging;
private final BuildConfiguration hostConfiguration;
private final ConfigurationFragmentPolicy configurationFragmentPolicy;
- private final FragmentClassSet universalFragments;
+ private final ConfiguredRuleClassProvider ruleClassProvider;
private final RuleErrorConsumer reporter;
@Nullable private final ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
private final ExecGroupCollection execGroupCollection;
- private final ConstraintSemantics<RuleContext> constraintSemantics;
@Nullable private final RequiredConfigFragmentsProvider requiredConfigFragments;
private final List<Expander> makeVariableExpanders = new ArrayList<>();
@@ -185,13 +176,6 @@
private transient ConfigurationMakeVariableContext configurationMakeVariableContext = null;
/**
- * The StarlarkSemantics to use for rule analysis. Should be the same as what's reported by the
- * AnalysisEnvironment, but saving it here is more convenient since {@link
- * AnalysisEnvironment#getStarlarkSemantics()} can throw InterruptedException.
- */
- private final StarlarkSemantics starlarkSemantics;
-
- /**
* Thread used for any Starlark evaluation during analysis, e.g. rule implementation function for
* a Starlark-defined rule, or Starlarkified helper logic for native rules that have been
* partially migrated to {@code @_builtins}.
@@ -211,18 +195,7 @@
Builder builder,
AttributeMap attributes,
ListMultimap<String, ConfiguredTargetAndData> targetMap,
- ImmutableMap<Label, ConfigMatchingProvider> configConditions,
- FragmentClassSet universalFragments,
- String ruleClassNameForLogging,
- ActionLookupKey actionLookupKey,
- ImmutableMap<String, Attribute> aspectAttributes,
- @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
- ExecGroupCollection execGroupCollection,
- ConstraintSemantics<RuleContext> constraintSemantics,
- @Nullable RequiredConfigFragmentsProvider requiredConfigFragments,
- String toolsRepository,
- StarlarkSemantics starlarkSemantics,
- Mutability mutability) {
+ ExecGroupCollection execGroupCollection) {
super(
builder.env,
builder.target.getAssociatedRule(),
@@ -231,28 +204,25 @@
builder.visibility);
this.rule = builder.target.getAssociatedRule();
this.aspects = builder.aspects;
- this.aspectDescriptors =
- builder.aspects.stream().map(Aspect::getDescriptor).collect(toImmutableList());
+ this.aspectDescriptors = aspects.stream().map(Aspect::getDescriptor).collect(toImmutableList());
this.configurationFragmentPolicy = builder.configurationFragmentPolicy;
- this.universalFragments = universalFragments;
+ this.ruleClassProvider = builder.ruleClassProvider;
this.targetMap = targetMap;
- this.configConditions = configConditions;
- this.attributes = new AspectAwareAttributeMapper(attributes, aspectAttributes);
+ this.configConditions = builder.configConditions.asProviders();
+ this.attributes = new AspectAwareAttributeMapper(attributes, builder.aspectAttributes);
Set<String> allEnabledFeatures = new HashSet<>();
Set<String> allDisabledFeatures = new HashSet<>();
getAllFeatures(allEnabledFeatures, allDisabledFeatures);
this.enabledFeatures = ImmutableSortedSet.copyOf(allEnabledFeatures);
this.disabledFeatures = ImmutableSortedSet.copyOf(allDisabledFeatures);
- this.ruleClassNameForLogging = ruleClassNameForLogging;
+ this.ruleClassNameForLogging = builder.getRuleClassNameForLogging();
this.hostConfiguration = builder.hostConfiguration;
- this.actionOwnerSymbolGenerator = new SymbolGenerator<>(actionLookupKey);
- reporter = builder.reporter;
- this.toolchainContexts = toolchainContexts;
+ this.actionOwnerSymbolGenerator = new SymbolGenerator<>(builder.actionOwnerSymbol);
+ this.reporter = builder.reporter;
+ this.toolchainContexts = builder.toolchainContexts;
this.execGroupCollection = execGroupCollection;
- this.constraintSemantics = constraintSemantics;
- this.requiredConfigFragments = requiredConfigFragments;
- this.starlarkSemantics = starlarkSemantics;
- this.starlarkThread = createStarlarkThread(toolsRepository, mutability); // uses above state
+ this.requiredConfigFragments = builder.requiredConfigFragments;
+ this.starlarkThread = createStarlarkThread(builder.mutability); // uses above state
}
private void getAllFeatures(Set<String> allEnabledFeatures, Set<String> allDisabledFeatures) {
@@ -294,6 +264,12 @@
}
}
+ public boolean isAllowTagsPropagation() {
+ return getAnalysisEnvironment()
+ .getStarlarkSemantics()
+ .getBool(BuildLanguageOptions.EXPERIMENTAL_ALLOW_TAGS_PROPAGATION);
+ }
+
public RepositoryName getRepository() {
return rule.getRepository();
}
@@ -527,7 +503,7 @@
public <T extends Fragment> boolean isLegalFragment(
Class<T> fragment, ConfigurationTransition transition) {
- return universalFragments.contains(fragment)
+ return ruleClassProvider.getFragmentRegistry().getUniversalFragments().contains(fragment)
|| configurationFragmentPolicy.isLegalConfigurationFragment(fragment, transition);
}
@@ -1143,17 +1119,13 @@
return configurationMakeVariableContext;
}
- public StarlarkSemantics getStarlarkSemantics() {
- return starlarkSemantics;
- }
-
- private StarlarkThread createStarlarkThread(String toolsRepository, Mutability mutability) {
+ private StarlarkThread createStarlarkThread(Mutability mutability) {
AnalysisEnvironment env = getAnalysisEnvironment();
- StarlarkThread thread = new StarlarkThread(mutability, starlarkSemantics);
+ StarlarkThread thread = new StarlarkThread(mutability, env.getStarlarkSemantics());
thread.setPrintHandler(Event.makeDebugPrintHandler(env.getEventHandler()));
new BazelStarlarkContext(
BazelStarlarkContext.Phase.ANALYSIS,
- toolsRepository,
+ ruleClassProvider.getToolsRepository(),
/*fragmentNameToClass=*/ null,
getTarget().getPackage().getRepositoryMapping(),
/*convertedLabelsInPackage=*/ new HashMap<>(),
@@ -1265,8 +1237,8 @@
return toolchainContexts.getTargetPlatform().constraints().hasConstraintValue(constraintValue);
}
- public ConstraintSemantics<RuleContext> getConstraintSemantics() {
- return constraintSemantics;
+ public ConfiguredRuleClassProvider getRuleClassProvider() {
+ return ruleClassProvider;
}
/** Returns the configuration fragments this rule uses. */
@@ -1643,30 +1615,24 @@
}
/** Builder class for a RuleContext. */
- // TODO(bazel-team): I get the feeling we could delete much of the boilerplate by replacing some
- // of these fields with a RuleClassProvider -- both in the builder and in the RuleContext itself.
public static final class Builder implements RuleErrorConsumer {
private final AnalysisEnvironment env;
private final Target target;
- private final ConfigurationFragmentPolicy configurationFragmentPolicy;
- private FragmentClassSet universalFragments;
+ private final ImmutableList<Aspect> aspects;
private final BuildConfiguration configuration;
- private final BuildConfiguration hostConfiguration;
- private final ActionLookupKey actionOwnerSymbol;
- private final PrerequisiteValidator prerequisiteValidator;
private final RuleErrorConsumer reporter;
+ private ConfiguredRuleClassProvider ruleClassProvider;
+ private BuildConfiguration hostConfiguration;
+ private ConfigurationFragmentPolicy configurationFragmentPolicy;
+ private ActionLookupKey actionOwnerSymbol;
private OrderedSetMultimap<Attribute, ConfiguredTargetAndData> prerequisiteMap;
private ConfigConditions configConditions;
- private String toolsRepository;
- private StarlarkSemantics starlarkSemantics;
private Mutability mutability;
private NestedSet<PackageGroupContents> visibility;
- private ImmutableMap<String, Attribute> aspectAttributes;
- private final ImmutableList<Aspect> aspects;
+ private ImmutableMap<String, Attribute> aspectAttributes = ImmutableMap.of();
private ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
private ExecGroupCollection.Builder execGroupCollectionBuilder;
private ImmutableMap<String, String> rawExecProperties;
- private ConstraintSemantics<RuleContext> constraintSemantics;
@Nullable private RequiredConfigFragmentsProvider requiredConfigFragments;
@VisibleForTesting
@@ -1674,19 +1640,11 @@
AnalysisEnvironment env,
Target target,
ImmutableList<Aspect> aspects,
- BuildConfiguration configuration,
- BuildConfiguration hostConfiguration,
- PrerequisiteValidator prerequisiteValidator,
- ConfigurationFragmentPolicy configurationFragmentPolicy,
- ActionLookupKey actionOwnerSymbol) {
+ BuildConfiguration configuration) {
this.env = Preconditions.checkNotNull(env);
this.target = Preconditions.checkNotNull(target);
- this.aspects = aspects;
- this.configurationFragmentPolicy = Preconditions.checkNotNull(configurationFragmentPolicy);
+ this.aspects = Preconditions.checkNotNull(aspects);
this.configuration = Preconditions.checkNotNull(configuration);
- this.hostConfiguration = Preconditions.checkNotNull(hostConfiguration);
- this.prerequisiteValidator = prerequisiteValidator;
- this.actionOwnerSymbol = Preconditions.checkNotNull(actionOwnerSymbol);
if (configuration.allowAnalysisFailures()) {
reporter = new SuppressingErrorReporter();
} else {
@@ -1698,13 +1656,14 @@
@VisibleForTesting
public RuleContext build() throws InvalidExecGroupException {
+ Preconditions.checkNotNull(ruleClassProvider);
+ Preconditions.checkNotNull(hostConfiguration);
+ Preconditions.checkNotNull(configurationFragmentPolicy);
+ Preconditions.checkNotNull(actionOwnerSymbol);
Preconditions.checkNotNull(prerequisiteMap);
Preconditions.checkNotNull(configConditions);
- Preconditions.checkNotNull(toolsRepository);
- Preconditions.checkNotNull(starlarkSemantics);
Preconditions.checkNotNull(mutability);
Preconditions.checkNotNull(visibility);
- Preconditions.checkNotNull(constraintSemantics);
AttributeMap attributes =
ConfiguredAttributeMapper.of(
target.getAssociatedRule(), configConditions.asProviders(), configuration.checksum());
@@ -1725,18 +1684,7 @@
this,
attributes,
targetMap,
- configConditions.asProviders(),
- universalFragments,
- getRuleClassNameForLogging(),
- actionOwnerSymbol,
- firstNonNull(aspectAttributes, ImmutableMap.of()),
- toolchainContexts,
- createExecGroupCollection(execGroupCollectionBuilder, attributes),
- constraintSemantics,
- requiredConfigFragments,
- toolsRepository,
- starlarkSemantics,
- mutability);
+ createExecGroupCollection(execGroupCollectionBuilder, attributes));
}
private ExecGroupCollection createExecGroupCollection(
@@ -1775,15 +1723,23 @@
}
}
- // TODO(bazel-team): This field is only used by BazelStarlarkContext. Investigate whether that's
- // even needed in the analysis phase, and delete it if not.
- public Builder setToolsRepository(String toolsRepository) {
- this.toolsRepository = toolsRepository;
+ public Builder setRuleClassProvider(ConfiguredRuleClassProvider ruleClassProvider) {
+ this.ruleClassProvider = ruleClassProvider;
return this;
}
- public Builder setStarlarkSemantics(StarlarkSemantics starlarkSemantics) {
- this.starlarkSemantics = starlarkSemantics;
+ public Builder setHostConfiguration(BuildConfiguration hostConfiguration) {
+ this.hostConfiguration = hostConfiguration;
+ return this;
+ }
+
+ public Builder setConfigurationFragmentPolicy(ConfigurationFragmentPolicy policy) {
+ this.configurationFragmentPolicy = policy;
+ return this;
+ }
+
+ public Builder setActionOwnerSymbol(ActionLookupKey actionOwnerSymbol) {
+ this.actionOwnerSymbol = actionOwnerSymbol;
return this;
}
@@ -1822,16 +1778,6 @@
return this;
}
- /** Sets the fragment that can be legally accessed even when not explicitly declared. */
- public Builder setUniversalFragments(FragmentClassSet fragments) {
- // TODO(bazel-team): Add this directly to ConfigurationFragmentPolicy, so we
- // don't need separate logic specifically for checking this fragment. The challenge is
- // that we need RuleClassProvider to figure out what this fragment is, and not every
- // call state that creates ConfigurationFragmentPolicy has access to that.
- this.universalFragments = fragments;
- return this;
- }
-
/** Sets the {@link ResolvedToolchainContext} used to access toolchains used by this rule. */
public Builder setToolchainContext(ResolvedToolchainContext toolchainContext) {
Preconditions.checkState(
@@ -1870,11 +1816,6 @@
return this;
}
- public Builder setConstraintSemantics(ConstraintSemantics<RuleContext> constraintSemantics) {
- this.constraintSemantics = constraintSemantics;
- return this;
- }
-
public Builder setRequiredConfigFragments(
@Nullable RequiredConfigFragmentsProvider requiredConfigFragments) {
this.requiredConfigFragments = requiredConfigFragments;
@@ -1919,15 +1860,6 @@
return mapBuilder.build();
}
- /**
- * Post a raw event to the analysis environment's event handler. This circumvents normal error
- * and warning reporting functionality to post events, and should only be used in rare cases
- * where a custom event needs to be handled.
- */
- public void post(Postable event) {
- env.getEventHandler().post(event);
- }
-
@Override
public void ruleError(String message) {
reporter.ruleError(message);
@@ -2039,17 +1971,17 @@
}
/**
- * Expose the Starlark semantics that governs the building of this rule (and the rest of the
- * build)
+ * Returns the {@link StarlarkSemantics} governs the building of this rule (and the rest of the
+ * build).
*/
- public StarlarkSemantics getStarlarkSemantics() throws InterruptedException {
+ public StarlarkSemantics getStarlarkSemantics() {
return env.getStarlarkSemantics();
}
/**
* Returns a rule class name suitable for log messages, including an aspect name if applicable.
*/
- public String getRuleClassNameForLogging() {
+ private String getRuleClassNameForLogging() {
if (aspects.isEmpty()) {
return target.getAssociatedRule().getRuleClass();
}
@@ -2240,7 +2172,7 @@
validateDirectPrerequisiteType(prerequisite, attribute);
validateDirectPrerequisiteFileTypes(prerequisite, attribute);
if (attribute.performPrereqValidatorCheck()) {
- prerequisiteValidator.validate(this, prerequisite, attribute);
+ ruleClassProvider.getPrerequisiteValidator().validate(this, prerequisite, attribute);
}
}
}