diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index dff0c982..583f74b0 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1975,27 +1975,26 @@ def visit_function(self, node) -> List[Node]: ) else: elements = [self.create_template_prefix(node)] + # TODO: handle constexpr when parser has been updated + # but Doxygen seems to leave it in the type anyway + typ = "".join(n.astext() for n in self.render(node.get_type())) + # Doxygen sometimes leaves 'static' in the type, + # e.g., for "constexpr static auto f()" + typ = typ.replace("static ", "") if node.static == "yes": elements.append("static") if node.inline == "yes": elements.append("inline") if node.kind == "friend": + # In Doxygen up to somewhere between 1.8.17 to exclusive 1.9.1 + # the 'friend' part is also left in the type. + # See also: #767, #916 + typ = re.sub(r"(^|\s+)friend(\s+)", r"\1\2", typ) elements.append("friend") if node.virt in ("virtual", "pure-virtual"): elements.append("virtual") if node.explicit == "yes": elements.append("explicit") - # TODO: handle constexpr when parser has been updated - # but Doxygen seems to leave it in the type anyway - typ = "".join(n.astext() for n in self.render(node.get_type())) - # Doxygen sometimes leaves 'static' in the type, - # e.g., for "constexpr static auto f()" - typ = typ.replace("static ", "") - # In Doxygen up to somewhere between 1.8.17 to exclusive 1.9.1 - # the 'friend' part is also left in the type. - # See also #767. - if typ.startswith("friend "): - typ = typ[7:] elements.append(typ) elements.append(name) elements.append(node.get_argsstring()) diff --git a/tests/test_renderer.py b/tests/test_renderer.py index a858c65d..42f9054e 100644 --- a/tests/test_renderer.py +++ b/tests/test_renderer.py @@ -592,3 +592,18 @@ def test_ellipsis(app): # Verify that parsing an ellipsis works ast_param = cls._parse_args(argsstrings[0]) ret = cls._resolve_function(matches, ast_param, None) + + +def test_render_constexpr_friend_func(app): + member_def = WrappedMemberDef( + kind="function", + definition="constexpr friend bool operator==", + type_="constexpr friend bool", + name="operator==", + argsstring="(cat const x, int const y)", + virt="non-virtual", + const="no", + ) + rendered = render(app, member_def) + signature = find_node(rendered, "desc_signature") + assert signature.astext().startswith("friend constexpr bool")