From df04f677d959450537370bf3959d403087e24363 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Wed, 6 May 2020 20:48:54 +0200 Subject: [PATCH] Render function candidates without using Sphinx directives Fixes michaeljones/breathe#504 --- breathe/directive/base.py | 6 ++-- breathe/directives.py | 61 ++++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/breathe/directive/base.py b/breathe/directive/base.py index 9b03ef79..b84ccae8 100644 --- a/breathe/directive/base.py +++ b/breathe/directive/base.py @@ -3,6 +3,8 @@ from ..renderer import format_parser_error, DoxygenToRstRendererFactory from ..parser import ParserError, FileIOError +from sphinx.directives import SphinxDirective + from docutils import nodes from docutils.parsers import rst @@ -44,12 +46,12 @@ def create_warning(project_info, state, lineno, **kwargs): return WarningHandler(state, context) -class BaseDirective(rst.Directive): +class BaseDirective(SphinxDirective): def __init__(self, finder_factory, project_info_factory, filter_factory, target_handler_factory, parser_factory, *args): - rst.Directive.__init__(self, *args) + super().__init__(*args) self.directive_args = list(args) # Convert tuple to list to allow modification. self.finder_factory = finder_factory diff --git a/breathe/directives.py b/breathe/directives.py index 10411ce0..6e019010 100644 --- a/breathe/directives.py +++ b/breathe/directives.py @@ -1,11 +1,12 @@ from .finder.core import FinderFactory -from .parser import DoxygenParserFactory -from .renderer import DoxygenToRstRendererFactory +from .parser import DoxygenParserFactory, ParserError, FileIOError +from .renderer import format_parser_error, DoxygenToRstRendererFactory from .renderer.base import RenderContext from .renderer.filter import FilterFactory from .renderer.target import TargetHandlerFactory from .renderer.mask import MaskFactory, NullMaskFactory, NoParameterNamesMask +from .renderer.sphinxrenderer import WithContext from .finder.core import DoxygenItemFinderFactoryCreator from .directive.base import BaseDirective, create_warning @@ -19,6 +20,7 @@ from docutils.parsers.rst.directives import unchanged_required, unchanged, flag from sphinx.writers.text import TextWriter from sphinx.builders.text import TextBuilder +from sphinx.domains import cpp import os import fnmatch @@ -206,6 +208,45 @@ def parse_args(self, function_description): return args + def create_function_signature(self, node_stack, project_info, filter_, target_handler, mask_factory, + directive_args): + "Standard render process used by subclasses" + + renderer_factory = DoxygenToRstRendererFactory( + self.parser_factory, + project_info + ) + + try: + object_renderer = renderer_factory.create_renderer( + node_stack, + self.state, + self.state.document, + filter_, + target_handler, + ) + except ParserError as e: + return format_parser_error("doxygenclass", e.error, e.filename, self.state, + self.lineno, True) + except FileIOError as e: + return format_parser_error("doxygenclass", e.error, e.filename, self.state, self.lineno) + + context = RenderContext(node_stack, mask_factory, directive_args) + node = node_stack[0] + with WithContext(object_renderer, context): + # this part should be kept in sync with visit_function in sphinxrenderer + name = node.get_name() + # assume we are only doing this for C++ declarations + declaration = ' '.join([ + object_renderer.create_template_prefix(node), + ''.join(n.astext() for n in object_renderer.render(node.get_type())), + name, + node.get_argsstring() + ]) + parser = cpp.DefinitionParser(declaration, location=self.get_source_info(), config=self.config) + ast = parser.parse_declaration('function', 'function') + return str(ast) + def resolve_function(self, matches, args, project_info): if not matches: @@ -234,11 +275,8 @@ def resolve_function(self, matches, args, project_info): directive_args = self.directive_args[:] directive_args[2] = text_options - nodes = self.render(entry, project_info, filter_, target_handler, mask_factory, - directive_args) - - # Render the nodes to text - signature = self.text_renderer.render(nodes, self.state.document) + signature = self.create_function_signature(entry, project_info, filter_, target_handler, + mask_factory, directive_args) signatures.append(signature) match = re.match(r"([^(]*)(.*)", signature) @@ -249,13 +287,8 @@ def resolve_function(self, matches, args, project_info): # Match them against the arg spec if args == match_args: - node_stack = entry - break - - if not node_stack: - raise UnableToResolveFunctionError(signatures) - - return node_stack + return entry + raise UnableToResolveFunctionError(signatures) class DoxygenClassLikeDirective(BaseDirective):