| // Copyright 2020 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.packages; | |
| import com.google.devtools.build.docgen.annot.DocCategory; | |
| import net.starlark.java.annot.Param; | |
| import net.starlark.java.annot.StarlarkBuiltin; | |
| import net.starlark.java.annot.StarlarkMethod; | |
| import net.starlark.java.eval.Printer; | |
| import net.starlark.java.eval.Starlark; | |
| import net.starlark.java.eval.StarlarkThread; | |
| import net.starlark.java.eval.StarlarkValue; | |
| // TODO(#11437): Note that if Stardoc's current design were to be long-lived, we'd want to factor | |
| // out an API into starlarkbuildapi. As it is that almost certainly won't be necessary. | |
| /** | |
| * The {@code _builtins} Starlark object, visible only to {@code @_builtins} .bzl files, supporting | |
| * access to internal APIs. | |
| */ | |
| @StarlarkBuiltin( | |
| name = "_builtins", | |
| category = DocCategory.BUILTIN, | |
| documented = false, | |
| doc = | |
| "A module accessible only to @_builtins .bzls, that permits access to the original " | |
| + "(uninjected) native builtins, as well as internal-only symbols not accessible to " | |
| + "users.") | |
| public class BuiltinsInternalModule implements StarlarkValue { | |
| // _builtins.native | |
| private final Object uninjectedNativeObject; | |
| // _builtins.toplevel | |
| private final Object uninjectedToplevelObject; | |
| // _builtins.internal | |
| private final Object internalObject; | |
| public BuiltinsInternalModule( | |
| Object uninjectedNativeObject, Object uninjectedToplevelObject, Object internalObject) { | |
| this.uninjectedNativeObject = uninjectedNativeObject; | |
| this.uninjectedToplevelObject = uninjectedToplevelObject; | |
| this.internalObject = internalObject; | |
| } | |
| @Override | |
| public void repr(Printer printer) { | |
| printer.append("<_builtins module>"); | |
| } | |
| @Override | |
| public boolean isImmutable() { | |
| return true; | |
| } | |
| @StarlarkMethod( | |
| name = "native", | |
| doc = | |
| "A view of the <code>native</code> object as it would exist if builtins injection were" | |
| + " disabled. For example, if builtins injection provides a Starlark definition for" | |
| + " <code>cc_library</code> in <code>exported_rules</code>, then" | |
| + " <code>native.cc_library</code> in a user .bzl file would refer to that" | |
| + " definition, but <code>_builtins.native.cc_library</code> in a" | |
| + " <code>@_builtins</code> .bzl file would still be the one defined in Java code." | |
| + " (Note that for clarity and to avoid a conceptual cycle, the regular top-level" | |
| + " <code>native</code> object is not defined for <code>@_builtins</code> .bzl" | |
| + " files.)", | |
| documented = false, | |
| structField = true) | |
| public Object getUninjectedNativeObject() { | |
| return uninjectedNativeObject; | |
| } | |
| @StarlarkMethod( | |
| name = "toplevel", | |
| doc = | |
| "A view of the top-level .bzl symbols that would exist if builtins injection were" | |
| + " disabled; analogous to <code>_builtins.native</code>. For example, if builtins" | |
| + " injection provides a Starlark definition for <code>CcInfo</code> in" | |
| + " <code>exported_toplevels</code>, then <code>_builtins.toplevel.CcInfo</code>" | |
| + " refers to the original Java definition, not the Starlark one. (Just as for" | |
| + " <code>_builtins.native</code>, the top-level <code>CcInfo</code> symbol is not" | |
| + " available to <code>@_builtins</code> .bzl files.)", | |
| documented = false, | |
| structField = true) | |
| public Object getUninjectedToplevelObject() { | |
| return uninjectedToplevelObject; | |
| } | |
| @StarlarkMethod( | |
| name = "internal", | |
| doc = | |
| "A view of symbols that were registered (via the Java method" | |
| + "<code>ConfiguredRuleClassProvider#addStarlarkBuiltinsInternal</code>) to be made" | |
| + " available to <code>@_builtins</code> code but not necessarily user code.", | |
| documented = false, | |
| structField = true) | |
| public Object getInternalObject() { | |
| return internalObject; | |
| } | |
| @StarlarkMethod( | |
| name = "get_flag", | |
| doc = | |
| "Returns the value of a <code>StarlarkSemantics</code> flag, or a default value if it" | |
| + " could not be retrieved (either because the flag does not exist or because it was" | |
| + " not assigned an explicit value). Fails if the flag value exists but is not a" | |
| + " Starlark value.", | |
| documented = false, | |
| parameters = { | |
| @Param(name = "name", doc = "Name of the flag, without the leading dashes"), | |
| /* | |
| * Because of the way flag values are stored in StarlarkSemantics, we cannot retrieve a flag | |
| * whose value was not explicitly set, nor can we programmatically determine its default | |
| * value. This parameter is essentially a hack to avoid a slightly costlier refactoring of | |
| * StarlarkSemantics and BuildLanguageOptions. If the value passed in here by the caller | |
| * differs from the true default value of the flag, you could end up in a situation where | |
| * the semantics of some @_builtins code varies depending on whether a flag was set to its | |
| * default value implicitly or explicitly. | |
| */ | |
| @Param( | |
| name = "default", | |
| doc = | |
| "Value to return if flag was not set or does not exist. This should always be set" | |
| + " to the same value as the flag's default value.") | |
| }, | |
| useStarlarkThread = true) | |
| public Object getFlag(String name, Object defaultValue, StarlarkThread thread) { | |
| Object value = thread.getSemantics().getGeneric(name, defaultValue); | |
| return Starlark.fromJava(value, thread.mutability()); | |
| } | |
| } |