C++, semicolon, move it entirely to ASTDeclaration

This commit is contained in:
Jakob Lykke Andersen 2020-04-24 10:57:23 +02:00
parent 50ae1b04e8
commit ef0c2bf83c
4 changed files with 35 additions and 16 deletions

View File

@ -109,6 +109,7 @@ T = TypeVar('T')
simple-declaration ->
attribute-specifier-seq[opt] decl-specifier-seq[opt]
init-declarator-list[opt] ;
# Make the semicolon optional.
# For now: drop the attributes (TODO).
# Use at most 1 init-declarator.
-> decl-specifier-seq init-declarator
@ -2690,13 +2691,11 @@ class ASTInitializer(ASTBase):
class ASTType(ASTBase):
def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator,
semicolon: bool = False) -> None:
def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator) -> None:
assert declSpecs
assert decl
self.declSpecs = declSpecs
self.decl = decl
self.semicolon = semicolon
@property
def name(self) -> ASTNestedName:
@ -2770,8 +2769,6 @@ class ASTType(ASTBase):
if self.decl.require_space_after_declSpecs() and len(declSpecs) > 0:
res.append(' ')
res.append(transform(self.decl))
if self.semicolon:
res.append(';')
return ''.join(res)
def get_type_declaration_prefix(self) -> str:
@ -2792,8 +2789,6 @@ class ASTType(ASTBase):
if mode == 'markType':
mode = 'noneIsName'
self.decl.describe_signature(signode, mode, env, symbol)
if self.semicolon:
signode += nodes.Text(';')
class ASTTemplateParamConstrainedTypeWithInit(ASTBase):
@ -5876,7 +5871,6 @@ class DefinitionParser(BaseParser):
raise Exception('Internal error, unknown outer "%s".' % outer)
if outer != 'operatorCast':
assert named
semicolon = False
if outer in ('type', 'function'):
# We allow type objects to just be a name.
# 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)
decl = self._parse_declarator(named=True, paramMode=outer,
typed=False)
semicolon = self.skip_string_and_ws(';')
self.assert_end()
self.assert_end(allowSemicolon=True)
except DefinitionError as exUntyped:
if outer == 'type':
desc = "If just a name"
@ -5944,7 +5937,7 @@ class DefinitionParser(BaseParser):
named = 'single'
declSpecs = self._parse_decl_specs(outer=outer)
decl = self._parse_declarator(named=named, paramMode=paramMode)
return ASTType(declSpecs, decl, semicolon)
return ASTType(declSpecs, decl)
def _parse_type_with_init(
self, named: Union[bool, str],
@ -6300,7 +6293,8 @@ class DefinitionParser(BaseParser):
templatePrefix,
fullSpecShorthand=False,
isMember=objectType == 'member')
semicolon = self.skip_string_and_ws(';')
self.skip_ws()
semicolon = self.skip_string(';')
return ASTDeclaration(objectType, directiveType, visibility,
templatePrefix, declaration, semicolon)

View File

@ -338,10 +338,14 @@ class BaseParser:
self.pos = self.end
return rv
def assert_end(self) -> None:
def assert_end(self, *, allowSemicolon: bool = False) -> None:
self.skip_ws()
if not self.eof:
self.fail('Expected end of definition.')
if allowSemicolon:
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.')
################################################################################

View 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;

View File

@ -87,7 +87,7 @@ def check(name, input, idDict, output=None):
# First, check without semicolon
_check(name, input, idDict, output)
# Second, check with semicolon
_check(name, input + ';', idDict, output + ';')
_check(name, input + ' ;', idDict, output + ';')
def test_fundamental_types():
@ -910,6 +910,13 @@ def test_build_domain_cpp_backslash_ok(app, status, warning):
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',
confoverrides={'nitpicky': True, 'strip_signature_backslash': True})
def test_build_domain_cpp_backslash_ok(app, status, warning):