adding the breathe files

This commit is contained in:
Celine Mercier
2015-05-11 17:18:23 +02:00
parent 7e74b40b0a
commit 66296e1c06
62 changed files with 12237 additions and 0 deletions

View File

Binary file not shown.

View File

@@ -0,0 +1,2 @@

Binary file not shown.

View File

@@ -0,0 +1,383 @@
from .base import Renderer, RenderContext
from . import index as indexrenderer
from . import compound as compoundrenderer
from docutils import nodes
import textwrap
class RstContentCreator(object):
def __init__(self, list_type, dedent):
self.list_type = list_type
self.dedent = dedent
def __call__(self, text):
# Remove the first line which is "embed:rst[:leading-asterisk]"
text = "\n".join(text.split(u"\n")[1:])
# Remove starting whitespace
text = self.dedent(text)
# Inspired by autodoc.py in Sphinx
result = self.list_type()
for line in text.split("\n"):
result.append(line, "<breathe>")
return result
class UnicodeRenderer(Renderer):
def render(self):
# Skip any nodes that are pure whitespace
# Probably need a better way to do this as currently we're only doing
# it skip whitespace between higher-level nodes, but this will also
# skip any pure whitespace entries in actual content nodes
#
# We counter that second issue slightly by allowing through single white spaces
#
if self.data_object.strip():
return [self.node_factory.Text(self.data_object)]
elif self.data_object == unicode(" "):
return [self.node_factory.Text(self.data_object)]
else:
return []
class NullRenderer(Renderer):
def __init__(self):
pass
def render(self):
return []
class DoxygenToRstRendererFactory(object):
def __init__(
self,
node_type,
renderers,
renderer_factory_creator,
node_factory,
project_info,
state,
document,
rst_content_creator,
filter_,
target_handler,
domain_directive_factory
):
self.node_type = node_type
self.node_factory = node_factory
self.project_info = project_info
self.renderers = renderers
self.renderer_factory_creator = renderer_factory_creator
self.state = state
self.document = document
self.rst_content_creator = rst_content_creator
self.filter_ = filter_
self.target_handler = target_handler
self.domain_directive_factory = domain_directive_factory
def create_renderer(
self,
context
):
parent_data_object = context.node_stack[1]
data_object = context.node_stack[0]
if not self.filter_.allow(context.node_stack):
return NullRenderer()
child_renderer_factory = self.renderer_factory_creator.create_child_factory(
self.project_info,
data_object,
self
)
try:
node_type = data_object.node_type
except AttributeError as e:
# Horrible hack to silence errors on filtering unicode objects
# until we fix the parsing
if type(data_object) == unicode:
node_type = "unicode"
else:
raise e
Renderer = self.renderers[node_type]
common_args = [
self.project_info,
context,
child_renderer_factory,
self.node_factory,
self.state,
self.document,
self.target_handler,
self.domain_directive_factory
]
if node_type == "docmarkup":
creator = self.node_factory.inline
if data_object.type_ == "emphasis":
creator = self.node_factory.emphasis
elif data_object.type_ == "computeroutput":
creator = self.node_factory.literal
elif data_object.type_ == "bold":
creator = self.node_factory.strong
elif data_object.type_ == "superscript":
creator = self.node_factory.superscript
elif data_object.type_ == "subscript":
creator = self.node_factory.subscript
elif data_object.type_ == "center":
print("Warning: does not currently handle 'center' text display")
elif data_object.type_ == "small":
print("Warning: does not currently handle 'small' text display")
return Renderer(
creator,
*common_args
)
if node_type == "verbatim":
return Renderer(
self.rst_content_creator,
*common_args
)
if node_type == "compound":
kind = data_object.kind
if kind in ["file", "dir", "page", "example", "group"]:
return Renderer(indexrenderer.FileRenderer, *common_args)
class_ = indexrenderer.CompoundTypeSubRenderer
# For compound node types Renderer is CreateCompoundTypeSubRenderer
# as defined below. This could be cleaner
return Renderer(
class_,
*common_args
)
if node_type == "memberdef":
if data_object.kind in ("function", "slot") or (data_object.kind == 'friend' and data_object.argsstring):
Renderer = compoundrenderer.FuncMemberDefTypeSubRenderer
elif data_object.kind == "enum":
Renderer = compoundrenderer.EnumMemberDefTypeSubRenderer
elif data_object.kind == "typedef":
Renderer = compoundrenderer.TypedefMemberDefTypeSubRenderer
elif data_object.kind == "variable":
Renderer = compoundrenderer.VariableMemberDefTypeSubRenderer
elif data_object.kind == "define":
Renderer = compoundrenderer.DefineMemberDefTypeSubRenderer
if node_type == "param":
return Renderer(
parent_data_object.node_type != "templateparamlist",
*common_args
)
if node_type == "docsimplesect":
if data_object.kind == "par":
Renderer = compoundrenderer.ParDocSimpleSectTypeSubRenderer
return Renderer(
*common_args
)
class CreateCompoundTypeSubRenderer(object):
def __init__(self, parser_factory):
self.parser_factory = parser_factory
def __call__(self, class_, project_info, *args):
compound_parser = self.parser_factory.create_compound_parser(project_info)
return class_(compound_parser, project_info, *args)
class CreateRefTypeSubRenderer(object):
def __init__(self, parser_factory):
self.parser_factory = parser_factory
def __call__(self, project_info, *args):
compound_parser = self.parser_factory.create_compound_parser(project_info)
return compoundrenderer.RefTypeSubRenderer(compound_parser, project_info, *args)
class DoxygenToRstRendererFactoryCreator(object):
def __init__(
self,
node_factory,
parser_factory,
domain_directive_factory,
rst_content_creator,
project_info
):
self.node_factory = node_factory
self.parser_factory = parser_factory
self.domain_directive_factory = domain_directive_factory
self.rst_content_creator = rst_content_creator
self.project_info = project_info
def create_factory(self, node_stack, state, document, filter_, target_handler):
data_object = node_stack[0]
renderers = {
"doxygen" : indexrenderer.DoxygenTypeSubRenderer,
"compound" : CreateCompoundTypeSubRenderer(self.parser_factory),
"doxygendef" : compoundrenderer.DoxygenTypeSubRenderer,
"compounddef" : compoundrenderer.CompoundDefTypeSubRenderer,
"sectiondef" : compoundrenderer.SectionDefTypeSubRenderer,
"memberdef" : compoundrenderer.MemberDefTypeSubRenderer,
"enumvalue" : compoundrenderer.EnumvalueTypeSubRenderer,
"linkedtext" : compoundrenderer.LinkedTextTypeSubRenderer,
"description" : compoundrenderer.DescriptionTypeSubRenderer,
"param" : compoundrenderer.ParamTypeSubRenderer,
"docreftext" : compoundrenderer.DocRefTextTypeSubRenderer,
"docheading" : compoundrenderer.DocHeadingTypeSubRenderer,
"docpara" : compoundrenderer.DocParaTypeSubRenderer,
"docmarkup" : compoundrenderer.DocMarkupTypeSubRenderer,
"docparamlist" : compoundrenderer.DocParamListTypeSubRenderer,
"docparamlistitem" : compoundrenderer.DocParamListItemSubRenderer,
"docparamnamelist" : compoundrenderer.DocParamNameListSubRenderer,
"docparamname" : compoundrenderer.DocParamNameSubRenderer,
"docsect1" : compoundrenderer.DocSect1TypeSubRenderer,
"docsimplesect" : compoundrenderer.DocSimpleSectTypeSubRenderer,
"doctitle" : compoundrenderer.DocTitleTypeSubRenderer,
"docformula" : compoundrenderer.DocForumlaTypeSubRenderer,
"docimage" : compoundrenderer.DocImageTypeSubRenderer,
"docurllink" : compoundrenderer.DocURLLinkSubRenderer,
"listing" : compoundrenderer.ListingTypeSubRenderer,
"codeline" : compoundrenderer.CodeLineTypeSubRenderer,
"highlight" : compoundrenderer.HighlightTypeSubRenderer,
"templateparamlist" : compoundrenderer.TemplateParamListRenderer,
"inc" : compoundrenderer.IncTypeSubRenderer,
"ref" : CreateRefTypeSubRenderer(self.parser_factory),
"verbatim" : compoundrenderer.VerbatimTypeSubRenderer,
"mixedcontainer" : compoundrenderer.MixedContainerRenderer,
"unicode" : UnicodeRenderer,
"doclist": compoundrenderer.DocListTypeSubRenderer,
"doclistitem": compoundrenderer.DocListItemTypeSubRenderer,
}
try:
node_type = data_object.node_type
except AttributeError as e:
# Horrible hack to silence errors on filtering unicode objects
# until we fix the parsing
if type(data_object) == unicode:
node_type = "unicode"
else:
raise e
return DoxygenToRstRendererFactory(
"root",
renderers,
self,
self.node_factory,
self.project_info,
state,
document,
self.rst_content_creator,
filter_,
target_handler,
self.domain_directive_factory
)
def create_child_factory( self, project_info, data_object, parent_renderer_factory ):
try:
node_type = data_object.node_type
except AttributeError as e:
# Horrible hack to silence errors on filtering unicode objects
# until we fix the parsing
if type(data_object) == unicode:
node_type = "unicode"
else:
raise e
return DoxygenToRstRendererFactory(
node_type,
parent_renderer_factory.renderers,
self,
self.node_factory,
parent_renderer_factory.project_info,
parent_renderer_factory.state,
parent_renderer_factory.document,
self.rst_content_creator,
parent_renderer_factory.filter_,
parent_renderer_factory.target_handler,
parent_renderer_factory.domain_directive_factory
)
# FactoryFactoryFactory. Ridiculous but necessary.
class DoxygenToRstRendererFactoryCreatorConstructor(object):
def __init__(
self,
node_factory,
parser_factory,
domain_directive_factory,
rst_content_creator
):
self.node_factory = node_factory
self.parser_factory = parser_factory
self.domain_directive_factory = domain_directive_factory
self.rst_content_creator = rst_content_creator
def create_factory_creator(self, project_info, document, options, target_handler):
return DoxygenToRstRendererFactoryCreator(
self.node_factory,
self.parser_factory,
self.domain_directive_factory,
self.rst_content_creator,
project_info,
)
def format_parser_error(name, error, filename, state, lineno, do_unicode_warning):
warning = '%s: Unable to parse xml file "%s". ' % (name, filename)
explanation = 'Reported error: %s. ' % error
unicode_explanation_text = ""
unicode_explanation = []
if do_unicode_warning:
unicode_explanation_text = textwrap.dedent("""
Parsing errors are often due to unicode errors associated with the encoding of the original
source files. Doxygen propagates invalid characters from the input source files to the
output xml.""").strip().replace("\n", " ")
unicode_explanation = [nodes.paragraph("", "", nodes.Text(unicode_explanation_text))]
return [nodes.warning("",
nodes.paragraph("", "", nodes.Text(warning)),
nodes.paragraph("", "", nodes.Text(explanation)),
*unicode_explanation
),
state.document.reporter.warning(warning + explanation + unicode_explanation_text, line=lineno)
]

