Skip to content

Commit 35b6675

Browse files
committed
format: Format
1 parent d7e4a82 commit 35b6675

2 files changed

Lines changed: 199 additions & 115 deletions

File tree

build_tools/generate_stdlib_docs.py

Lines changed: 123 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def _split_generic_args(s: str) -> list[str]:
184184
# XML doc comment parsing
185185
# ---------------------------------------------------------------------------
186186

187+
187188
def _strip_xml_tags(text: str) -> str:
188189
"""Convert XML doc content to plain text."""
189190
if not text:
@@ -218,9 +219,7 @@ def _parse_xml_doc(lines: list[str]) -> dict:
218219
root = ElementTree.fromstring(wrapped)
219220
except ElementTree.ParseError:
220221
# Fallback: extract summary with regex
221-
summary_match = re.search(
222-
r"<summary>(.*?)</summary>", xml_text, re.DOTALL
223-
)
222+
summary_match = re.search(r"<summary>(.*?)</summary>", xml_text, re.DOTALL)
224223
return {
225224
"summary": _strip_xml_tags(summary_match.group(1)) if summary_match else ""
226225
}
@@ -293,6 +292,7 @@ def _inner_xml(el: ElementTree.Element) -> str:
293292
# Data model
294293
# ---------------------------------------------------------------------------
295294

295+
296296
@dataclass
297297
class DocParam:
298298
name: str
@@ -304,6 +304,7 @@ class DocParam:
304304
@dataclass
305305
class DocMember:
306306
"""A documented method, property, or constant."""
307+
307308
kind: str # "method", "property", "constant"
308309
name: str # Sharpy name (snake_case)
309310
cs_name: str # Original C# name
@@ -321,6 +322,7 @@ class DocMember:
321322
@dataclass
322323
class DocType:
323324
"""A documented module type (e.g., ArgumentParser in argparse)."""
325+
324326
name: str
325327
cs_name: str
326328
summary: str = ""
@@ -330,6 +332,7 @@ class DocType:
330332
@dataclass
331333
class DocModule:
332334
"""A documented module or core type."""
335+
333336
name: str # Sharpy module name
334337
kind: str # "module", "type", "builtins"
335338
summary: str = ""
@@ -345,16 +348,20 @@ class DocModule:
345348

346349
# Skip patterns
347350
_SKIP_NAMES = {
348-
"GetEnumerator", "GetReverseEnumerator", "CompareTo",
349-
"GetHashCode", "Equals", "ToString", "Dispose",
350-
"TryGetValue", "ContainsKey",
351+
"GetEnumerator",
352+
"GetReverseEnumerator",
353+
"CompareTo",
354+
"GetHashCode",
355+
"Equals",
356+
"ToString",
357+
"Dispose",
358+
"TryGetValue",
359+
"ContainsKey",
351360
}
352361

353362

354363
def _is_operator(name: str) -> bool:
355-
return name.startswith("operator") and (
356-
len(name) <= 8 or not name[8].isalnum()
357-
)
364+
return name.startswith("operator") and (len(name) <= 8 or not name[8].isalnum())
358365

359366

360367
def _is_skippable(name: str, doc_lines: list[str]) -> bool:
@@ -429,11 +436,13 @@ def _parse_params(param_str: str, is_extension: bool = False) -> list[DocParam]:
429436
tokens = part.rsplit(None, 1)
430437
if len(tokens) == 2:
431438
ptype, pname = tokens
432-
params.append(DocParam(
433-
name=pascal_to_snake(pname),
434-
type=map_type(ptype.strip()),
435-
default=default,
436-
))
439+
params.append(
440+
DocParam(
441+
name=pascal_to_snake(pname),
442+
type=map_type(ptype.strip()),
443+
default=default,
444+
)
445+
)
437446
elif len(tokens) == 1:
438447
params.append(DocParam(name=tokens[0], type=""))
439448

