From ddadba46294052f2d04b1cc35be8a0191757ed82 Mon Sep 17 00:00:00 2001 From: yut23 Date: Thu, 16 Jan 2025 16:22:16 -0500 Subject: [PATCH] Fix error in template specialization with qualified arguments --- breathe/renderer/filter.py | 7 ++++++- breathe/renderer/sphinxrenderer.py | 11 +++++++---- documentation/source/conf.py | 1 + documentation/source/specific.rst | 8 ++++++++ examples/specific/Makefile | 2 +- .../specific/cpp_ns_template_specialization.cfg | 13 +++++++++++++ .../specific/cpp_ns_template_specialization.h | 15 +++++++++++++++ 7 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 examples/specific/cpp_ns_template_specialization.cfg create mode 100644 examples/specific/cpp_ns_template_specialization.h diff --git a/breathe/renderer/filter.py b/breathe/renderer/filter.py index 3860b2f97..e94692fc4 100644 --- a/breathe/renderer/filter.py +++ b/breathe/renderer/filter.py @@ -475,7 +475,12 @@ def allow(self, node_stack) -> bool: name = self.name_accessor(node_stack) try: - namespace, name = name.rsplit("::", 1) + # strip out any template arguments before splitting on '::', to + # avoid errors if a template specialization has qualified arguments + # (see examples/specific/cpp_ns_template_specialization) + cleaned_name, sep, rest = name.partition("<") + namespace, name = cleaned_name.rsplit("::", 1) + name += sep + rest except ValueError: namespace, name = "", name diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index 75157b6ac..236d31031 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1021,12 +1021,15 @@ def visit_class(self, node) -> List[Node]: # Defer to domains specific directive. names = self.get_qualification() - # TODO: this breaks if it's a template specialization - # and one of the arguments contain '::' + # strip out any template arguments before splitting on '::', to + # avoid errors if a template specialization has qualified arguments + # (see examples/specific/cpp_ns_template_specialization) + cleaned_name, sep, rest = nodeDef.compoundname.partition("<") if self.nesting_level == 0: - names.extend(nodeDef.compoundname.split("::")) + names.extend(cleaned_name.split("::")) else: - names.append(nodeDef.compoundname.split("::")[-1]) + names.append(cleaned_name.split("::")[-1]) + names[-1] += sep + rest decls = [ self.create_template_prefix(nodeDef), self.join_nested_name(names), diff --git a/documentation/source/conf.py b/documentation/source/conf.py index b56a4769d..bbcf35f7b 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -232,6 +232,7 @@ "cpp_function_lookup": "../../examples/specific/cpp_function_lookup/xml/", "cpp_friendclass": "../../examples/specific/cpp_friendclass/xml/", "cpp_inherited_members": "../../examples/specific/cpp_inherited_members/xml/", + "cpp_ns_template_specialization": "../../examples/specific/cpp_ns_template_specialization/xml/", "cpp_trailing_return_type": "../../examples/specific/cpp_trailing_return_type/xml/", "cpp_constexpr_hax": "../../examples/specific/cpp_constexpr_hax/xml/", "xrefsect": "../../examples/specific/xrefsect/xml/", diff --git a/documentation/source/specific.rst b/documentation/source/specific.rst index f39126709..39c00db83 100644 --- a/documentation/source/specific.rst +++ b/documentation/source/specific.rst @@ -239,6 +239,14 @@ C++ Inherited Members .. doxygenclass:: B :project: cpp_inherited_members +C++ Template Specialization with Namespace +------------------------------------------ + +.. cpp:namespace:: @ex_specific_cpp_ns_template_specialization + +.. doxygenfile:: cpp_ns_template_specialization.h + :project: cpp_ns_template_specialization + C++ Trailing Return Type ------------------------ diff --git a/examples/specific/Makefile b/examples/specific/Makefile index 91941d5bf..22ed568e1 100644 --- a/examples/specific/Makefile +++ b/examples/specific/Makefile @@ -26,7 +26,7 @@ projects = nutshell alias rst inline namespacefile array inheritance \ enum define interface xrefsect tables \ cpp_anon cpp_concept cpp_enum cpp_union cpp_function cpp_friendclass \ cpp_inherited_members cpp_trailing_return_type cpp_constexpr_hax \ - cpp_function_lookup \ + cpp_function_lookup cpp_ns_template_specialization \ c_file c_struct c_enum c_typedef c_macro c_union membergroups \ simplesect code_blocks dot_graphs diff --git a/examples/specific/cpp_ns_template_specialization.cfg b/examples/specific/cpp_ns_template_specialization.cfg new file mode 100644 index 000000000..c9cd9ad05 --- /dev/null +++ b/examples/specific/cpp_ns_template_specialization.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "C++ Template Specialization with Namespace" +OUTPUT_DIRECTORY = cpp_ns_template_specialization +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = cpp_ns_template_specialization.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES + +WARN_IF_UNDOCUMENTED = NO diff --git a/examples/specific/cpp_ns_template_specialization.h b/examples/specific/cpp_ns_template_specialization.h new file mode 100644 index 000000000..b944ee797 --- /dev/null +++ b/examples/specific/cpp_ns_template_specialization.h @@ -0,0 +1,15 @@ +namespace ns1 { +struct Foo { + int value; +}; +} // namespace ns1 + +namespace ns2 { +template struct Trait { + static constexpr bool valid = false; +}; + +template <> struct Trait { + static constexpr bool valid = true; +}; +} // namespace ns2