Binary file not shown.

View File

@@ -0,0 +1,127 @@
class Renderer(object):
def __init__(self,
project_info,
context,
renderer_factory,
node_factory,
state,
document,
target_handler,
domain_directive_factory,
):
self.project_info = project_info
self.context = context
self.data_object = context.node_stack[0]
self.renderer_factory = renderer_factory
self.node_factory = node_factory
self.state = state
self.document = document
self.target_handler = target_handler
self.domain_directive_factory = domain_directive_factory
if self.context.domain == '':
self.context.domain = self.get_domain()
def get_domain(self):
"""Returns the domain for the current node."""
def get_filename(node):
"""Returns the name of a file where the declaration represented by node is located."""
try:
return node.location.file
except AttributeError:
return None
node_stack = self.context.node_stack
node = node_stack[0]
# An enumvalue node doesn't have location, so use its parent node for detecting the domain instead.
if type(node) == unicode or node.node_type == "enumvalue":
node = node_stack[1]
filename = get_filename(node)
if not filename and node.node_type == "compound":
file_data = self.compound_parser.parse(node.refid)
filename = get_filename(file_data.compounddef)
return self.project_info.domain_for_file(filename) if filename else ''
def get_fully_qualified_name(self):
names = []
node_stack = self.context.node_stack
node = node_stack[0]
if node.node_type == 'enumvalue':
names.append(node.name)
# Skip the name of the containing enum because it is not a part of the fully qualified name.
node_stack = node_stack[2:]
# If the node is a namespace, use its name because namespaces are skipped in the main loop.
if node.node_type == 'compound' and node.kind == 'namespace':
names.append(node.name)
for node in node_stack:
if node.node_type == 'ref' and len(names) == 0:
return node.valueOf_
if (node.node_type == 'compound' and node.kind not in ['file', 'namespace']) or \
node.node_type == 'memberdef':
# We skip the 'file' entries because the file name doesn't form part of the
# qualified name for the identifier. We skip the 'namespace' entries because if we
# find an object through the namespace 'compound' entry in the index.xml then we'll
# also have the 'compounddef' entry in our node stack and we'll get it from that. We
# need the 'compounddef' entry because if we find the object through the 'file'
# entry in the index.xml file then we need to get the namespace name from somewhere
names.insert(0, node.name)
if (node.node_type == 'compounddef' and node.kind == 'namespace'):
# Nested namespaces include their parent namespace(s) in compoundname. ie,
# compoundname is 'foo::bar' instead of just 'bar' for namespace 'bar' nested in
# namespace 'foo'. We need full compoundname because node_stack doesn't necessarily
# include parent namespaces and we stop here in case it does.
names.insert(0, node.compoundname)
break
return '::'.join(names)
def create_template_node(self, decl):
"""Creates a node for the ``template <...>`` part of the declaration."""
if not decl.templateparamlist:
return None
context = self.context.create_child_context(decl.templateparamlist)
renderer = self.renderer_factory.create_renderer(context)
nodes = [self.node_factory.Text("template <")]
nodes.extend(renderer.render())
nodes.append(self.node_factory.Text(">"))
signode = self.node_factory.desc_signature()
signode.extend(nodes)
return signode
def run_domain_directive(self, kind, names):
domain_directive = self.renderer_factory.domain_directive_factory.create(
self.context.domain, [kind, names] + self.context.directive_args[2:])
# 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
nodes = domain_directive.run()
# Filter out outer class names if we are rendering a member as a part of a class content.
signode = nodes[1].children[0]
if len(names) > 0 and self.context.child:
signode.children = [n for n in signode.children if not n.tagname == 'desc_addname']
return nodes
class RenderContext(object):
def __init__(self, node_stack, mask_factory, directive_args, domain='', child=False):
self.node_stack = node_stack
self.mask_factory = mask_factory
self.directive_args = directive_args
self.domain = domain
self.child = child
def create_child_context(self, data_object):
node_stack = self.node_stack[:]
node_stack.insert(0, self.mask_factory.mask(data_object))
return RenderContext(node_stack, self.mask_factory, self.directive_args, self.domain, True)

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,115 @@
from .base import Renderer
class DoxygenTypeSubRenderer(Renderer):
def render(self):
nodelist = []
# Process all the compound children
for compound in self.data_object.get_compound():
context = self.context.create_child_context(compound)
compound_renderer = self.renderer_factory.create_renderer(context)
nodelist.extend(compound_renderer.render())
return nodelist
class CompoundRenderer(Renderer):
"""Base class for CompoundTypeSubRenderer and RefTypeSubRenderer."""
def __init__(self, compound_parser, render_empty_node, *args):
self.compound_parser = compound_parser
self.render_empty_node = render_empty_node
Renderer.__init__(self, *args)
def create_doxygen_target(self):
"""Can be overridden to create a target node which uses the doxygen refid information
which can be used for creating links between internal doxygen elements.
The default implementation should suffice most of the time.
"""
refid = "%s%s" % (self.project_info.name(), self.data_object.refid)
return self.target_handler.create_target(refid)
def render_signature(self, file_data, doxygen_target):
# Defer to domains specific directive.
name, kind = self.get_node_info(file_data)
self.context.directive_args[1] = [self.get_fully_qualified_name()]
nodes = self.run_domain_directive(kind, self.context.directive_args[1])
node = nodes[1]
signode, contentnode = node.children
# 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 ".
signode[0] = self.node_factory.desc_annotation(kind + ' ', kind + ' ')
# Check if there is template information and format it as desired
template_signode = self.create_template_node(file_data.compounddef)
if template_signode:
node.insert(0, template_signode)
node.children[0].insert(0, doxygen_target)
return nodes, contentnode
def render(self):
# Read in the corresponding xml file and process
file_data = self.compound_parser.parse(self.data_object.refid)
parent_context = self.context.create_child_context(file_data)
data_renderer = self.renderer_factory.create_renderer(parent_context)
rendered_data = data_renderer.render()
if not rendered_data and not self.render_empty_node:
return []
file_data = parent_context.node_stack[0]
new_context = parent_context.create_child_context(file_data.compounddef)
nodes, contentnode = self.render_signature(file_data, self.create_doxygen_target())
if file_data.compounddef.includes:
for include in file_data.compounddef.includes:
context = new_context.create_child_context(include)
renderer = self.renderer_factory.create_renderer(context)
contentnode.extend(renderer.render())
contentnode.extend(rendered_data)
return nodes
class CompoundTypeSubRenderer(CompoundRenderer):
def __init__(self, compound_parser, *args):
CompoundRenderer.__init__(self, compound_parser, True, *args)
def get_node_info(self, file_data):
return self.data_object.name, self.data_object.kind
class FileRenderer(CompoundTypeSubRenderer):
def render_signature(self, file_data, doxygen_target):
# Build targets for linking
targets = []
targets.extend(doxygen_target)
title_signode = self.node_factory.desc_signature()
title_signode.extend(targets)
# Set up the title
name, kind = self.get_node_info(file_data)
title_signode.append(self.node_factory.emphasis(text=kind))
title_signode.append(self.node_factory.Text(" "))
title_signode.append(self.node_factory.desc_name(text=name))
contentnode = self.node_factory.desc_content()
node = self.node_factory.desc()
node.document = self.state.document
node['objtype'] = kind
node.append(title_signode)
node.append(contentnode)
return [node], contentnode

