Repository: trafficserver Updated Branches: refs/heads/master 4bb3d98e0 -> b5b12230c
TS-2832 docs: Fix links to the source code if an API description is nested in another description Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/b5b12230 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/b5b12230 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/b5b12230 Branch: refs/heads/master Commit: b5b12230cd5c7f44ffe382d41b4631c9cbd25799 Parents: 4bb3d98 Author: Jack Bates <[email protected]> Authored: Tue Sep 2 12:56:11 2014 -0700 Committer: Jack Bates <[email protected]> Committed: Tue Sep 2 12:56:11 2014 -0700 ---------------------------------------------------------------------- .gitignore | 17 +++---- doc/ext/doxygen.py | 126 ++++++++++++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b5b12230/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index b242455..d15c45f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ *.trs .*.sw* -.deps +.deps/ .dirstamp @@ -36,9 +36,11 @@ Makefile-pl config.status config.nice config.h -doc/html/ + +doc/_build/html/api/ doc/docbuild/ doc/locale/pot +doc/xml/ MYMETA.* pm_to_blib @@ -67,7 +69,6 @@ lib/ts/test_Map lib/ts/test_Vec lib/perl/lib/Apache/TS.pm - iocore/net/test_certlookup iocore/aio/test_AIO iocore/eventsystem/test_Buffer @@ -106,15 +107,9 @@ rc/trafficserver.xml rc/trafficserver.conf rc/trafficserver.service -proxy/api/include/ts - -*/.libs -*/*/.libs -*/*/*/.libs -*/*/*/*/.libs +.libs/ -.svn -*/.svn/ +.svn/ tsxs http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b5b12230/doc/ext/doxygen.py ---------------------------------------------------------------------- diff --git a/doc/ext/doxygen.py b/doc/ext/doxygen.py index c37745b..864592d 100644 --- a/doc/ext/doxygen.py +++ b/doc/ext/doxygen.py @@ -44,76 +44,106 @@ def escape(name): return name.replace('_', '__').replace(':', '_1').replace('/', '_2').replace('<', '_3').replace('>', '_4').replace('*', '_5').replace('&', '_6').replace('|', '_7').replace('.', '_8').replace('!', '_9').replace(',', '_00').replace(' ', '_01').replace('{', '_02').replace('}', '_03').replace('?', '_04').replace('^', '_05').replace('%', '_06').replace('(', '_07').replace(')', '_08').replace('+', '_09').replace('=', '_0A').replace('$', '_0B').replace('\\', '_0C') -def doctree_resolved(app, doctree, docname): +class doctree_resolved: """ Add links from an API description to the source code for that object. - Doxygen knows where in the source code objects are located. Based on - the sphinx.ext.viewcode and sphinx.ext.linkcode extensions. + Doxygen knows where in the source code it's located. + Based on the sphinx.ext.viewcode and sphinx.ext.linkcode extensions. """ - traverse = doctree.traverse(addnodes.desc_signature) - if traverse: - for signode in traverse: + has_link = None - # Get the name of the object. The C++ domain splits names into - # owner and name. - owner = None - for child in signode: - if isinstance(child, addnodes.desc_addname): + def __init__(self, app, doctree, docname): - # The owner ends with :: - owner = child.astext()[:-2] + self.app = app + self.docname = docname - elif isinstance(child, addnodes.desc_name): - name = child.astext() + self.traverse(doctree, None) + if self.has_link: - break + # Style the links + raw = nodes.raw('', '<style> .rst-content dl dt .headerlink { display: inline-block } .rst-content dl dt .headerlink:after { visibility: hidden } .rst-content dl dt .viewcode-link { color: #2980b9; float: right; font-size: inherit; font-weight: normal } .rst-content dl dt:hover .headerlink:after { visibility: visible } </style>', format='html') + doctree.insert(0, raw) - # Lookup the object in the Doxygen index - try: - compound, = index.xpath('descendant::compound[(not($owner) or name[text() = $owner]) and descendant::name[text() = $name]][1]', owner=owner, name=name) + def traverse(self, node, owner): + """ + If an API description is nested in another description, + lookup the child in the context of the parent + """ - except ValueError: - continue + # nodes.Text iterates over characters, not children + for child in node.children: + if isinstance(child, addnodes.desc): + for desc_child in child.children: + if isinstance(desc_child, addnodes.desc_signature): - filename = compound.get('refid') + '.xml' - if filename not in cache: - cache[filename] = etree.parse('xml/' + filename) + # Get the name of the object. An owner in the signature + # overrides an owner from a parent description. + signature_owner = None + for child in desc_child.children: + if isinstance(child, addnodes.desc_addname): - # An enumvalue has no location - memberdef, = cache[filename].xpath('descendant::compounddef[compoundname[text() = $name]]', name=name) or cache[filename].xpath('descendant::memberdef[name[text() = $name] | enumvalue[name[text() = $name]]]', name=name) + # An owner in the signature ends with :: + signature_owner = child.astext()[:-2] - # Append the link after the object's signature. Get the source - # file and line number from Doxygen and use them to construct the - # link. - location = memberdef.find('location') - filename = path.basename(location.get('file')) + elif isinstance(child, addnodes.desc_name): + name = child.astext() - # Declarations have no bodystart - line = location.get('bodystart') or location.get('line') + break - emphasis = nodes.emphasis('', ' ' + filename + ' line ' + line) + # Lookup the object in the Doxygen index + try: + compound, = index.xpath('descendant::compound[(not($owner) or name[text() = $owner]) and descendant::name[text() = $name]][1]', owner=signature_owner or owner, name=name) - # Use a relative link if the output is HTML, otherwise fall back - # on an absolute link to Read the Docs. I can't figure out how to - # get the highlighted source file for e.g. a struct from Doxygen - # so ape Doxygen escapeCharsInString() instead. - refuri = 'api/' + escape(filename) + '_source.html#l' + line.rjust(5, '0') - if app.builder.name == 'html': - refuri = osutil.relative_uri(app.builder.get_target_uri(docname), refuri) + except ValueError: + continue - else: - refuri = 'http://docs.trafficserver.apache.org/en/latest/' + refuri + filename = compound.get('refid') + '.xml' + if filename not in cache: + cache[filename] = etree.parse('xml/' + filename) + + # An enumvalue has no location + memberdef, = cache[filename].xpath('descendant::compounddef[compoundname[text() = $name]]', name=name) or cache[filename].xpath('descendant::memberdef[name[text() = $name] | enumvalue[name[text() = $name]]]', name=name) + + # Append the link after the object's signature. + # Get the source file and line number from Doxygen and use + # them to construct the link. + location = memberdef.find('location') + filename = path.basename(location.get('file')) + + # Declarations have no bodystart + line = location.get('bodystart') or location.get('line') + + emphasis = nodes.emphasis('', ' ' + filename + ' line ' + line) + + # Use a relative link if the output is HTML, otherwise fall + # back on an absolute link to Read the Docs. I haven't + # figured out how to get the page name for e.g. a struct + # from the XML files so ape Doxygen escapeCharsInString() + # instead. + refuri = 'api/' + escape(filename) + '_source.html#l' + line.rjust(5, '0') + if self.app.builder.name == 'html': + refuri = osutil.relative_uri(self.app.builder.get_target_uri(self.docname), refuri) - reference = nodes.reference('', '', emphasis, classes=['viewcode-link'], reftitle='Source code', refuri=refuri) - signode += reference + else: + refuri = 'http://docs.trafficserver.apache.org/en/latest/' + refuri - # Style the links - raw = nodes.raw('', '<style> .rst-content dl dt .headerlink { display: inline-block } .rst-content dl dt .headerlink:after { visibility: hidden } .rst-content dl dt .viewcode-link { color: #2980b9; float: right; font-size: inherit; font-weight: normal } .rst-content dl dt:hover .headerlink:after { visibility: visible } </style>', format='html') - doctree.insert(0, raw) + reference = nodes.reference('', '', emphasis, classes=['viewcode-link'], reftitle='Source code', refuri=refuri) + desc_child += reference + + # Style the links + self.has_link = True + + else: + self.traverse(desc_child, name) + + else: + self.traverse(child, owner) def setup(app): if etree and path.isfile('xml/index.xml'): + + # The doctree-read event hasn't got the docname argument app.connect('doctree-resolved', doctree_resolved) else:
