From ffd2d4a79bc0b7931aed4c5ad02e6e54d5b4e4b7 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sun, 20 Nov 2022 16:39:51 -0800 Subject: [PATCH] DOCS Fix rendering of function types and null (#3271) --- docs/sphinx_pyodide/sphinx_pyodide/jsdoc.py | 45 +++--- docs/sphinx_pyodide/tests/test_directives.py | 143 +++++++++++++++++++ 2 files changed, 170 insertions(+), 18 deletions(-) diff --git a/docs/sphinx_pyodide/sphinx_pyodide/jsdoc.py b/docs/sphinx_pyodide/sphinx_pyodide/jsdoc.py index 525afb2aa..f5fc08b30 100644 --- a/docs/sphinx_pyodide/sphinx_pyodide/jsdoc.py +++ b/docs/sphinx_pyodide/sphinx_pyodide/jsdoc.py @@ -128,14 +128,33 @@ def object_literal_type_name(self, decl): valuetype = self._type_name(index_sig["type"]) children.append(f"[{keyname}: {keytype}]: {valuetype}") if "children" in decl: - children.extend( - child["name"] + ": " + self._type_name(child["type"]) - for child in decl["children"] - ) + for child in decl["children"]: + maybe_optional = "" + if child["flags"].get("isOptional"): + maybe_optional = "?" + children.append( + child["name"] + maybe_optional + ": " + self._type_name(child["type"]) + ) return "{" + ", ".join(children) + "}" +def function_type_name(self, decl): + decl_sig = None + if "signatures" in decl: + decl_sig = decl["signatures"][0] + elif decl["kindString"] == "Call signature": + decl_sig = decl + assert decl_sig + params = [ + f'{ty["name"]}: {self._type_name(ty["type"])}' + for ty in decl_sig.get("parameters", []) + ] + params_str = ", ".join(params) + ret_str = self._type_name(decl_sig["type"]) + return f"({params_str}) => {ret_str}" + + def reflection_type_name(self, type): """Fill in the type names for type_of_type == "reflection" @@ -154,21 +173,9 @@ def reflection_type_name(self, type): (a : string, b : number) => string """ decl = type["declaration"] - if decl["kindString"] == "Type literal": + if decl["kindString"] == "Type literal" and "signatures" not in decl: return object_literal_type_name(self, decl) - decl_sig = None - if "signatures" in decl: - decl_sig = decl["signatures"][0] - elif decl["kindString"] == "Call signature": - decl_sig = decl - assert decl_sig - params = [ - f'{ty["name"]}: {self._type_name(ty["type"])}' - for ty in decl_sig.get("parameters", []) - ] - params_str = ", ".join(params) - ret_str = self._type_name(decl_sig["type"]) - return f"({params_str}) => {ret_str}" + return function_type_name(self, decl) def _type_name(self, type): @@ -189,6 +196,8 @@ def _type_name(self, type): name = type["name"] type = self._type_name(type["element"]) return f"{name}: {type}" + if type_of_type == "literal" and type["value"] is None: + return "null" raise NotImplementedError( f"Cannot render type name for type_of_type={type_of_type}" ) diff --git a/docs/sphinx_pyodide/tests/test_directives.py b/docs/sphinx_pyodide/tests/test_directives.py index f1fb91dbc..7b5a535d7 100644 --- a/docs/sphinx_pyodide/tests/test_directives.py +++ b/docs/sphinx_pyodide/tests/test_directives.py @@ -201,3 +201,146 @@ def test_summary(): "loadPackagesFromImports", "(code, messageCallback, errorCallback)", ) + + +def test_type_name(): + tn = inner_analyzer._type_name + assert tn({"name": "void", "type": "intrinsic"}) == "void" + assert tn({"value": None, "type": "literal"}) == "null" + assert ( + tn( + { + "name": "Promise", + "type": "reference", + "typeArguments": [{"name": "string", "type": "intrinsic"}], + } + ) + == "Promise" + ) + + assert ( + tn( + { + "asserts": False, + "name": "jsobj", + "targetType": {"name": "PyProxy", "type": "reference"}, + "type": "predicate", + } + ) + == "boolean (typeguard for PyProxy)" + ) + + assert ( + tn( + { + "declaration": { + "kindString": "Method", + "name": "messageCallback", + "signatures": [ + { + "kindString": "Call signature", + "name": "messageCallback", + "parameters": [ + { + "flags": {}, + "kindString": "Parameter", + "name": "message", + "type": {"name": "string", "type": "intrinsic"}, + } + ], + "type": {"name": "void", "type": "intrinsic"}, + } + ], + }, + "type": "reflection", + } + ) + == "(message: string) => void" + ) + + assert ( + tn( + { + "name": "Iterable", + "type": "reference", + "typeArguments": [ + { + "elements": [ + { + "element": {"name": "string", "type": "intrinsic"}, + "isOptional": False, + "name": "key", + "type": "named-tuple-member", + }, + { + "element": {"name": "any", "type": "intrinsic"}, + "isOptional": False, + "name": "value", + "type": "named-tuple-member", + }, + ], + "type": "tuple", + } + ], + } + ) + == "Iterable<[key: string, value: any]>" + ) + + assert ( + tn( + { + "declaration": { + "flags": {}, + "indexSignature": { + "flags": {}, + "kindString": "Index signature", + "parameters": [ + { + "flags": {}, + "name": "key", + "type": {"name": "string", "type": "intrinsic"}, + } + ], + "type": {"name": "string", "type": "intrinsic"}, + }, + "kindString": "Type literal", + }, + "type": "reflection", + } + ) + == "{[key: string]: string}" + ) + + assert ( + tn( + { + "declaration": { + "children": [ + { + "flags": {}, + "kindString": "Property", + "name": "cache", + "type": {"name": "PyProxyCache", "type": "reference"}, + }, + { + "flags": {"isOptional": True}, + "kindString": "Property", + "name": "destroyed_msg", + "type": {"name": "string", "type": "intrinsic"}, + }, + { + "flags": {}, + "kindString": "Property", + "name": "ptr", + "type": {"name": "number", "type": "intrinsic"}, + }, + ], + "flags": {}, + "kindString": "Type literal", + }, + "type": "reflection", + } + ) + == "{cache: PyProxyCache, destroyed_msg?: string, ptr: number}" + )