Create new config module that is responsible for creating BuildSetting descriptor objects.

Build settings are units of configuration i.e. a key/value pair of a setting (e.g. cpu) and a value (e.g. ppc). A build setting descriptor is used to describe what kind of build setting a skylark rule is (if any at all). The BuildSettingDescriptor implementation of the API describes two facets of the build setting rule: the type of the value and whether or not the setting is settable on the command line.

The methods exposed here will eventually be hooked up to a new parameter in the <code> rule() </code> function. Validation for these restrictions will also happen in a later CL attached to the same bug.

Add a new test config_apis_test for skylark config apis which will be more populated as this work continues.

PiperOrigin-RevId: 214991588
diff --git a/src/main/java/com/google/devtools/build/docgen/SymbolFamilies.java b/src/main/java/com/google/devtools/build/docgen/SymbolFamilies.java
index d51e058..b22be9b 100644
--- a/src/main/java/com/google/devtools/build/docgen/SymbolFamilies.java
+++ b/src/main/java/com/google/devtools/build/docgen/SymbolFamilies.java
@@ -32,6 +32,7 @@
 import com.google.devtools.build.lib.util.Classpath.ClassPathException;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeActionsInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeBuildApiGlobals;
+import com.google.devtools.build.skydoc.fakebuildapi.FakeConfigApi;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeDefaultInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeOutputGroupInfo.FakeOutputGroupInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkAttrApi;
@@ -170,7 +171,8 @@
             new FakeAndroidResourcesInfoProvider(),
             new FakeAndroidNativeLibsInfoProvider());
     AppleBootstrap appleBootstrap = new AppleBootstrap(new FakeAppleCommon());
-    ConfigBootstrap configBootstrap = new ConfigBootstrap(new FakeConfigSkylarkCommon());
+    ConfigBootstrap configBootstrap =
+        new ConfigBootstrap(new FakeConfigSkylarkCommon(), new FakeConfigApi());
     CcBootstrap ccBootstrap = new CcBootstrap(new FakeCcModule());
     JavaBootstrap javaBootstrap =
         new JavaBootstrap(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkConfig.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkConfig.java
new file mode 100644
index 0000000..bc4d6e4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkConfig.java
@@ -0,0 +1,89 @@
+// Copyright 2018 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.analysis.skylark;
+
+import static com.google.devtools.build.lib.packages.BuildType.LABEL;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
+import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
+import static com.google.devtools.build.lib.syntax.Type.INTEGER;
+import static com.google.devtools.build.lib.syntax.Type.STRING;
+import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
+
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkConfigApi;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+import com.google.devtools.build.lib.syntax.Type;
+
+/**
+ * Skylark namespace for creating build setting descriptors.
+ */
+public class SkylarkConfig implements SkylarkConfigApi {
+
+  @Override
+  public BuildSettingDescriptor intSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, INTEGER);
+  }
+
+  @Override
+  public BuildSettingDescriptor boolSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, BOOLEAN);
+  }
+
+  @Override
+  public BuildSettingDescriptor stringSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, STRING);
+  }
+
+  @Override
+  public BuildSettingDescriptor stringListSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, STRING_LIST);
+  }
+
+  @Override
+  public BuildSettingDescriptor labelSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, LABEL);
+  }
+
+  @Override
+  public BuildSettingDescriptor labelListSetting(Boolean flag) {
+    return new BuildSettingDescriptor(flag, LABEL_LIST);
+  }
+
+  @Override
+  public void repr(SkylarkPrinter printer) {
+    printer.append("<config>");
+  }
+
+  /**
+   * An object that describes what time of build setting a skylark rule is (if any type).
+   */
+  private static final class BuildSettingDescriptor implements SkylarkConfigApi.BuildSettingApi {
+    private final boolean isFlag;
+    private final Type<?> type;
+
+    BuildSettingDescriptor(boolean isFlag, Type<?> type) {
+      this.isFlag = isFlag;
+      this.type = type;
+    }
+
+    public Type<?> getType() {
+      return type;
+    }
+
+    @Override
+    public void repr(SkylarkPrinter printer) {
+      printer.append("<build_setting." + type.toString() + ">");
+    }
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRules.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRules.java
index 0962257..1281325 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRules.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRules.java
@@ -17,6 +17,7 @@
 import com.google.devtools.build.lib.analysis.BaseRuleClasses;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.RuleSet;
+import com.google.devtools.build.lib.analysis.skylark.SkylarkConfig;
 import com.google.devtools.build.lib.rules.core.CoreRules;
 import com.google.devtools.build.lib.rules.platform.PlatformRules;
 import com.google.devtools.build.lib.skylarkbuildapi.config.ConfigBootstrap;
@@ -41,7 +42,8 @@
         new ConfigFeatureFlagConfiguration.Loader());
 
     builder.addRuleDefinition(new ConfigRuleClasses.ConfigFeatureFlagRule());
