[Lldb-commits] [lldb] [lldb][docs] Generate the Python API enums page from headers (PR #202780)

via lldb-commits lldb-commits at lists.llvm.org
Wed Jun 10 06:30:35 PDT 2026


================
@@ -0,0 +1,309 @@
+"""Generate the "Python API enumerators and constants" documentation page.
+
+LLDB exposes the enumerators from `lldb-enumerations.h` and the constants from
+`lldb-defines.h` as attributes of the `lldb` Python module. This script parses
+those two headers and emits a Markdown page documenting every public value, so
+the page can no longer drift out of sync with the source the way a
+hand-maintained copy does.
+
+The page is generated at build time and pulled into `python_api_enums.md` via
+the `{build-include}` directive (see `lldb/docs/_ext/build_include.py`).
+"""
+
+import argparse
+import re
+from dataclasses import dataclass, field
+
+# Matches the start of an enum declaration up to and including the opening
+# brace, capturing the enum name. Covers plain `enum Name {`, scoped
+# `enum Name : type {`, and the `FLAGS_ENUM(Name){` / `FLAGS_ANONYMOUS_ENUM()`
+# macros from lldb-enumerations.h. Enum bodies never contain nested braces, so
+# the matching `}` is simply the next one in the text.
+ENUM_RE = re.compile(
+    r"(?:enum\s+(?P<name>\w+)\s*(?::\s*[\w:]+\s*)?"
+    r"|FLAGS_ENUM\(\s*(?P<flags_name>\w+)\s*\)"
+    r"|FLAGS_ANONYMOUS_ENUM\(\s*\))\s*\{"
+)
+
+# Doxygen inline commands that wrap a following word for emphasis or reference.
+# We drop the command itself and keep its argument.
+DOXYGEN_CMD_RE = re.compile(r"\\(?:a|b|c|e|p|ref|see|link|endlink)\b\s?")
+
+# Constants are grouped editorially to match the long-standing layout of the
+# page. The classifier is prefix-based so new constants land in a sensible
+# group without further maintenance; anything unrecognized falls into
+# "Miscellaneous constants".
+CONSTANT_GROUP_ORDER = [
+    "Generic register numbers",
+    "Invalid value definitions",
+    "CPU types",
+    "Option set definitions",
+    "Miscellaneous constants",
+]
+
+
+def slugify(text):
+    return re.sub(r"[^a-z0-9]+", "-", text.lower()).strip("-")
+
+
+def clean_comment(text):
+    """Strip a doc-comment fragment down to its prose."""
+    return DOXYGEN_CMD_RE.sub("", text).rstrip()
+
+
+ at dataclass
+class Member:
+    name: str
+    desc: list = field(default_factory=list)  # lines; "" marks a paragraph break
+
+
+def parse_enum_body(body):
+    """Parse the body of an enum into a list of documented members.
+
+    Comment association follows Doxygen conventions, with one accommodation for
+    the header's occasional misuse of `///<` on its own line as a *leading*
+    comment (see WatchpointValueKind): a trailing `///<` documents the member on
+    its own line, while a standalone doc comment that isn't continuing a
+    trailing comment is treated as a leading comment for the next member.
+    """
+    members = []
+    pending_lead = []  # leading doc lines awaiting the next member
+    current = None  # most recently named member (target of trailing comments)
+    in_trailing = False  # currently extending a member's trailing comment
+    awaiting_name = True  # next identifier starts a new member
+    depth = 0  # parenthesis nesting, to find top-level commas
+
+    def attach_lead(member):
+        # Drop a leading line that merely repeats the member name (the style
+        # used by CommandFlags) along with its trailing blank.
+        lead = pending_lead[:]
+        while lead and lead[0] == "":
+            lead.pop(0)
+        if lead and lead[0] == member.name:
+            lead.pop(0)
+            while lead and lead[0] == "":
+                lead.pop(0)
+        member.desc.extend(lead)
+
+    for line in body.splitlines():
+        comment_start = line.find("//")
+        if comment_start == -1:
+            code, comment = line, None
+        else:
+            code, comment = line[:comment_start], line[comment_start:]
+
+        # Walk the code, picking out member names and top-level commas.
+        i = 0
+        while i < len(code):
+            ch = code[i]
+            if ch == "(":
+                depth += 1
+            elif ch == ")":
+                depth -= 1
----------------
Nerixyz wrote:

```suggestion
                depth -= 1
                assert depth >= 0
```
This looks correct, but better be safe.

https://github.com/llvm/llvm-project/pull/202780


More information about the lldb-commits mailing list