@@ -557,20 +566,25 @@ def parse_cs_file(
557566
doc_lines = _collect_doc_lines(lines, i)
558567
if not _is_skippable(cname, doc_lines):
559568
doc = _parse_xml_doc(doc_lines)
560-
members.append(DocMember(
561-
kind="constant",
562-
name=pascal_to_snake(cname),
563-
cs_name=cname,
564-
signature="",
565-
summary=doc.get("summary", ""),
566-
return_type=map_type(ctype.strip()),
567-
is_static=True,
568-
))
569+
members.append(
570+
DocMember(
571+
kind="constant",
572+
name=pascal_to_snake(cname),
573+
cs_name=cname,
574+
signature="",
575+
summary=doc.get("summary", ""),
576+
return_type=map_type(ctype.strip()),
577+
is_static=True,
578+
)
579+
)
569580
i = end_i + 1
570581
continue
571582

572583
# Skip class/struct/interface/enum declarations
573-
if re.match(r"public\s+(?:(?:static|sealed|abstract|partial|readonly)\s+)*(?:class|struct|interface|enum)\s", joined):
584+
if re.match(
585+
r"public\s+(?:(?:static|sealed|abstract|partial|readonly)\s+)*(?:class|struct|interface|enum)\s",
586+
joined,
587+
):
574588
i = end_i + 1
575589
continue
576590

@@ -617,20 +631,22 @@ def parse_cs_file(
617631
if mapped_ret and mapped_ret != "None":
618632
sig += f" -> {mapped_ret}"
619633

620-
members.append(DocMember(
621-
kind="method",
622-
name=sharpy_name,
623-
cs_name=mname,
624-
signature=sig,
625-
summary=doc.get("summary", ""),
626-
params=params,
627-
returns=doc.get("returns", ""),
628-
return_type=mapped_ret,
629-
example=doc.get("example", ""),
630-
remarks=doc.get("remarks", ""),
631-
exceptions=doc.get("exceptions", []),
632-
is_static=is_static,
633-
))
634+
members.append(
635+
DocMember(
636+
kind="method",
637+
name=sharpy_name,
638+
cs_name=mname,
639+
signature=sig,
640+
summary=doc.get("summary", ""),
641+
params=params,
642+
returns=doc.get("returns", ""),
643+
return_type=mapped_ret,
644+
example=doc.get("example", ""),
645+
remarks=doc.get("remarks", ""),
646+
exceptions=doc.get("exceptions", []),
647+
is_static=is_static,
648+
)
649+
)
634650
i = end_i + 1
635651
continue
636652

@@ -642,15 +658,17 @@ def parse_cs_file(
642658
doc_lines = _collect_doc_lines(lines, i)
643659
if not _is_skippable(pname, doc_lines):
644660
doc = _parse_xml_doc(doc_lines)
645-
members.append(DocMember(
646-
kind="property",
647-
name=pascal_to_snake(pname),
648-
cs_name=pname,
649-
signature="",
650-
summary=doc.get("summary", ""),
651-
return_type=map_type(ptype.strip()),
652-
is_static="static" in modifiers,
653-
))
661+
members.append(
662+
DocMember(
663+
kind="property",
664+
name=pascal_to_snake(pname),
665+
cs_name=pname,
666+
signature="",
667+
summary=doc.get("summary", ""),
668+
return_type=map_type(ptype.strip()),
669+
is_static="static" in modifiers,
670+
)
671+
)
654672

655673
i = end_i + 1
656674

@@ -682,6 +700,7 @@ def _get_class_summary(filepath: Path) -> str:
682700
# Source discovery
683701
# ---------------------------------------------------------------------------
684702

703+
685704
def discover_modules(core_dir: Path) -> list[DocModule]:
686705
"""Discover all stdlib modules from Sharpy.Core source."""
687706
modules: list[DocModule] = []
@@ -724,15 +743,18 @@ def discover_modules(core_dir: Path) -> list[DocModule]:
724743

725744
# Check if this file contains SharpyModuleType-annotated classes
726745
file_text = cs_file.read_text(encoding="utf-8")
727-
type_annotations = list(re.finditer(
728-
r'\[SharpyModuleType\("([^"]+)"\)\]', file_text,
729-
))
746+
type_annotations = list(
747+
re.finditer(
748+
r'\[SharpyModuleType\("([^"]+)"\)\]',
749+
file_text,
750+
)
751+
)
730752
if type_annotations:
731753
# Find all annotated class names and their line positions
732754
file_lines = file_text.split("\n")
733755
annotated_classes: list[tuple[str, int, int]] = []
734756
for ta in type_annotations:
735-
after = file_text[ta.end():]
757+
after = file_text[ta.end() :]
736758
cm = re.search(
737759
r"public\s+(?:sealed\s+|abstract\s+|static\s+|partial\s+)*"
738760
r"class\s+(\w+)",
@@ -747,34 +769,41 @@ def discover_modules(core_dir: Path) -> list[DocModule]:
747769
# Compute end lines (start of next class or EOF)
748770
for ci in range(len(annotated_classes)):
749771
name, start, _ = annotated_classes[ci]
750-
end = (annotated_classes[ci + 1][1] - 1
751-
if ci + 1 < len(annotated_classes)
752-
else len(file_lines) - 1)
772+
end = (
773+
annotated_classes[ci + 1][1] - 1
774+
if ci + 1 < len(annotated_classes)
775+
else len(file_lines) - 1
776+
)
753777
annotated_classes[ci] = (name, start, end)
754778

755779
# Parse each class range separately
756780
for class_name, start, end in annotated_classes:
757781
type_summary = _get_class_summary(cs_file)
758782
type_members = parse_cs_file(
759-
cs_file, line_range=(start, end),
783+
cs_file,
784+
line_range=(start, end),
785+
)
786+
all_types.append(
787+
DocType(
788+
name=class_name,
789+
cs_name=cs_file.stem,
790+
summary=type_summary,
791+
members=type_members,
792+
)
760793
)
761-
all_types.append(DocType(
762-
name=class_name,
763-
cs_name=cs_file.stem,
764-
summary=type_summary,
765-
members=type_members,
766-
))
767794
else:
768795
members = parse_cs_file(cs_file)
769796
all_members.extend(members)
770797

771-
modules.append(DocModule(
772-
name=mod_name,
773-
kind="module",
774-
summary=summary,
775-
members=all_members,
776-
types=all_types,
777-
))
798+
modules.append(
799+
DocModule(
800+
name=mod_name,
801+
kind="module",
802+
summary=summary,
803+
members=all_members,
804+
types=all_types,
805+
)
806+
)
778807

779808
return modules
780809

@@ -809,12 +838,14 @@ def discover_core_types(core_dir: Path) -> list[DocModule]:
809838
members = parse_cs_file(cs_file, is_extension=is_extension)
810839
all_members.extend(members)
811840

812-
types.append(DocModule(
813-
name=type_name,
814-
kind="type",
815-
summary=summary,
816-
members=all_members,
817-
))
841+
types.append(
842+
DocModule(
843+
name=type_name,
844+
kind="type",
845+
summary=summary,
846+
members=all_members,
847+
)
848+
)
818849

819850
return types
820851

@@ -854,6 +885,7 @@ def discover_builtins(core_dir: Path) -> DocModule:
854885
# Markdown rendering
855886
# ---------------------------------------------------------------------------
856887

888+
857889
def _one_line(text: str) -> str:
858890
"""Collapse multi-line text into a single line for table cells."""
859891
return " ".join(text.split()).strip()
@@ -930,10 +962,16 @@ def _render_constants_table(constants: list[DocMember]) -> str:
930962
if not constants:
931963
return ""
932964

933-
lines = ["## Constants", "", "| Name | Type | Description |",
934-
"|------|------|-------------|"]
965+
lines = [
966+
"## Constants",
967+
"",
968+
"| Name | Type | Description |",
969+
"|------|------|-------------|",
970+
]
935971
for c in constants:
936-
lines.append(f"| `{c.name}` | `{c.return_type}` | {_escape_table_cell(c.summary)} |")
972+
lines.append(
973+
f"| `{c.name}` | `{c.return_type}` | {_escape_table_cell(c.summary)} |"
974+
)
937975
lines.append("")
938976
return "\n".join(lines)
939977

@@ -971,13 +1009,17 @@ def render_module_page(module: DocModule) -> str:
9711009
lines.append("| Name | Type | Description |")
9721010
lines.append("|------|------|-------------|")
9731011
for p in unique_props:
974-
lines.append(f"| `{p.name}` | `{p.return_type}` | {_escape_table_cell(p.summary)} |")
1012+
lines.append(
1013+
f"| `{p.name}` | `{p.return_type}` | {_escape_table_cell(p.summary)} |"
1014+
)
9751015
lines.append("")
9761016

9771017
# Methods/Functions
9781018
methods = [m for m in module.members if m.kind == "method"]
9791019
if methods:
980-
section_title = "Functions" if module.kind in ("module", "builtins") else "Methods"
1020+
section_title = (
1021+
"Functions" if module.kind in ("module", "builtins") else "Methods"
1022+
)
9811023
lines.append(f"## {section_title}")
9821024
lines.append("")
9831025

@@ -1020,7 +1062,7 @@ def render_index_page(
10201062
"",
10211063
"## Built-in Functions",
10221064
"",
1023-
f"[Built-in functions](builtins.md) available without any import: "
1065+
f"[Built-in functions](builtins.md) available without any import: ",
10241066
]
10251067

10261068
builtin_names = sorted(set(m.name for m in builtins.members if m.kind == "method"))
@@ -1058,6 +1100,7 @@ def render_index_page(
10581100
# Main
10591101
# ---------------------------------------------------------------------------
10601102

1103+
10611104
def generate(
10621105
source_dir: Path,
10631106
output_dir: Path,

0 commit comments

Comments
 (0)