diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BUILD index 0830f09d87d558..c3751456fc1f9a 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BUILD +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BUILD @@ -59,7 +59,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib/cmdline", "//src/main/java/com/google/devtools/build/lib/events", "//src/main/java/com/google/devtools/build/lib/packages", - "//src/main/java/net/starlark/java/annot", + "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository", "//src/main/java/net/starlark/java/eval", "//src/main/java/net/starlark/java/syntax", "//third_party:auto_value", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtension.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtension.java index 20dc263ccb1d66..408710dbefc4a0 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtension.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtension.java @@ -14,16 +14,9 @@ package com.google.devtools.build.lib.bazel.bzlmod; -import com.google.api.client.util.Preconditions; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.devtools.build.docgen.annot.DocCategory; -import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.events.EventHandler; -import com.google.devtools.build.lib.packages.StarlarkExportable; -import javax.annotation.Nullable; -import net.starlark.java.annot.StarlarkBuiltin; import net.starlark.java.eval.StarlarkCallable; import net.starlark.java.eval.StarlarkValue; import net.starlark.java.syntax.Location; @@ -32,11 +25,8 @@ * A module extension object, which can be used to perform arbitrary logic in order to create repos. */ @AutoValue -@StarlarkBuiltin( - name = "module_extension", - category = DocCategory.BUILTIN, - doc = "A module extension declared using the module_extension function.") public abstract class ModuleExtension implements StarlarkValue { + public abstract StarlarkCallable getImplementation(); public abstract ImmutableMap getTagClasses(); @@ -58,8 +48,6 @@ public abstract static class Builder { public abstract Builder setLocation(Location value); - public abstract Builder setName(String value); - public abstract Builder setImplementation(StarlarkCallable value); public abstract Builder setTagClasses(ImmutableMap value); @@ -68,42 +56,4 @@ public abstract static class Builder { public abstract ModuleExtension build(); } - - /** - * A {@link ModuleExtension} exposed to Starlark. We can't use {@link ModuleExtension} directly - * because the name isn't known until the object is exported, so this class holds a builder until - * it's exported, at which point it sets the name and builds the underlying {@link - * ModuleExtension}. - */ - @StarlarkBuiltin(name = "module_extension", doc = "A module extension.") - public static class InStarlark implements StarlarkExportable { - private final Builder builder; - @Nullable - private ModuleExtension built; - - public InStarlark() { - builder = builder(); - built = null; - } - - public Builder getBuilder() { - return builder; - } - - @Override - public boolean isExported() { - return built != null; - } - - @Override - public void export(EventHandler handler, Label extensionLabel, String exportedName) { - built = builder.setName(exportedName).build(); - } - - /** Throws {@link IllegalStateException} if this is not exported yet. */ - public ModuleExtension get() { - Preconditions.checkState(isExported(), "the module extension was never exported"); - return built; - } - } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/TagClass.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/TagClass.java index f2bdc7c1e93e8d..fbc3b8d83313d0 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/TagClass.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/TagClass.java @@ -18,16 +18,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.packages.Attribute; -import net.starlark.java.annot.StarlarkBuiltin; -import net.starlark.java.eval.StarlarkValue; +import com.google.devtools.build.lib.starlarkbuildapi.repository.RepositoryModuleApi.TagClassApi; import net.starlark.java.syntax.Location; /** * Represents a tag class, which is a "class" of {@link Tag}s that share the same attribute schema. */ -@StarlarkBuiltin(name = "tag_class", doc = "Defines a schema of attributes for a tag.") @AutoValue -public abstract class TagClass implements StarlarkValue { +public abstract class TagClass implements TagClassApi { /** The list of attributes of this tag class. */ public abstract ImmutableList getAttributes(); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD index 9fda919f03e600..8bdb024b79cced 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/BUILD @@ -52,6 +52,7 @@ java_library( "//src/main/java/net/starlark/java/annot", "//src/main/java/net/starlark/java/eval", "//src/main/java/net/starlark/java/syntax", + "//third_party:error_prone_annotations", "//third_party:guava", "//third_party:java-diff-utils", "//third_party:jsr305", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java index 96da8a38220eb2..a350c5956420e4 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.docgen.annot.DocCategory; -import com.google.devtools.build.docgen.annot.DocumentMethods; import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.starlark.StarlarkAttrModule.Descriptor; import com.google.devtools.build.lib.bazel.bzlmod.ModuleExtension; @@ -49,9 +48,7 @@ import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.devtools.build.lib.starlarkbuildapi.repository.RepositoryModuleApi; import java.util.Map; -import net.starlark.java.annot.Param; import net.starlark.java.annot.StarlarkBuiltin; -import net.starlark.java.annot.StarlarkMethod; import net.starlark.java.eval.Dict; import net.starlark.java.eval.EvalException; import net.starlark.java.eval.Module; @@ -66,7 +63,6 @@ * The Starlark module containing the definition of {@code repository_rule} function to define a * Starlark remote repository. */ -@DocumentMethods public class StarlarkRepositoryModule implements RepositoryModuleApi { @Override @@ -266,48 +262,7 @@ public void failWithIncompatibleUseCcConfigureFromRulesCc(StarlarkThread thread) } } - @StarlarkMethod( - name = "module_extension", - doc = - "Creates a new module extension. Store it in a global value, so that it can be exported" - + " and used in a MODULE.bazel file.", - parameters = { - @Param( - name = "implementation", - named = true, - doc = - "The function that implements this module extension. Must take a single parameter," - + " module_ctx. The function is" - + " called once at the beginning of a build to determine the set of available" - + " repos."), - @Param( - name = "tag_classes", - defaultValue = "{}", - doc = - "A dictionary to declare all the tag classes used by the extension. It maps from" - + " the name of the tag class to a tag_class object.", - named = true, - positional = false), - @Param( - name = "doc", - defaultValue = "''", - doc = - "A description of the module extension that can be extracted by documentation" - + " generating tools.", - named = true, - positional = false), - @Param( - name = "environ", - defaultValue = "[]", - doc = - "Provides a list of environment variable that this module extension depends on. If " - + "an environment variable in that list changes, the extension will be " - + "re-evaluated.", - named = true, - positional = false) - }, - useStarlarkThread = true) + @Override public ModuleExtension moduleExtension( StarlarkCallable implementation, Dict tagClasses, // Dict @@ -320,34 +275,12 @@ public ModuleExtension moduleExtension( .setTagClasses( ImmutableMap.copyOf(Dict.cast(tagClasses, String.class, TagClass.class, "tag_classes"))) .setDoc(doc) + .setEnvVariables(ImmutableList.copyOf(Sequence.cast(environ, String.class, "environ"))) .setLocation(thread.getCallerLocation()) .build(); } - @StarlarkMethod( - name = "tag_class", - doc = - "Creates a new tag_class object, which defines an attribute schema for a class of tags," - + " which are data objects usable by a module extension.", - parameters = { - @Param( - name = "attrs", - defaultValue = "{}", - named = true, - doc = - "A dictionary to declare all the attributes of this tag class. It maps from an" - + " attribute name to an attribute object (see attr" - + " module)."), - @Param( - name = "doc", - defaultValue = "''", - doc = - "A description of the tag class that can be extracted by documentation" - + " generating tools.", - named = true, - positional = false) - }, - useStarlarkThread = true) + @Override public TagClass tagClass( Dict attrs, // Dict String doc, diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository/RepositoryModuleApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository/RepositoryModuleApi.java index cb9268c92de3cd..81d267d0f62cb0 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository/RepositoryModuleApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository/RepositoryModuleApi.java @@ -14,10 +14,12 @@ package com.google.devtools.build.lib.starlarkbuildapi.repository; +import com.google.devtools.build.docgen.annot.DocCategory; import com.google.devtools.build.docgen.annot.DocumentMethods; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import net.starlark.java.annot.Param; import net.starlark.java.annot.ParamType; +import net.starlark.java.annot.StarlarkBuiltin; import net.starlark.java.annot.StarlarkMethod; import net.starlark.java.eval.Dict; import net.starlark.java.eval.EvalException; @@ -25,6 +27,7 @@ import net.starlark.java.eval.Sequence; import net.starlark.java.eval.StarlarkCallable; import net.starlark.java.eval.StarlarkThread; +import net.starlark.java.eval.StarlarkValue; /** * The Starlark module containing the definition of {@code repository_rule} function to define a @@ -118,6 +121,96 @@ StarlarkCallable repositoryRule( StarlarkThread thread) throws EvalException; + @StarlarkMethod( + name = "module_extension", + doc = + "Creates a new module extension. Store it in a global value, so that it can be exported" + + " and used in a MODULE.bazel file.", + parameters = { + @Param( + name = "implementation", + named = true, + doc = + "The function that implements this module extension. Must take a single parameter," + + " module_ctx. The function is" + + " called once at the beginning of a build to determine the set of available" + + " repos."), + @Param( + name = "tag_classes", + defaultValue = "{}", + doc = + "A dictionary to declare all the tag classes used by the extension. It maps from" + + " the name of the tag class to a tag_class object.", + named = true, + positional = false), + @Param( + name = "doc", + defaultValue = "''", + doc = + "A description of the module extension that can be extracted by documentation" + + " generating tools.", + named = true, + positional = false), + @Param( + name = "environ", + allowedTypes = { + @ParamType(type = Sequence.class, generic1 = String.class), + }, + defaultValue = "[]", + doc = + "Provides a list of environment variable that this module extension depends on. If " + + "an environment variable in that list changes, the extension will be " + + "re-evaluated.", + named = true, + positional = false), + }, + useStarlarkThread = true) + Object moduleExtension( + StarlarkCallable implementation, + Dict tagClasses, // Dict + String doc, + Sequence environ, // + StarlarkThread thread) + throws EvalException; + + @StarlarkMethod( + name = "tag_class", + doc = + "Creates a new tag_class object, which defines an attribute schema for a class of tags," + + " which are data objects usable by a module extension.", + parameters = { + @Param( + name = "attrs", + defaultValue = "{}", + named = true, + doc = + "A dictionary to declare all the attributes of this tag class. It maps from an" + + " attribute name to an attribute object (see attr" + + " module)."), + @Param( + name = "doc", + defaultValue = "''", + doc = + "A description of the tag class that can be extracted by documentation" + + " generating tools.", + named = true, + positional = false) + }, + useStarlarkThread = true) + TagClassApi tagClass( + Dict attrs, // Dict + String doc, + StarlarkThread thread) + throws EvalException; + + /** Represents a tag class, which is a "class" of tags that share the same attribute schema. */ + @StarlarkBuiltin( + name = "tag_class", + category = DocCategory.BUILTIN, + doc = "Defines a schema of attributes for a tag.") + interface TagClassApi extends StarlarkValue {} + @StarlarkMethod( name = "__do_not_use_fail_with_incompatible_use_cc_configure_from_rules_cc", doc = 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 2cbf475276304a..69f597b44f3e83 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 @@ -115,6 +115,23 @@ public String getName() { } } + @Override + public Object moduleExtension( + StarlarkCallable implementation, + Dict tagClasses, + String doc, + Sequence environ, + StarlarkThread thread) + throws EvalException { + return new Object(); + } + + @Override + public TagClassApi tagClass(Dict attrs, String doc, StarlarkThread thread) + throws EvalException { + return new TagClassApi() {}; + } + @Override public void failWithIncompatibleUseCcConfigureFromRulesCc(StarlarkThread thread) throws EvalException { diff --git a/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModuleTest.java b/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModuleTest.java index 0528a15687e476..189b2cb91f8952 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModuleTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModuleTest.java @@ -61,7 +61,8 @@ private static ModuleExtension.Builder getBaseExtensionBuilder() { return ModuleExtension.builder() .setDoc("") .setLocation(Location.BUILTIN) - .setImplementation(() -> "maven"); + .setImplementation(() -> "maven") + .setEnvVariables(ImmutableList.of()); } @Test