Merge pull request #9023 from jakobandersen/decl_styling

Flexible declaration styling
This commit is contained in:
Jakob Lykke Andersen 2021-04-12 22:02:57 +02:00 committed by GitHub
commit 8954770f67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 864 additions and 453 deletions

View File

@ -7,12 +7,17 @@ Dependencies
Incompatible changes
--------------------
* #9023: Change the CSS classes on :rst:role:`cpp:expr` and
:rst:role:`cpp:texpr`.
Deprecated
----------
Features added
--------------
* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.
Bugs fixed
----------

View File

@ -8,18 +8,32 @@ Doctree node classes added by Sphinx
Nodes for domain-specific object descriptions
---------------------------------------------
Top-level nodes
...............
These nodes form the top-most levels of object descriptions.
.. autoclass:: desc
.. autoclass:: desc_signature
.. autoclass:: desc_signature_line
.. autoclass:: desc_content
.. autoclass:: desc_inline
Nodes for high-level structure in signatures
............................................
These nodes occur in in non-multiline :py:class:`desc_signature` nodes
and in :py:class:`desc_signature_line` nodes.
.. autoclass:: desc_name
.. autoclass:: desc_addname
.. autoclass:: desc_type
.. autoclass:: desc_returns
.. autoclass:: desc_name
.. autoclass:: desc_parameterlist
.. autoclass:: desc_parameter
.. autoclass:: desc_optional
.. autoclass:: desc_annotation
.. autoclass:: desc_content
New admonition-like constructs
------------------------------

View File

