diff --git a/sphinx_js/renderers.py b/sphinx_js/renderers.py index 12bc0ef7..f722dad3 100644 --- a/sphinx_js/renderers.py +++ b/sphinx_js/renderers.py @@ -467,10 +467,11 @@ def _return_formatter(self, return_: Return) -> tuple[list[str], str]: def _type_param_formatter(self, tparam: TypeParam) -> tuple[list[str], str] | None: v = tparam.name + descr = render_description(tparam.description) if tparam.extends: - v += " extends " + self.render_type(tparam.extends) + descr += " (extends " + self.render_type(tparam.extends) + ")" heads = ["typeparam", v] - return heads, render_description(tparam.description) + return heads, descr def _param_formatter(self, param: Param) -> tuple[list[str], str] | None: """Derive heads and tail from ``@param`` blocks.""" diff --git a/tests/test_build_ts/source/module.ts b/tests/test_build_ts/source/module.ts index 3b49ab04..71256aca 100644 --- a/tests/test_build_ts/source/module.ts +++ b/tests/test_build_ts/source/module.ts @@ -25,8 +25,11 @@ export class A { } } -export class Z { - x: number; +/** + * @typeParam T Description of T + */ +export class Z { + x: T; constructor(a: number, b: number) {} z() {} diff --git a/tests/test_build_ts/test_build_ts.py b/tests/test_build_ts/test_build_ts.py index 362aea56..cfa08971 100644 --- a/tests/test_build_ts/test_build_ts.py +++ b/tests/test_build_ts/test_build_ts.py @@ -1,6 +1,6 @@ from textwrap import dedent -from bs4 import BeautifulSoup +from bs4 import BeautifulSoup, Tag from conftest import TYPEDOC_VERSION from tests.testing import SphinxBuildTestCase @@ -303,6 +303,9 @@ class module.Z(a, b) *exported from* "module" + Type parameters: + **T** -- Description of T (extends "A()") + Arguments: * **a** (number) @@ -310,7 +313,7 @@ class module.Z(a, b) Z.x - type: number + type: T Z.z() @@ -342,6 +345,21 @@ def test_implements_links(self): "autoclass_class_with_interface_and_supers" ) + def test_extends_type_param_links(self): + """Make sure implemented interfaces link to their definitions.""" + soup = BeautifulSoup(self._file_contents("automodule"), "html.parser") + z = soup.find(id="module.Z") + assert z + assert z.parent + t = z.parent.find_all(class_="sphinx_js-type") + s: Tag = t[0] + href: Tag = list(s.children)[0] + assert href.name == "a" + assert href.get_text() == "A()" + assert href.attrs["class"] == ["reference", "internal"] + assert href.attrs["title"] == "module.A" + assert href.attrs["href"] == "#module.A" + def test_xrefs(self): soup = BeautifulSoup(self._file_contents("xrefs"), "html.parser") diff --git a/tests/test_typedoc_analysis/test_typedoc_analysis.py b/tests/test_typedoc_analysis/test_typedoc_analysis.py index 32b96a0c..acc7a367 100644 --- a/tests/test_typedoc_analysis/test_typedoc_analysis.py +++ b/tests/test_typedoc_analysis/test_typedoc_analysis.py @@ -501,7 +501,8 @@ def test_constrained_by_key(self): rst = rst.replace("\\", "").replace(" ", " ") assert ":typeparam T: The type of the object" in rst assert ( - ":typeparam K extends string | number | symbol: The type of the key" in rst + ":typeparam K: The type of the key (extends string | number | symbol)" + in rst ) def test_class_constrained(self): @@ -522,7 +523,7 @@ def test_class_constrained(self): a._options = {} rst = a.rst([obj.name], obj) rst = rst.replace("\\ ", "").replace("\\", "").replace(" ", " ") - assert ":typeparam S extends number[]: The type we contain" in rst + assert ":typeparam S: The type we contain (extends number[])" in rst def test_constrained_by_constructor(self): """Make sure ``new ()`` expressions and, more generally, per-property