mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #8876 from jakobandersen/c_cpp_alias
C and C++, alias fixes and improvements
This commit is contained in:
commit
be6391fa0d
9
CHANGES
9
CHANGES
@ -76,6 +76,12 @@ Features added
|
|||||||
* C++, also hyperlink operator overloads in expressions and alias declarations.
|
* C++, also hyperlink operator overloads in expressions and alias declarations.
|
||||||
* #8247: Allow production lists to refer to tokens from other production groups
|
* #8247: Allow production lists to refer to tokens from other production groups
|
||||||
* #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
|
||||||
|
declarations.
|
||||||
|
* C, add ``noroot`` option to :rst:dir:`c:alias` to render only nested
|
||||||
|
declarations.
|
||||||
|
* C++, add ``noroot`` option to :rst:dir:`cpp:alias` to render only nested
|
||||||
|
declarations.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
@ -148,6 +154,9 @@ Bugs fixed
|
|||||||
builds
|
builds
|
||||||
* #8865: LaTeX: Restructure the index nodes inside title nodes only on LaTeX
|
* #8865: LaTeX: Restructure the index nodes inside title nodes only on LaTeX
|
||||||
builds
|
builds
|
||||||
|
* C, :rst:dir:`c:alias` skip symbols without explicit declarations
|
||||||
|
instead of crashing.
|
||||||
|
* C, :rst:dir:`c:alias` give a warning when the root symbol is not declared.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -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::
|
||||||
|
|
||||||
@ -1179,6 +1186,24 @@ The following directive can be used for this purpose.
|
|||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
|
||||||
|
.. rubric:: Options
|
||||||
|
|
||||||
|
.. rst:directive:option:: maxdepth: int
|
||||||
|
|
||||||
|
Insert nested declarations as well, up to the total depth given.
|
||||||
|
Use 0 for infinite depth and 1 for just the mentioned declaration.
|
||||||
|
Defaults to 1.
|
||||||
|
|
||||||
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
.. rst:directive:option:: noroot
|
||||||
|
|
||||||
|
Skip the mentioned declarations and only render nested declarations.
|
||||||
|
Requires ``maxdepth`` either 0 or at least 2.
|
||||||
|
|
||||||
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
|
||||||
Constrained Templates
|
Constrained Templates
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -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, document: Any) -> List[Node]:
|
def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool,
|
||||||
nodes = [] # type: List[Node]
|
aliasOptions: dict, renderOptions: dict,
|
||||||
options = dict() # type: ignore
|
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,26 +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 # type: Union[List[Node], addnodes.desc]
|
||||||
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:
|
||||||
childNodes = self._render_symbol(sChild, maxdepth, document)
|
if sChild.declaration is None:
|
||||||
desc.extend(childNodes)
|
continue
|
||||||
|
childNodes = self._render_symbol(
|
||||||
|
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:
|
||||||
@ -3531,17 +3545,40 @@ class AliasTransform(SphinxTransform):
|
|||||||
location=node)
|
location=node)
|
||||||
node.replace_self(signode)
|
node.replace_self(signode)
|
||||||
continue
|
continue
|
||||||
|
# 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, '')
|
||||||
|
node.append(signode)
|
||||||
|
signode.clear()
|
||||||
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
|
||||||
nodes = self._render_symbol(s, maxdepth=node.maxdepth, document=node.document)
|
logger.warning(
|
||||||
|
"Can not render C declaration for alias '%s'. No such declaration." % name,
|
||||||
|
location=node)
|
||||||
|
node.replace_self(signode)
|
||||||
|
continue
|
||||||
|
|
||||||
|
nodes = self._render_symbol(s, maxdepth=node.aliasOptions['maxdepth'],
|
||||||
|
skipThis=node.aliasOptions['noroot'],
|
||||||
|
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:
|
||||||
@ -3555,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]
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, Type,
|
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, Type,
|
||||||
TypeVar, Union)
|
TypeVar, Union, cast)
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.nodes import Element, Node, TextElement, system_message
|
from docutils.nodes import Element, Node, TextElement, system_message
|
||||||
@ -3742,6 +3742,7 @@ class ASTDeclaration(ASTBase):
|
|||||||
elif self.objectType == 'enumerator':
|
elif self.objectType == 'enumerator':
|
||||||
mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
|
mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
|
||||||
else:
|
else:
|
||||||
|
print(self.objectType)
|
||||||
assert False
|
assert False
|
||||||
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
|
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
|
||||||
lastDeclNode = mainDeclNode
|
lastDeclNode = mainDeclNode
|
||||||
@ -7046,10 +7047,12 @@ class CPPNamespacePopObject(SphinxDirective):
|
|||||||
|
|
||||||
|
|
||||||
class AliasNode(nodes.Element):
|
class AliasNode(nodes.Element):
|
||||||
def __init__(self, sig: str, env: "BuildEnvironment" = None,
|
def __init__(self, sig: str, aliasOptions: dict,
|
||||||
|
env: "BuildEnvironment" = None,
|
||||||
parentKey: LookupKey = None) -> None:
|
parentKey: LookupKey = None) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.sig = sig
|
self.sig = sig
|
||||||
|
self.aliasOptions = aliasOptions
|
||||||
if env is not None:
|
if env is not None:
|
||||||
if 'cpp:parent_symbol' not in env.temp_data:
|
if 'cpp:parent_symbol' not in env.temp_data:
|
||||||
root = env.domaindata['cpp']['root_symbol']
|
root = env.domaindata['cpp']['root_symbol']
|
||||||
@ -7060,14 +7063,62 @@ class AliasNode(nodes.Element):
|
|||||||
self.parentKey = parentKey
|
self.parentKey = parentKey
|
||||||
|
|
||||||
def copy(self) -> 'AliasNode':
|
def copy(self) -> 'AliasNode':
|
||||||
return self.__class__(self.sig, env=None, parentKey=self.parentKey)
|
return self.__class__(self.sig, self.aliasOptions,
|
||||||
|
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, skipThis: bool,
|
||||||
|
aliasOptions: dict, renderOptions: dict,
|
||||||
|
document: Any) -> List[Node]:
|
||||||
|
if maxdepth == 0:
|
||||||
|
recurse = True
|
||||||
|
elif maxdepth == 1:
|
||||||
|
recurse = False
|
||||||
|
else:
|
||||||
|
maxdepth -= 1
|
||||||
|
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 skipThis:
|
||||||
|
childContainer = nodes # type: Union[List[Node], addnodes.desc]
|
||||||
|
else:
|
||||||
|
content = addnodes.desc_content()
|
||||||
|
desc = addnodes.desc()
|
||||||
|
content.append(desc)
|
||||||
|
desc.document = document
|
||||||
|
desc['domain'] = 'cpp'
|
||||||
|
# 'desctype' is a backwards compatible attribute
|
||||||
|
desc['objtype'] = desc['desctype'] = 'alias'
|
||||||
|
desc['noindex'] = True
|
||||||
|
childContainer = desc
|
||||||
|
|
||||||
|
for sChild in s._children:
|
||||||
|
if sChild.declaration is None:
|
||||||
|
continue
|
||||||
|
if sChild.declaration.objectType in ("templateParam", "functionParam"):
|
||||||
|
continue
|
||||||
|
childNodes = self._render_symbol(
|
||||||
|
sChild, maxdepth=maxdepth, skipThis=False,
|
||||||
|
aliasOptions=aliasOptions, renderOptions=renderOptions,
|
||||||
|
document=document)
|
||||||
|
childContainer.extend(childNodes)
|
||||||
|
|
||||||
|
if not skipThis and len(desc.children) != 0:
|
||||||
|
nodes.append(content)
|
||||||
|
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:
|
||||||
@ -7131,22 +7182,31 @@ class AliasTransform(SphinxTransform):
|
|||||||
signode.clear()
|
signode.clear()
|
||||||
signode += addnodes.desc_name(sig, sig)
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
|
||||||
logger.warning("Could not find C++ declaration for alias '%s'." % ast,
|
logger.warning("Can not find C++ declaration for alias '%s'." % ast,
|
||||||
location=node)
|
location=node)
|
||||||
node.replace_self(signode)
|
node.replace_self(signode)
|
||||||
else:
|
else:
|
||||||
nodes = []
|
nodes = []
|
||||||
options = dict()
|
renderOptions = {
|
||||||
options['tparam-line-spec'] = False
|
'tparam-line-spec': False,
|
||||||
|
}
|
||||||
for s in symbols:
|
for s in symbols:
|
||||||
signode = addnodes.desc_signature(sig, '')
|
assert s.declaration is not None
|
||||||
nodes.append(signode)
|
res = self._render_symbol(
|
||||||
s.declaration.describe_signature(signode, 'markName', self.env, options)
|
s, maxdepth=node.aliasOptions['maxdepth'],
|
||||||
|
skipThis=node.aliasOptions['noroot'],
|
||||||
|
aliasOptions=node.aliasOptions,
|
||||||
|
renderOptions=renderOptions,
|
||||||
|
document=node.document)
|
||||||
|
nodes.extend(res)
|
||||||
node.replace_self(nodes)
|
node.replace_self(nodes)
|
||||||
|
|
||||||
|
|
||||||
class CPPAliasObject(ObjectDescription):
|
class CPPAliasObject(ObjectDescription):
|
||||||
option_spec = {} # type: Dict
|
option_spec = {
|
||||||
|
'maxdepth': directives.nonnegative_int,
|
||||||
|
'noroot': directives.flag,
|
||||||
|
} # type: Dict
|
||||||
|
|
||||||
def run(self) -> List[Node]:
|
def run(self) -> List[Node]:
|
||||||
"""
|
"""
|
||||||
@ -7166,9 +7226,19 @@ class CPPAliasObject(ObjectDescription):
|
|||||||
node['objtype'] = node['desctype'] = self.objtype
|
node['objtype'] = node['desctype'] = self.objtype
|
||||||
|
|
||||||
self.names = [] # type: List[str]
|
self.names = [] # type: List[str]
|
||||||
|
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, env=self.env))
|
node.append(AliasNode(sig, aliasOptions, env=self.env))
|
||||||
|
|
||||||
contentnode = addnodes.desc_content()
|
contentnode = addnodes.desc_content()
|
||||||
node.append(contentnode)
|
node.append(contentnode)
|
||||||
|
Loading…
Reference in New Issue
Block a user