From 11cd4202214641481e39db4bbc28c5d8eb087b21 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Fri, 27 Mar 2020 12:32:58 +0100 Subject: [PATCH 1/5] Create directives with the domain name --- breathe/renderer/sphinxrenderer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index d5654e15..b0e548df 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -148,11 +148,13 @@ def create(domain, args): cls, name = DomainDirectiveFactory.php_classes.get( arg_0, (php.PhpClasslike, 'class')) else: + domain = 'cpp' cls, name = DomainDirectiveFactory.cpp_classes.get( args[0], (cpp.CPPMemberObject, 'member')) # Replace the directive name because domain directives don't know how to handle # Breathe's "doxygen" directives. - args = [name] + args[1:] + assert ':' not in name + args = [domain + ':' + name] + args[1:] return cls(*args) From b6a11df55e8aff9fab27e40ee7e06abf495cb145 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Wed, 23 Jan 2019 22:21:24 +0100 Subject: [PATCH 2/5] Let Sphinx handle base classes --- breathe/renderer/sphinxrenderer.py | 52 ++++++++++-------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index b0e548df..faecc56a 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -31,7 +31,6 @@ def __exit__(self, et, ev, bt): class DoxyCPPClassObject(cpp.CPPClassObject): - __bases = [] @property def display_object_type(self): @@ -43,32 +42,7 @@ def display_object_type(self): return self.objtype def parse_definition(self, parser): - # add the base classes - ast = parser.parse_declaration("class", "class") - - bases = [] - - for base in self.__bases: - namestr = base.content_[0].value - - # build a name object - # TODO: work out if we can use base.refid in a pending_xref somewhere - parser = cpp.DefinitionParser(namestr, - location=self.get_source_info(), - config=self.env.config) - name = parser._parse_nested_name() - parser.assert_end() - - bases.append( - cpp.ASTBaseClass(name, base.prot, base.virt == 'virtual', False) - ) - - ast.declaration.bases = bases - - return ast - - def augment(self, bases): - self.__bases = bases or [] + return parser.parse_declaration("class", "class") class DomainDirectiveFactory(object): @@ -358,13 +332,10 @@ def create_template_prefix(self, decl): nodes = self.render(decl.templateparamlist) return 'template<' + ''.join(n.astext() for n in nodes) + '>' - def run_domain_directive(self, kind, names, augment=None): + def run_domain_directive(self, kind, names): domain_directive = DomainDirectiveFactory.create( self.context.domain, [kind, names] + self.context.directive_args[2:]) - if hasattr(domain_directive, 'augment') and augment is not None: - domain_directive.augment(**augment) - # Translate Breathe's no-link option into the standard noindex option. if 'no-link' in self.context.directive_args[2]: domain_directive.options['noindex'] = True @@ -500,13 +471,24 @@ def render_signature(file_data, doxygen_target, name, kind): templatePrefix = self.create_template_prefix(file_data.compounddef) arg = "%s %s" % (templatePrefix, self.get_fully_qualified_name()) + # add base classes if kind in ('class', 'struct'): - augment = dict(bases=file_data.compounddef.basecompoundref) - else: - augment = None + bs = [] + for base in file_data.compounddef.basecompoundref: + b = [] + if base.prot is not None: + b.append(base.prot) + if base.virt == 'virtual': + b.append("virtual") + b.append(base.content_[0].value) + bs.append(" ".join(b)) + if len(bs) != 0: + arg += " : " + arg += ", ".join(bs) self.context.directive_args[1] = [arg] - nodes = self.run_domain_directive(kind, self.context.directive_args[1], augment=augment) + + nodes = self.run_domain_directive(kind, self.context.directive_args[1]) rst_node = nodes[1] finder = NodeFinder(rst_node.document) From f90c267d4476b735e95d2e98bb171037264ae4e0 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 20 Jan 2019 17:10:35 +0100 Subject: [PATCH 3/5] Render structs with 'struct' instead of 'class'. --- breathe/renderer/sphinxrenderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index faecc56a..db9779b1 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -49,7 +49,7 @@ class DomainDirectiveFactory(object): # A mapping from node kinds to cpp domain classes and directive names. cpp_classes = { 'class': (DoxyCPPClassObject, 'class'), - 'struct': (DoxyCPPClassObject, 'class'), + 'struct': (DoxyCPPClassObject, 'struct'), 'interface': (DoxyCPPClassObject, 'interface'), 'function': (cpp.CPPFunctionObject, 'function'), 'friend': (cpp.CPPFunctionObject, 'function'), From 2a1e6c20ab22613122a817b6d77581809c80c85b Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 20 Jan 2019 19:22:49 +0100 Subject: [PATCH 4/5] Use Sphinx class and struct directives directly --- breathe/renderer/sphinxrenderer.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index db9779b1..af4d6d70 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -30,16 +30,14 @@ def __exit__(self, et, ev, bt): self.previous = None -class DoxyCPPClassObject(cpp.CPPClassObject): +class DoxyCPPInterfaceObject(cpp.CPPClassObject): + object_type = 'class' @property def display_object_type(self): - # override because we also have the 'interface' type - assert self.objtype in ('class', 'struct', 'interface') - # TODO: remove this if it should be rendered as 'interface' as well - if self.objtype == 'interface': - return 'class' - return self.objtype + # override because we have the 'interface' type + assert self.objtype == 'interface' + return 'class' # TODO: change to 'interface' if that is the desired rendering def parse_definition(self, parser): return parser.parse_declaration("class", "class") @@ -48,9 +46,9 @@ def parse_definition(self, parser): class DomainDirectiveFactory(object): # A mapping from node kinds to cpp domain classes and directive names. cpp_classes = { - 'class': (DoxyCPPClassObject, 'class'), - 'struct': (DoxyCPPClassObject, 'struct'), - 'interface': (DoxyCPPClassObject, 'interface'), + 'class': (cpp.CPPClassObject, 'class'), + 'struct': (cpp.CPPClassObject, 'struct'), + 'interface': (DoxyCPPInterfaceObject, 'interface'), 'function': (cpp.CPPFunctionObject, 'function'), 'friend': (cpp.CPPFunctionObject, 'function'), 'signal': (cpp.CPPFunctionObject, 'function'), @@ -494,9 +492,10 @@ def render_signature(file_data, doxygen_target, name, kind): finder = NodeFinder(rst_node.document) rst_node.walk(finder) - # The cpp domain in Sphinx doesn't support structs at the moment, so change the text - # from "class " to the correct kind which can be "class " or "struct ". - finder.declarator[0] = self.node_factory.desc_annotation(kind + ' ', kind + ' ') + if kind in ('interface', 'namespace'): + # This is not a real C++ declaration type that Sphinx supports, + # so we hax the replacement of it. + finder.declarator[0] = self.node_factory.desc_annotation(kind + ' ', kind + ' ') rst_node.children[0].insert(0, doxygen_target) return nodes, finder.content From b999b31d1923d3a4239fb8eae30e1a278a90fab6 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Fri, 27 Mar 2020 15:33:43 +0100 Subject: [PATCH 5/5] Simplify handling of anon entities --- breathe/renderer/sphinxrenderer.py | 4 +--- documentation/source/conf.py | 1 + documentation/source/specific.rst | 8 ++++++++ examples/specific/Makefile | 1 + examples/specific/cpp_anon.cfg | 11 +++++++++++ examples/specific/cpp_anon.h | 13 +++++++++++++ 6 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 examples/specific/cpp_anon.cfg create mode 100644 examples/specific/cpp_anon.h diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index af4d6d70..242a9c33 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1045,10 +1045,8 @@ def update_define_signature(signature, obj_type): return self.render_declaration(node, declaration, update_signature=update_define_signature) def visit_enum(self, node): - # Sphinx requires a name to be a valid identifier, so replace anonymous enum name of the - # form @id generated by Doxygen with "@anon_id". name = self.get_fully_qualified_name() - declaration = name.replace("@", "@anon_") if node.name.startswith("@") else name + declaration = name description_nodes = self.description(node) name = self.node_factory.emphasis("", self.node_factory.Text("Values:")) diff --git a/documentation/source/conf.py b/documentation/source/conf.py index f7dca1d5..85a8c06c 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -215,6 +215,7 @@ "c_union":"../../examples/specific/c_union/xml/", "define":"../../examples/specific/define/xml/", "multifile":"../../examples/specific/multifilexml/xml/", + "cpp_anon":"../../examples/specific/cpp_anon/xml/", } breathe_projects_source = { diff --git a/documentation/source/specific.rst b/documentation/source/specific.rst index 50ccad1e..dc3a6402 100644 --- a/documentation/source/specific.rst +++ b/documentation/source/specific.rst @@ -170,3 +170,11 @@ Interface Class .. doxygeninterface:: InterfaceClass :project: interface + +C++ Anonymous Entities +---------------------- + +.. cpp:namespace:: @ex_specific_cpp_anon + +.. doxygenfile:: cpp_anon.h + :project: cpp_anon diff --git a/examples/specific/Makefile b/examples/specific/Makefile index 18e01cd0..fc2abb20 100644 --- a/examples/specific/Makefile +++ b/examples/specific/Makefile @@ -24,6 +24,7 @@ projects = nutshell alias rst inline namespacefile array inheritance \ headings links parameters template_class template_class_non_type \ template_function template_type_alias template_specialisation \ enum define interface \ + cpp_anon \ c_file c_struct c_enum c_typedef c_macro c_union special = programlisting decl_impl multifilexml auto class typedef diff --git a/examples/specific/cpp_anon.cfg b/examples/specific/cpp_anon.cfg new file mode 100644 index 00000000..34d071ab --- /dev/null +++ b/examples/specific/cpp_anon.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "C++ Anonymous" +OUTPUT_DIRECTORY = cpp_anon +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = cpp_anon.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/examples/specific/cpp_anon.h b/examples/specific/cpp_anon.h new file mode 100644 index 00000000..c2d49600 --- /dev/null +++ b/examples/specific/cpp_anon.h @@ -0,0 +1,13 @@ +struct ClassWithAnonEntities { + struct { + int structMember; + }; + + union { + int unionMember; + }; + + enum { + Enumerator + }; +};