@ -115,25 +115,53 @@ class toctree(nodes.General, nodes.Element, translatable):
return messages
# domain-specific object descriptions (class, function etc.)
#############################################################
# Domain-specific object descriptions (class, function etc.)
#############################################################
class _desc_classes_injector(nodes.Element, not_smartquotable):
"""Helper base class for injecting a fixes list of classes.
Use as the first base class.
"""
classes: List[str] = []
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self['classes'].extend(self.classes)
# Top-level nodes
#################
class desc(nodes.Admonition, nodes.Element):
"""Node for object descriptions.
"""Node for a list of object signatures and a common description of them.
This node is similar to a "definition list" with one definition. It
contains one or more ``desc_signature`` and a ``desc_content``.
Contains one or more :py:class:`desc_signature` nodes
and then a single :py:class:`desc_content` node.
This node always has two classes:
- The name of the domain it belongs to, e.g., ``py`` or ``cpp``.
- The name of the object type in the domain, e.g., ``function``.
"""
# TODO: can we introduce a constructor
# that forces the specification of the domain and objtyp?
class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for object signatures.
The "term" part of the custom Sphinx definition list.
class desc_signature(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for a single object signature.
As default the signature is a single line signature,
but set ``is_multiline = True`` to describe a multi-line signature.
In that case all child nodes must be ``desc_signature_line`` nodes.
As default the signature is a single-line signature.
Set ``is_multiline = True`` to describe a multi-line signature.
In that case all child nodes must be :py:class:`desc_signature_line` nodes.
This node always has the classes ``sig``, ``sig-object``, and the domain it belongs to.
"""
# Note: the domain name is being added through a post-transform DescSigAddDomainAsClass
classes = ['sig', 'sig-object']
@property
def child_text_separator(self):
@ -144,18 +172,63 @@ class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a line in a multi-line object signatures.
"""Node for a line in a multi-line object signature.
It should only be used in a ``desc_signature`` with ``is_multiline`` set.
It should only be used as a child of a :py:class:`desc_signature`
with ``is_multiline`` set to ``True``.
Set ``add_permalink = True`` for the line that should get the permalink.
"""
sphinx_line_type = ''
class desc_content(nodes.General, nodes.Element):
"""Node for object description content.
Must be the last child node in a :py:class:`desc` node.
"""
class desc_inline(_desc_classes_injector, nodes.Inline, nodes.TextElement):
"""Node for a signature fragment in inline text.
This is for example used for roles like :rst:role:`cpp:expr`.
This node always has the classes ``sig``, ``sig-inline``,
and the name of the domain it belongs to.
"""
classes = ['sig', 'sig-inline']
def __init__(self, domain: str, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self['classes'].append(domain)
# Nodes for high-level structure in signatures
##############################################
# nodes to use within a desc_signature or desc_signature_line
class desc_addname(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for additional name parts (module name, class name)."""
class desc_name(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for the main object name.
For example, in the declaration of a Python class ``MyModule.MyClass``,
the main name is ``MyClass``.
This node always has the class ``sig-name``.
"""
classes = ['sig-name', 'descname'] # 'descname' is for backwards compatibility
class desc_addname(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for additional name parts for an object.
For example, in the declaration of a Python class ``MyModule.MyClass``,
the additional name part is ``MyModule.``.
This node always has the class ``sig-prename``.
"""
# 'descclassname' is for backwards compatibility
classes = ['sig-prename', 'descclassname']
# compatibility alias
@ -168,14 +241,11 @@ class desc_type(nodes.Part, nodes.Inline, nodes.FixedTextElement):
class desc_returns(desc_type):
"""Node for a "returns" annotation (a la -> in Python)."""
def astext(self) -> str:
return ' -> ' + super().astext()
class desc_name(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for the main object name."""
class desc_parameterlist(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a general parameter list."""
child_text_separator = ', '
@ -200,14 +270,14 @@ class desc_annotation(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for signature annotations (not Python 3-style annotations)."""
class desc_content(nodes.General, nodes.Element):
"""Node for object description content.
# Leaf nodes for markup of text fragments
#########################################
This is the "definition" part of the custom Sphinx definition list.
"""
# Signature text elements, generally translated to node.inline
# in SigElementFallbackTransform.
# When adding a new one, add it to SIG_ELEMENTS.
class desc_sig_element(nodes.inline):
class desc_sig_element(nodes.inline, _desc_classes_injector):
"""Common parent class of nodes for inline text of a signature."""
classes: List[str] = []
@ -217,8 +287,20 @@ class desc_sig_element(nodes.inline):
self['classes'].extend(self.classes)
# to not reinvent the wheel, the classes in the following desc_sig classes
# are based on those used in Pygments
class desc_sig_space(desc_sig_element):
"""Node for a space in a signature."""
classes = ["w"]
def __init__(self, rawsource: str = '', text: str = ' ',
*children: Element, **attributes: Any) -> None:
super().__init__(rawsource, text, *children, **attributes)
class desc_sig_name(desc_sig_element):
"""Node for a name in a signature."""
"""Node for an identifier in a signature."""
classes = ["n"]
@ -228,10 +310,44 @@ class desc_sig_operator(desc_sig_element):
class desc_sig_punctuation(desc_sig_element):
"""Node for a punctuation in a signature."""
"""Node for punctuation in a signature."""
classes = ["p"]
class desc_sig_keyword(desc_sig_element):
"""Node for a general keyword in a signature."""
classes = ["k"]
class desc_sig_keyword_type(desc_sig_element):
"""Node for a keyword which is a built-in type in a signature."""
classes = ["kt"]
class desc_sig_literal_number(desc_sig_element):
"""Node for a numeric literal in a signature."""
classes = ["m"]
class desc_sig_literal_string(desc_sig_element):
"""Node for a string literal in a signature."""
classes = ["s"]
class desc_sig_literal_char(desc_sig_element):
"""Node for a character literal in a signature."""
classes = ["sc"]
SIG_ELEMENTS = [desc_sig_space,
desc_sig_name,
desc_sig_operator,
desc_sig_punctuation,
desc_sig_keyword, desc_sig_keyword_type,
desc_sig_literal_number, desc_sig_literal_string, desc_sig_literal_char]
###############################################################
# new admonition-like constructs
class versionmodified(nodes.Admonition, nodes.TextElement):
@ -336,6 +452,7 @@ class pending_xref(nodes.Inline, nodes.Element):
These nodes are resolved before writing output, in
BuildEnvironment.resolve_references.
"""
child_text_separator = ''
class pending_xref_condition(nodes.Inline, nodes.TextElement):
@ -412,21 +529,25 @@ class manpage(nodes.Inline, nodes.FixedTextElement):
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_node(toctree)
app.add_node(desc)
app.add_node(desc_signature)
app.add_node(desc_signature_line)
app.add_node(desc_content)
app.add_node(desc_inline)
app.add_node(desc_name)
app.add_node(desc_addname)
app.add_node(desc_type)
app.add_node(desc_returns)
app.add_node(desc_name)
app.add_node(desc_parameterlist)
app.add_node(desc_parameter)
app.add_node(desc_optional)
app.add_node(desc_annotation)
app.add_node(desc_content)
app.add_node(desc_sig_name)
app.add_node(desc_sig_operator)
app.add_node(desc_sig_punctuation)
for n in SIG_ELEMENTS:
app.add_node(n)
app.add_node(versionmodified)
app.add_node(seealso)
app.add_node(productionlist)

View File

@ -172,6 +172,7 @@ class ObjectDescription(SphinxDirective, Generic[T]):
node['noindex'] = noindex = ('noindex' in self.options)
if self.domain:
node['classes'].append(self.domain)
node['classes'].append(node['objtype'])
self.names: List[T] = []
signatures = self.get_signatures()

View File

@ -9,8 +9,7 @@
"""
import re
from typing import (Any, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar,
Union, cast)
from typing import Any, Callable, Dict, Generator, Iterator, List, Tuple, TypeVar, Union, cast
from docutils import nodes
from docutils.nodes import Element, Node, TextElement, system_message
@ -132,6 +131,10 @@ class ASTIdentifier(ASTBaseBase):
prefix: str, symbol: "Symbol") -> None:
# note: slightly different signature of describe_signature due to the prefix
verify_description_mode(mode)
if self.is_anon():
node = addnodes.desc_sig_name(text="[anonymous]")
else:
node = addnodes.desc_sig_name(self.identifier, self.identifier)
if mode == 'markType':
targetText = prefix + self.identifier
pnode = addnodes.pending_xref('', refdomain='c',
@ -139,21 +142,14 @@ class ASTIdentifier(ASTBaseBase):
reftarget=targetText, modname=None,
classname=None)
pnode['c:parent_key'] = symbol.get_lookup_key()
if self.is_anon():
pnode += nodes.strong(text="[anonymous]")
else:
pnode += nodes.Text(self.identifier)
pnode += node
signode += pnode
elif mode == 'lastIsName':
if self.is_anon():
signode += nodes.strong(text="[anonymous]")
else:
signode += addnodes.desc_name(self.identifier, self.identifier)
nameNode = addnodes.desc_name()
nameNode += node
signode += nameNode
elif mode == 'noneIsName':
if self.is_anon():
signode += nodes.strong(text="[anonymous]")
else:
signode += nodes.Text(self.identifier)
signode += node
else:
raise Exception('Unknown description mode: %s' % mode)
@ -184,18 +180,18 @@ class ASTNestedName(ASTBase):
# just print the name part, with template args, not template params
if mode == 'noneIsName':
if self.rooted:
assert False, "Can this happen?" # TODO
signode += nodes.Text('.')
for i in range(len(self.names)):
if i != 0:
assert False, "Can this happen?" # TODO
signode += nodes.Text('.')
n = self.names[i]
n.describe_signature(signode, mode, env, '', symbol)
elif mode == 'param':
assert not self.rooted, str(self)
assert len(self.names) == 1
node = nodes.emphasis()
self.names[0].describe_signature(node, 'noneIsName', env, '', symbol)
signode += node
self.names[0].describe_signature(signode, 'noneIsName', env, '', symbol)
elif mode == 'markType' or mode == 'lastIsName' or mode == 'markName':
# Each element should be a pending xref targeting the complete
# prefix.
@ -213,13 +209,13 @@ class ASTNestedName(ASTBase):
if self.rooted:
prefix += '.'
if mode == 'lastIsName' and len(names) == 0:
signode += nodes.Text('.')
signode += addnodes.desc_sig_punctuation('.', '.')
else:
dest += nodes.Text('.')
dest += addnodes.desc_sig_punctuation('.', '.')
for i in range(len(names)):
ident = names[i]
if not first:
dest += nodes.Text('.')
dest += addnodes.desc_sig_punctuation('.', '.')
prefix += '.'
first = False
txt_ident = str(ident)
@ -228,7 +224,7 @@ class ASTNestedName(ASTBase):
prefix += txt_ident
if mode == 'lastIsName':
if len(self.names) > 1:
dest += addnodes.desc_addname('.', '.')
dest += addnodes.desc_sig_punctuation('.', '.')
signode += dest
self.names[-1].describe_signature(signode, mode, env, '', symbol)
else:
@ -262,7 +258,8 @@ class ASTBooleanLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text(str(self)))
txt = str(self)
signode += addnodes.desc_sig_keyword(txt, txt)
class ASTNumberLiteral(ASTLiteral):
@ -275,7 +272,7 @@ class ASTNumberLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
signode += addnodes.desc_sig_literal_number(txt, txt)
class ASTCharLiteral(ASTLiteral):
@ -297,7 +294,7 @@ class ASTCharLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
signode += addnodes.desc_sig_literal_char(txt, txt)
class ASTStringLiteral(ASTLiteral):
@ -310,7 +307,7 @@ class ASTStringLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
signode += addnodes.desc_sig_literal_string(txt, txt)
class ASTIdExpression(ASTExpression):
@ -341,9 +338,9 @@ class ASTParenExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('(', '('))
signode += addnodes.desc_sig_punctuation('(', '(')
self.expr.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')', ')'))
signode += addnodes.desc_sig_punctuation(')', ')')
# Postfix expressions
@ -374,9 +371,9 @@ class ASTPostfixArray(ASTPostfixOp):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('['))
signode += addnodes.desc_sig_punctuation('[', '[')
self.expr.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(']'))
signode += addnodes.desc_sig_punctuation(']', ']')
class ASTPostfixInc(ASTPostfixOp):
@ -385,7 +382,7 @@ class ASTPostfixInc(ASTPostfixOp):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('++'))
signode += addnodes.desc_sig_operator('++', '++')
class ASTPostfixDec(ASTPostfixOp):
@ -394,7 +391,7 @@ class ASTPostfixDec(ASTPostfixOp):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('--'))
signode += addnodes.desc_sig_operator('--', '--')
class ASTPostfixMemberOfPointer(ASTPostfixOp):
@ -406,7 +403,7 @@ class ASTPostfixMemberOfPointer(ASTPostfixOp):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('->'))
signode += addnodes.desc_sig_operator('->', '->')
self.name.describe_signature(signode, 'noneIsName', env, symbol)
@ -444,9 +441,11 @@ class ASTUnaryOpExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text(self.op))
if self.op[0] in 'cn':
signode.append(nodes.Text(" "))
signode += addnodes.desc_sig_keyword(self.op, self.op)
signode += addnodes.desc_sig_space()
else:
signode += addnodes.desc_sig_operator(self.op, self.op)
self.expr.describe_signature(signode, mode, env, symbol)
@ -459,9 +458,10 @@ class ASTSizeofType(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('sizeof('))
signode += addnodes.desc_sig_keyword('sizeof', 'sizeof')
signode += addnodes.desc_sig_punctuation('(', '(')
self.typ.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')'))
signode += addnodes.desc_sig_punctuation(')', ')')
class ASTSizeofExpr(ASTExpression):
@ -473,7 +473,8 @@ class ASTSizeofExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('sizeof '))
signode += addnodes.desc_sig_keyword('sizeof', 'sizeof')
signode += addnodes.desc_sig_space()
self.expr.describe_signature(signode, mode, env, symbol)
@ -486,9 +487,10 @@ class ASTAlignofExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('alignof('))
signode += addnodes.desc_sig_keyword('alignof', 'alignof')
signode += addnodes.desc_sig_punctuation('(', '(')
self.typ.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')'))
signode += addnodes.desc_sig_punctuation(')', ')')
# Other expressions
@ -508,9 +510,9 @@ class ASTCastExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('('))
signode += addnodes.desc_sig_punctuation('(', '(')
self.typ.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')'))
signode += addnodes.desc_sig_punctuation(')', ')')
self.expr.describe_signature(signode, mode, env, symbol)
@ -535,9 +537,13 @@ class ASTBinOpExpr(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.exprs[0].describe_signature(signode, mode, env, symbol)
for i in range(1, len(self.exprs)):
signode.append(nodes.Text(' '))
signode.append(nodes.Text(self.ops[i - 1]))
signode.append(nodes.Text(' '))
signode += addnodes.desc_sig_space()
op = self.ops[i - 1]
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'):
signode += addnodes.desc_sig_keyword(op, op)
else:
signode += addnodes.desc_sig_operator(op, op)
signode += addnodes.desc_sig_space()
self.exprs[i].describe_signature(signode, mode, env, symbol)
@ -562,9 +568,13 @@ class ASTAssignmentExpr(ASTExpression):
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.exprs[0].describe_signature(signode, mode, env, symbol)
for i in range(1, len(self.exprs)):
signode.append(nodes.Text(' '))
signode.append(nodes.Text(self.ops[i - 1]))
signode.append(nodes.Text(' '))
signode += addnodes.desc_sig_space()
op = self.ops[i - 1]
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'):
signode += addnodes.desc_sig_keyword(op, op)
else:
signode += addnodes.desc_sig_operator(op, op)
signode += addnodes.desc_sig_space()
self.exprs[i].describe_signature(signode, mode, env, symbol)
@ -580,7 +590,7 @@ class ASTFallbackExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode += nodes.Text(self.expr)
signode += nodes.literal(self.expr, self.expr)
################################################################################
@ -600,7 +610,7 @@ class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode += nodes.Text(str(self.name))
signode += addnodes.desc_sig_keyword_type(self.name, self.name)
class ASTTrailingTypeSpecName(ASTTrailingTypeSpec):
@ -623,8 +633,8 @@ class ASTTrailingTypeSpecName(ASTTrailingTypeSpec):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
if self.prefix:
signode += addnodes.desc_annotation(self.prefix, self.prefix)
signode += nodes.Text(' ')
signode += addnodes.desc_sig_keyword(self.prefix, self.prefix)
signode += addnodes.desc_sig_space()
self.nestedName.describe_signature(signode, mode, env, symbol=symbol)
@ -647,7 +657,7 @@ class ASTFunctionParameter(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
if self.ellipsis:
signode += nodes.Text('...')
signode += addnodes.desc_sig_punctuation('...', '...')
else:
self.arg.describe_signature(signode, mode, env, symbol=symbol)
@ -688,17 +698,18 @@ class ASTParameters(ASTBase):
paramlist += param
signode += paramlist
else:
signode += nodes.Text('(', '(')
signode += addnodes.desc_sig_punctuation('(', '(')
first = True
for arg in self.args:
if not first:
signode += nodes.Text(', ', ', ')
signode += addnodes.desc_sig_punctuation(',', ',')
signode += addnodes.desc_sig_space()
first = False
arg.describe_signature(signode, 'markType', env, symbol=symbol)
signode += nodes.Text(')', ')')
signode += addnodes.desc_sig_punctuation(')', ')')
for attr in self.attrs:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
attr.describe_signature(signode)
@ -744,12 +755,12 @@ class ASTDeclSpecsSimple(ASTBaseBase):
def describe_signature(self, modifiers: List[Node]) -> None:
def _add(modifiers: List[Node], text: str) -> None:
if len(modifiers) > 0:
modifiers.append(nodes.Text(' '))
modifiers.append(addnodes.desc_annotation(text, text))
modifiers.append(addnodes.desc_sig_space())
modifiers.append(addnodes.desc_sig_keyword(text, text))
for attr in self.attrs:
if len(modifiers) > 0:
modifiers.append(nodes.Text(' '))
modifiers.append(addnodes.desc_sig_space())
modifiers.append(attr.describe_signature(modifiers))
if self.storage:
_add(modifiers, self.storage)
@ -799,24 +810,19 @@ class ASTDeclSpecs(ASTBase):
verify_description_mode(mode)
modifiers: List[Node] = []
def _add(modifiers: List[Node], text: str) -> None:
if len(modifiers) > 0:
modifiers.append(nodes.Text(' '))
modifiers.append(addnodes.desc_annotation(text, text))
self.leftSpecs.describe_signature(modifiers)
for m in modifiers:
signode += m
if self.trailingTypeSpec:
if len(modifiers) > 0:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
self.trailingTypeSpec.describe_signature(signode, mode, env,
symbol=symbol)
modifiers = []
self.rightSpecs.describe_signature(modifiers)
if len(modifiers) > 0:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
for m in modifiers:
signode += m
@ -857,13 +863,13 @@ class ASTArray(ASTBase):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
signode.append(nodes.Text("["))
signode += addnodes.desc_sig_punctuation('[', '[')
addSpace = False
def _add(signode: TextElement, text: str) -> bool:
if addSpace:
signode += nodes.Text(' ')
signode += addnodes.desc_annotation(text, text)
signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_keyword(text, text)
return True
if self.static:
@ -875,12 +881,12 @@ class ASTArray(ASTBase):
if self.const:
addSpace = _add(signode, 'const')
if self.vla:
signode.append(nodes.Text('*'))
signode += addnodes.desc_sig_punctuation('*', '*')
elif self.size:
if addSpace:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
self.size.describe_signature(signode, 'markType', env, symbol)
signode.append(nodes.Text("]"))
signode += addnodes.desc_sig_punctuation(']', ']')
class ASTDeclarator(ASTBase):
@ -964,7 +970,9 @@ class ASTDeclaratorNameBitField(ASTDeclarator):
verify_description_mode(mode)
if self.declId:
self.declId.describe_signature(signode, mode, env, symbol)
signode += nodes.Text(' : ', ' : ')
signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_punctuation(':', ':')
signode += addnodes.desc_sig_space()
self.size.describe_signature(signode, mode, env, symbol)
@ -1016,28 +1024,28 @@ class ASTDeclaratorPtr(ASTDeclarator):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
signode += nodes.Text("*")
signode += addnodes.desc_sig_punctuation('*', '*')
for a in self.attrs:
a.describe_signature(signode)
if len(self.attrs) > 0 and (self.restrict or self.volatile or self.const):
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
def _add_anno(signode: TextElement, text: str) -> None:
signode += addnodes.desc_annotation(text, text)
signode += addnodes.desc_sig_keyword(text, text)
if self.restrict:
_add_anno(signode, 'restrict')
if self.volatile:
if self.restrict:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
_add_anno(signode, 'volatile')
if self.const:
if self.restrict or self.volatile:
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
_add_anno(signode, 'const')
if self.const or self.volatile or self.restrict or len(self.attrs) > 0:
if self.next.require_space_after_declSpecs():
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
self.next.describe_signature(signode, mode, env, symbol)
@ -1070,9 +1078,9 @@ class ASTDeclaratorParen(ASTDeclarator):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
signode += nodes.Text('(')
signode += addnodes.desc_sig_punctuation('(', '(')
self.inner.describe_signature(signode, mode, env, symbol)
signode += nodes.Text(')')
signode += addnodes.desc_sig_punctuation(')', ')')
self.next.describe_signature(signode, "noneIsName", env, symbol)
@ -1090,15 +1098,16 @@ class ASTParenExprList(ASTBaseParenExprList):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
signode.append(nodes.Text('('))
signode += addnodes.desc_sig_punctuation('(', '(')
first = True
for e in self.exprs:
if not first:
signode.append(nodes.Text(', '))
signode += addnodes.desc_sig_punctuation(',', ',')
signode += addnodes.desc_sig_space()
else:
first = False
e.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')'))
signode += addnodes.desc_sig_punctuation(')', ')')
class ASTBracedInitList(ASTBase):
@ -1114,17 +1123,18 @@ class ASTBracedInitList(ASTBase):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
signode.append(nodes.Text('{'))
signode += addnodes.desc_sig_punctuation('{', '{')
first = True
for e in self.exprs:
if not first:
signode.append(nodes.Text(', '))
signode += addnodes.desc_sig_punctuation(',', ',')
signode += addnodes.desc_sig_space()
else:
first = False
e.describe_signature(signode, mode, env, symbol)
if self.trailingComma:
signode.append(nodes.Text(','))
signode.append(nodes.Text('}'))
signode += addnodes.desc_sig_punctuation(',', ',')
signode += addnodes.desc_sig_punctuation('}', '}')
class ASTInitializer(ASTBase):
@ -1144,7 +1154,9 @@ class ASTInitializer(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
if self.hasAssign:
signode.append(nodes.Text(' = '))
signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_punctuation('=', '=')
signode += addnodes.desc_sig_space()
self.value.describe_signature(signode, 'markType', env, symbol)
@ -1187,7 +1199,7 @@ class ASTType(ASTBase):
self.declSpecs.describe_signature(signode, 'markType', env, symbol)
if (self.decl.require_space_after_declSpecs() and
len(str(self.declSpecs)) > 0):
signode += nodes.Text(' ')
signode += addnodes.desc_sig_space()
# for parameters that don't really declare new names we get 'markType',
# this should not be propagated, but be 'noneIsName'.
if mode == 'markType':
@ -1241,10 +1253,10 @@ class ASTMacroParameter(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
if self.ellipsis:
signode += nodes.Text('...')
signode += addnodes.desc_sig_punctuation('...', '...')
elif self.variadic:
name = str(self)
signode += nodes.emphasis(name, name)
signode += addnodes.desc_sig_name(name, name)
else:
self.arg.describe_signature(signode, mode, env, symbol=symbol)
@ -1427,23 +1439,27 @@ class ASTDeclaration(ASTBaseBase):
elif self.objectType == 'macro':
pass
elif self.objectType == 'struct':
mainDeclNode += addnodes.desc_annotation('struct ', 'struct ')
mainDeclNode += addnodes.desc_sig_keyword('struct', 'struct')
mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'union':
mainDeclNode += addnodes.desc_annotation('union ', 'union ')
mainDeclNode += addnodes.desc_sig_keyword('union', 'union')
mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'enum':
mainDeclNode += addnodes.desc_annotation('enum ', 'enum ')
mainDeclNode += addnodes.desc_sig_keyword('enum', 'enum')
mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'enumerator':
mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
mainDeclNode += addnodes.desc_sig_keyword('enumerator', 'enumerator')
mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'type':
decl = cast(ASTType, self.declaration)
prefix = decl.get_type_declaration_prefix()
prefix += ' '
mainDeclNode += addnodes.desc_annotation(prefix, prefix)
mainDeclNode += addnodes.desc_sig_keyword(prefix, prefix)
mainDeclNode += addnodes.desc_sig_space()
else:
assert False
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
if self.semicolon:
mainDeclNode += nodes.Text(';')
mainDeclNode += addnodes.desc_sig_punctuation(';', ';')
class SymbolLookupResult:
@ -3661,31 +3677,28 @@ class CExprRole(SphinxRole):
if asCode:
# render the expression as inline code
self.class_type = 'c-expr'
self.node_type: Type[TextElement] = nodes.literal
else:
# render the expression as inline text
self.class_type = 'c-texpr'
self.node_type = nodes.inline
def run(self) -> Tuple[List[Node], List[system_message]]:
text = self.text.replace('\n', ' ')
parser = DefinitionParser(text, location=self.get_source_info(),
config=self.env.config)
# attempt to mimic XRefRole classes, except that...
classes = ['xref', 'c', self.class_type]
try:
ast = parser.parse_expression()
except DefinitionError as ex:
logger.warning('Unparseable C expression: %r\n%s', text, ex,
location=self.get_source_info())
# see below
return [self.node_type(text, text, classes=classes)], []
return [addnodes.desc_inline('c', text, text, classes=[self.class_type])], []
parentSymbol = self.env.temp_data.get('c:parent_symbol', None)
if parentSymbol is None:
parentSymbol = self.env.domaindata['c']['root_symbol']
# ...most if not all of these classes should really apply to the individual references,
# not the container node
signode = self.node_type(classes=classes)
signode = addnodes.desc_inline('c', classes=[self.class_type])
ast.describe_signature(signode, 'markType', self.env, parentSymbol)
return [signode], []

File diff suppressed because it is too large Load Diff

View File

@ -508,6 +508,63 @@ table.hlist td {
vertical-align: top;
}
/* -- object description styles --------------------------------------------- */
.sig {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
}
.sig-name, code.descname {
background-color: transparent;
font-weight: bold;
}
.sig-name {
font-size: 1.1em;
}
code.descname {
font-size: 1.2em;
}
.sig-prename, code.descclassname {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.sig-param.n {
font-style: italic;
}
/* C++ specific styling */
.sig-inline.c-texpr,
.sig-inline.cpp-texpr {
font-family: unset;
}
.sig.c .k, .sig.c .kt,
.sig.cpp .k, .sig.cpp .kt {
color: #0033B3;
}
.sig.c .m,
.sig.cpp .m {
color: #1750EB;
}
.sig.c .s, .sig.c .sc,
.sig.cpp .s, .sig.cpp .sc {
color: #067D17;
}
/* -- other body styles ----------------------------------------------------- */
@ -634,14 +691,6 @@ dl.glossary dt {
font-size: 1.1em;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.versionmodified {
font-style: italic;
}
@ -786,16 +835,6 @@ div.literal-block-wrapper {
margin: 1em 0;
}
code.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
code.descclassname {
background-color: transparent;
}
code.xref, a code {
background-color: transparent;
font-weight: bold;

View File

@ -206,13 +206,9 @@ class OnlyNodeTransform(SphinxPostTransform):
class SigElementFallbackTransform(SphinxPostTransform):
"""Fallback desc_sig_element nodes to inline if translator does not supported them."""
"""Fallback various desc_* nodes to inline if translator does not supported them."""
default_priority = 200
SIG_ELEMENTS = [addnodes.desc_sig_name,
addnodes.desc_sig_operator,
addnodes.desc_sig_punctuation]
def run(self, **kwargs: Any) -> None:
def has_visitor(translator: Type[nodes.NodeVisitor], node: Type[Element]) -> bool:
return hasattr(translator, "visit_%s" % node.__name__)
@ -222,24 +218,35 @@ class SigElementFallbackTransform(SphinxPostTransform):
# subclass of SphinxTranslator supports desc_sig_element nodes automatically.
return
if all(has_visitor(translator, node) for node in self.SIG_ELEMENTS):
# the translator supports all desc_sig_element nodes
return
else:
self.fallback()
# for the leaf elements (desc_sig_element), the translator should support _all_
if not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS):
self.fallback(addnodes.desc_sig_element)
def fallback(self) -> None:
for node in self.document.traverse(addnodes.desc_sig_element):
if not has_visitor(translator, addnodes.desc_inline):
self.fallback(addnodes.desc_inline)
def fallback(self, nodeType: Any) -> None:
for node in self.document.traverse(nodeType):
newnode = nodes.inline()
newnode.update_all_atts(node)
newnode.extend(node)
node.replace_self(newnode)
class PropagateDescDomain(SphinxPostTransform):
"""Add the domain name of the parent node as a class in each desc_signature node."""
default_priority = 200
def run(self, **kwargs: Any) -> None:
for node in self.document.traverse(addnodes.desc_signature):
node['classes'].append(node.parent['domain'])
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(ReferencesResolver)
app.add_post_transform(OnlyNodeTransform)
app.add_post_transform(SigElementFallbackTransform)
app.add_post_transform(PropagateDescDomain)
return {
'version': 'builtin',

View File

@ -107,8 +107,15 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def depart_start_of_file(self, node: Element) -> None:
self.docnames.pop()
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes for descriptions
##################################
def visit_desc(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dl', CLASS=node['objtype']))
self.body.append(self.starttag(node, 'dl'))
def depart_desc(self, node: Element) -> None:
self.body.append('</dl>\n\n')
@ -133,8 +140,29 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
self.add_permalink_ref(node.parent, _('Permalink to this definition'))
self.body.append('<br />')
def visit_desc_content(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dd', ''))
def depart_desc_content(self, node: Element) -> None:
self.body.append('</dd>')
def visit_desc_inline(self, node: Element) -> None:
self.body.append(self.starttag(node, 'span', ''))
def depart_desc_inline(self, node: Element) -> None:
self.body.append('</span>')
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
self.body.append(self.starttag(node, 'code', ''))
def depart_desc_name(self, node: Element) -> None:
self.body.append('</code>')
def visit_desc_addname(self, node: Element) -> None:
self.body.append(self.starttag(node, 'code', '', CLASS='descclassname'))
self.body.append(self.starttag(node, 'code', ''))
def depart_desc_addname(self, node: Element) -> None:
self.body.append('</code>')
@ -151,12 +179,6 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_returns(self, node: Element) -> None:
pass
def visit_desc_name(self, node: Element) -> None:
self.body.append(self.starttag(node, 'code', '', CLASS='descname'))
def depart_desc_name(self, node: Element) -> None:
self.body.append('</code>')
def visit_desc_parameterlist(self, node: Element) -> None:
self.body.append('<span class="sig-paren">(</span>')
self.first_param = 1
@ -205,11 +227,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_annotation(self, node: Element) -> None:
self.body.append('</em>')
def visit_desc_content(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dd', ''))
def depart_desc_content(self, node: Element) -> None:
self.body.append('</dd>')
##############################################
def visit_versionmodified(self, node: Element) -> None:
self.body.append(self.starttag(node, 'div', CLASS=node['type']))

View File

@ -78,8 +78,15 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_start_of_file(self, node: Element) -> None:
self.docnames.pop()
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes for descriptions
##################################
def visit_desc(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dl', CLASS=node['objtype']))
self.body.append(self.starttag(node, 'dl'))
def depart_desc(self, node: Element) -> None:
self.body.append('</dl>\n\n')
@ -104,11 +111,32 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
self.add_permalink_ref(node.parent, _('Permalink to this definition'))
self.body.append('<br />')
def visit_desc_content(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dd', ''))
def depart_desc_content(self, node: Element) -> None:
self.body.append('</dd>')
def visit_desc_inline(self, node: Element) -> None:
self.body.append(self.starttag(node, 'span', ''))
def depart_desc_inline(self, node: Element) -> None:
self.body.append('</span>')
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
self.body.append(self.starttag(node, 'span', ''))
def depart_desc_name(self, node: Element) -> None:
self.body.append('</span>')
def visit_desc_addname(self, node: Element) -> None:
self.body.append(self.starttag(node, 'code', '', CLASS='sig-prename descclassname'))
self.body.append(self.starttag(node, 'span', ''))
def depart_desc_addname(self, node: Element) -> None:
self.body.append('</code>')
self.body.append('</span>')
def visit_desc_type(self, node: Element) -> None:
pass
@ -122,12 +150,6 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_desc_returns(self, node: Element) -> None:
pass
def visit_desc_name(self, node: Element) -> None:
self.body.append(self.starttag(node, 'code', '', CLASS='sig-name descname'))
def depart_desc_name(self, node: Element) -> None:
self.body.append('</code>')
def visit_desc_parameterlist(self, node: Element) -> None:
self.body.append('<span class="sig-paren">(</span>')
self.first_param = 1
@ -176,11 +198,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_desc_annotation(self, node: Element) -> None:
self.body.append('</em>')
def visit_desc_content(self, node: Element) -> None:
self.body.append(self.starttag(node, 'dd', ''))
def depart_desc_content(self, node: Element) -> None:
self.body.append('</dd>')
##############################################
def visit_versionmodified(self, node: Element) -> None:
self.body.append(self.starttag(node, 'div', CLASS=node['type']))

View File

@ -698,6 +698,13 @@ class LaTeXTranslator(SphinxTranslator):
def depart_subtitle(self, node: Element) -> None:
self.body.append(self.context.pop())
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes for descriptions
##################################
def visit_desc(self, node: Element) -> None:
if self.config.latex_show_urls == 'footnote':
self.body.append(BLANKLINE)
@ -750,6 +757,31 @@ class LaTeXTranslator(SphinxTranslator):
def depart_desc_signature_line(self, node: Element) -> None:
self._depart_signature_line(node)
def visit_desc_content(self, node: Element) -> None:
if node.children and not isinstance(node.children[0], nodes.paragraph):
# avoid empty desc environment which causes a formatting bug
self.body.append('~')
def depart_desc_content(self, node: Element) -> None:
pass
def visit_desc_inline(self, node: Element) -> None:
self.body.append(r'\sphinxcode{\sphinxupquote{')
def depart_desc_inline(self, node: Element) -> None:
self.body.append('}}')
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
self.body.append(r'\sphinxbfcode{\sphinxupquote{')
self.literal_whitespace += 1
def depart_desc_name(self, node: Element) -> None:
self.body.append('}}')
self.literal_whitespace -= 1
def visit_desc_addname(self, node: Element) -> None:
self.body.append(r'\sphinxcode{\sphinxupquote{')
self.literal_whitespace += 1
@ -770,14 +802,6 @@ class LaTeXTranslator(SphinxTranslator):
def depart_desc_returns(self, node: Element) -> None:
self.body.append(r'}')
def visit_desc_name(self, node: Element) -> None:
self.body.append(r'\sphinxbfcode{\sphinxupquote{')
self.literal_whitespace += 1
def depart_desc_name(self, node: Element) -> None:
self.body.append('}}')
self.literal_whitespace -= 1
def visit_desc_parameterlist(self, node: Element) -> None:
# close name, open parameterlist
self.body.append('}{')
@ -811,13 +835,7 @@ class LaTeXTranslator(SphinxTranslator):
def depart_desc_annotation(self, node: Element) -> None:
self.body.append('}}')
def visit_desc_content(self, node: Element) -> None:
if node.children and not isinstance(node.children[0], nodes.paragraph):
# avoid empty desc environment which causes a formatting bug
self.body.append('~')
def depart_desc_content(self, node: Element) -> None:
pass
##############################################
def visit_seealso(self, node: Element) -> None:
self.body.append(BLANKLINE)

View File

@ -120,6 +120,13 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
def depart_start_of_file(self, node: Element) -> None:
pass
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes for descriptions
##################################
def visit_desc(self, node: Element) -> None:
self.visit_definition_list(node)
@ -139,6 +146,27 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_signature_line(self, node: Element) -> None:
self.body.append(' ')
def visit_desc_content(self, node: Element) -> None:
self.visit_definition(node)
def depart_desc_content(self, node: Element) -> None:
self.depart_definition(node)
def visit_desc_inline(self, node: Element) -> None:
pass
def depart_desc_inline(self, node: Element) -> None:
pass
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
pass
def depart_desc_name(self, node: Element) -> None:
pass
def visit_desc_addname(self, node: Element) -> None:
pass
@ -157,12 +185,6 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_returns(self, node: Element) -> None:
pass
def visit_desc_name(self, node: Element) -> None:
pass
def depart_desc_name(self, node: Element) -> None:
pass
def visit_desc_parameterlist(self, node: Element) -> None:
self.body.append('(')
self.first_param = 1
@ -191,11 +213,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_annotation(self, node: Element) -> None:
pass
def visit_desc_content(self, node: Element) -> None:
self.visit_definition(node)
def depart_desc_content(self, node: Element) -> None:
self.depart_definition(node)
##############################################
def visit_versionmodified(self, node: Element) -> None:
self.visit_paragraph(node)

View File

@ -1367,7 +1367,12 @@ class TexinfoTranslator(SphinxTranslator):
self.body.append('\n\n')
raise nodes.SkipNode
# -- Desc
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes for descriptions
##################################
def visit_desc(self, node: addnodes.desc) -> None:
self.descs.append(node)
@ -1408,6 +1413,21 @@ class TexinfoTranslator(SphinxTranslator):
def depart_desc_signature_line(self, node: Element) -> None:
pass
def visit_desc_content(self, node: Element) -> None:
pass
def depart_desc_content(self, node: Element) -> None:
pass
def visit_desc_inline(self, node: Element) -> None:
pass
def depart_desc_inline(self, node: Element) -> None:
pass
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
pass
@ -1470,11 +1490,7 @@ class TexinfoTranslator(SphinxTranslator):
def depart_desc_annotation(self, node: Element) -> None:
pass
def visit_desc_content(self, node: Element) -> None:
pass
def depart_desc_content(self, node: Element) -> None:
pass
##############################################
def visit_inline(self, node: Element) -> None:
pass

View File

@ -536,6 +536,13 @@ class TextTranslator(SphinxTranslator):
def depart_attribution(self, node: Element) -> None:
pass
#############################################################
# Domain-specific object descriptions
#############################################################
# Top-level nodes
#################
def visit_desc(self, node: Element) -> None:
pass
@ -555,6 +562,22 @@ class TextTranslator(SphinxTranslator):
def depart_desc_signature_line(self, node: Element) -> None:
self.add_text('\n')
def visit_desc_content(self, node: Element) -> None:
self.new_state()
self.add_text(self.nl)
def depart_desc_content(self, node: Element) -> None:
self.end_state()
def visit_desc_inline(self, node: Element) -> None:
pass
def depart_desc_inline(self, node: Element) -> None:
pass
# Nodes for high-level structure in signatures
##############################################
def visit_desc_name(self, node: Element) -> None:
pass
@ -606,12 +629,7 @@ class TextTranslator(SphinxTranslator):
def depart_desc_annotation(self, node: Element) -> None:
pass
def visit_desc_content(self, node: Element) -> None:
self.new_state()
self.add_text(self.nl)
def depart_desc_content(self, node: Element) -> None:
self.end_state()
##############################################
def visit_figure(self, node: Element) -> None:
self.new_state()

View File

@ -213,3 +213,9 @@ CPP domain
.. cpp:function:: T& operator[]( unsigned j )
const T& operator[]( unsigned j ) const
.. cpp:function:: template<typename T1, typename T2> \
requires A<T1, T2> \
void f()
- :cpp:expr:`a + b`

View File

@ -285,10 +285,10 @@ def test_html4_output(app, status, warning):
'objects.html': [
(".//dt[@id='mod.Cls.meth1']", ''),
(".//dt[@id='errmod.Error']", ''),
(".//dt/code/span", r'long\(parameter,'),
(".//dt/code/span", r'list\)'),
(".//dt/code/span", 'another'),
(".//dt/code/span", 'one'),
(".//dt/span[@class='sig-name descname']/span[@class='pre']", r'long\(parameter,'),
(".//dt/span[@class='sig-name descname']/span[@class='pre']", r'list\)'),
(".//dt/span[@class='sig-name descname']/span[@class='pre']", 'another'),
(".//dt/span[@class='sig-name descname']/span[@class='pre']", 'one'),
(".//a[@href='#mod.Cls'][@class='reference internal']", ''),
(".//dl[@class='std userdesc']", ''),
(".//dt[@id='userdesc-myobj']", ''),

View File

@ -73,6 +73,7 @@ def _check(name, input, idDict, output, key, asTextOutput):
print("Input: ", input)
print("astext(): ", resAsText)
print("Expected: ", outputAsText)
print("Node:", parentNode)
raise DefinitionError("")
idExpected = [None]
@ -743,6 +744,9 @@ def test_anon_definitions():
check('class', '@1', {3: "Ut1_1"}, asTextOutput='class [anonymous]')
check('class', '@a::A', {3: "NUt1_a1AE"}, asTextOutput='class [anonymous]::A')
check('function', 'int f(int @a)', {1: 'f__i', 2: '1fi'},
asTextOutput='int f(int [anonymous])')
def test_templates():
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> {key}A<T>")
@ -1206,7 +1210,7 @@ not found in `{test}`
cpp_any_role = RoleClasses('cpp-any', 'a', ['code'])
# NYI: consistent looks
# texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'code'])
expr_role = RoleClasses('cpp-expr', 'code', ['a'])
expr_role = RoleClasses('cpp-expr', 'span', ['a'])
texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'span'])
# XRefRole-style classes
@ -1223,8 +1227,7 @@ not found in `{test}`
for role in (expr_role, texpr_role):
name = role.name
expect = '`{name}` puts the domain and role classes at its root'.format(name=name)
# NYI: xref should go in the references
assert {'xref', 'cpp', name} <= role.classes, expect
assert {'sig', 'sig-inline', 'cpp', name} <= role.classes, expect
# reference classes

View File

@ -258,10 +258,10 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning):
'<span class="pre">Bar</span></code></a>' in html)
assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#foons"'
' title="(in foo v2.0)"><span class="pre">foons</span></a>' in html)
' title="(in foo v2.0)"><span class="n"><span class="pre">foons</span></span></a>' in html)
assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#foons_bartype"'
' title="(in foo v2.0)"><span class="pre">bartype</span></a>' in html)
' title="(in foo v2.0)"><span class="n"><span class="pre">bartype</span></span></a>' in html)
def test_missing_reference_jsdomain(tempdir, app, status, warning):