Better error messaging for needing transition whitelist + updated docs. Allow the way throw in a note about attaching to starlark transitions to native rules since we've been getting a lot of questions about that recently.

#7056

PiperOrigin-RevId: 296113789
diff --git a/site/docs/skylark/config.md b/site/docs/skylark/config.md
index 1d1343a..cadf03d 100644
--- a/site/docs/skylark/config.md
+++ b/site/docs/skylark/config.md
@@ -331,6 +331,23 @@
 is how we change configuration of
 configured targets in the build graph.
 
+> IMPORTANT: In order to use Starlark transitions, you need to attach a
+> special attribute to the rule to which the transition is attached:
+>
+> ```python
+> "_whitelist_function_transition": attr.label(
+>      default = "@bazel_tools//tools/whitelists/function_transition_whitelist"
+>  )
+> ```
+>
+> By adding transitions you can pretty easily explode the size of
+> your build graph. This sets a whitelist on the packages in which you can
+> create targets of this rule. The default value in the codeblock above
+> whitelists everything. But if you'd like to restrict who is using your rule,
+> you can set that attribute to point to your own custom whitelist.
+> Contact bazel-discuss@googlegroups.com if you'd like advice or assistance
+> understanding how transitions can affect on your build performance.
+
 ### Defining Transitions in Starlark
 
 Transitions define configuration changes between rules. For example, a request
@@ -418,6 +435,11 @@
 edge transition) and transition their dependencies' configurations (outgoing
 edge transition).
 
+NOTE: There is currently no way to attach Starlark transitions to native rules.
+If you need to do this, contact
+bazel-discuss@googlegroups.com
+and we can help you try to figure out a workaround.
+
 #### Incoming Edge Transitions
 Incoming edge transitions are activated by attaching a `transition` object
 (created by `transition()`) to `rule()`'s `cfg` parameter:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 9fdae97..7100116 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -99,9 +99,7 @@
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 
-/**
- * A helper class to provide an easier API for Skylark rule definitions.
- */
+/** A helper class to provide an easier API for Skylark rule definitions. */
 public class SkylarkRuleClassFunctions implements SkylarkRuleFunctionsApi<Artifact> {
 
   // TODO(bazel-team): Copied from ConfiguredRuleClassProvider for the transition from built-in
@@ -266,10 +264,12 @@
                   "Expected list of strings or dictionary of string -> string for 'fields'");
       fieldNames = list;
     } else if (fields instanceof Dict) {
-      Map<String, String> dict = SkylarkType.castMap(
-          fields,
-          String.class, String.class,
-          "Expected list of strings or dictionary of string -> string for 'fields'");
+      Map<String, String> dict =
+          SkylarkType.castMap(
+              fields,
+              String.class,
+              String.class,
+              "Expected list of strings or dictionary of string -> string for 'fields'");
       fieldNames = dict.keySet();
     }
     return SkylarkProvider.createUnexportedSchemaful(fieldNames, thread.getCallerLocation());
@@ -362,8 +362,7 @@
 
     builder.addRequiredToolchains(
         collectToolchainLabels(
-            toolchains.getContents(String.class, "toolchains"),
-            bazelContext.getRepoMapping()));
+            toolchains.getContents(String.class, "toolchains"), bazelContext.getRepoMapping()));
 
     if (!buildSetting.equals(Starlark.NONE) && !cfg.equals(Starlark.NONE)) {
       throw Starlark.errorf(
@@ -439,8 +438,7 @@
   }
 
   private static ImmutableList<Label> collectToolchainLabels(
-      Iterable<String> rawLabels,
-      ImmutableMap<RepositoryName, RepositoryName> mapping)
+      Iterable<String> rawLabels, ImmutableMap<RepositoryName, RepositoryName> mapping)
       throws EvalException {
     ImmutableList.Builder<Label> requiredToolchains = new ImmutableList.Builder<>();
     for (String rawLabel : rawLabels) {
@@ -457,8 +455,7 @@
   }
 
   private static ImmutableList<Label> collectConstraintLabels(
-      Iterable<String> rawLabels,
-      ImmutableMap<RepositoryName, RepositoryName> mapping)
+      Iterable<String> rawLabels, ImmutableMap<RepositoryName, RepositoryName> mapping)
       throws EvalException {
     ImmutableList.Builder<Label> constraintLabels = new ImmutableList.Builder<>();
     for (String rawLabel : rawLabels) {
@@ -673,15 +670,16 @@
       return Starlark.NONE;
     }
 
-    /**
-     * Export a RuleFunction from a Skylark file with a given name.
-     */
+    /** Export a RuleFunction from a Skylark file with a given name. */
     public void export(Label skylarkLabel, String ruleClassName) throws EvalException {
       Preconditions.checkState(ruleClass == null && builder != null);
       this.skylarkLabel = skylarkLabel;
       if (type == RuleClassType.TEST != TargetUtils.isTestRuleName(ruleClassName)) {
-        throw new EvalException(definitionLocation, "Invalid rule class name '" + ruleClassName
-            + "', test rule class names must end with '_test' and other rule classes must not");
+        throw new EvalException(
+            definitionLocation,
+            "Invalid rule class name '"
+                + ruleClassName
+                + "', test rule class names must end with '_test' and other rule classes must not");
       }
       // Thus far, we only know if we have a rule transition. While iterating through attributes,
       // check if we have an attribute transition.
@@ -742,7 +740,9 @@
           throw new EvalException(
               getLocation(),
               String.format(
-                  "Use of Starlark transition without whitelist: %s %s",
+                  "Use of Starlark transition without whitelist attribute"
+                      + " '_whitelist_function_transition'. See Starlark transitions documentation"
+                      + " for details and usage: %s %s",
                   builder.getRuleDefinitionEnvironmentLabel(), builder.getType()));
         }
       } else {