From 654614b8f4f8934bc90702067f88dc95985dea78 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Sep 2023 17:05:17 -0700 Subject: [PATCH 1/5] Emit xrefs --- sphinx_js/renderers.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sphinx_js/renderers.py b/sphinx_js/renderers.py index 6b592968..d4fc4441 100644 --- a/sphinx_js/renderers.py +++ b/sphinx_js/renderers.py @@ -26,6 +26,7 @@ Type, TypeParam, TypeXRef, + TypeXRefInternal, ) from .jsdoc import Analyzer as JsAnalyzer from .parsers import PathVisitor @@ -236,17 +237,23 @@ def strs() -> Iterator[str]: return "".join(res) def render_xref(self, s: TypeXRef, escape: bool = False) -> str: + if isinstance(s, TypeXRefInternal): + name = rst.escape(s.name) + result = f":js:class:`{name}`" + else: + result = s.name if escape: - return rst.escape(s.name) - return s.name + result = rst.escape(result) + return result def _return_formatter(self, return_: Return) -> tuple[list[str], str]: """Derive heads and tail from ``@returns`` blocks.""" - tail = "" + tail = [] if return_.type: - tail += "**%s** -- " % self.format_type(return_.type, escape=True) - tail += return_.description - return ["returns"], tail + tail.append(self.format_type(return_.type, escape=False)) + if return_.description: + tail.append(return_.description) + return ["returns"], " -- ".join(tail) def _type_param_formatter(self, tparam: TypeParam) -> tuple[list[str], str] | None: v = tparam.name From 1634368beed4cbe8d76ae2f18cda2bfa357e806d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Sep 2023 18:08:41 -0700 Subject: [PATCH 2/5] Fix js tests --- requirements_dev.txt | 1 + sphinx_js/renderers.py | 10 +++++++--- tests/test_build_js/test_build_js.py | 24 ++++++++++++------------ tests/test_build_ts/source/class.ts | 13 +++++++++++++ tests/test_build_ts/test_build_ts.py | 26 ++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 15 deletions(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index ee574901..39460775 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -5,3 +5,4 @@ pytest==7.2.0 recommonmark==0.7.1 nox twine==4.0.2 +beautifulsoup4 diff --git a/sphinx_js/renderers.py b/sphinx_js/renderers.py index d4fc4441..c6b4e73e 100644 --- a/sphinx_js/renderers.py +++ b/sphinx_js/renderers.py @@ -208,11 +208,15 @@ def _formal_params(self, obj: Function | Class) -> str: return "({})".format(", ".join(formals)) - def format_type(self, type: Type, escape: bool = False) -> str: + def format_type(self, type: Type, escape: bool = False, bold: bool = True) -> str: if not type: return "" if isinstance(type, str): - return self.format_type([type]) + if bold: + type = "**%s**" % type + if escape: + type = rst.escape(type) + return type it = iter(type) def strs() -> Iterator[str]: @@ -287,7 +291,7 @@ def _exception_formatter(self, exception: Exc) -> tuple[list[str], str]: """Derive heads and tail from ``@throws`` blocks.""" heads = ["throws"] if exception.type: - heads.append(self.format_type(exception.type)) + heads.append(self.format_type(exception.type, bold=False)) tail = exception.description return heads, tail diff --git a/tests/test_build_js/test_build_js.py b/tests/test_build_js/test_build_js.py index 0b9e85ba..7f424214 100644 --- a/tests/test_build_js/test_build_js.py +++ b/tests/test_build_js/test_build_js.py @@ -43,14 +43,14 @@ def test_autofunction_typedef(self): """Make sure @typedef uses can be documented with autofunction.""" self._file_contents_eq( "autofunction_typedef", - "TypeDefinition()\n\n Arguments:\n * **width** (*Number*) -- width in pixels\n", + "TypeDefinition()\n\n Arguments:\n * **width** (**Number**) -- width in pixels\n", ) def test_autofunction_callback(self): """Make sure @callback uses can be documented with autofunction.""" self._file_contents_eq( "autofunction_callback", - "requestCallback(responseCode)\n\n Some global callback\n\n Arguments:\n * **responseCode** (*number*) --\n", + "requestCallback(responseCode)\n\n Some global callback\n\n Arguments:\n * **responseCode** (**number**) --\n", ) def test_autofunction_example(self): @@ -71,10 +71,10 @@ def test_autofunction_destructured_params(self): "autofunction_destructured_params", "destructuredParams(p1, p2)\n\n" " Arguments:\n" - " * **p1** (*number*) --\n\n" - " * **p2** (*Object*) --\n\n" - " * **p2.foo** (*string*) --\n\n" - " * **p2.bar** (*string*) --\n", + " * **p1** (**number**) --\n\n" + " * **p2** (**Object**) --\n\n" + " * **p2.foo** (**string**) --\n\n" + " * **p2.bar** (**string**) --\n", ) def test_autofunction_defaults_in_doclet(self): @@ -84,9 +84,9 @@ def test_autofunction_defaults_in_doclet(self): "autofunction_defaults_doclet", 'defaultsDocumentedInDoclet(func=() => 5, str="a string with \\" quote", strNum="42", strBool="true", num=5, nil=null)\n\n' " Arguments:\n" - " * **func** (*function*) --\n\n" - " * **strNum** (*string*) --\n\n" - " * **strBool** (*string*) --\n", + " * **func** (**function**) --\n\n" + " * **strNum** (**string**) --\n\n" + " * **strBool** (**string**) --\n", ) def test_autofunction_defaults_in_code(self): @@ -361,7 +361,7 @@ def test_restructuredtext_injection(self): "injection(a_, b)\n\n" " Arguments:\n" " * **a_** -- Snorf\n\n" - " * **b** (>>type_<<) -- >>Borf_<<\n\n" + " * **b** (**type_**) -- >>Borf_<<\n\n" " Returns:\n" " **rtype_** -- >>Dorf_<<\n", ) @@ -377,7 +377,7 @@ def test_union_types(self): switched from " | " as the union separator back to "|". """ - assert "* **fnodeA** (*Node|Fnode*) --" in self._file_contents("union") + assert "* **fnodeA** (**Node|Fnode**) --" in self._file_contents("union") def test_field_list_unwrapping(self): """Ensure the tails of field lists have line breaks and leading @@ -414,7 +414,7 @@ def test_field_list_unwrapping(self): FIELDS = """ Arguments: - * **node** (*Node*) -- Something of a single type + * **node** (**Node**) -- Something of a single type Throws: **PartyError|FartyError** -- Something with multiple types and a diff --git a/tests/test_build_ts/source/class.ts b/tests/test_build_ts/source/class.ts index de9365c6..0a7962ce 100644 --- a/tests/test_build_ts/source/class.ts +++ b/tests/test_build_ts/source/class.ts @@ -53,3 +53,16 @@ export interface OptionalThings { foop?(): void; boop?: boolean; } + +/** + * Words words words + * @param a An optional thing + * @returns The result + */ +export function blah(a: OptionalThings) : ConstructorlessClass { + return 0 as ConstructorlessClass; +} + +export function thunk(b : typeof blah) { + +} diff --git a/tests/test_build_ts/test_build_ts.py b/tests/test_build_ts/test_build_ts.py index e29fd28f..896673b9 100644 --- a/tests/test_build_ts/test_build_ts.py +++ b/tests/test_build_ts/test_build_ts.py @@ -1,3 +1,4 @@ +from bs4 import BeautifulSoup from conftest import TYPEDOC_VERSION from tests.testing import SphinxBuildTestCase @@ -121,3 +122,28 @@ def test_implements_links(self): assert 'href="index.html#class.Interface"' in self._file_contents( "autoclass_class_with_interface_and_supers" ) + + def test_xrefs(self): + soup = BeautifulSoup(self._file_contents("xrefs"), "html.parser") + + def get_links(id): + return soup.find(id=id).parent.find_all("a") + + links = get_links("blah") + href = links[1] + assert href.attrs["class"] == ["reference", "internal"] + assert href.attrs["href"] == "autoclass_interface_optionals.html#OptionalThings" + assert href.attrs["title"] == "OptionalThings" + assert next(href.children).name == "code" + assert href.get_text() == "OptionalThings()" + + href = links[2] + assert href.attrs["class"] == ["reference", "internal"] + assert ( + href.attrs["href"] == "autoclass_constructorless.html#ConstructorlessClass" + ) + assert href.get_text() == "ConstructorlessClass()" + + thunk_links = get_links("thunk") + assert thunk_links[1].get_text() == "ConstructorlessClass()" + assert thunk_links[2].get_text() == "OptionalThings()" From b81fbd4008c50eb83b499b924ae674cf9979f231 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Sep 2023 18:11:55 -0700 Subject: [PATCH 3/5] Add forgotten file --- tests/test_build_ts/source/docs/xrefs.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/test_build_ts/source/docs/xrefs.rst diff --git a/tests/test_build_ts/source/docs/xrefs.rst b/tests/test_build_ts/source/docs/xrefs.rst new file mode 100644 index 00000000..a369855d --- /dev/null +++ b/tests/test_build_ts/source/docs/xrefs.rst @@ -0,0 +1,8 @@ +.. js:autofunction:: blah + + blah + +.. js:autofunction:: thunk + + Xrefs in the function type of the argument + From 13d7108b384b63c80cb0cf84a738d085447ab761 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Sep 2023 18:12:43 -0700 Subject: [PATCH 4/5] format --- tests/test_build_ts/source/docs/xrefs.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_build_ts/source/docs/xrefs.rst b/tests/test_build_ts/source/docs/xrefs.rst index a369855d..cfca799d 100644 --- a/tests/test_build_ts/source/docs/xrefs.rst +++ b/tests/test_build_ts/source/docs/xrefs.rst @@ -5,4 +5,3 @@ .. js:autofunction:: thunk Xrefs in the function type of the argument - From 051d17172914f8a0194b2f35db7196266a8fb120 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Sep 2023 18:14:36 -0700 Subject: [PATCH 5/5] Fix test --- tests/test_build_ts/test_build_ts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_build_ts/test_build_ts.py b/tests/test_build_ts/test_build_ts.py index 896673b9..ca6c6dc1 100644 --- a/tests/test_build_ts/test_build_ts.py +++ b/tests/test_build_ts/test_build_ts.py @@ -145,5 +145,5 @@ def get_links(id): assert href.get_text() == "ConstructorlessClass()" thunk_links = get_links("thunk") - assert thunk_links[1].get_text() == "ConstructorlessClass()" - assert thunk_links[2].get_text() == "OptionalThings()" + assert thunk_links[1].get_text() == "OptionalThings()" + assert thunk_links[2].get_text() == "ConstructorlessClass()"