If an API description is nested in another description, lookup the child in the context of the parent
(self, node, owner)
| 72 | doctree.insert(0, raw) |
| 73 | |
| 74 | def traverse(self, node, owner): |
| 75 | """ |
| 76 | If an API description is nested in another description, |
| 77 | lookup the child in the context of the parent |
| 78 | """ |
| 79 | |
| 80 | # nodes.Text iterates over characters, not children |
| 81 | for child in node.children: |
| 82 | if isinstance(child, addnodes.desc): |
| 83 | for desc_child in child.children: |
| 84 | if isinstance(desc_child, addnodes.desc_signature): |
| 85 | |
| 86 | # Get the name of the object. An owner in the signature |
| 87 | # overrides an owner from a parent description. |
| 88 | signature_owner = None |
| 89 | for child in desc_child.children: |
| 90 | if isinstance(child, addnodes.desc_addname): |
| 91 | |
| 92 | # An owner in the signature ends with :: |
| 93 | signature_owner = child.astext()[:-2] |
| 94 | |
| 95 | elif isinstance(child, addnodes.desc_name): |
| 96 | name = child.astext() |
| 97 | |
| 98 | break |
| 99 | |
| 100 | # Lookup the object in the Doxygen index |
| 101 | try: |
| 102 | compound, = index.xpath( |
| 103 | 'descendant::compound[(not($owner) or name[text() = $owner]) and descendant::name[text() = $name]][1]', |
| 104 | owner=signature_owner or owner, |
| 105 | name=name) |
| 106 | |
| 107 | except ValueError: |
| 108 | continue |
| 109 | |
| 110 | filename = compound.get('refid') + '.xml' |
| 111 | if filename not in cache: |
| 112 | cache[filename] = etree.parse('xml/' + filename) |
| 113 | |
| 114 | # An enumvalue has no location |
| 115 | memberdef, = cache[filename].xpath( |
| 116 | 'descendant::compounddef[compoundname[text() = $name]]', name=name) or cache[filename].xpath( |
| 117 | 'descendant::memberdef[name[text() = $name] | enumvalue[name[text() = $name]]]', name=name) |
| 118 | |
| 119 | # Append the link after the object's signature. |
| 120 | # Get the source file and line number from Doxygen and use |
| 121 | # them to construct the link. |
| 122 | location = memberdef.find('location') |
| 123 | filename = path.basename(location.get('file')) |
| 124 | |
| 125 | # Declarations have no bodystart |
| 126 | line = location.get('bodystart') or location.get('line') |
| 127 | |
| 128 | emphasis = nodes.emphasis('', ' ' + filename + ' line ' + line) |
| 129 | |
| 130 | # Use a relative link if the output is HTML, otherwise fall |
| 131 | # back on an absolute link to Read the Docs. I haven't |