-    builder.addSkylarkBootstrap(new ConfigBootstrap(new ConfigSkylarkCommon()));
+    builder.addSkylarkBootstrap(
+        new ConfigBootstrap(new ConfigSkylarkCommon(), new SkylarkConfig()));
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkConfigApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkConfigApi.java
new file mode 100644
index 0000000..4a455c5
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkConfigApi.java
@@ -0,0 +1,148 @@
+// Copyright 2018 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.skylarkbuildapi;
+
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
+
+
+/**
+ *  The "config" module of the Build API.
+ *
+ *  This exposes methods to describe what kind of build setting (if any) a skylark rule is using
+ *  the {@code build_setting} attr of the {@code rule(...)} function.
+ */
+@SkylarkModule(
+    name = "config",
+    namespace = true,
+    category = SkylarkModuleCategory.BUILTIN,
+    doc = "Note: This API is experimental and may change at any time."
+        + ""
+        + "<p>This is a top-level module for creating build setting descriptors which describe "
+        + "what kind of build setting (if any) a skylark rule is. "
+        + ""
+        + "<p>ex: the following rule is marked as a build setting by setting the "
+        + "<code>build_setting</code> parameter of the <code>rule()</code> function. Specifically "
+        + "it is a build setting of type <code>int</code> and is a <code>flag</code> which means "
+        + "this build setting is callable on the command line.<br><pre class=language-python>"
+        + "  my_rule = rule(\n"
+        + "    implementation = _impl,\n"
+        + "    build_setting = config.int(flag = True),\n"
+        + "    ...\n"
+        + "  )</pre>")
+//TODO(juliexxia): Create formal documentation for skylark build configuration efforts (b/112545834)
+public interface SkylarkConfigApi extends SkylarkValue {
+
+  static final String FLAG_ARG = "flag";
+  static final String FLAG_ARG_DOC =
+      "Whether or not this build setting is callable on the command line.";
+
+  @SkylarkCallable(
+      name = "int",
+      doc = "An integer-typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi intSetting(Boolean flag);
+
+  @SkylarkCallable(
+      name = "bool",
+      doc = "A bool-typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi boolSetting(Boolean flag);
+
+  @SkylarkCallable(
+      name = "string",
+      doc = "A string-typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi stringSetting(Boolean flag);
+
+  @SkylarkCallable(
+      name = "string_list",
+      doc = "A string list-typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi stringListSetting(Boolean flag);
+
+  @SkylarkCallable(
+      name = "label",
+      doc = "A label typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi labelSetting(Boolean flag);
+
+  @SkylarkCallable(
+      name = "label_list",
+      doc = "A label list-typed build setting",
+      parameters = {
+        @Param(
+            name = FLAG_ARG,
+            type = Boolean.class,
+            defaultValue = "False",
+            doc = FLAG_ARG_DOC,
+            named = true,
+            positional = false)
+      })
+  BuildSettingApi labelListSetting(Boolean flag);
+
+  /** The API for build setting descriptors. */
+  @SkylarkModule(
+      name = "BuildSetting",
+      category = SkylarkModuleCategory.NONE,
+      doc =
+          "The descriptor for a single piece of configuration information. If configuration is a "
+              + "key-value map of settings like {'cpu': 'ppc', 'copt': '-DFoo'}, this describes a "
+              + "single entry in that map.")
+  interface BuildSettingApi extends SkylarkValue {}
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigBootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigBootstrap.java
index 0624ebf..80379a3 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/config/ConfigBootstrap.java
@@ -16,6 +16,7 @@
 
 import com.google.common.collect.ImmutableMap.Builder;
 import com.google.devtools.build.lib.skylarkbuildapi.Bootstrap;
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkConfigApi;
 
 /**
  * A {@link Bootstrap} for config-related libraries of the build API.
@@ -23,13 +24,17 @@
 public class ConfigBootstrap implements Bootstrap {
 
   private final ConfigSkylarkCommonApi configSkylarkCommonApi;
+  private final SkylarkConfigApi skylarkConfigApi;
 
-  public ConfigBootstrap(ConfigSkylarkCommonApi configSkylarkCommonApi) {
+  public ConfigBootstrap(
+      ConfigSkylarkCommonApi configSkylarkCommonApi, SkylarkConfigApi skylarkConfigApi) {
     this.configSkylarkCommonApi = configSkylarkCommonApi;
+    this.skylarkConfigApi = skylarkConfigApi;
   }
 
   @Override
   public void addBindingsToBuilder(Builder<String, Object> builder) {
     builder.put("config_common", configSkylarkCommonApi);
+    builder.put("config", skylarkConfigApi);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
index 53a87d5..c3daeb5 100644
--- a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
+++ b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
@@ -42,6 +42,7 @@
 import com.google.devtools.build.lib.syntax.SkylarkImport;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeActionsInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeBuildApiGlobals;
+import com.google.devtools.build.skydoc.fakebuildapi.FakeConfigApi;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeDefaultInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeOutputGroupInfo.FakeOutputGroupInfoProvider;
 import com.google.devtools.build.skydoc.fakebuildapi.FakeSkylarkAttrApi;
@@ -318,7 +319,8 @@
         new FakeAndroidResourcesInfoProvider(),
         new FakeAndroidNativeLibsInfoProvider());
     AppleBootstrap appleBootstrap = new AppleBootstrap(new FakeAppleCommon());
-    ConfigBootstrap configBootstrap = new ConfigBootstrap(new FakeConfigSkylarkCommon());
+    ConfigBootstrap configBootstrap =
+        new ConfigBootstrap(new FakeConfigSkylarkCommon(), new FakeConfigApi());
     CcBootstrap ccBootstrap = new CcBootstrap(new FakeCcModule());
     JavaBootstrap javaBootstrap = new JavaBootstrap(new FakeJavaCommon(),
         new FakeJavaInfoProvider(),
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildSettingDescriptor.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildSettingDescriptor.java
new file mode 100644
index 0000000..9135f97
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeBuildSettingDescriptor.java
@@ -0,0 +1,26 @@
+// Copyright 2018 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.skydoc.fakebuildapi;
+
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkConfigApi.BuildSettingApi;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+
+/**
+ * Fake implementation of {@link BuildSettingApi}.
+ */
+public class FakeBuildSettingDescriptor implements BuildSettingApi {
+  @Override
+  public void repr(SkylarkPrinter printer) {}
+}
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeConfigApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeConfigApi.java
new file mode 100644
index 0000000..2bd322b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeConfigApi.java
@@ -0,0 +1,57 @@
+// Copyright 2018 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.skydoc.fakebuildapi;
+
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkConfigApi;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+
+/**
+ * Fake implementation of {@link SkylarkConfigApi}.
+ */
+public class FakeConfigApi implements SkylarkConfigApi {
+
+  @Override
+  public BuildSettingApi intSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public BuildSettingApi boolSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public BuildSettingApi stringSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public BuildSettingApi stringListSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public BuildSettingApi labelSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public BuildSettingApi labelListSetting(Boolean flag) {
+    return new FakeBuildSettingDescriptor();
+  }
+
+  @Override
+  public void repr(SkylarkPrinter printer) {}
+}
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/golden.txt b/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/golden.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/golden.txt
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/input.bzl b/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/input.bzl
new file mode 100644
index 0000000..7c95887
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/config_apis_test/input.bzl
@@ -0,0 +1,6 @@
+def exercise_the_api():
+    # TODO(juliexxia): This isn't actually where this module would be used.
+    # Move this to the rule definition when the relevant parameter is set up.
+    var5 = config.int(flag = True)
+
+exercise_the_api()
diff --git a/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/input.bzl b/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/input.bzl
index 10ef29d..dfc2170 100644
--- a/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/input.bzl
+++ b/src/test/java/com/google/devtools/build/skydoc/testdata/misc_apis_test/input.bzl
@@ -1,3 +1,7 @@
+# This is here to test that built-in names can be shadowed by global names.
+# (Regression test for http://b/35984389).
+config = "value for global config variable"
+
 def my_rule_impl(ctx):
     return struct()