From 0b8fa7f1e5d5e68f87b5beac0ecaef676981b3e7 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Tue, 20 Apr 2021 21:49:43 +0200 Subject: [PATCH] When rendering template params, insert name by parsing Uses internals in the C++ domain. Needs Sphinx 4.1. Fixes michaeljones/breathe#652 --- breathe/renderer/sphinxrenderer.py | 62 ++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index 898dcebb5..458069118 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1,4 +1,5 @@ -from breathe.parser import DoxygenCompoundParser +import sphinx +from breathe.parser import compound, DoxygenCompoundParser from breathe.project import ProjectInfo from breathe.renderer import RenderContext from breathe.renderer.filter import Filter @@ -925,8 +926,8 @@ def visit_doxygen(self, node) -> List[Node]: nodelist = [] # Process all the compound children - for compound in node.get_compound(): - nodelist.extend(self.render(compound)) + for n in node.get_compound(): + nodelist.extend(self.render(n)) return nodelist def visit_doxygendef(self, node) -> List[Node]: @@ -2013,7 +2014,8 @@ def visit_friendclass(self, node) -> List[Node]: signode += nodes.Text(node.name) return [desc] - def visit_param(self, node) -> List[Node]: + def visit_param(self, node: compound.paramTypeSub, *, + insertDeclNameByParsing: bool = False) -> List[Node]: nodelist = [] # Parameter type @@ -2031,10 +2033,30 @@ def visit_param(self, node) -> List[Node]: # Parameter name if node.declname: - if nodelist: - nodelist.append(nodes.Text(" ")) - nodelist.append(nodes.emphasis(text=node.declname)) - + dom = self.get_domain() + if not dom: + dom = 'cpp' + appendDeclName = True + if insertDeclNameByParsing: + if dom == 'cpp' and sphinx.version_info >= (4, 1, 0): + parser = cpp.DefinitionParser( + ''.join(n.astext() for n in nodelist), + location=self.state.state_machine.get_source_and_line(), + config=self.app.config) + ast = parser._parse_type(named='single', outer='templateParam') + assert ast.name is None + nn = cpp.ASTNestedName( + names=[cpp.ASTNestedNameElement(cpp.ASTIdentifier(node.declname), None)], + templates=[False], rooted=False) + ast.name = nn + # the actual nodes doesn't matter, as it is astext()-ed later + nodelist = [nodes.Text(str(ast))] + appendDeclName = False + + if appendDeclName: + if nodelist: + nodelist.append(nodes.Text(" ")) + nodelist.append(nodes.emphasis(text=node.declname)) elif self.output_defname and node.defname: # We only want to output the definition name (from the cpp file) if the declaration name # (from header file) isn't present @@ -2053,6 +2075,16 @@ def visit_param(self, node) -> List[Node]: return nodelist + def visit_templateparamlist(self, node: compound.templateparamlistTypeSub) -> List[Node]: + nodelist = [] # type: List[Node] + self.output_defname = False + for i, item in enumerate(node.param): + if i: + nodelist.append(nodes.Text(", ")) + nodelist.extend(self.visit_param(item, insertDeclNameByParsing=True)) + self.output_defname = True + return nodelist + def visit_docparamlist(self, node) -> List[Node]: """Parameter/Exception/TemplateParameter documentation""" @@ -2081,16 +2113,6 @@ def visit_docparamnamelist(self, node) -> List[Node]: def visit_docparamname(self, node) -> List[Node]: return self.render_iterable(node.content_) - def visit_templateparamlist(self, node) -> List[Node]: - nodelist = [] # type: List[Node] - self.output_defname = False - for i, item in enumerate(node.param): - if i: - nodelist.append(nodes.Text(", ")) - nodelist.extend(self.render(item)) - self.output_defname = True - return nodelist - def visit_unknown(self, node) -> List[Node]: """Visit a node of unknown type.""" return [] @@ -2162,10 +2184,10 @@ def dispatch_memberdef(self, node) -> List[Node]: "mixedcontainer": visit_mixedcontainer, "description": visit_description, "param": visit_param, + "templateparamlist": visit_templateparamlist, "docparamlist": visit_docparamlist, "docparamnamelist": visit_docparamnamelist, "docparamname": visit_docparamname, - "templateparamlist": visit_templateparamlist, "docxrefsect": visit_docxrefsect, "docvariablelist": visit_docvariablelist, "docvarlistentry": visit_docvarlistentry, @@ -2188,7 +2210,7 @@ def render(self, node, context: Optional[RenderContext] = None) -> List[Node]: result = self.visit_unicode(node) else: method = SphinxRenderer.methods.get(node.node_type, SphinxRenderer.visit_unknown) - result = method(self, node) + result = method(self, node) # type: ignore return result def render_optional(self, node) -> List[Node]: