diff --git a/CHANGES b/CHANGES
index e941339f5..45a4315e0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -30,15 +30,26 @@ Dependencies
Incompatible changes
--------------------
+* #9023: Change the CSS classes on :rst:role:`cpp:expr` and
+ :rst:role:`cpp:texpr`.
+
Deprecated
----------
Features added
--------------
+* #8818: autodoc: Super class having ``Any`` arguments causes nit-picky warning
+* #9103: LaTeX: imgconverter: conversion runs even if not needed
+* #8127: py domain: Ellipsis in info-field-list causes nit-picky warning
+* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.
+
Bugs fixed
----------
+* C, C++, fix ``KeyError`` when an ``alias`` directive is the first C/C++
+ directive in a file with another C/C++ directive later.
+
Testing
--------
diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst
index ad04951f3..d9c04f413 100644
--- a/doc/extdev/index.rst
+++ b/doc/extdev/index.rst
@@ -171,10 +171,26 @@ as metadata of the extension. Metadata keys currently recognized are:
source files can be used when the extension is loaded. It defaults to
``False``, i.e. you have to explicitly specify your extension to be
parallel-read-safe after checking that it is.
+
+ .. note:: The *parallel-read-safe* extension must satisfy the following
+ conditions:
+
+ * The core logic of the extension is parallely executable during
+ the reading phase.
+ * It has event handlers for :event:`env-merge-info` and
+ :event:`env-purge-doc` events if it stores dataa to the build
+ environment object (env) during the reading phase.
+
* ``'parallel_write_safe'``: a boolean that specifies if parallel writing of
output files can be used when the extension is loaded. Since extensions
usually don't negatively influence the process, this defaults to ``True``.
+ .. note:: The *parallel-write-safe* extension must satisfy the following
+ conditions:
+
+ * The core logic of the extension is parallely executable during
+ the writing phase.
+
APIs used for writing extensions
--------------------------------
diff --git a/doc/extdev/nodes.rst b/doc/extdev/nodes.rst
index 3976de4c7..77872df40 100644
--- a/doc/extdev/nodes.rst
+++ b/doc/extdev/nodes.rst
@@ -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
------------------------------
diff --git a/doc/usage/extensions/extlinks.rst b/doc/usage/extensions/extlinks.rst
index 221b79d99..c345a7c82 100644
--- a/doc/usage/extensions/extlinks.rst
+++ b/doc/usage/extensions/extlinks.rst
@@ -51,6 +51,10 @@ The extension adds a config value:
that generate links, i.e. ``:issue:`this issue <123>```. In this case, the
*caption* is not relevant.
+ .. versionchanged:: 4.0
+
+ Support to substitute by '%s' in the caption.
+
.. note::
Since links are generated from the role in the reading stage, they appear as
diff --git a/doc/usage/extensions/napoleon.rst b/doc/usage/extensions/napoleon.rst
index 066c56e2d..bd2bcad3f 100644
--- a/doc/usage/extensions/napoleon.rst
+++ b/doc/usage/extensions/napoleon.rst
@@ -301,6 +301,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True
+ napoleon_preprocess_types = False
napoleon_type_aliases = None
napoleon_attr_annotations = True
@@ -510,6 +511,16 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
:returns: *bool* -- True if successful, False otherwise
+.. confval:: napoleon_preprocess_types
+
+ True to convert the type definitions in the docstrings as references.
+ Defaults to *True*.
+
+ .. versionadded:: 3.2.1
+ .. versionchanged:: 3.5
+
+ Do preprocess the Google style docstrings also.
+
.. confval:: napoleon_type_aliases
A mapping to translate type names to other names or references. Works
@@ -570,4 +581,4 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
.. versionadded:: 1.8
.. versionchanged:: 3.5
- Support ``params_style`` and ``returns_style``
\ No newline at end of file
+ Support ``params_style`` and ``returns_style``
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py
index 5645ac91b..8a020b02e 100644
--- a/sphinx/addnodes.py
+++ b/sphinx/addnodes.py
@@ -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)
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index e1ccc8be7..8e8d65f03 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -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()
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index 72b9746ac..b0711f68e 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -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:
@@ -3438,7 +3454,8 @@ class AliasNode(nodes.Element):
if 'c:parent_symbol' not in env.temp_data:
root = env.domaindata['c']['root_symbol']
env.temp_data['c:parent_symbol'] = root
- self.parentKey = env.temp_data['c:parent_symbol'].get_lookup_key()
+ env.ref_context['c:parent_key'] = root.get_lookup_key()
+ self.parentKey = env.ref_context['c:parent_key']
else:
assert parentKey is not None
self.parentKey = parentKey
@@ -3661,31 +3678,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], []
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index abe961791..d57c6e257 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -9,8 +9,8 @@
"""
import re
-from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, Type,
- TypeVar, Union, cast)
+from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
+ Union, cast)
from docutils import nodes
from docutils.nodes import Element, Node, TextElement, system_message
@@ -604,6 +604,10 @@ class ASTIdentifier(ASTBase):
def describe_signature(self, signode: TextElement, mode: str, env: "BuildEnvironment",
prefix: str, templateArgs: str, symbol: "Symbol") -> None:
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 + templateArgs
pnode = addnodes.pending_xref('', refdomain='cpp',
@@ -611,21 +615,17 @@ class ASTIdentifier(ASTBase):
reftarget=targetText, modname=None,
classname=None)
pnode['cpp: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
+ elif mode == 'param':
+ node['classes'].append('sig-param')
+ signode += node
elif mode == 'udl':
# the target is 'operator""id' instead of just 'id'
assert len(prefix) == 0
@@ -637,7 +637,7 @@ class ASTIdentifier(ASTBase):
reftarget=targetText, modname=None,
classname=None)
pnode['cpp:parent_key'] = symbol.get_lookup_key()
- pnode += nodes.Text(self.identifier)
+ pnode += node
signode += pnode
else:
raise Exception('Unknown description mode: %s' % mode)
@@ -669,7 +669,7 @@ class ASTNestedNameElement(ASTBase):
tArgs = str(self.templateArgs) if self.templateArgs is not None else ''
self.identOrOp.describe_signature(signode, mode, env, prefix, tArgs, symbol)
if self.templateArgs is not None:
- self.templateArgs.describe_signature(signode, mode, env, symbol)
+ self.templateArgs.describe_signature(signode, 'markType', env, symbol)
class ASTNestedName(ASTBase):
@@ -730,12 +730,15 @@ 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:
- signode += nodes.Text('::')
+ assert False, "Can this happen?" # TODO
+ signode += nodes.Text('::blah')
n = self.names[i]
if self.templates[i]:
+ assert False, "Can this happen?" # TODO
signode += nodes.Text("template")
signode += nodes.Text(" ")
n.describe_signature(signode, mode, env, '', symbol)
@@ -743,9 +746,7 @@ class ASTNestedName(ASTBase):
assert not self.rooted, str(self)
assert len(self.names) == 1
assert not self.templates[0]
- node = nodes.emphasis()
- self.names[0].describe_signature(node, 'noneIsName', env, '', symbol)
- signode += node
+ self.names[0].describe_signature(signode, 'param', env, '', symbol)
elif mode == 'markType' or mode == 'lastIsName' or mode == 'markName':
# Each element should be a pending xref targeting the complete
# prefix. however, only the identifier part should be a link, such
@@ -771,17 +772,18 @@ 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)):
nne = names[i]
template = self.templates[i]
if not first:
- dest += nodes.Text('::')
+ dest += addnodes.desc_sig_punctuation('::', '::')
prefix += '::'
if template:
- dest += nodes.Text("template ")
+ dest += addnodes.desc_sig_keyword('template', 'template')
+ dest += addnodes.desc_sig_space()
first = False
txt_nne = str(nne)
if txt_nne != '':
@@ -793,10 +795,11 @@ class ASTNestedName(ASTBase):
prefix += txt_nne
if mode == 'lastIsName':
if len(self.names) > 1:
- dest += addnodes.desc_addname('::', '::')
+ dest += addnodes.desc_sig_punctuation('::', '::')
signode += dest
if self.templates[-1]:
- signode += nodes.Text("template ")
+ signode += addnodes.desc_sig_keyword('template', 'template')
+ signode += addnodes.desc_sig_space()
self.names[-1].describe_signature(signode, mode, env, '', symbol)
else:
raise Exception('Unknown description mode: %s' % mode)
@@ -831,7 +834,7 @@ class ASTPointerLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('nullptr'))
+ signode += addnodes.desc_sig_keyword('nullptr', 'nullptr')
class ASTBooleanLiteral(ASTLiteral):
@@ -852,7 +855,7 @@ class ASTBooleanLiteral(ASTLiteral):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text(str(self)))
+ signode += addnodes.desc_sig_keyword(str(self), str(self))
class ASTNumberLiteral(ASTLiteral):
@@ -868,8 +871,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(self.data, self.data)
class ASTStringLiteral(ASTLiteral):
@@ -885,8 +887,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(self.data, self.data)
class ASTCharLiteral(ASTLiteral):
@@ -913,8 +914,10 @@ 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))
+ if self.prefix is not None:
+ signode += addnodes.desc_sig_keyword(self.prefix, self.prefix)
+ txt = "'" + self.data + "'"
+ signode += addnodes.desc_sig_literal_char(txt, txt)
class ASTUserDefinedLiteral(ASTLiteral):
@@ -946,7 +949,7 @@ class ASTThisLiteral(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text("this"))
+ signode += addnodes.desc_sig_keyword('this', 'this')
class ASTFoldExpr(ASTExpression):
@@ -996,19 +999,19 @@ class ASTFoldExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('('))
+ signode += addnodes.desc_sig_punctuation('(', '(')
if self.leftExpr:
self.leftExpr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(' '))
- signode.append(nodes.Text(self.op))
- signode.append(nodes.Text(' '))
- signode.append(nodes.Text('...'))
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_operator(self.op, self.op)
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('...', '...')
if self.rightExpr:
- signode.append(nodes.Text(' '))
- signode.append(nodes.Text(self.op))
- signode.append(nodes.Text(' '))
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_operator(self.op, self.op)
+ signode += addnodes.desc_sig_space()
self.rightExpr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTParenExpr(ASTExpression):
@@ -1023,9 +1026,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(')', ')')
class ASTIdExpression(ASTExpression):
@@ -1068,9 +1071,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 ASTPostfixMember(ASTPostfixOp):
@@ -1085,7 +1088,7 @@ class ASTPostfixMember(ASTPostfixOp):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('.'))
+ signode += addnodes.desc_sig_punctuation('.', '.')
self.name.describe_signature(signode, 'noneIsName', env, symbol)
@@ -1101,7 +1104,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)
@@ -1114,7 +1117,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):
@@ -1126,7 +1129,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 ASTPostfixCallExpr(ASTPostfixOp):
@@ -1195,13 +1198,13 @@ class ASTExplicitCast(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text(self.cast))
- signode.append(nodes.Text('<'))
+ signode += addnodes.desc_sig_keyword(self.cast, self.cast)
+ signode += addnodes.desc_sig_punctuation('<', '<')
self.typ.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text('>'))
- signode.append(nodes.Text('('))
+ signode += addnodes.desc_sig_punctuation('>', '>')
+ signode += addnodes.desc_sig_punctuation('(', '(')
self.expr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTTypeId(ASTExpression):
@@ -1218,10 +1221,10 @@ class ASTTypeId(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('typeid'))
- signode.append(nodes.Text('('))
+ signode += addnodes.desc_sig_keyword('typeid', 'typeid')
+ signode += addnodes.desc_sig_punctuation('(', '(')
self.typeOrExpr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
# Unary expressions
@@ -1243,9 +1246,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)
@@ -1261,10 +1266,12 @@ class ASTSizeofParamPack(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('...', '...')
+ signode += addnodes.desc_sig_punctuation('(', '(')
self.identifier.describe_signature(signode, 'markType', env,
symbol=symbol, prefix="", templateArgs="")
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTSizeofType(ASTExpression):
@@ -1279,9 +1286,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):
@@ -1296,7 +1304,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)
@@ -1312,9 +1321,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(')', ')')
class ASTNoexceptExpr(ASTExpression):
@@ -1329,9 +1339,10 @@ class ASTNoexceptExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('noexcept('))
+ signode += addnodes.desc_sig_keyword('noexcept', 'noexcept')
+ signode += addnodes.desc_sig_punctuation('(', '(')
self.expr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTNewExpr(ASTExpression):
@@ -1371,8 +1382,9 @@ class ASTNewExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
if self.rooted:
- signode.append(nodes.Text('::'))
- signode.append(nodes.Text('new '))
+ signode += addnodes.desc_sig_punctuation('::', '::')
+ signode += addnodes.desc_sig_keyword('new', 'new')
+ signode += addnodes.desc_sig_space()
# TODO: placement
if self.isNewTypeId:
self.typ.describe_signature(signode, mode, env, symbol)
@@ -1408,10 +1420,12 @@ class ASTDeleteExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
if self.rooted:
- signode.append(nodes.Text('::'))
- signode.append(nodes.Text('delete '))
+ signode += addnodes.desc_sig_punctuation('::', '::')
+ signode += addnodes.desc_sig_keyword('delete', 'delete')
+ signode += addnodes.desc_sig_space()
if self.array:
- signode.append(nodes.Text('[] '))
+ signode += addnodes.desc_sig_punctuation('[]', '[]')
+ signode += addnodes.desc_sig_space()
self.expr.describe_signature(signode, mode, env, symbol)
@@ -1435,9 +1449,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)
@@ -1471,9 +1485,13 @@ class ASTBinOpExpr(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)
@@ -1494,17 +1512,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 ASTAssignmentExpr(ASTExpression):
@@ -1536,9 +1555,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)
@@ -1563,7 +1586,8 @@ class ASTCommaExpr(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 += addnodes.desc_sig_punctuation(',', ',')
+ signode += addnodes.desc_sig_space()
self.exprs[i].describe_signature(signode, mode, env, symbol)
@@ -1579,7 +1603,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)
################################################################################
@@ -1599,24 +1623,39 @@ class ASTOperator(ASTBase):
def get_id(self, version: int) -> str:
raise NotImplementedError()
+ def _describe_identifier(self, signode: TextElement, identnode: TextElement,
+ env: "BuildEnvironment", symbol: "Symbol") -> None:
+ """Render the prefix into signode, and the last part into identnode."""
+ raise NotImplementedError()
+
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", prefix: str, templateArgs: str,
symbol: "Symbol") -> None:
verify_description_mode(mode)
- identifier = str(self)
if mode == 'lastIsName':
- signode += addnodes.desc_name(identifier, identifier)
+ mainName = addnodes.desc_name()
+ self._describe_identifier(mainName, mainName, env, symbol)
+ signode += mainName
elif mode == 'markType':
- targetText = prefix + identifier + templateArgs
+ targetText = prefix + str(self) + templateArgs
pnode = addnodes.pending_xref('', refdomain='cpp',
reftype='identifier',
reftarget=targetText, modname=None,
classname=None)
pnode['cpp:parent_key'] = symbol.get_lookup_key()
- pnode += nodes.Text(identifier)
+ # Render the identifier part, but collapse it into a string
+ # and make that the a link to this operator.
+ # E.g., if it is 'operator SomeType', then 'SomeType' becomes
+ # a link to the operator, not to 'SomeType'.
+ container = nodes.literal()
+ self._describe_identifier(signode, container, env, symbol)
+ txt = container.astext()
+ pnode += addnodes.desc_name(txt, txt)
signode += pnode
else:
- signode += addnodes.desc_addname(identifier, identifier)
+ addName = addnodes.desc_addname()
+ self._describe_identifier(addName, addName, env, symbol)
+ signode += addName
class ASTOperatorBuildIn(ASTOperator):
@@ -1641,6 +1680,13 @@ class ASTOperatorBuildIn(ASTOperator):
else:
return 'operator' + self.op
+ def _describe_identifier(self, signode: TextElement, identnode: TextElement,
+ env: "BuildEnvironment", symbol: "Symbol") -> None:
+ signode += addnodes.desc_sig_keyword('operator', 'operator')
+ if self.op in ('new', 'new[]', 'delete', 'delete[]') or self.op[0] in "abcnox":
+ signode += addnodes.desc_sig_space()
+ identnode += addnodes.desc_sig_operator(self.op, self.op)
+
class ASTOperatorLiteral(ASTOperator):
def __init__(self, identifier: ASTIdentifier) -> None:
@@ -1655,6 +1701,12 @@ class ASTOperatorLiteral(ASTOperator):
def _stringify(self, transform: StringifyTransform) -> str:
return 'operator""' + transform(self.identifier)
+ def _describe_identifier(self, signode: TextElement, identnode: TextElement,
+ env: "BuildEnvironment", symbol: "Symbol") -> None:
+ signode += addnodes.desc_sig_keyword('operator', 'operator')
+ signode += addnodes.desc_sig_literal_string('""', '""')
+ self.identifier.describe_signature(identnode, 'markType', env, '', '', symbol)
+
class ASTOperatorType(ASTOperator):
def __init__(self, type: "ASTType") -> None:
@@ -1672,6 +1724,12 @@ class ASTOperatorType(ASTOperator):
def get_name_no_template(self) -> str:
return str(self)
+ def _describe_identifier(self, signode: TextElement, identnode: TextElement,
+ env: "BuildEnvironment", symbol: "Symbol") -> None:
+ signode += addnodes.desc_sig_keyword('operator', 'operator')
+ signode += addnodes.desc_sig_space()
+ self.type.describe_signature(identnode, 'markType', env, symbol)
+
class ASTTemplateArgConstant(ASTBase):
def __init__(self, value: ASTExpression) -> None:
@@ -1730,16 +1788,17 @@ class ASTTemplateArgs(ASTBase):
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('<', '<')
first = True
for a in self.args:
if not first:
- signode += nodes.Text(', ')
+ signode += addnodes.desc_sig_punctuation(',', ',')
+ signode += addnodes.desc_sig_space()
first = False
a.describe_signature(signode, 'markType', env, symbol=symbol)
if self.packExpansion:
- signode += nodes.Text('...')
- signode += nodes.Text('>')
+ signode += addnodes.desc_sig_punctuation('...', '...')
+ signode += addnodes.desc_sig_punctuation('>', '>')
# Main part of declarations
@@ -1780,7 +1839,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 ASTTrailingTypeSpecDecltypeAuto(ASTTrailingTypeSpec):
@@ -1794,7 +1853,10 @@ class ASTTrailingTypeSpecDecltypeAuto(ASTTrailingTypeSpec):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text(str(self)))
+ signode += addnodes.desc_sig_keyword('decltype', 'decltype')
+ signode += addnodes.desc_sig_punctuation('(', '(')
+ signode += addnodes.desc_sig_keyword('auto', 'auto')
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTTrailingTypeSpecDecltype(ASTTrailingTypeSpec):
@@ -1811,9 +1873,10 @@ class ASTTrailingTypeSpecDecltype(ASTTrailingTypeSpec):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode.append(nodes.Text('decltype('))
+ signode += addnodes.desc_sig_keyword('decltype', 'decltype')
+ signode += addnodes.desc_sig_punctuation('(', '(')
self.expr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTTrailingTypeSpecName(ASTTrailingTypeSpec):
@@ -1839,8 +1902,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)
@@ -1872,7 +1935,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)
@@ -1888,18 +1951,19 @@ class ASTNoexceptSpec(ASTBase):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode += addnodes.desc_annotation('noexcept', 'noexcept')
+ signode += addnodes.desc_sig_keyword('noexcept', 'noexcept')
if self.expr:
- signode.append(nodes.Text('('))
- self.expr.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ signode += addnodes.desc_sig_punctuation('(', '(')
+ self.expr.describe_signature(signode, 'markType', env, symbol)
+ signode += addnodes.desc_sig_punctuation(')', ')')
class ASTParametersQualifiers(ASTBase):
def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool,
- refQual: str, exceptionSpec: ASTNoexceptSpec, trailingReturn: "ASTType",
+ refQual: Optional[str], exceptionSpec: ASTNoexceptSpec,
+ trailingReturn: "ASTType",
override: bool, final: bool, attrs: List[ASTAttribute],
- initializer: str) -> None:
+ initializer: Optional[str]) -> None:
self.args = args
self.volatile = volatile
self.const = const
@@ -1988,43 +2052,51 @@ class ASTParametersQualifiers(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(')', ')')
def _add_anno(signode: TextElement, text: str) -> None:
- signode += nodes.Text(' ')
- signode += addnodes.desc_annotation(text, text)
-
- def _add_text(signode: TextElement, text: str) -> None:
- signode += nodes.Text(' ' + text)
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_keyword(text, text)
if self.volatile:
_add_anno(signode, 'volatile')
if self.const:
_add_anno(signode, 'const')
if self.refQual:
- _add_text(signode, self.refQual)
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation(self.refQual, self.refQual)
if self.exceptionSpec:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.exceptionSpec.describe_signature(signode, mode, env, symbol)
if self.trailingReturn:
- signode += nodes.Text(' -> ')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_operator('->', '->')
+ signode += addnodes.desc_sig_space()
self.trailingReturn.describe_signature(signode, mode, env, symbol)
if self.final:
_add_anno(signode, 'final')
if self.override:
_add_anno(signode, 'override')
for attr in self.attrs:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
attr.describe_signature(signode)
if self.initializer:
- _add_text(signode, '= ' + str(self.initializer))
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('=', '=')
+ signode += addnodes.desc_sig_space()
+ assert self.initializer in ('0', 'delete', 'default')
+ if self.initializer == '0':
+ signode += addnodes.desc_sig_literal_number('0', '0')
+ else:
+ signode += addnodes.desc_sig_keyword(self.initializer, self.initializer)
class ASTDeclSpecsSimple(ASTBase):
@@ -2083,14 +2155,14 @@ class ASTDeclSpecsSimple(ASTBase):
addSpace = False
for attr in self.attrs:
if addSpace:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
addSpace = True
attr.describe_signature(signode)
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.storage:
@@ -2168,7 +2240,7 @@ class ASTDeclSpecs(ASTBase):
if self.trailingTypeSpec:
if addSpace:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
numChildren = len(signode)
self.trailingTypeSpec.describe_signature(signode, mode, env,
symbol=symbol)
@@ -2176,7 +2248,7 @@ class ASTDeclSpecs(ASTBase):
if len(str(self.rightSpecs)) > 0:
if addSpace:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.rightSpecs.describe_signature(signode)
@@ -2209,10 +2281,10 @@ 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('[', '[')
if self.size:
self.size.describe_signature(signode, 'markType', env, symbol)
- signode.append(nodes.Text("]"))
+ signode += addnodes.desc_sig_punctuation(']', ']')
class ASTDeclarator(ASTBase):
@@ -2375,7 +2447,9 @@ class ASTDeclaratorNameBitField(ASTDeclarator):
verify_description_mode(mode)
if self.declId:
self.declId.describe_signature(signode, mode, env, symbol)
- signode.append(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)
@@ -2461,23 +2535,23 @@ 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.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.volatile:
_add_anno(signode, 'volatile')
if self.const:
if self.volatile:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
_add_anno(signode, 'const')
if self.const or self.volatile 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)
@@ -2538,11 +2612,11 @@ class ASTDeclaratorRef(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.next.require_space_after_declSpecs():
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.next.describe_signature(signode, mode, env, symbol)
@@ -2595,9 +2669,9 @@ class ASTDeclaratorParamPack(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('...', '...')
if self.next.name:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.next.describe_signature(signode, mode, env, symbol)
@@ -2680,18 +2754,19 @@ class ASTDeclaratorMemPtr(ASTDeclarator):
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
self.className.describe_signature(signode, 'markType', env, symbol)
- signode += nodes.Text('::*')
+ signode += addnodes.desc_sig_punctuation('::', '::')
+ signode += addnodes.desc_sig_punctuation('*', '*')
def _add_anno(signode: TextElement, text: str) -> None:
- signode += addnodes.desc_annotation(text, text)
+ signode += addnodes.desc_sig_keyword(text, text)
if self.volatile:
_add_anno(signode, 'volatile')
if self.const:
if self.volatile:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
_add_anno(signode, 'const')
if self.next.require_space_after_declSpecs():
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.next.describe_signature(signode, mode, env, symbol)
@@ -2752,9 +2827,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)
@@ -2775,7 +2850,7 @@ class ASTPackExpansionExpr(ASTExpression):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.expr.describe_signature(signode, mode, env, symbol)
- signode += nodes.Text('...')
+ signode += addnodes.desc_sig_punctuation('...', '...')
class ASTParenExprList(ASTBaseParenExprList):
@@ -2792,15 +2867,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 ASTInitializer(ASTBase):
@@ -2820,7 +2896,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)
@@ -2924,7 +3002,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':
@@ -2966,7 +3044,9 @@ class ASTTemplateParamConstrainedTypeWithInit(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.type.describe_signature(signode, mode, env, symbol)
if self.init:
- signode += nodes.Text(" = ")
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('=', '=')
+ signode += addnodes.desc_sig_space()
self.init.describe_signature(signode, mode, env, symbol)
@@ -3034,7 +3114,9 @@ class ASTTypeUsing(ASTBase):
verify_description_mode(mode)
self.name.describe_signature(signode, mode, env, symbol=symbol)
if self.type:
- signode += nodes.Text(' = ')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('=', '=')
+ signode += addnodes.desc_sig_space()
self.type.describe_signature(signode, 'markType', env, symbol=symbol)
@@ -3079,7 +3161,6 @@ class ASTBaseClass(ASTBase):
def _stringify(self, transform: StringifyTransform) -> str:
res = []
-
if self.visibility is not None:
res.append(self.visibility)
res.append(' ')
@@ -3094,15 +3175,15 @@ class ASTBaseClass(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode)
if self.visibility is not None:
- signode += addnodes.desc_annotation(self.visibility,
- self.visibility)
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_keyword(self.visibility,
+ self.visibility)
+ signode += addnodes.desc_sig_space()
if self.virtual:
- signode += addnodes.desc_annotation('virtual', 'virtual')
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_keyword('virtual', 'virtual')
+ signode += addnodes.desc_sig_space()
self.name.describe_signature(signode, 'markType', env, symbol=symbol)
if self.pack:
- signode += nodes.Text('...')
+ signode += addnodes.desc_sig_punctuation('...', '...')
class ASTClass(ASTBase):
@@ -3134,13 +3215,17 @@ class ASTClass(ASTBase):
verify_description_mode(mode)
self.name.describe_signature(signode, mode, env, symbol=symbol)
if self.final:
- signode += nodes.Text(' ')
- signode += addnodes.desc_annotation('final', 'final')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_keyword('final', 'final')
if len(self.bases) > 0:
- signode += nodes.Text(' : ')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation(':', ':')
+ signode += addnodes.desc_sig_space()
for b in self.bases:
b.describe_signature(signode, mode, env, symbol=symbol)
- signode += nodes.Text(', ')
+ signode += addnodes.desc_sig_punctuation(',', ',')
+ signode += addnodes.desc_sig_space()
+ signode.pop()
signode.pop()
@@ -3191,7 +3276,9 @@ class ASTEnum(ASTBase):
# self.scoped has been done by the CPPEnumObject
self.name.describe_signature(signode, mode, env, symbol=symbol)
if self.underlyingType:
- signode += nodes.Text(' : ')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation(':', ':')
+ signode += addnodes.desc_sig_space()
self.underlyingType.describe_signature(signode, 'noneIsName',
env, symbol=symbol)
@@ -3281,17 +3368,19 @@ class ASTTemplateKeyParamPackIdDefault(ASTTemplateParam):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode += nodes.Text(self.key)
+ signode += addnodes.desc_sig_keyword(self.key, self.key)
if self.parameterPack:
if self.identifier:
- signode += nodes.Text(' ')
- signode += nodes.Text('...')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('...', '...')
if self.identifier:
if not self.parameterPack:
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.identifier.describe_signature(signode, mode, env, '', '', symbol)
if self.default:
- signode += nodes.Text(' = ')
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_punctuation('=', '=')
+ signode += addnodes.desc_sig_space()
self.default.describe_signature(signode, 'markType', env, symbol)
@@ -3364,7 +3453,7 @@ class ASTTemplateParamTemplateType(ASTTemplateParam):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.nestedParams.describe_signature(signode, 'noneIsName', env, symbol)
- signode += nodes.Text(' ')
+ signode += addnodes.desc_sig_space()
self.data.describe_signature(signode, mode, env, symbol)
@@ -3436,14 +3525,16 @@ class ASTTemplateParams(ASTBase):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode += nodes.Text("template<")
+ signode += addnodes.desc_sig_keyword('template', 'template')
+ signode += addnodes.desc_sig_punctuation('<', '<')
first = True
for param in self.params:
if not first:
- signode += nodes.Text(", ")
+ signode += addnodes.desc_sig_punctuation(',', ',')
+ signode += addnodes.desc_sig_space()
first = False
param.describe_signature(signode, mode, env, symbol)
- signode += nodes.Text(">")
+ signode += addnodes.desc_sig_punctuation('>', '>')
def describe_signature_as_introducer(
self, parentNode: desc_signature, mode: str, env: "BuildEnvironment",
@@ -3454,18 +3545,20 @@ class ASTTemplateParams(ASTBase):
signode.sphinx_line_type = 'templateParams'
return signode
lineNode = makeLine(parentNode)
- lineNode += nodes.Text("template<")
+ lineNode += addnodes.desc_sig_keyword('template', 'template')
+ lineNode += addnodes.desc_sig_punctuation('<', '<')
first = True
for param in self.params:
if not first:
- lineNode += nodes.Text(", ")
+ lineNode += addnodes.desc_sig_punctuation(',', ',')
+ lineNode += addnodes.desc_sig_space()
first = False
if lineSpec:
lineNode = makeLine(parentNode)
param.describe_signature(lineNode, mode, env, symbol)
if lineSpec and not first:
lineNode = makeLine(parentNode)
- lineNode += nodes.Text(">")
+ lineNode += addnodes.desc_sig_punctuation('>', '>')
# Template introducers
@@ -3519,7 +3612,7 @@ class ASTTemplateIntroductionParameter(ASTBase):
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
if self.parameterPack:
- signode += nodes.Text('...')
+ signode += addnodes.desc_sig_punctuation('...', '...')
self.identifier.describe_signature(signode, mode, env, '', '', symbol)
@@ -3564,14 +3657,15 @@ class ASTTemplateIntroduction(ASTBase):
parentNode += signode
signode.sphinx_line_type = 'templateIntroduction'
self.concept.describe_signature(signode, 'markType', env, symbol)
- signode += nodes.Text('{')
+ signode += addnodes.desc_sig_punctuation('{', '{')
first = True
for param in self.params:
if not first:
- signode += nodes.Text(', ')
+ signode += addnodes.desc_sig_punctuation(',', ',')
+ signode += addnodes.desc_sig_space()
first = False
param.describe_signature(signode, mode, env, symbol)
- signode += nodes.Text('}')
+ signode += addnodes.desc_sig_punctuation('}', '}')
################################################################################
@@ -3613,7 +3707,8 @@ class ASTRequiresClause(ASTBase):
def describe_signature(self, signode: addnodes.desc_signature_line, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
- signode += nodes.Text('requires ', 'requires ')
+ signode += addnodes.desc_sig_keyword('requires', 'requires')
+ signode += addnodes.desc_sig_space()
self.expr.describe_signature(signode, mode, env, symbol)
@@ -3733,39 +3828,42 @@ class ASTDeclaration(ASTBase):
self.requiresClause.describe_signature(reqNode, 'markType', env, self.symbol)
signode += mainDeclNode
if self.visibility and self.visibility != "public":
- mainDeclNode += addnodes.desc_annotation(self.visibility + " ",
- self.visibility + " ")
+ mainDeclNode += addnodes.desc_sig_keyword(self.visibility, self.visibility)
+ mainDeclNode += addnodes.desc_sig_space()
if self.objectType == 'type':
prefix = self.declaration.get_type_declaration_prefix()
- prefix += ' '
- mainDeclNode += addnodes.desc_annotation(prefix, prefix)
+ mainDeclNode += addnodes.desc_sig_keyword(prefix, prefix)
+ mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'concept':
- mainDeclNode += addnodes.desc_annotation('concept ', 'concept ')
+ mainDeclNode += addnodes.desc_sig_keyword('concept', 'concept')
+ mainDeclNode += addnodes.desc_sig_space()
elif self.objectType == 'member':
pass
elif self.objectType == 'function':
pass
elif self.objectType == 'class':
assert self.directiveType in ('class', 'struct')
- prefix = self.directiveType + ' '
- mainDeclNode += addnodes.desc_annotation(prefix, prefix)
+ mainDeclNode += addnodes.desc_sig_keyword(self.directiveType, self.directiveType)
+ 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':
- if self.directiveType == 'enum':
- prefix = 'enum '
- elif self.directiveType == 'enum-class':
- prefix = 'enum class '
+ mainDeclNode += addnodes.desc_sig_keyword('enum', 'enum')
+ mainDeclNode += addnodes.desc_sig_space()
+ if self.directiveType == 'enum-class':
+ mainDeclNode += addnodes.desc_sig_keyword('class', 'class')
+ mainDeclNode += addnodes.desc_sig_space()
elif self.directiveType == 'enum-struct':
- prefix = 'enum struct '
+ mainDeclNode += addnodes.desc_sig_keyword('struct', 'struct')
+ mainDeclNode += addnodes.desc_sig_space()
else:
- assert False # wrong directiveType used
- mainDeclNode += addnodes.desc_annotation(prefix, prefix)
+ assert self.directiveType == 'enum', self.directiveType
elif self.objectType == 'enumerator':
- mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
+ mainDeclNode += addnodes.desc_sig_keyword('enumerator', 'enumerator')
+ mainDeclNode += addnodes.desc_sig_space()
else:
- print(self.objectType)
- assert False
+ assert False, self.objectType
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
lastDeclNode = mainDeclNode
if self.trailingRequiresClause:
@@ -3776,7 +3874,7 @@ class ASTDeclaration(ASTBase):
self.trailingRequiresClause.describe_signature(
trailingReqNode, 'markType', env, self.symbol)
if self.semicolon:
- lastDeclNode += nodes.Text(';')
+ lastDeclNode += addnodes.desc_sig_punctuation(';', ';')
class ASTNamespace(ASTBase):
@@ -7079,7 +7177,8 @@ class AliasNode(nodes.Element):
if 'cpp:parent_symbol' not in env.temp_data:
root = env.domaindata['cpp']['root_symbol']
env.temp_data['cpp:parent_symbol'] = root
- self.parentKey = env.temp_data['cpp:parent_symbol'].get_lookup_key()
+ env.ref_context['cpp:parent_key'] = root.get_lookup_key()
+ self.parentKey = env.ref_context['cpp:parent_key']
else:
assert parentKey is not None
self.parentKey = parentKey
@@ -7307,11 +7406,9 @@ class CPPExprRole(SphinxRole):
if asCode:
# render the expression as inline code
self.class_type = 'cpp-expr'
- self.node_type: Type[TextElement] = nodes.literal
else:
# render the expression as inline text
self.class_type = 'cpp-texpr'
- self.node_type = nodes.inline
def run(self) -> Tuple[List[Node], List[system_message]]:
text = self.text.replace('\n', ' ')
@@ -7319,20 +7416,19 @@ class CPPExprRole(SphinxRole):
location=self.get_source_info(),
config=self.config)
# attempt to mimic XRefRole classes, except that...
- classes = ['xref', 'cpp', 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('cpp', text, text, classes=[self.class_type])], []
parentSymbol = self.env.temp_data.get('cpp:parent_symbol', None)
if parentSymbol is None:
parentSymbol = self.env.domaindata['cpp']['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('cpp', classes=[self.class_type])
ast.describe_signature(signode, 'markType', self.env, parentSymbol)
return [signode], []
@@ -7604,9 +7700,10 @@ class CPPDomain(Domain):
title += '()' * addParen
# and reconstruct the title again
contnode += nodes.Text(title)
- return make_refnode(builder, fromdocname, docname,
- declaration.get_newest_id(), contnode, displayName
- ), declaration.objectType
+ res = make_refnode(builder, fromdocname, docname,
+ declaration.get_newest_id(), contnode, displayName
+ ), declaration.objectType
+ return res
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, contnode: Element
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index d0c5f7118..dbb315e6e 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -304,7 +304,7 @@ class PyXrefMixin:
def make_xrefs(self, rolename: str, domain: str, target: str,
innernode: Type[TextlikeNode] = nodes.emphasis,
contnode: Node = None, env: BuildEnvironment = None) -> List[Node]:
- delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+)'
+ delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+|\.\.\.)'
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)
diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py
index ba8f62a18..8e513a9d0 100644
--- a/sphinx/ext/napoleon/__init__.py
+++ b/sphinx/ext/napoleon/__init__.py
@@ -240,7 +240,7 @@ class Config:
:returns: *bool* -- True if successful, False otherwise
napoleon_preprocess_types : :obj:`bool` (Defaults to False)
- Enable the type preprocessor for numpy style docstrings.
+ Enable the type preprocessor.
napoleon_type_aliases : :obj:`dict` (Defaults to None)
Add a mapping of strings to string, translating types in numpy
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index 6264f20d2..25ab688e4 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -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;
diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py
index 653097cd8..e2899d994 100644
--- a/sphinx/transforms/post_transforms/__init__.py
+++ b/sphinx/transforms/post_transforms/__init__.py
@@ -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',
diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py
index f9b78837f..c9ed572b8 100644
--- a/sphinx/transforms/post_transforms/images.py
+++ b/sphinx/transforms/post_transforms/images.py
@@ -197,7 +197,7 @@ class ImageConverter(BaseImageConverter):
def match(self, node: nodes.image) -> bool:
if not self.app.builder.supported_image_types:
return False
- elif set(node['candidates']) & set(self.app.builder.supported_image_types):
+ elif set(self.guess_mimetypes(node)) & set(self.app.builder.supported_image_types):
# builder supports the image; no need to convert
return False
elif self.available is None:
diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index fcecb8bb1..957f8a332 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -138,16 +138,16 @@ def _restify_py37(cls: Optional[Type]) -> str:
if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType:
if len(cls.__args__) > 2:
args = ', '.join(restify(a) for a in cls.__args__[:-1])
- return ':obj:`Optional`\\ [:obj:`Union`\\ [%s]]' % args
+ return ':obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args
else:
- return ':obj:`Optional`\\ [%s]' % restify(cls.__args__[0])
+ return ':obj:`~typing.Optional`\\ [%s]' % restify(cls.__args__[0])
else:
args = ', '.join(restify(a) for a in cls.__args__)
- return ':obj:`Union`\\ [%s]' % args
+ return ':obj:`~typing.Union`\\ [%s]' % args
elif inspect.isgenericalias(cls):
if getattr(cls, '_name', None):
if cls.__module__ == 'typing':
- text = ':class:`%s`' % cls._name
+ text = ':class:`~%s.%s`' % (cls.__module__, cls._name)
else:
text = ':class:`%s.%s`' % (cls.__module__, cls._name)
else:
@@ -167,20 +167,23 @@ def _restify_py37(cls: Optional[Type]) -> str:
return text
elif hasattr(cls, '__qualname__'):
if cls.__module__ == 'typing':
- return ':class:`%s`' % cls.__qualname__
+ return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__)
else:
return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__)
elif hasattr(cls, '_name'):
# SpecialForm
if cls.__module__ == 'typing':
- return ':obj:`%s`' % cls._name
+ return ':obj:`~%s.%s`' % (cls.__module__, cls._name)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls._name)
elif isinstance(cls, ForwardRef):
return ':class:`%s`' % cls.__forward_arg__
else:
# not a class (ex. TypeVar)
- return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
+ if cls.__module__ == 'typing':
+ return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__)
+ else:
+ return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
def _restify_py36(cls: Optional[Type]) -> str:
@@ -203,13 +206,23 @@ def _restify_py36(cls: Optional[Type]) -> str:
if (isinstance(cls, typing.TupleMeta) and # type: ignore
not hasattr(cls, '__tuple_params__')):
+ if module == 'typing':
+ reftext = ':class:`~typing.%s`' % qualname
+ else:
+ reftext = ':class:`%s`' % qualname
+
params = cls.__args__
if params:
param_str = ', '.join(restify(p) for p in params)
- return ':class:`%s`\\ [%s]' % (qualname, param_str)
+ return reftext + '\\ [%s]' % param_str
else:
- return ':class:`%s`' % qualname
+ return reftext
elif isinstance(cls, typing.GenericMeta):
+ if module == 'typing':
+ reftext = ':class:`~typing.%s`' % qualname
+ else:
+ reftext = ':class:`%s`' % qualname
+
if cls.__args__ is None or len(cls.__args__) <= 2: # type: ignore # NOQA
params = cls.__args__ # type: ignore
elif cls.__origin__ == Generator: # type: ignore
@@ -217,13 +230,13 @@ def _restify_py36(cls: Optional[Type]) -> str:
else: # typing.Callable
args = ', '.join(restify(arg) for arg in cls.__args__[:-1]) # type: ignore
result = restify(cls.__args__[-1]) # type: ignore
- return ':class:`%s`\\ [[%s], %s]' % (qualname, args, result)
+ return reftext + '\\ [[%s], %s]' % (args, result)
if params:
param_str = ', '.join(restify(p) for p in params)
- return ':class:`%s`\\ [%s]' % (qualname, param_str)
+ return reftext + '\\ [%s]' % (param_str)
else:
- return ':class:`%s`' % qualname
+ return reftext
elif (hasattr(cls, '__origin__') and
cls.__origin__ is typing.Union):
params = cls.__args__
@@ -231,32 +244,36 @@ def _restify_py36(cls: Optional[Type]) -> str:
if len(params) > 1 and params[-1] is NoneType:
if len(params) > 2:
param_str = ", ".join(restify(p) for p in params[:-1])
- return ':obj:`Optional`\\ [:obj:`Union`\\ [%s]]' % param_str
+ return (':obj:`~typing.Optional`\\ '
+ '[:obj:`~typing.Union`\\ [%s]]' % param_str)
else:
- return ':obj:`Optional`\\ [%s]' % restify(params[0])
+ return ':obj:`~typing.Optional`\\ [%s]' % restify(params[0])
else:
param_str = ', '.join(restify(p) for p in params)
- return ':obj:`Union`\\ [%s]' % param_str
+ return ':obj:`~typing.Union`\\ [%s]' % param_str
else:
return ':obj:`Union`'
elif hasattr(cls, '__qualname__'):
if cls.__module__ == 'typing':
- return ':class:`%s`' % cls.__qualname__
+ return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__)
else:
return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__)
elif hasattr(cls, '_name'):
# SpecialForm
if cls.__module__ == 'typing':
- return ':obj:`%s`' % cls._name
+ return ':obj:`~%s.%s`' % (cls.__module__, cls._name)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls._name)
elif hasattr(cls, '__name__'):
# not a class (ex. TypeVar)
- return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
+ if cls.__module__ == 'typing':
+ return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__)
+ else:
+ return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
else:
# others (ex. Any)
if cls.__module__ == 'typing':
- return ':obj:`%s`' % qualname
+ return ':obj:`~%s.%s`' % (cls.__module__, qualname)
else:
return ':obj:`%s.%s`' % (cls.__module__, qualname)
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index a92927cab..d633f07e8 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -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('\n\n')
@@ -133,8 +140,29 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
self.add_permalink_ref(node.parent, _('Permalink to this definition'))
self.body.append('
')
+ 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('')
+
+ 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('')
+
+ # 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('')
+
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('')
@@ -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('')
-
def visit_desc_parameterlist(self, node: Element) -> None:
self.body.append('(')
self.first_param = 1
@@ -205,11 +227,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def depart_desc_annotation(self, node: Element) -> None:
self.body.append('')
- 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('')
+ ##############################################
def visit_versionmodified(self, node: Element) -> None:
self.body.append(self.starttag(node, 'div', CLASS=node['type']))
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index fa7360c4e..469642591 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -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('\n\n')
@@ -104,11 +111,32 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
self.add_permalink_ref(node.parent, _('Permalink to this definition'))
self.body.append('
')
+ 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('')
+
+ 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('')
+
+ # 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('')
+
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('')
+ self.body.append('')
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('')
-
def visit_desc_parameterlist(self, node: Element) -> None:
self.body.append('(')
self.first_param = 1
@@ -176,11 +198,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_desc_annotation(self, node: Element) -> None:
self.body.append('')
- 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('')
+ ##############################################
def visit_versionmodified(self, node: Element) -> None:
self.body.append(self.starttag(node, 'div', CLASS=node['type']))
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index edef5417f..546db9e31 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -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)
diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py
index c11c49892..3f0eea5eb 100644
--- a/sphinx/writers/manpage.py
+++ b/sphinx/writers/manpage.py
@@ -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)
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index cad6f3685..6df558323 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -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
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index 5bd96de76..d8dab9181 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -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()
diff --git a/tests/roots/test-ext-imgconverter/img.pdf b/tests/roots/test-ext-imgconverter/img.pdf
new file mode 100644
index 000000000..cacbd855d
Binary files /dev/null and b/tests/roots/test-ext-imgconverter/img.pdf differ
diff --git a/tests/roots/test-ext-imgconverter/index.rst b/tests/roots/test-ext-imgconverter/index.rst
index 786c92e8d..f8ef1d6e2 100644
--- a/tests/roots/test-ext-imgconverter/index.rst
+++ b/tests/roots/test-ext-imgconverter/index.rst
@@ -2,3 +2,4 @@ test-ext-imgconverter
=====================
.. image:: svgimg.svg
+.. image:: img.pdf
diff --git a/tests/roots/test-root/objects.txt b/tests/roots/test-root/objects.txt
index adb090a44..d5ec2a486 100644
--- a/tests/roots/test-root/objects.txt
+++ b/tests/roots/test-root/objects.txt
@@ -213,3 +213,9 @@ CPP domain
.. cpp:function:: T& operator[]( unsigned j )
const T& operator[]( unsigned j ) const
+
+.. cpp:function:: template \
+ requires A \
+ void f()
+
+- :cpp:expr:`a + b`
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index b01d6f4eb..c74552d9e 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -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']", ''),
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index edd5ea5bc..52aaad850 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -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", {2: "IE1AI1TE"}, output="template<> {key}A")
@@ -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
diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py
index f5df9084b..214cb58a0 100644
--- a/tests/test_domain_py.py
+++ b/tests/test_domain_py.py
@@ -876,7 +876,9 @@ def test_info_field_list(app):
"\n"
" :param str name: blah blah\n"
" :param age: blah blah\n"
- " :type age: int\n")
+ " :type age: int\n"
+ " :param items: blah blah\n"
+ " :type items: Tuple[str, ...]\n")
doctree = restructuredtext.parse(app, text)
print(doctree)
@@ -890,6 +892,7 @@ def test_info_field_list(app):
assert_node(doctree[3][1][0][0],
([nodes.field_name, "Parameters"],
[nodes.field_body, nodes.bullet_list, ([nodes.list_item, nodes.paragraph],
+ [nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph])]))
# :param str name:
@@ -916,6 +919,26 @@ def test_info_field_list(app):
refdomain="py", reftype="class", reftarget="int",
**{"py:module": "example", "py:class": "Class"})
+ # :param items: + :type items:
+ assert_node(doctree[3][1][0][0][1][0][2][0],
+ ([addnodes.literal_strong, "items"],
+ " (",
+ [pending_xref, addnodes.literal_emphasis, "Tuple"],
+ [addnodes.literal_emphasis, "["],
+ [pending_xref, addnodes.literal_emphasis, "str"],
+ [addnodes.literal_emphasis, ", "],
+ [addnodes.literal_emphasis, "..."],
+ [addnodes.literal_emphasis, "]"],
+ ")",
+ " -- ",
+ "blah blah"))
+ assert_node(doctree[3][1][0][0][1][0][2][0][2], pending_xref,
+ refdomain="py", reftype="class", reftarget="Tuple",
+ **{"py:module": "example", "py:class": "Class"})
+ assert_node(doctree[3][1][0][0][1][0][2][0][4], pending_xref,
+ refdomain="py", reftype="class", reftarget="str",
+ **{"py:module": "example", "py:class": "Class"})
+
def test_info_field_list_var(app):
text = (".. py:class:: Class\n"
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index 8ace97813..ccdee6bb2 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -1893,12 +1893,12 @@ def test_autodoc_GenericAlias(app):
' .. py:attribute:: Class.T',
' :module: target.genericalias',
'',
- ' alias of :class:`List`\\ [:class:`int`]',
+ ' alias of :class:`~typing.List`\\ [:class:`int`]',
'',
'.. py:attribute:: T',
' :module: target.genericalias',
'',
- ' alias of :class:`List`\\ [:class:`int`]',
+ ' alias of :class:`~typing.List`\\ [:class:`int`]',
]
else:
assert list(actual) == [
diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py
index 940263387..d879f8e14 100644
--- a/tests/test_ext_autodoc_autoclass.py
+++ b/tests/test_ext_autodoc_autoclass.py
@@ -256,7 +256,8 @@ def test_show_inheritance_for_subclass_of_generic_type(app):
'.. py:class:: Quux(iterable=(), /)',
' :module: target.classes',
'',
- ' Bases: :class:`List`\\ [:obj:`Union`\\ [:class:`int`, :class:`float`]]',
+ ' Bases: :class:`~typing.List`\\ '
+ '[:obj:`~typing.Union`\\ [:class:`int`, :class:`float`]]',
'',
' A subclass of List[Union[int, float]]',
'',
diff --git a/tests/test_ext_imgconverter.py b/tests/test_ext_imgconverter.py
index 5f6f236cf..b4fd46d25 100644
--- a/tests/test_ext_imgconverter.py
+++ b/tests/test_ext_imgconverter.py
@@ -19,6 +19,11 @@ def test_ext_imgconverter(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').read_text()
+
+ # supported image (not converted)
+ assert '\\sphinxincludegraphics{{img}.pdf}' in content
+
+ # non supported image (converted)
assert '\\sphinxincludegraphics{{svgimg}.png}' in content
assert not (app.outdir / 'svgimg.svg').exists()
assert (app.outdir / 'svgimg.png').exists()
diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py
index 523ed2acc..62456a3f4 100644
--- a/tests/test_ext_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -258,10 +258,10 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning):
'Bar' in html)
assert ('foons' in html)
+ ' title="(in foo v2.0)">foons' in html)
assert ('bartype' in html)
+ ' title="(in foo v2.0)">bartype' in html)
def test_missing_reference_jsdomain(tempdir, app, status, warning):
diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py
index 5a5808ac5..d85eb0849 100644
--- a/tests/test_util_typing.py
+++ b/tests/test_util_typing.py
@@ -47,42 +47,56 @@ def test_restify():
assert restify(Integral) == ":class:`numbers.Integral`"
assert restify(Struct) == ":class:`struct.Struct`"
assert restify(TracebackType) == ":class:`types.TracebackType`"
- assert restify(Any) == ":obj:`Any`"
+ assert restify(Any) == ":obj:`~typing.Any`"
def test_restify_type_hints_containers():
- assert restify(List) == ":class:`List`"
- assert restify(Dict) == ":class:`Dict`"
- assert restify(List[int]) == ":class:`List`\\ [:class:`int`]"
- assert restify(List[str]) == ":class:`List`\\ [:class:`str`]"
- assert restify(Dict[str, float]) == ":class:`Dict`\\ [:class:`str`, :class:`float`]"
- assert restify(Tuple[str, str, str]) == ":class:`Tuple`\\ [:class:`str`, :class:`str`, :class:`str`]"
- assert restify(Tuple[str, ...]) == ":class:`Tuple`\\ [:class:`str`, ...]"
- assert restify(List[Dict[str, Tuple]]) == ":class:`List`\\ [:class:`Dict`\\ [:class:`str`, :class:`Tuple`]]"
- assert restify(MyList[Tuple[int, int]]) == ":class:`tests.test_util_typing.MyList`\\ [:class:`Tuple`\\ [:class:`int`, :class:`int`]]"
- assert restify(Generator[None, None, None]) == ":class:`Generator`\\ [:obj:`None`, :obj:`None`, :obj:`None`]"
+ assert restify(List) == ":class:`~typing.List`"
+ assert restify(Dict) == ":class:`~typing.Dict`"
+ assert restify(List[int]) == ":class:`~typing.List`\\ [:class:`int`]"
+ assert restify(List[str]) == ":class:`~typing.List`\\ [:class:`str`]"
+ assert restify(Dict[str, float]) == (":class:`~typing.Dict`\\ "
+ "[:class:`str`, :class:`float`]")
+ assert restify(Tuple[str, str, str]) == (":class:`~typing.Tuple`\\ "
+ "[:class:`str`, :class:`str`, :class:`str`]")
+ assert restify(Tuple[str, ...]) == ":class:`~typing.Tuple`\\ [:class:`str`, ...]"
+ assert restify(List[Dict[str, Tuple]]) == (":class:`~typing.List`\\ "
+ "[:class:`~typing.Dict`\\ "
+ "[:class:`str`, :class:`~typing.Tuple`]]")
+ assert restify(MyList[Tuple[int, int]]) == (":class:`tests.test_util_typing.MyList`\\ "
+ "[:class:`~typing.Tuple`\\ "
+ "[:class:`int`, :class:`int`]]")
+ assert restify(Generator[None, None, None]) == (":class:`~typing.Generator`\\ "
+ "[:obj:`None`, :obj:`None`, :obj:`None`]")
def test_restify_type_hints_Callable():
- assert restify(Callable) == ":class:`Callable`"
+ assert restify(Callable) == ":class:`~typing.Callable`"
if sys.version_info >= (3, 7):
- assert restify(Callable[[str], int]) == ":class:`Callable`\\ [[:class:`str`], :class:`int`]"
- assert restify(Callable[..., int]) == ":class:`Callable`\\ [[...], :class:`int`]"
+ assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ "
+ "[[:class:`str`], :class:`int`]")
+ assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ "
+ "[[...], :class:`int`]")
else:
- assert restify(Callable[[str], int]) == ":class:`Callable`\\ [:class:`str`, :class:`int`]"
- assert restify(Callable[..., int]) == ":class:`Callable`\\ [..., :class:`int`]"
+ assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ "
+ "[:class:`str`, :class:`int`]")
+ assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ "
+ "[..., :class:`int`]")
def test_restify_type_hints_Union():
- assert restify(Optional[int]) == ":obj:`Optional`\\ [:class:`int`]"
- assert restify(Union[str, None]) == ":obj:`Optional`\\ [:class:`str`]"
- assert restify(Union[int, str]) == ":obj:`Union`\\ [:class:`int`, :class:`str`]"
+ assert restify(Optional[int]) == ":obj:`~typing.Optional`\\ [:class:`int`]"
+ assert restify(Union[str, None]) == ":obj:`~typing.Optional`\\ [:class:`str`]"
+ assert restify(Union[int, str]) == ":obj:`~typing.Union`\\ [:class:`int`, :class:`str`]"
if sys.version_info >= (3, 7):
- assert restify(Union[int, Integral]) == ":obj:`Union`\\ [:class:`int`, :class:`numbers.Integral`]"
+ assert restify(Union[int, Integral]) == (":obj:`~typing.Union`\\ "
+ "[:class:`int`, :class:`numbers.Integral`]")
assert (restify(Union[MyClass1, MyClass2]) ==
- ":obj:`Union`\\ [:class:`tests.test_util_typing.MyClass1`, :class:`tests.test_util_typing.`]")
+ (":obj:`~typing.Union`\\ "
+ "[:class:`tests.test_util_typing.MyClass1`, "
+ ":class:`tests.test_util_typing.`]"))
else:
assert restify(Union[int, Integral]) == ":class:`numbers.Integral`"
assert restify(Union[MyClass1, MyClass2]) == ":class:`tests.test_util_typing.MyClass1`"
@@ -97,7 +111,7 @@ def test_restify_type_hints_typevars():
assert restify(T) == ":obj:`tests.test_util_typing.T`"
assert restify(T_co) == ":obj:`tests.test_util_typing.T_co`"
assert restify(T_contra) == ":obj:`tests.test_util_typing.T_contra`"
- assert restify(List[T]) == ":class:`List`\\ [:obj:`tests.test_util_typing.T`]"
+ assert restify(List[T]) == ":class:`~typing.List`\\ [:obj:`tests.test_util_typing.T`]"
assert restify(MyInt) == ":class:`MyInt`"
@@ -110,7 +124,7 @@ def test_restify_type_hints_alias():
MyStr = str
MyTuple = Tuple[str, str]
assert restify(MyStr) == ":class:`str`"
- assert restify(MyTuple) == ":class:`Tuple`\\ [:class:`str`, :class:`str`]" # type: ignore
+ assert restify(MyTuple) == ":class:`~typing.Tuple`\\ [:class:`str`, :class:`str`]"
@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')