mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, semicolon, move it entirely to ASTDeclaration
This commit is contained in:
@@ -109,6 +109,7 @@ T = TypeVar('T')
|
|||||||
simple-declaration ->
|
simple-declaration ->
|
||||||
attribute-specifier-seq[opt] decl-specifier-seq[opt]
|
attribute-specifier-seq[opt] decl-specifier-seq[opt]
|
||||||
init-declarator-list[opt] ;
|
init-declarator-list[opt] ;
|
||||||
|
# Make the semicolon optional.
|
||||||
# For now: drop the attributes (TODO).
|
# For now: drop the attributes (TODO).
|
||||||
# Use at most 1 init-declarator.
|
# Use at most 1 init-declarator.
|
||||||
-> decl-specifier-seq init-declarator
|
-> decl-specifier-seq init-declarator
|
||||||
@@ -2690,13 +2691,11 @@ class ASTInitializer(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTType(ASTBase):
|
class ASTType(ASTBase):
|
||||||
def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator,
|
def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator) -> None:
|
||||||
semicolon: bool = False) -> None:
|
|
||||||
assert declSpecs
|
assert declSpecs
|
||||||
assert decl
|
assert decl
|
||||||
self.declSpecs = declSpecs
|
self.declSpecs = declSpecs
|
||||||
self.decl = decl
|
self.decl = decl
|
||||||
self.semicolon = semicolon
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> ASTNestedName:
|
def name(self) -> ASTNestedName:
|
||||||
@@ -2770,8 +2769,6 @@ class ASTType(ASTBase):
|
|||||||
if self.decl.require_space_after_declSpecs() and len(declSpecs) > 0:
|
if self.decl.require_space_after_declSpecs() and len(declSpecs) > 0:
|
||||||
res.append(' ')
|
res.append(' ')
|
||||||
res.append(transform(self.decl))
|
res.append(transform(self.decl))
|
||||||
if self.semicolon:
|
|
||||||
res.append(';')
|
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def get_type_declaration_prefix(self) -> str:
|
def get_type_declaration_prefix(self) -> str:
|
||||||
@@ -2792,8 +2789,6 @@ class ASTType(ASTBase):
|
|||||||
if mode == 'markType':
|
if mode == 'markType':
|
||||||
mode = 'noneIsName'
|
mode = 'noneIsName'
|
||||||
self.decl.describe_signature(signode, mode, env, symbol)
|
self.decl.describe_signature(signode, mode, env, symbol)
|
||||||
if self.semicolon:
|
|
||||||
signode += nodes.Text(';')
|
|
||||||
|
|
||||||
|
|
||||||
class ASTTemplateParamConstrainedTypeWithInit(ASTBase):
|
class ASTTemplateParamConstrainedTypeWithInit(ASTBase):
|
||||||
@@ -5876,7 +5871,6 @@ class DefinitionParser(BaseParser):
|
|||||||
raise Exception('Internal error, unknown outer "%s".' % outer)
|
raise Exception('Internal error, unknown outer "%s".' % outer)
|
||||||
if outer != 'operatorCast':
|
if outer != 'operatorCast':
|
||||||
assert named
|
assert named
|
||||||
semicolon = False
|
|
||||||
if outer in ('type', 'function'):
|
if outer in ('type', 'function'):
|
||||||
# We allow type objects to just be a name.
|
# We allow type objects to just be a name.
|
||||||
# Some functions don't have normal return types: constructors,
|
# Some functions don't have normal return types: constructors,
|
||||||
@@ -5888,8 +5882,7 @@ class DefinitionParser(BaseParser):
|
|||||||
declSpecs = self._parse_decl_specs(outer=outer, typed=False)
|
declSpecs = self._parse_decl_specs(outer=outer, typed=False)
|
||||||
decl = self._parse_declarator(named=True, paramMode=outer,
|
decl = self._parse_declarator(named=True, paramMode=outer,
|
||||||
typed=False)
|
typed=False)
|
||||||
semicolon = self.skip_string_and_ws(';')
|
self.assert_end(allowSemicolon=True)
|
||||||
self.assert_end()
|
|
||||||
except DefinitionError as exUntyped:
|
except DefinitionError as exUntyped:
|
||||||
if outer == 'type':
|
if outer == 'type':
|
||||||
desc = "If just a name"
|
desc = "If just a name"
|
||||||
@@ -5944,7 +5937,7 @@ class DefinitionParser(BaseParser):
|
|||||||
named = 'single'
|
named = 'single'
|
||||||
declSpecs = self._parse_decl_specs(outer=outer)
|
declSpecs = self._parse_decl_specs(outer=outer)
|
||||||
decl = self._parse_declarator(named=named, paramMode=paramMode)
|
decl = self._parse_declarator(named=named, paramMode=paramMode)
|
||||||
return ASTType(declSpecs, decl, semicolon)
|
return ASTType(declSpecs, decl)
|
||||||
|
|
||||||
def _parse_type_with_init(
|
def _parse_type_with_init(
|
||||||
self, named: Union[bool, str],
|
self, named: Union[bool, str],
|
||||||
@@ -6300,7 +6293,8 @@ class DefinitionParser(BaseParser):
|
|||||||
templatePrefix,
|
templatePrefix,
|
||||||
fullSpecShorthand=False,
|
fullSpecShorthand=False,
|
||||||
isMember=objectType == 'member')
|
isMember=objectType == 'member')
|
||||||
semicolon = self.skip_string_and_ws(';')
|
self.skip_ws()
|
||||||
|
semicolon = self.skip_string(';')
|
||||||
return ASTDeclaration(objectType, directiveType, visibility,
|
return ASTDeclaration(objectType, directiveType, visibility,
|
||||||
templatePrefix, declaration, semicolon)
|
templatePrefix, declaration, semicolon)
|
||||||
|
|
||||||
|
|||||||
@@ -338,10 +338,14 @@ class BaseParser:
|
|||||||
self.pos = self.end
|
self.pos = self.end
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def assert_end(self) -> None:
|
def assert_end(self, *, allowSemicolon: bool = False) -> None:
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if not self.eof:
|
if allowSemicolon:
|
||||||
self.fail('Expected end of definition.')
|
if not self.eof and self.definition[self.pos:] != ';':
|
||||||
|
self.fail('Expected end of definition or ;.')
|
||||||
|
else:
|
||||||
|
if not self.eof:
|
||||||
|
self.fail('Expected end of definition.')
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|||||||
14
tests/roots/test-domain-cpp/semicolon.rst
Normal file
14
tests/roots/test-domain-cpp/semicolon.rst
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.. cpp:class:: Class;
|
||||||
|
.. cpp:struct:: Struct;
|
||||||
|
.. cpp:union:: Union;
|
||||||
|
.. cpp:function:: void f();
|
||||||
|
.. cpp:member:: int member;
|
||||||
|
.. cpp:var:: int var;
|
||||||
|
.. cpp:type:: Type;
|
||||||
|
.. cpp:type:: int TypeDef;
|
||||||
|
.. cpp:type:: Alias = int;
|
||||||
|
.. cpp:concept:: template<typename T> Concept;
|
||||||
|
.. cpp:enum:: Enum;
|
||||||
|
.. cpp:enum-struct:: EnumStruct;
|
||||||
|
.. cpp:enum-class:: EnumClass;
|
||||||
|
.. cpp:enumerator:: Enumerator;
|
||||||
@@ -87,7 +87,7 @@ def check(name, input, idDict, output=None):
|
|||||||
# First, check without semicolon
|
# First, check without semicolon
|
||||||
_check(name, input, idDict, output)
|
_check(name, input, idDict, output)
|
||||||
# Second, check with semicolon
|
# Second, check with semicolon
|
||||||
_check(name, input + ';', idDict, output + ';')
|
_check(name, input + ' ;', idDict, output + ';')
|
||||||
|
|
||||||
|
|
||||||
def test_fundamental_types():
|
def test_fundamental_types():
|
||||||
@@ -910,6 +910,13 @@ def test_build_domain_cpp_backslash_ok(app, status, warning):
|
|||||||
assert len(ws) == 0
|
assert len(ws) == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'nitpicky': True})
|
||||||
|
def test_build_domain_cpp_semicolon(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
ws = filter_warnings(warning, "semicolon")
|
||||||
|
assert len(ws) == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(testroot='domain-cpp',
|
@pytest.mark.sphinx(testroot='domain-cpp',
|
||||||
confoverrides={'nitpicky': True, 'strip_signature_backslash': True})
|
confoverrides={'nitpicky': True, 'strip_signature_backslash': True})
|
||||||
def test_build_domain_cpp_backslash_ok(app, status, warning):
|
def test_build_domain_cpp_backslash_ok(app, status, warning):
|
||||||
|
|||||||
Reference in New Issue
Block a user