Skip to content

Commit

Permalink
Replace ComposingTransition.decomposeTransitions with the visitor
Browse files Browse the repository at this point in the history
pattern.

Part of the work on #7814.

Closes #7912.

PiperOrigin-RevId: 241378193
  • Loading branch information
katre authored and copybara-github committed Apr 1, 2019
1 parent 5b1d33e commit a05d5b6
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -67,6 +66,13 @@ public String getName() {
return "(" + transition1.getName() + " + " + transition2.getName() + ")";
}

// Override to allow recursive visiting.
@Override
public <E extends Exception> void visit(Visitor<E> visitor) throws E {
this.transition1.visit(visitor);
this.transition2.visit(visitor);
}

@Override
public int hashCode() {
return Objects.hash(transition1, transition2);
Expand Down Expand Up @@ -118,29 +124,4 @@ public static ConfigurationTransition of(
private static boolean isFinal(ConfigurationTransition transition) {
return transition == NullTransition.INSTANCE || transition.isHostTransition();
}

/**
* Recursively decompose a composing transition into all the {@link ConfigurationTransition}
* instances that it holds.
*
* @param root {@link ComposingTransition} to decompose
*/
public static ImmutableList<ConfigurationTransition> decomposeTransition(
ConfigurationTransition root) {
ArrayList<ConfigurationTransition> toBeInspected = new ArrayList<>();
ImmutableList.Builder<ConfigurationTransition> transitions = new ImmutableList.Builder<>();
toBeInspected.add(root);
ConfigurationTransition current;
while (!toBeInspected.isEmpty()) {
current = toBeInspected.remove(0);
if (current instanceof ComposingTransition) {
ComposingTransition composingCurrent = (ComposingTransition) current;
toBeInspected.addAll(
ImmutableList.of(composingCurrent.transition1, composingCurrent.transition2));
} else {
transitions.add(current);
}
}
return transitions.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,15 @@ default boolean isHostTransition() {
default String getName() {
return this.getClass().getSimpleName();
}

/** Allows the given {@link Visitor} to inspect this transition. */
default <E extends Exception> void visit(Visitor<E> visitor) throws E {
visitor.accept(this);
}

/** Helper object that can be used to inspect {@link ConfigurationTransition} instances. */
@FunctionalInterface
interface Visitor<E extends Exception> {
void accept(ConfigurationTransition transition) throws E;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,16 @@ public String getMessage() {
// TODO(juliexxia): handle the possibility of aliased build settings.
public static ImmutableSet<SkyKey> getBuildSettingPackageKeys(ConfigurationTransition root) {
ImmutableSet.Builder<SkyKey> keyBuilder = new ImmutableSet.Builder<>();
for (ConfigurationTransition transition : ComposingTransition.decomposeTransition(root)) {
if (transition instanceof StarlarkTransition) {
for (Label setting : getChangedStarlarkSettings((StarlarkTransition) transition)) {
keyBuilder.add(PackageValue.key(setting.getPackageIdentifier()));
}
}
try {
root.visit(
(StarlarkTransitionVisitor)
transition -> {
for (Label setting : getChangedStarlarkSettings(transition)) {
keyBuilder.add(PackageValue.key(setting.getPackageIdentifier()));
}
});
} catch (TransitionException e) {
// Not actually thrown in the visitor, but declared.
}
return keyBuilder.build();
}
Expand Down Expand Up @@ -129,42 +133,41 @@ public static void validate(
throws TransitionException {
replayEvents(eventHandler, root);

List<ConfigurationTransition> transitions = ComposingTransition.decomposeTransition(root);
// collect settings changed during this transition and their types
Map<Label, Type<?>> changedSettingToType = Maps.newHashMap();
for (ConfigurationTransition transition : transitions) {
if (!(transition instanceof StarlarkTransition)) {
continue;
}
StarlarkTransition starlarkTransition = (StarlarkTransition) transition;
List<Label> changedSettings = getChangedStarlarkSettings(starlarkTransition);
for (Label setting : changedSettings) {
Package buildSettingPackage =
((PackageValue)
buildSettingPackages.get(PackageValue.key(setting.getPackageIdentifier())))
.getPackage();
Target buildSettingTarget;
try {
buildSettingTarget = buildSettingPackage.getTarget(setting.getName());
} catch (NoSuchTargetException e) {
throw new TransitionException(e);
}
if (buildSettingTarget.getAssociatedRule() == null
|| buildSettingTarget.getAssociatedRule().getRuleClassObject().getBuildSetting()
== null) {
throw new TransitionException(
String.format(
"attempting to transition on '%s' which is not a build setting", setting));
}
changedSettingToType.put(
setting,
buildSettingTarget
.getAssociatedRule()
.getRuleClassObject()
.getBuildSetting()
.getType());
}
}
root.visit(
(StarlarkTransitionVisitor)
transition -> {
List<Label> changedSettings = getChangedStarlarkSettings(transition);
for (Label setting : changedSettings) {
Package buildSettingPackage =
((PackageValue)
buildSettingPackages.get(
PackageValue.key(setting.getPackageIdentifier())))
.getPackage();
Target buildSettingTarget;
try {
buildSettingTarget = buildSettingPackage.getTarget(setting.getName());
} catch (NoSuchTargetException e) {
throw new TransitionException(e);
}
if (buildSettingTarget.getAssociatedRule() == null
|| buildSettingTarget.getAssociatedRule().getRuleClassObject().getBuildSetting()
== null) {
throw new TransitionException(
String.format(
"attempting to transition on '%s' which is not a build setting",
setting));
}
changedSettingToType.put(
setting,
buildSettingTarget
.getAssociatedRule()
.getRuleClassObject()
.getBuildSetting()
.getType());
}
});

// verify changed settings were changed to something reasonable for their type
for (BuildOptions options : toOptions) {
Expand Down Expand Up @@ -193,18 +196,17 @@ private static List<Label> getChangedStarlarkSettings(StarlarkTransition transit
*/
private static void replayEvents(ExtendedEventHandler eventHandler, ConfigurationTransition root)
throws TransitionException {
List<ConfigurationTransition> transitions = ComposingTransition.decomposeTransition(root);
for (ConfigurationTransition transition : transitions) {
if (transition instanceof StarlarkTransition) {
StarlarkTransition starlarkTransition = (StarlarkTransition) transition;
// Replay events and errors and throw if there were errors
boolean hasErrors = starlarkTransition.hasErrors();
starlarkTransition.replayOn(eventHandler);
if (hasErrors) {
throw new TransitionException("Errors encountered while applying Starlark transition");
}
}
}
root.visit(
(StarlarkTransitionVisitor)
transition -> {
// Replay events and errors and throw if there were errors
boolean hasErrors = transition.hasErrors();
transition.replayOn(eventHandler);
if (hasErrors) {
throw new TransitionException(
"Errors encountered while applying Starlark transition");
}
});
}

@Override
Expand All @@ -224,4 +226,19 @@ public boolean equals(Object object) {
public int hashCode() {
return Objects.hashCode(starlarkDefinedConfigTransition);
}

@FunctionalInterface
// This is only used in this class to handle the cast and the exception
@SuppressWarnings("FunctionalInterfaceMethodChanged")
private interface StarlarkTransitionVisitor
extends ConfigurationTransition.Visitor<TransitionException> {
@Override
default void accept(ConfigurationTransition transition) throws TransitionException {
if (transition instanceof StarlarkTransition) {
this.accept((StarlarkTransition) transition);
}
}

void accept(StarlarkTransition transition) throws TransitionException;
}
}

0 comments on commit a05d5b6

Please sign in to comment.