Binary file not shown.

View File

@@ -0,0 +1,62 @@
"""
Masks
=====
Masks are related to filters. Filters can block the processing of particular parts of the xml
hierarchy but they can only work on node level. If the part of the xml hierarchy that you want to
filter out is read in as an instance of one of the classes in parser/doxygen/*.py then you can use
the filters. However, if you want to filter out an attribute from one of the nodes (and some of the
xml child nodes are read in as attributes on their parents) then you can't use a filter.
We introduce the Mask's to fulfil this need. The masks are designed to be applied to a particular
node type and to limit the access to particular attributes on the node. For example, then
NoParameterNamesMask wraps a node a returns all its standard attributes but returns None for the
'declname' and 'defname' attributes.
Currently the Mask functionality is only used for the text signature rendering for doing function
matching.
"""
class NoParameterNamesMask(object):
def __init__(self, data_object):
self.data_object = data_object
def __getattr__(self, attr):
if attr in ['declname', 'defname', 'defval']:
return None
return getattr(self.data_object, attr)
class MaskFactory(object):
def __init__(self, lookup):
self.lookup = lookup
def mask(self, data_object):
try:
node_type = data_object.node_type
except AttributeError as e:
# Horrible hack to silence errors on filtering unicode objects
# until we fix the parsing
if type(data_object) == unicode:
node_type = "unicode"
else:
raise e
if node_type in self.lookup:
Mask = self.lookup[node_type]
return Mask(data_object)
return data_object
class NullMaskFactory(object):
def mask(self, data_object):
return data_object

Binary file not shown.

View File

@@ -0,0 +1,40 @@
class TargetHandler(object):
def __init__(self, project_info, node_factory, document):
self.project_info = project_info
self.node_factory = node_factory
self.document = document
def create_target(self, id_):
"""Creates a target node and registers it with the document and returns it in a list"""
target = self.node_factory.target(ids=[id_], names=[id_])
try:
self.document.note_explicit_target(target)
except Exception:
# TODO: We should really return a docutils warning node here
print("Warning: Duplicate target detected: %s" % id_)
return [target]
class NullTargetHandler(object):
def create_target(self, refid):
return []
class TargetHandlerFactory(object):
def __init__(self, node_factory):
self.node_factory = node_factory
def create_target_handler(self, options, project_info, document):
if options.has_key("no-link"):
return NullTargetHandler()
return TargetHandler(project_info, self.node_factory, document)

Binary file not shown.