Convert ToolchainCollection to use AutoValue. Also Break the subclass relationship between ExecGroupCollection and ToolchainCollection. This adds toString, hashCode, and equals implementations for both classes. PiperOrigin-RevId: 314338648
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD index de3bbfe..026d10d 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD +++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD
@@ -1024,6 +1024,7 @@ deps = [ ":toolchain_context", "//src/main/java/com/google/devtools/build/lib/cmdline", + "//third_party:auto_value", "//third_party:guava", ], )
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ExecGroupCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/ExecGroupCollection.java index a7f8545..db8af35 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ExecGroupCollection.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ExecGroupCollection.java
@@ -13,6 +13,9 @@ // limitations under the License. package com.google.devtools.build.lib.analysis; +import static com.google.devtools.build.lib.analysis.ToolchainCollection.DEFAULT_EXEC_GROUP_NAME; + +import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.skylarkbuildapi.platform.ExecGroupCollectionApi; @@ -29,16 +32,20 @@ * A {@link StarlarkIndexable} collection of resolved toolchain contexts that can be exposed to * starlark. */ -public class ExecGroupCollection extends ToolchainCollection<ResolvedToolchainContext> - implements ExecGroupCollectionApi { +@AutoValue +public abstract class ExecGroupCollection implements ExecGroupCollectionApi { - public ExecGroupCollection(ToolchainCollection<ResolvedToolchainContext> toolchainCollection) { - super(toolchainCollection); + /** Returns a new {@link ExecGroupCollection} backed by the given {@code toolchainCollection}. */ + public static ExecGroupCollection create( + ToolchainCollection<ResolvedToolchainContext> toolchainCollection) { + return new AutoValue_ExecGroupCollection(toolchainCollection); } + protected abstract ToolchainCollection<ResolvedToolchainContext> toolchainCollection(); + @VisibleForTesting public ImmutableMap<String, ResolvedToolchainContext> getToolchainCollectionForTesting() { - return getContextMap(); + return toolchainCollection().getContextMap(); } public static boolean isValidGroupName(String execGroupName) { @@ -48,7 +55,8 @@ @Override public boolean containsKey(StarlarkSemantics semantics, Object key) throws EvalException { String group = castGroupName(key); - return !DEFAULT_EXEC_GROUP_NAME.equals(group) && getExecGroups().contains(group); + return !DEFAULT_EXEC_GROUP_NAME.equals(group) + && toolchainCollection().getExecGroups().contains(group); } /** @@ -62,11 +70,11 @@ if (!containsKey(semantics, key)) { throw Starlark.errorf( "In %s, unrecognized exec group '%s' requested. Available exec groups: [%s]", - getDefaultToolchainContext().targetDescription(), + toolchainCollection().getDefaultToolchainContext().targetDescription(), execGroup, String.join(", ", getScrubbedExecGroups())); } - return new ExecGroupContext(getToolchainContext(execGroup)); + return new ExecGroupContext(toolchainCollection().getToolchainContext(execGroup)); } private static String castGroupName(Object key) throws EvalException { @@ -87,7 +95,7 @@ } private List<String> getScrubbedExecGroups() { - return getExecGroups().stream() + return toolchainCollection().getExecGroups().stream() .filter(group -> !DEFAULT_EXEC_GROUP_NAME.equals(group)) .sorted() .collect(Collectors.toList()); @@ -105,7 +113,7 @@ } @Override - public ResolvedToolchainContext toolchains() throws EvalException { + public ResolvedToolchainContext toolchains() { return resolvedToolchainContext; }
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 9d96691..79e1f75 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
@@ -1856,7 +1856,7 @@ this.toolchainContexts == null, "toolchainContexts has already been set for this Builder"); this.toolchainContexts = - new ToolchainCollection.Builder<ResolvedToolchainContext>() + ToolchainCollection.<ResolvedToolchainContext>builder() .addDefaultContext(toolchainContext) .build(); return this;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainCollection.java index 206a8d6..4991889 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainCollection.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainCollection.java
@@ -15,6 +15,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; +import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; @@ -29,30 +30,56 @@ * @param <T> any class that extends ToolchainContext. This generic allows ToolchainCollection to be * used, e.g., both before and after toolchain resolution. */ -public class ToolchainCollection<T extends ToolchainContext> { +@AutoValue +public abstract class ToolchainCollection<T extends ToolchainContext> { // This is intentionally a string that would fail {@code Identifier.isValid} so that // users can't create a group with the same name. @VisibleForTesting public static final String DEFAULT_EXEC_GROUP_NAME = "default-exec-group"; /** A map of execution group names to toolchain contexts. */ - private final ImmutableMap<String, T> toolchainContexts; + public abstract ImmutableMap<String, T> getContextMap(); - private ToolchainCollection(Map<String, T> contexts) { - Preconditions.checkArgument(contexts.containsKey(DEFAULT_EXEC_GROUP_NAME)); - toolchainContexts = ImmutableMap.copyOf(contexts); + T getDefaultToolchainContext() { + return getContextMap().get(DEFAULT_EXEC_GROUP_NAME); } - ToolchainCollection(ToolchainCollection<T> toCopy) { - toolchainContexts = ImmutableMap.copyOf(toCopy.getContextMap()); + boolean hasToolchainContext(String execGroup) { + return getContextMap().containsKey(execGroup); + } + + public T getToolchainContext(String execGroup) { + return getContextMap().get(execGroup); + } + + public ImmutableSet<Label> getResolvedToolchains() { + return getContextMap().values().stream() + .flatMap(c -> c.resolvedToolchainLabels().stream()) + .collect(toImmutableSet()); + } + + ImmutableSet<String> getExecGroups() { + return getContextMap().keySet(); + } + + @SuppressWarnings("unchecked") + public ToolchainCollection<ToolchainContext> asToolchainContexts() { + return (ToolchainCollection<ToolchainContext>) this; + } + + /** Returns a new builder for {@link ToolchainCollection} instances. */ + public static <T extends ToolchainContext> Builder<T> builder() { + return new Builder<T>(); } /** Builder for ToolchainCollection. */ - public static class Builder<T extends ToolchainContext> { + public static final class Builder<T extends ToolchainContext> { + // This is not immutable so that we can check for duplicate keys easily. private final Map<String, T> toolchainContexts = new HashMap<>(); public ToolchainCollection<T> build() { - return new ToolchainCollection<>(toolchainContexts); + Preconditions.checkArgument(toolchainContexts.containsKey(DEFAULT_EXEC_GROUP_NAME)); + return new AutoValue_ToolchainCollection<T>(ImmutableMap.copyOf(toolchainContexts)); } public void addContext(String execGroup, T context) { @@ -68,34 +95,4 @@ return this; } } - - T getDefaultToolchainContext() { - return toolchainContexts.get(DEFAULT_EXEC_GROUP_NAME); - } - - boolean hasToolchainContext(String execGroup) { - return toolchainContexts.containsKey(execGroup); - } - - public T getToolchainContext(String execGroup) { - return toolchainContexts.get(execGroup); - } - - public ImmutableSet<Label> getResolvedToolchains() { - return toolchainContexts.values().stream() - .flatMap(c -> c.resolvedToolchainLabels().stream()) - .collect(toImmutableSet()); - } - - ImmutableSet<String> getExecGroups() { - return toolchainContexts.keySet(); - } - - public ToolchainCollection<ToolchainContext> asToolchainContexts() { - return new ToolchainCollection<>(ImmutableMap.copyOf(toolchainContexts)); - } - - public ImmutableMap<String, T> getContextMap() { - return toolchainContexts; - } }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleContext.java index 25eae40..5910713 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/StarlarkRuleContext.java
@@ -709,7 +709,8 @@ @Override public ExecGroupCollection execGroups() { - return new ExecGroupCollection(ruleContext.getToolchainContexts()); + // Create a thin wrapper around the toolchain collection, to expose the Starlark API. + return ExecGroupCollection.create(ruleContext.getToolchainContexts()); } @Override
diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetAccessor.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetAccessor.java index e8a91d3..c8fe5d0 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetAccessor.java +++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetAccessor.java
@@ -223,7 +223,7 @@ ImmutableMap<String, ExecGroup> execGroups = rule.getRuleClassObject().getExecGroups(); ToolchainCollection.Builder<UnloadedToolchainContext> toolchainContexts = - new ToolchainCollection.Builder<>(); + ToolchainCollection.builder(); try { for (Map.Entry<String, ExecGroup> group : execGroups.entrySet()) { ExecGroup execGroup = group.getValue();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java index 5601f39..627d206 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -421,7 +421,7 @@ configConditions, unloadedToolchainContext == null ? null - : new ToolchainCollection.Builder<>() + : ToolchainCollection.builder() .addDefaultContext(unloadedToolchainContext) .build(), ruleClassProvider,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java index ef001ad..685c86f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -325,7 +325,7 @@ if (unloadedToolchainContexts != null) { String targetDescription = target.toString(); ToolchainCollection.Builder<ResolvedToolchainContext> contextsBuilder = - new ToolchainCollection.Builder<>(); + ToolchainCollection.builder(); for (Map.Entry<String, UnloadedToolchainContext> unloadedContext : unloadedToolchainContexts.getContextMap().entrySet()) { contextsBuilder.addContext( @@ -514,7 +514,7 @@ boolean valuesMissing = env.valuesMissing(); ToolchainCollection.Builder<UnloadedToolchainContext> toolchainContexts = - valuesMissing ? null : new ToolchainCollection.Builder<>(); + valuesMissing ? null : ToolchainCollection.builder(); for (Map.Entry<String, ToolchainContextKey> unloadedToolchainContextKey : toolchainContextKeys.entrySet()) { UnloadedToolchainContext unloadedToolchainContext =
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java index 52f8132..6fc88cd 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java
@@ -527,7 +527,7 @@ toolchainContextKeys.values(), ToolchainException.class); ToolchainCollection.Builder<UnloadedToolchainContext> unloadedToolchainContexts = - new ToolchainCollection.Builder<>(); + ToolchainCollection.builder(); for (Map.Entry<String, ToolchainContextKey> unloadedToolchainContextKey : toolchainContextKeys.entrySet()) { UnloadedToolchainContext unloadedToolchainContext = @@ -552,7 +552,7 @@ String targetDescription = target.toString(); ToolchainCollection.Builder<ResolvedToolchainContext> resolvedToolchainContext = - new ToolchainCollection.Builder<>(); + ToolchainCollection.builder(); for (Map.Entry<String, UnloadedToolchainContext> unloadedToolchainContext : unloadedToolchainCollection.getContextMap().entrySet()) { ResolvedToolchainContext toolchainContext =