bazel syntax: enforce that ClassObject.getValue returns legal Starlark values
EvalUtils.getAttr now enforces that the value returned by
ClassObject.getValue is a legal value.
Previously, only the ternary SkylarkClassObject.getValue method
offered this postcondition, and it wasn't enforced.
This turned up BuildConfiguration.Fragment,
which was used as a value (e.g. in ctx.fragments.android)
but had forgotten to declare its relationship to StarlarkValue.
Also:
- remove obsolete 'instanceof Class' check.
- remove try/catch of IllegalArgumentException.
Instead do this check with narrower scope in the fragment code.
We will fix other cases as they appear.
PiperOrigin-RevId: 284644428
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 f167e8a..0810a03 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
@@ -475,18 +475,25 @@
}
@Nullable
- public Fragment getSkylarkFragment(String name, ConfigurationTransition transition) {
+ public Fragment getSkylarkFragment(String name, ConfigurationTransition transition)
+ throws EvalException {
Class<? extends Fragment> fragmentClass =
getConfiguration(transition).getSkylarkFragmentByName(name);
if (fragmentClass == null) {
return null;
}
- return getFragment(fragmentClass, name,
- String.format(
- " Please update the '%1$sfragments' argument of the rule definition "
- + "(for example: %1$sfragments = [\"%2$s\"])",
- (transition.isHostTransition()) ? "host_" : "", name),
- transition);
+ try {
+ return getFragment(
+ fragmentClass,
+ name,
+ String.format(
+ " Please update the '%1$sfragments' argument of the rule definition "
+ + "(for example: %1$sfragments = [\"%2$s\"])",
+ transition.isHostTransition() ? "host_" : "", name),
+ transition);
+ } catch (IllegalArgumentException ex) { // fishy
+ throw new EvalException(null, ex.getMessage());
+ }
}
public ImmutableCollection<String> getSkylarkFragmentNames(ConfigurationTransition transition) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index 9b07ff9..5fbd7bd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -48,6 +48,7 @@
import com.google.devtools.build.lib.skylarkbuildapi.BuildConfigurationApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.syntax.StarlarkValue;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -110,8 +111,10 @@
* <p>All implementations must be immutable and communicate this as clearly as possible (e.g.
* declare {@link ImmutableList} signatures on their interfaces vs. {@link List}). This is because
* fragment instances may be shared across configurations.
+ *
+ * <p>Fragments are Starlark values, as returned by {@code ctx.fragments.android}, for example.
*/
- public abstract static class Fragment {
+ public abstract static class Fragment implements StarlarkValue {
/**
* Validates the options for this Fragment. Issues warnings for the use of deprecated options,
* and warnings or errors for any option settings that conflict.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java
index d396bcc..11f2ab7 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java
@@ -19,6 +19,7 @@
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skylarkbuildapi.FragmentCollectionApi;
+import com.google.devtools.build.lib.syntax.EvalException;
import javax.annotation.Nullable;
/** Represents a collection of configuration fragments in Skylark. */
@@ -35,7 +36,7 @@
@Override
@Nullable
- public Object getValue(String name) {
+ public Object getValue(String name) throws EvalException {
return ruleContext.getSkylarkFragment(name, transition);
}