mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add 'cpp:struct' directive and 'cpp:struct' role.
They are cosmetic variants of the class directive/role.
This commit is contained in:
committed by
Jakob Lykke Andersen
parent
4e6dacd81b
commit
9e6fe21c6a
3
CHANGES
3
CHANGES
@@ -58,6 +58,8 @@ Incompatible changes
|
||||
to insert custom user definitions. See :ref:`latex-macros`.
|
||||
* quickstart: Simplify generated ``conf.py``
|
||||
* websupport: unbundled from sphinx core. Please use sphinxcontrib-websupport
|
||||
* C++, the visibility of base classes is now always rendered as present in the
|
||||
input. That is, ``private`` is now shown, where it was ellided before.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
@@ -160,6 +162,7 @@ Features added
|
||||
* #5841: apidoc: Add --extensions option to sphinx-apidoc
|
||||
* #4981: C++, added an alias directive for inserting lists of declarations,
|
||||
that references existing declarations (e.g., for making a synopsis).
|
||||
* C++: add ``cpp:struct`` to complement ``cpp:class``.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
@@ -548,11 +548,16 @@ The following directives are available. All declarations can start with a
|
||||
visibility statement (``public``, ``private`` or ``protected``).
|
||||
|
||||
.. rst:directive:: .. cpp:class:: class specifier
|
||||
.. cpp:struct:: class specifier
|
||||
|
||||
Describe a class/struct, possibly with specification of inheritance, e.g.,::
|
||||
|
||||
.. cpp:class:: MyClass : public MyBase, MyOtherBase
|
||||
|
||||
The difference between :rst:dir:`cpp:class` and :rst:dir:`cpp:struct` is
|
||||
only cosmetic: the prefix rendered in the output, and the specifier shown
|
||||
in the index.
|
||||
|
||||
The class can be directly declared inside a nested scope, e.g.,::
|
||||
|
||||
.. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase
|
||||
@@ -574,6 +579,9 @@ visibility statement (``public``, ``private`` or ``protected``).
|
||||
.. cpp:class:: template<typename T> \
|
||||
std::array<T, 42>
|
||||
|
||||
.. versionadded:: 2.0
|
||||
The :rst:dir:`cpp:struct` directive.
|
||||
|
||||
.. rst:directive:: .. cpp:function:: (member) function prototype
|
||||
|
||||
Describe a function or member function, e.g.,::
|
||||
@@ -1037,6 +1045,7 @@ These roles link to the given declaration types:
|
||||
|
||||
.. rst:role:: cpp:any
|
||||
cpp:class
|
||||
cpp:struct
|
||||
cpp:func
|
||||
cpp:member
|
||||
cpp:var
|
||||
@@ -1048,6 +1057,9 @@ These roles link to the given declaration types:
|
||||
Reference a C++ declaration by name (see below for details). The name must
|
||||
be properly qualified relative to the position of the link.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class` role.
|
||||
|
||||
.. admonition:: Note on References with Templates Parameters/Arguments
|
||||
|
||||
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be
|
||||
|
||||
@@ -3471,7 +3471,8 @@ class ASTBaseClass(ASTBase):
|
||||
def _stringify(self, transform):
|
||||
# type: (Callable[[Any], str]) -> str
|
||||
res = []
|
||||
if self.visibility != 'private':
|
||||
|
||||
if self.visibility is not None:
|
||||
res.append(self.visibility)
|
||||
res.append(' ')
|
||||
if self.virtual:
|
||||
@@ -3484,7 +3485,7 @@ class ASTBaseClass(ASTBase):
|
||||
def describe_signature(self, signode, mode, env, symbol):
|
||||
# type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
|
||||
_verify_description_mode(mode)
|
||||
if self.visibility != 'private':
|
||||
if self.visibility is not None:
|
||||
signode += addnodes.desc_annotation(self.visibility,
|
||||
self.visibility)
|
||||
signode += nodes.Text(' ')
|
||||
@@ -3624,9 +3625,10 @@ class ASTEnumerator(ASTBase):
|
||||
|
||||
|
||||
class ASTDeclaration(ASTBase):
|
||||
def __init__(self, objectType, visibility, templatePrefix, declaration):
|
||||
# type: (str, str, ASTTemplateDeclarationPrefix, Any) -> None
|
||||
def __init__(self, objectType, directiveType, visibility, templatePrefix, declaration):
|
||||
# type: (str, str, str, ASTTemplateDeclarationPrefix, Any) -> None
|
||||
self.objectType = objectType
|
||||
self.directiveType = directiveType
|
||||
self.visibility = visibility
|
||||
self.templatePrefix = templatePrefix
|
||||
self.declaration = declaration
|
||||
@@ -3634,8 +3636,6 @@ class ASTDeclaration(ASTBase):
|
||||
self.symbol = None # type: Symbol
|
||||
# set by CPPObject._add_enumerator_to_parent
|
||||
self.enumeratorScopedSymbol = None # type: Symbol
|
||||
# set by CPPEnumObject.parse_definition
|
||||
self.scoped = None # type: str
|
||||
|
||||
def clone(self):
|
||||
# type: () -> ASTDeclaration
|
||||
@@ -3643,8 +3643,8 @@ class ASTDeclaration(ASTBase):
|
||||
templatePrefixClone = self.templatePrefix.clone()
|
||||
else:
|
||||
templatePrefixClone = None
|
||||
return ASTDeclaration(self.objectType, self.visibility,
|
||||
templatePrefixClone,
|
||||
return ASTDeclaration(self.objectType, self.directiveType,
|
||||
self.visibility, templatePrefixClone,
|
||||
self.declaration.clone())
|
||||
|
||||
@property
|
||||
@@ -3725,14 +3725,20 @@ class ASTDeclaration(ASTBase):
|
||||
elif self.objectType == 'function':
|
||||
pass
|
||||
elif self.objectType == 'class':
|
||||
mainDeclNode += addnodes.desc_annotation('class ', 'class ')
|
||||
assert self.directiveType in ('class', 'struct')
|
||||
prefix = self.directiveType + ' '
|
||||
mainDeclNode += addnodes.desc_annotation(prefix, prefix)
|
||||
elif self.objectType == 'union':
|
||||
mainDeclNode += addnodes.desc_annotation('union ', 'union ')
|
||||
elif self.objectType == 'enum':
|
||||
prefix = 'enum '
|
||||
if self.scoped:
|
||||
prefix += self.scoped
|
||||
prefix += ' '
|
||||
if self.directiveType == 'enum':
|
||||
prefix = 'enum '
|
||||
elif self.directiveType == 'enum-class':
|
||||
prefix = 'enum class '
|
||||
elif self.directiveType == 'enum-struct':
|
||||
prefix = 'enum struct '
|
||||
else:
|
||||
assert False # wrong directiveType used
|
||||
mainDeclNode += addnodes.desc_annotation(prefix, prefix)
|
||||
elif self.objectType == 'enumerator':
|
||||
mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
|
||||
@@ -3844,7 +3850,7 @@ class Symbol:
|
||||
continue
|
||||
# only add a declaration if we our self are from a declaration
|
||||
if self.declaration:
|
||||
decl = ASTDeclaration('templateParam', None, None, p)
|
||||
decl = ASTDeclaration('templateParam', None, None, None, p)
|
||||
else:
|
||||
decl = None
|
||||
nne = ASTNestedNameElement(p.get_identifier(), None)
|
||||
@@ -3859,7 +3865,7 @@ class Symbol:
|
||||
if nn is None:
|
||||
continue
|
||||
# (comparing to the template params: we have checked that we are a declaration)
|
||||
decl = ASTDeclaration('functionParam', None, None, p)
|
||||
decl = ASTDeclaration('functionParam', None, None, None, p)
|
||||
assert not nn.rooted
|
||||
assert len(nn.names) == 1
|
||||
self._add_symbols(nn, [], decl, self.docname)
|
||||
@@ -5997,7 +6003,7 @@ class DefinitionParser:
|
||||
if self.skip_string(':'):
|
||||
while 1:
|
||||
self.skip_ws()
|
||||
visibility = 'private'
|
||||
visibility = None
|
||||
virtual = False
|
||||
pack = False
|
||||
if self.skip_word_and_ws('virtual'):
|
||||
@@ -6231,11 +6237,15 @@ class DefinitionParser:
|
||||
templatePrefix = ASTTemplateDeclarationPrefix(newTemplates)
|
||||
return templatePrefix
|
||||
|
||||
def parse_declaration(self, objectType):
|
||||
# type: (str) -> ASTDeclaration
|
||||
if objectType not in ('type', 'concept', 'member',
|
||||
'function', 'class', 'union', 'enum', 'enumerator'):
|
||||
def parse_declaration(self, objectType, directiveType):
|
||||
# type: (str, str) -> ASTDeclaration
|
||||
if objectType not in ('class', 'union', 'function', 'member', 'type',
|
||||
'concept', 'enum', 'enumerator'):
|
||||
raise Exception('Internal error, unknown objectType "%s".' % objectType)
|
||||
if directiveType not in ('class', 'struct', 'union', 'function', 'member', 'var',
|
||||
'type', 'concept',
|
||||
'enum', 'enum-struct', 'enum-class', 'enumerator'):
|
||||
raise Exception('Internal error, unknown directiveType "%s".' % directiveType)
|
||||
visibility = None
|
||||
templatePrefix = None
|
||||
declaration = None # type: Any
|
||||
@@ -6285,7 +6295,7 @@ class DefinitionParser:
|
||||
templatePrefix,
|
||||
fullSpecShorthand=False,
|
||||
isMember=objectType == 'member')
|
||||
return ASTDeclaration(objectType, visibility,
|
||||
return ASTDeclaration(objectType, directiveType, visibility,
|
||||
templatePrefix, declaration)
|
||||
|
||||
def parse_namespace_object(self):
|
||||
@@ -6315,7 +6325,7 @@ class DefinitionParser:
|
||||
except DefinitionError as e1:
|
||||
try:
|
||||
self.pos = pos
|
||||
res2 = self.parse_declaration('function')
|
||||
res2 = self.parse_declaration('function', 'function')
|
||||
# if there are '()' left, just skip them
|
||||
self.skip_ws()
|
||||
self.skip_string('()')
|
||||
@@ -6405,7 +6415,7 @@ class CPPObject(ObjectDescription):
|
||||
# TODO: maybe issue a warning, enumerators in non-enums is weird,
|
||||
# but it is somewhat equivalent to unscoped enums, without the enum
|
||||
return
|
||||
if parentDecl.scoped:
|
||||
if parentDecl.directiveType != 'enum':
|
||||
return
|
||||
|
||||
targetSymbol = parentSymbol.parent
|
||||
@@ -6496,7 +6506,7 @@ class CPPObject(ObjectDescription):
|
||||
|
||||
def parse_definition(self, parser):
|
||||
# type: (DefinitionParser) -> ASTDeclaration
|
||||
return parser.parse_declaration(self.object_type)
|
||||
return parser.parse_declaration(self.object_type, self.objtype)
|
||||
|
||||
def describe_signature(self, signode, ast, options):
|
||||
# type: (addnodes.desc_signature, Any, Dict) -> None
|
||||
@@ -6615,20 +6625,6 @@ class CPPUnionObject(CPPObject):
|
||||
class CPPEnumObject(CPPObject):
|
||||
object_type = 'enum'
|
||||
|
||||
def parse_definition(self, parser):
|
||||
# type: (DefinitionParser) -> ASTDeclaration
|
||||
ast = super().parse_definition(parser)
|
||||
# self.objtype is set by ObjectDescription in run()
|
||||
if self.objtype == "enum":
|
||||
ast.scoped = None
|
||||
elif self.objtype == "enum-struct":
|
||||
ast.scoped = "struct"
|
||||
elif self.objtype == "enum-class":
|
||||
ast.scoped = "class"
|
||||
else:
|
||||
assert False
|
||||
return ast
|
||||
|
||||
|
||||
class CPPEnumeratorObject(CPPObject):
|
||||
object_type = 'enumerator'
|
||||
@@ -6968,6 +6964,7 @@ class CPPDomain(Domain):
|
||||
directives = {
|
||||
# declarations
|
||||
'class': CPPClassObject,
|
||||
'struct': CPPClassObject,
|
||||
'union': CPPUnionObject,
|
||||
'function': CPPFunctionObject,
|
||||
'member': CPPMemberObject,
|
||||
@@ -6988,6 +6985,7 @@ class CPPDomain(Domain):
|
||||
roles = {
|
||||
'any': CPPXRefRole(),
|
||||
'class': CPPXRefRole(),
|
||||
'struct': CPPXRefRole(),
|
||||
'union': CPPXRefRole(),
|
||||
'func': CPPXRefRole(fix_parens=True),
|
||||
'member': CPPXRefRole(),
|
||||
|
||||
@@ -25,7 +25,7 @@ def parse(name, string):
|
||||
cpp_paren_attributes = ["paren_attr"]
|
||||
parser = DefinitionParser(string, None, Config())
|
||||
parser.allowFallbackExpressionParsing = False
|
||||
ast = parser.parse_declaration(name)
|
||||
ast = parser.parse_declaration(name, name)
|
||||
parser.assert_end()
|
||||
# The scopedness would usually have been set by CPPEnumObject
|
||||
if name == "enum":
|
||||
@@ -526,11 +526,12 @@ def test_class_definitions():
|
||||
check('class', 'A', {1: "A", 2: "1A"})
|
||||
check('class', 'A::B::C', {1: "A::B::C", 2: "N1A1B1CE"})
|
||||
check('class', 'A : B', {1: "A", 2: "1A"})
|
||||
check('class', 'A : private B', {1: "A", 2: "1A"}, output='A : B')
|
||||
check('class', 'A : private B', {1: "A", 2: "1A"})
|
||||
check('class', 'A : public B', {1: "A", 2: "1A"})
|
||||
check('class', 'A : B, C', {1: "A", 2: "1A"})
|
||||
check('class', 'A : B, protected C, D', {1: "A", 2: "1A"})
|
||||
check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : virtual B')
|
||||
check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : private virtual B')
|
||||
check('class', 'A : private virtual B', {1: 'A', 2: '1A'})
|
||||
check('class', 'A : B, virtual C', {1: 'A', 2: '1A'})
|
||||
check('class', 'A : public virtual B', {1: 'A', 2: '1A'})
|
||||
check('class', 'A : B, C...', {1: 'A', 2: '1A'})
|
||||
|
||||
Reference in New Issue
Block a user