C, add noroot option to alias directive

This commit is contained in:
Jakob Lykke Andersen
2021-01-17 20:01:10 +01:00
parent d0a4d0147e
commit 06a956200b
3 changed files with 68 additions and 28 deletions

View File

@@ -78,6 +78,8 @@ Features added
* #8813: Show what extension (or module) caused it on errors on event handler * #8813: Show what extension (or module) caused it on errors on event handler
* #8213: C++: add ``maxdepth`` option to :rst:dir:`cpp:alias` to insert nested * #8213: C++: add ``maxdepth`` option to :rst:dir:`cpp:alias` to insert nested
declarations. declarations.
* C, add ``noroot`` option to :rst:dir:`c:alias` to render only nested
declarations.
Bugs fixed Bugs fixed
---------- ----------

View File

@@ -755,6 +755,13 @@ The following directive can be used for this purpose.
.. versionadded:: 3.3 .. versionadded:: 3.3
.. rst:directive:option:: noroot
Skip the mentioned declarations and only render nested declarations.
Requires ``maxdepth`` either 0 or at least 2.
.. versionadded:: 3.5
.. c:namespace-pop:: .. c:namespace-pop::

View File

@@ -3435,12 +3435,12 @@ class CNamespacePopObject(SphinxDirective):
class AliasNode(nodes.Element): class AliasNode(nodes.Element):
def __init__(self, sig: str, maxdepth: int, document: Any, env: "BuildEnvironment" = None, def __init__(self, sig: str, aliasOptions: dict,
document: Any, env: "BuildEnvironment" = None,
parentKey: LookupKey = None) -> None: parentKey: LookupKey = None) -> None:
super().__init__() super().__init__()
self.sig = sig self.sig = sig
self.maxdepth = maxdepth self.aliasOptions = aliasOptions
assert maxdepth >= 0
self.document = document self.document = document
if env is not None: if env is not None:
if 'c:parent_symbol' not in env.temp_data: if 'c:parent_symbol' not in env.temp_data:
@@ -3452,19 +3452,16 @@ class AliasNode(nodes.Element):
self.parentKey = parentKey self.parentKey = parentKey
def copy(self) -> 'AliasNode': def copy(self) -> 'AliasNode':
return self.__class__(self.sig, self.maxdepth, self.document, return self.__class__(self.sig, self.aliasOptions, self.document,
env=None, parentKey=self.parentKey) env=None, parentKey=self.parentKey)
class AliasTransform(SphinxTransform): class AliasTransform(SphinxTransform):
default_priority = ReferencesResolver.default_priority - 1 default_priority = ReferencesResolver.default_priority - 1
def _render_symbol(self, s: Symbol, maxdepth: int, def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool,
options: dict, document: Any) -> List[Node]: aliasOptions: dict, renderOptions: dict,
nodes = [] # type: List[Node] document: Any) -> List[Node]:
signode = addnodes.desc_signature('', '')
nodes.append(signode)
s.declaration.describe_signature(signode, 'markName', self.env, options)
if maxdepth == 0: if maxdepth == 0:
recurse = True recurse = True
elif maxdepth == 1: elif maxdepth == 1:
@@ -3472,28 +3469,43 @@ class AliasTransform(SphinxTransform):
else: else:
maxdepth -= 1 maxdepth -= 1
recurse = True recurse = True
nodes = [] # type: List[Node]
if not skipThis:
signode = addnodes.desc_signature('', '')
nodes.append(signode)
s.declaration.describe_signature(signode, 'markName', self.env, renderOptions)
if recurse: if recurse:
content = addnodes.desc_content() if skipThis:
desc = addnodes.desc() childContainer = nodes
content.append(desc) else:
desc.document = document content = addnodes.desc_content()
desc['domain'] = 'c' desc = addnodes.desc()
# 'desctype' is a backwards compatible attribute content.append(desc)
desc['objtype'] = desc['desctype'] = 'alias' desc.document = document
desc['noindex'] = True desc['domain'] = 'c'
# 'desctype' is a backwards compatible attribute
desc['objtype'] = desc['desctype'] = 'alias'
desc['noindex'] = True
childContainer = desc
for sChild in s.children: for sChild in s.children:
if sChild.declaration is None: if sChild.declaration is None:
continue continue
childNodes = self._render_symbol(sChild, maxdepth, options, document) childNodes = self._render_symbol(
desc.extend(childNodes) sChild, maxdepth=maxdepth, skipThis=False,
aliasOptions=aliasOptions, renderOptions=renderOptions,
document=document)
childContainer.extend(childNodes)
if len(desc.children) != 0: if not skipThis and len(desc.children) != 0:
nodes.append(content) nodes.append(content)
return nodes return nodes
def apply(self, **kwargs: Any) -> None: def apply(self, **kwargs: Any) -> None:
for node in self.document.traverse(AliasNode): for node in self.document.traverse(AliasNode):
node = cast(AliasNode, node)
sig = node.sig sig = node.sig
parentKey = node.parentKey parentKey = node.parentKey
try: try:
@@ -3533,7 +3545,10 @@ class AliasTransform(SphinxTransform):
location=node) location=node)
node.replace_self(signode) node.replace_self(signode)
continue continue
if s.declaration is None: # Declarations like .. var:: int Missing::var
# may introduce symbols without declarations.
# But if we skip the root then it is ok to start recursion from it.
if not node.aliasOptions['noroot'] and s.declaration is None:
signode = addnodes.desc_signature(sig, '') signode = addnodes.desc_signature(sig, '')
node.append(signode) node.append(signode)
signode.clear() signode.clear()
@@ -3545,18 +3560,25 @@ class AliasTransform(SphinxTransform):
node.replace_self(signode) node.replace_self(signode)
continue continue
options = dict() # type: ignore nodes = self._render_symbol(s, maxdepth=node.aliasOptions['maxdepth'],
nodes = self._render_symbol(s, maxdepth=node.maxdepth, skipThis=node.aliasOptions['noroot'],
options=options, document=node.document) aliasOptions=node.aliasOptions,
renderOptions=dict(), document=node.document)
node.replace_self(nodes) node.replace_self(nodes)
class CAliasObject(ObjectDescription): class CAliasObject(ObjectDescription):
option_spec = { option_spec = {
'maxdepth': directives.nonnegative_int 'maxdepth': directives.nonnegative_int,
'noroot': directives.flag,
} # type: Dict } # type: Dict
def run(self) -> List[Node]: def run(self) -> List[Node]:
"""
On purpose this doesn't call the ObjectDescription version, but is based on it.
Each alias signature may expand into multiple real signatures if 'noroot'.
The code is therefore based on the ObjectDescription version.
"""
if ':' in self.name: if ':' in self.name:
self.domain, self.objtype = self.name.split(':', 1) self.domain, self.objtype = self.name.split(':', 1)
else: else:
@@ -3570,10 +3592,19 @@ class CAliasObject(ObjectDescription):
node['noindex'] = True node['noindex'] = True
self.names = [] # type: List[str] self.names = [] # type: List[str]
maxdepth = self.options.get('maxdepth', 1) aliasOptions = {
'maxdepth': self.options.get('maxdepth', 1),
'noroot': 'noroot' in self.options,
}
if aliasOptions['noroot'] and aliasOptions['maxdepth'] == 1:
logger.warning("Error in C alias declaration."
" Requested 'noroot' but 'maxdepth' 1."
" When skipping the root declaration,"
" need 'maxdepth' 0 for infinite or at least 2.",
location=self.get_source_info())
signatures = self.get_signatures() signatures = self.get_signatures()
for i, sig in enumerate(signatures): for i, sig in enumerate(signatures):
node.append(AliasNode(sig, maxdepth, self.state.document, env=self.env)) node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env))
return [node] return [node]