bazel syntax: eliminate two subclasses of BuiltinFunction
This change replaces two test-only subclasses of BuiltinFunction with
StarlarkCallables. (The remaining two subclasses, rule and
repository_rule, will be dealt with in a follow-up.)
Also, change type of rule's and repository_rule's "implementation" parameter
to StarlarkFunction, and eliminate casts that already made this assumption.
Also, give StarlarkCallable.getLocation a default value of BUILTIN.
PiperOrigin-RevId: 285022081
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
index ec1c2fd..904e177 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
@@ -36,9 +36,9 @@
import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutor;
import com.google.devtools.build.lib.skyframe.BlacklistedPackagePrefixesValue;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
-import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Mutability;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.vfs.Path;
@@ -84,7 +84,7 @@
new SkylarkRepositoryDefinitionLocationEvent(
rule.getName(), rule.getDefinitionInformation()));
}
- BaseFunction function = rule.getRuleClassObject().getConfiguredTargetFunction();
+ StarlarkFunction function = rule.getRuleClassObject().getConfiguredTargetFunction();
if (declareEnvironmentDependencies(markerData, env, getEnviron(rule)) == null) {
return null;
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
index 4fdc01c..fdf1b9e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
@@ -49,6 +49,7 @@
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.syntax.SkylarkUtils;
import com.google.devtools.build.lib.syntax.Starlark;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import java.util.Map;
@@ -61,7 +62,7 @@
@Override
public BaseFunction repositoryRule(
- BaseFunction implementation,
+ StarlarkFunction implementation,
Object attrs,
Boolean local,
Sequence<?> environ, // <String> expected
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index f087893..29a0e35 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -55,10 +55,10 @@
import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
-import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.syntax.Starlark;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.StringUtil;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -640,7 +640,7 @@
PredicatesWithMessage.<Rule>alwaysTrue();
private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
private AdvertisedProviderSet.Builder advertisedProviders = AdvertisedProviderSet.builder();
- private BaseFunction configuredTargetFunction = null;
+ private StarlarkFunction configuredTargetFunction = null;
private BuildSetting buildSetting = null;
private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
NO_EXTERNAL_BINDINGS;
@@ -1150,10 +1150,8 @@
return attributes.containsKey(name);
}
- /**
- * Sets the rule implementation function. Meant for Skylark usage.
- */
- public Builder setConfiguredTargetFunction(BaseFunction func) {
+ /** Sets the rule implementation function. Meant for Skylark usage. */
+ public Builder setConfiguredTargetFunction(StarlarkFunction func) {
this.configuredTargetFunction = func;
return this;
}
@@ -1443,7 +1441,7 @@
/**
* The Skylark rule implementation of this RuleClass. Null for non Skylark executable RuleClasses.
*/
- @Nullable private final BaseFunction configuredTargetFunction;
+ @Nullable private final StarlarkFunction configuredTargetFunction;
/**
* The BuildSetting associated with this rule. Null for all RuleClasses except Skylark-defined
@@ -1530,7 +1528,7 @@
PredicateWithMessage<Rule> validityPredicate,
Predicate<String> preferredDependencyPredicate,
AdvertisedProviderSet advertisedProviders,
- @Nullable BaseFunction configuredTargetFunction,
+ @Nullable StarlarkFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
Function<? super Rule, ? extends Set<String>> optionReferenceFunction,
@Nullable Label ruleDefinitionEnvironmentLabel,
@@ -2369,10 +2367,9 @@
return binaryOutput;
}
- /**
- * Returns this RuleClass's custom Skylark rule implementation.
- */
- @Nullable public BaseFunction getConfiguredTargetFunction() {
+ /** Returns this RuleClass's custom Skylark rule implementation. */
+ @Nullable
+ public StarlarkFunction getConfiguredTargetFunction() {
return configuredTargetFunction;
}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
index 33afe11..8f7840c 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/RepositoryModuleApi.java
@@ -23,6 +23,7 @@
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Sequence;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
import com.google.devtools.build.lib.syntax.StarlarkThread;
@@ -41,12 +42,13 @@
parameters = {
@Param(
name = "implementation",
- type = BaseFunction.class,
+ type = StarlarkFunction.class,
named = true,
doc =
- "the function implementing this rule, has to have exactly one parameter: <code><a"
- + " href=\"repository_ctx.html\">repository_ctx</a></code>. The function is"
- + " called during loading phase for each instance of the rule."),
+ "the Starlark function that implements this rule. Must have a single parameter,"
+ + " <code><a href=\"repository_ctx.html\">repository_ctx</a></code>. The"
+ + " function is called during the loading phase for each instance of the"
+ + " rule."),
@Param(
name = "attrs",
type = Dict.class,
@@ -110,7 +112,7 @@
useAst = true,
useStarlarkThread = true)
BaseFunction repositoryRule(
- BaseFunction implementation,
+ StarlarkFunction implementation,
Object attrs,
Boolean local,
Sequence<?> environ, // <String> expected
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
index 90325f0..a248503 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
@@ -277,6 +277,7 @@
* @return the value resulting from evaluating the function with the given arguments
* @throws EvalException-s containing source information.
*/
+ @Override
public Object call(
List<Object> args,
@Nullable Map<String, Object> kwargs,
@@ -358,9 +359,4 @@
public void repr(Printer printer) {
printer.append("<function " + getName() + ">");
}
-
- @Override
- public Location getLocation() {
- return Location.BUILTIN;
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
index 8faf014..0cdd461 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinCallable.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.syntax;
-import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.profiler.SilentCloseable;
@@ -104,11 +103,6 @@
}
@Override
- public Location getLocation() {
- return Location.BUILTIN;
- }
-
- @Override
public String getName() {
return methodName;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
index b4d488d..a8372d1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkCallable.java
@@ -55,5 +55,7 @@
* Returns the location of the definition of this callable value, or BUILTIN if it was not defined
* in Starlark code.
*/
- Location getLocation();
+ default Location getLocation() {
+ return Location.BUILTIN;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
index 4486139..773fab5 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
@@ -25,6 +25,7 @@
import com.google.devtools.build.lib.syntax.FunctionSignature;
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.syntax.Starlark;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.skydoc.fakebuildapi.FakeDescriptor;
import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkRuleFunctionsApi.AttributeNameComparator;
@@ -51,7 +52,7 @@
@Override
public BaseFunction repositoryRule(
- BaseFunction implementation,
+ StarlarkFunction implementation,
Object attrs,
Boolean local,
Sequence<?> environ, // <String> expected
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
index 667e582..644934f 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContextTest.java
@@ -39,14 +39,12 @@
import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutor;
import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutor.ExecutionResult;
import com.google.devtools.build.lib.skyframe.BazelSkyframeExecutorConstants;
-import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Expression;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.FunctionSignature;
+import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInput;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkList;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
@@ -61,7 +59,6 @@
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Before;
@@ -70,11 +67,9 @@
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
-/**
- * Unit tests for complex function of SkylarkRepositoryContext.
- */
+/** Unit tests for complex function of SkylarkRepositoryContext. */
@RunWith(JUnit4.class)
-public class SkylarkRepositoryContextTest {
+public final class SkylarkRepositoryContextTest {
private Scratch scratch;
private Path outputDirectory;
@@ -100,18 +95,19 @@
}
ruleClassBuilder.setWorkspaceOnly();
ruleClassBuilder.setConfiguredTargetFunction(
- new BuiltinFunction(FunctionSignature.ANY) {
- @Override
- public String getName() {
- return "test";
- }
-
- public void invoke(
- List<Object> args, Map<String, Object> kwargs, StarlarkThread thread) {}
- });
+ (StarlarkFunction) execAndEval("def test(ctx): pass", "test"));
return ruleClassBuilder.build();
}
+ private static Object execAndEval(String... lines) {
+ try (Mutability mu = Mutability.create("impl")) {
+ return EvalUtils.execAndEvalOptionalFinalExpression(
+ ParserInput.fromLines(lines), StarlarkThread.builder(mu).useDefaultSemantics().build());
+ } catch (Exception ex) { // SyntaxError | EvalException | InterruptedException
+ throw new AssertionError("exec failed", ex);
+ }
+ }
+
protected void setUpContextForRule(
Map<String, Object> kwargs,
ImmutableSet<PathFragment> ignoredPathFragments,
@@ -126,11 +122,9 @@
"runfiles",
starlarkSemantics);
ExtendedEventHandler listener = Mockito.mock(ExtendedEventHandler.class);
- ParserInput input = ParserInput.fromLines("test()");
- FuncallExpression ast = (FuncallExpression) Expression.parse(input);
Rule rule =
WorkspaceFactoryHelper.createAndAddRepositoryRule(
- packageBuilder, buildRuleClass(attributes), null, kwargs, ast.getLocation());
+ packageBuilder, buildRuleClass(attributes), null, kwargs, Location.BUILTIN);
HttpDownloader downloader = Mockito.mock(HttpDownloader.class);
SkyFunction.Environment environment = Mockito.mock(SkyFunction.Environment.class);
when(environment.getListener()).thenReturn(listener);
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
index fbc4177..ceb1586 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
@@ -56,7 +56,7 @@
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase;
-import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.vfs.Path;
@@ -873,7 +873,7 @@
PredicateWithMessage<Rule> validityPredicate,
Predicate<String> preferredDependencyPredicate,
AdvertisedProviderSet advertisedProviders,
- @Nullable BaseFunction configuredTargetFunction,
+ @Nullable StarlarkFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
@Nullable StarlarkThread ruleDefinitionStarlarkThread,
Set<Class<?>> allowedConfigurationFragments,
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index dcb9f0f..9fb50eb 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -2088,34 +2088,34 @@
new NativeProvider<SkylarkClassObjectWithSkylarkCallables>(
SkylarkClassObjectWithSkylarkCallables.class, "struct_with_skylark_callables") {};
+ // A function that returns "fromValues".
+ Object returnFromValues =
+ new StarlarkCallable() {
+ @Override
+ public String getName() {
+ return "returnFromValues";
+ }
+
+ @Override
+ public Object call(
+ List<Object> args,
+ Map<String, Object> kwargs,
+ FuncallExpression call,
+ StarlarkThread thread) {
+ return "fromValues";
+ }
+ };
+
final Map<String, Object> fields =
ImmutableMap.of(
"values_only_field",
"fromValues",
"values_only_method",
- new BuiltinFunction(FunctionSignature.of()) {
- @Override
- public String getName() {
- return "values_only_method";
- }
-
- public String invoke() {
- return "fromValues";
- }
- },
+ returnFromValues,
"collision_field",
"fromValues",
"collision_method",
- new BuiltinFunction(FunctionSignature.of()) {
- @Override
- public String getName() {
- return "collision_method";
- }
-
- public String invoke() {
- return "fromValues";
- }
- });
+ returnFromValues);
SkylarkClassObjectWithSkylarkCallables() {
super(CONSTRUCTOR, Location.BUILTIN);