From c45a0272530e7502a32924be429074b64019992a Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 13 Sep 2020 16:25:09 +0200 Subject: [PATCH] C, recursive alias declarations Fixes sphinx-doc/sphinx#8141 --- CHANGES | 2 + doc/usage/restructuredtext/domains.rst | 12 +++++ sphinx/domains/c.py | 71 +++++++++++++++++++------- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index dca1b4a2e40..8a5da7a19bd 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,8 @@ Features added * #8100: html: Show a better error message for failures on copying html_static_files +* #8141: C: added a ``maxdepth`` option to :rst:dir:`c:alias` to insert + nested declarations. Bugs fixed ---------- diff --git a/doc/usage/restructuredtext/domains.rst b/doc/usage/restructuredtext/domains.rst index 311b03d666c..f3754ab7c20 100644 --- a/doc/usage/restructuredtext/domains.rst +++ b/doc/usage/restructuredtext/domains.rst @@ -744,6 +744,18 @@ The following directive can be used for this purpose. .. versionadded:: 3.2 + + .. rubric:: Options + + .. rst:directive:option:: maxdepth: int + + Insert nested declarations as well, up to the total depth given. + Use 0 for infinite depth and 1 for just the mentioned declaration. + Defaults to 1. + + .. versionadded:: 3.3 + + .. c:namespace-pop:: diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index c759dacbdf6..fc9ad7a1e10 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -136,8 +136,8 @@ def describe_signature(self, signode: TextElement, mode: str, env: "BuildEnviron reftype='identifier', reftarget=targetText, modname=None, classname=None) - # key = symbol.get_lookup_key() - # pnode['c:parent_key'] = key + key = symbol.get_lookup_key() + pnode['c:parent_key'] = key if self.is_anon(): pnode += nodes.strong(text="[anonymous]") else: @@ -1562,6 +1562,11 @@ def get_all_symbols(self) -> Iterator["Symbol"]: for s in sChild.get_all_symbols(): yield s + @property + def children(self) -> Iterator["Symbol"]: + for c in self._children: + yield c + @property def children_recurse_anon(self) -> Iterator["Symbol"]: for c in self._children: @@ -3408,10 +3413,13 @@ def run(self) -> List[Node]: class AliasNode(nodes.Element): - def __init__(self, sig: str, env: "BuildEnvironment" = None, + def __init__(self, sig: str, maxdepth: int, document: Any, env: "BuildEnvironment" = None, parentKey: LookupKey = None) -> None: super().__init__() self.sig = sig + self.maxdepth = maxdepth + assert maxdepth >= 0 + self.document = document if env is not None: if 'c:parent_symbol' not in env.temp_data: root = env.domaindata['c']['root_symbol'] @@ -3428,6 +3436,38 @@ def copy(self: T) -> T: class AliasTransform(SphinxTransform): default_priority = ReferencesResolver.default_priority - 1 + def _render_symbol(self, s: Symbol, maxdepth: int, document: Any) \ + -> List[Union[addnodes.desc_signature, addnodes.desc_content]]: + nodes = [] + options = dict() # type: ignore + signode = addnodes.desc_signature('', '') + nodes.append(signode) + s.declaration.describe_signature(signode, 'markName', self.env, options) + if maxdepth == 0: + recurse = True + elif maxdepth == 1: + recurse = False + else: + maxdepth -= 1 + recurse = True + if recurse: + content = addnodes.desc_content() + desc = addnodes.desc() + content.append(desc) + desc.document = document + desc['domain'] = 'c' + # 'desctype' is a backwards compatible attribute + desc['objtype'] = desc['desctype'] = 'alias' + desc['noindex'] = True + + for sChild in s.children: + childNodes = self._render_symbol(sChild, maxdepth, document) + desc.extend(childNodes) + + if len(desc.children) != 0: + nodes.append(content) + return nodes + def apply(self, **kwargs: Any) -> None: for node in self.document.traverse(AliasNode): sig = node.sig @@ -3468,17 +3508,16 @@ def apply(self, **kwargs: Any) -> None: logger.warning("Could not find C declaration for alias '%s'." % name, location=node) node.replace_self(signode) - else: - nodes = [] - options = dict() # type: ignore - signode = addnodes.desc_signature(sig, '') - nodes.append(signode) - s.declaration.describe_signature(signode, 'markName', self.env, options) - node.replace_self(nodes) + continue + + nodes = self._render_symbol(s, maxdepth=node.maxdepth, document=node.document) + node.replace_self(nodes) class CAliasObject(ObjectDescription): - option_spec = {} # type: Dict + option_spec = { + 'maxdepth': directives.nonnegative_int + } # type: Dict def run(self) -> List[Node]: if ':' in self.name: @@ -3494,16 +3533,10 @@ def run(self) -> List[Node]: node['noindex'] = True self.names = [] # type: List[str] + maxdepth = self.options.get('maxdepth', 1) signatures = self.get_signatures() for i, sig in enumerate(signatures): - node.append(AliasNode(sig, env=self.env)) - - contentnode = addnodes.desc_content() - node.append(contentnode) - self.before_content() - self.state.nested_parse(self.content, self.content_offset, contentnode) - self.env.temp_data['object'] = None - self.after_content() + node.append(AliasNode(sig, maxdepth, self.state.document, env=self.env)) return [node]