Add the concept of "generic" rules to our Starlark's doc-gen.

The documentation makes a distinction between "language-specific" and
"language-agnostic" (or "generic") rules.

It is an error for these to be different between rules within a "family"
(if one is generic, they must all be generic).

However, there is currently no way to mark a rule as "generic" in
Starlark.

So we check the "type" string that is parsed from the "doc-struct" and
if it's generic, we flag it is as such. Generic rules always have their
type set to "other" so there's no issue with overloading the string in
this way.

PiperOrigin-RevId: 628120344
Change-Id: I52e89448a653bd17b5501d42b6449c3fa8ad1d24
diff --git a/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java b/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
index fb7109a..d30d63c 100644
--- a/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
+++ b/src/main/java/com/google/devtools/build/docgen/BuildDocCollector.java
@@ -409,6 +409,12 @@
               ruleDocOrigin.get(ruleName).symbol(),
               ruleDocOrigin.get(ruleName).file());
         }
+        ImmutableSet.Builder<String> flags = ImmutableSet.builder();
+        if (ruleType.equals(DocgenConsts.STARLARK_GENERIC_RULE_TYPE)) {
+          // Note that if FLAG_GENERIC_RULE is set, RuleDocumentation constructor will set the rule
+          // type to OTHER.
+          flags.add(DocgenConsts.FLAG_GENERIC_RULE);
+        }
         RuleDocumentation ruleDoc =
             new RuleDocumentation(
                 ruleName,
@@ -417,7 +423,7 @@
                 ruleInfo.getDocString(),
                 ruleOriginFileLabel,
                 urlMapper.urlOfLabel(ruleOriginFileLabel),
-                ImmutableSet.of(),
+                flags.build(),
                 // Add family summary only to the first rule encountered, to avoid duplication in
                 // final rendered output
                 numRulesCollected == 0 ? ruleFamilySummary : "");
diff --git a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
index dcd93f4..e294910 100644
--- a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
+++ b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
@@ -90,8 +90,14 @@
   public static final String META_KEY_FAMILY = "FAMILY";
 
   /**
-   * Types a rule can have (Binary, Library, Test or Other).
+   * For Starlark rules, this type name is equivalent to {@link RuleType#OTHER} with the {@link
+   * FLAG_GENERIC_RULE} flag set.
+   *
+   * <p>Example: "generic_rules.genrule" would be classified as a generic rule of type OTHER.
    */
+  public static final String STARLARK_GENERIC_RULE_TYPE = "GENERIC";
+
+  /** Types a rule can have (Binary, Library, Test or Other). */
   public static enum RuleType {
       BINARY, LIBRARY, TEST, OTHER
   }
diff --git a/src/test/java/com/google/devtools/build/docgen/BuildDocCollectorTest.java b/src/test/java/com/google/devtools/build/docgen/BuildDocCollectorTest.java
index 5e9059c..9b7b0826 100644
--- a/src/test/java/com/google/devtools/build/docgen/BuildDocCollectorTest.java
+++ b/src/test/java/com/google/devtools/build/docgen/BuildDocCollectorTest.java
@@ -304,4 +304,23 @@
     assertThat(getAttribute(attributes, "uncommonly_named_attr").getGeneratedInRule("my_library"))
         .isEqualTo("my_library");
   }
+
+  @Test
+  public void collectModuleInfoDocs_genericRulesFlaggedAsGeneric() throws Exception {
+    ModuleInfo moduleInfo =
+        ModuleInfo.newBuilder()
+            .setModuleDocstring("Family")
+            .setFile("//:test.bzl")
+            .addRuleInfo(
+                RuleInfo.newBuilder()
+                    .setRuleName("generic_rules.my_rule")
+                    .setDocString("My rule")
+                    .setOriginKey(
+                        OriginKey.newBuilder().setName("my_rule").setFile("//:my_rule.bzl")))
+            .build();
+
+    assertThat(collectModuleInfoDocs(moduleInfo)).isEqualTo(1);
+    assertThat(ruleDocEntries.get("my_rule").isLanguageSpecific()).isFalse();
+    assertThat(ruleDocEntries.get("my_rule").getRuleFamily()).isEqualTo("Family");
+  }
 }