From 36bf56d1c4daf0baaa70d6406482a78d32646732 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 6 May 2024 19:12:21 +0200 Subject: [PATCH] Label readonly properties in the docs (#158) --- sphinx_js/ir.py | 1 + sphinx_js/js/convertTopLevel.ts | 7 +++++-- sphinx_js/js/ir.ts | 1 + sphinx_js/renderers.py | 5 ++++- tests/test_build_ts/source/class.ts | 5 ++++- tests/test_build_ts/test_build_ts.py | 26 +++++++++++++++++--------- tests/test_ir.py | 1 + 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sphinx_js/ir.py b/sphinx_js/ir.py index aae25ee4..971e45de 100644 --- a/sphinx_js/ir.py +++ b/sphinx_js/ir.py @@ -274,6 +274,7 @@ class Attribute(TopLevel, _Member): #: The type this property's value can have type: Type + readonly: bool = False kind: Literal["attribute"] = "attribute" diff --git a/sphinx_js/js/convertTopLevel.ts b/sphinx_js/js/convertTopLevel.ts index c1b57f6f..28f8e84c 100644 --- a/sphinx_js/js/convertTopLevel.ts +++ b/sphinx_js/js/convertTopLevel.ts @@ -471,6 +471,7 @@ export class Converter { const result: Attribute = { ...this.memberProps(v), ...this.topLevelProperties(v), + readonly: false, kind: "attribute", type, }; @@ -542,12 +543,12 @@ export class Converter { } else { type = this.convertType(prop.type!); } - // TODO: add a readonly indicator if it's readonly const result: Attribute = { type, ...this.memberProps(prop), ...this.topLevelProperties(prop), description: renderCommentSummary(prop.comment), + readonly: prop.flags.isReadonly, kind: "attribute", }; return [result, prop.children]; @@ -581,9 +582,11 @@ export class Converter { sig = prop.setSignature; type = sig.parameters![0].type!; } - // TODO: add a readonly indicator if there's no setter. + // If there's no setter say it's readonly + const readonly = !prop.setSignature; const result: Attribute = { type: this.convertType(type), + readonly, ...this.memberProps(prop), ...this.topLevelProperties(prop), kind: "attribute", diff --git a/sphinx_js/js/ir.ts b/sphinx_js/js/ir.ts index 5ad0c9be..d726e95f 100644 --- a/sphinx_js/js/ir.ts +++ b/sphinx_js/js/ir.ts @@ -113,6 +113,7 @@ export type TopLevel = { export type Attribute = TopLevel & Member & { type: Type; + readonly: boolean; kind: "attribute"; }; diff --git a/sphinx_js/renderers.py b/sphinx_js/renderers.py index cbc52604..ffb19c1f 100644 --- a/sphinx_js/renderers.py +++ b/sphinx_js/renderers.py @@ -657,8 +657,11 @@ class AutoAttributeRenderer(JsRenderer): def _template_vars(self, name: str, obj: Attribute | TypeAlias) -> dict[str, Any]: # type: ignore[override] is_optional = False + ty = self.render_type(obj.type) if isinstance(obj, Attribute): is_optional = obj.is_optional + if obj.readonly: + ty = "readonly " + ty type_params = "" is_type_alias = isinstance(obj, TypeAlias) fields: Iterator[tuple[list[str], str]] = iter([]) @@ -675,7 +678,7 @@ def _template_vars(self, name: str, obj: Attribute | TypeAlias) -> dict[str, Any is_optional=is_optional, see_also=obj.see_alsos, examples=[render_description(ex) for ex in obj.examples], - type=self.render_type(obj.type), + type=ty, content="\n".join(self._content), ) diff --git a/tests/test_build_ts/source/class.ts b/tests/test_build_ts/source/class.ts index 739fe904..f94613cb 100644 --- a/tests/test_build_ts/source/class.ts +++ b/tests/test_build_ts/source/class.ts @@ -109,6 +109,9 @@ export function weirdCodeInDescription() {} export function spinxLinkInDescription() {} export class GetSetDocs { + readonly x: number; + y: number; + /** * Getter with comment */ @@ -119,7 +122,7 @@ export class GetSetDocs { /** * Setter with comment */ - set b(x) {} + set b(x: number) {} } export class Base { diff --git a/tests/test_build_ts/test_build_ts.py b/tests/test_build_ts/test_build_ts.py index b6b8c961..f46f962d 100644 --- a/tests/test_build_ts/test_build_ts.py +++ b/tests/test_build_ts/test_build_ts.py @@ -193,21 +193,29 @@ def test_get_set(self): "getset", dedent( """\ - class GetSetDocs() +class GetSetDocs() - *exported from* "class" + *exported from* "class" + + GetSetDocs.a + + type: readonly number + + Getter with comment + + GetSetDocs.b - GetSetDocs.a + type: number - type: number + Setter with comment - Getter with comment + GetSetDocs.x - GetSetDocs.b + type: readonly number - type: any + GetSetDocs.y - Setter with comment + type: number """ ), ) @@ -224,7 +232,7 @@ class Base() Base.a - type: number + type: readonly number Base.f() diff --git a/tests/test_ir.py b/tests/test_ir.py index 05274298..311baa70 100644 --- a/tests/test_ir.py +++ b/tests/test_ir.py @@ -59,6 +59,7 @@ def test_missing_default(): is_optional=False, is_static=False, is_private=False, + readonly=False, type=[] ) attr_dict = {k: v for k, v in getmembers(attribute_base) if not k.startswith("_")}