mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C, allow semicolon in the end of declarations
(except macros)
This commit is contained in:
parent
ef0c2bf83c
commit
abe65423ca
@ -1272,10 +1272,12 @@ class ASTEnumerator(ASTBase):
|
||||
|
||||
|
||||
class ASTDeclaration(ASTBaseBase):
|
||||
def __init__(self, objectType: str, directiveType: str, declaration: Any) -> None:
|
||||
def __init__(self, objectType: str, directiveType: str, declaration: Any,
|
||||
semicolon: bool = False) -> None:
|
||||
self.objectType = objectType
|
||||
self.directiveType = directiveType
|
||||
self.declaration = declaration
|
||||
self.semicolon = semicolon
|
||||
|
||||
self.symbol = None # type: Symbol
|
||||
# set by CObject._add_enumerator_to_parent
|
||||
@ -1304,7 +1306,10 @@ class ASTDeclaration(ASTBaseBase):
|
||||
return self.get_id(_max_id, True)
|
||||
|
||||
def _stringify(self, transform: StringifyTransform) -> str:
|
||||
return transform(self.declaration)
|
||||
res = transform(self.declaration)
|
||||
if self.semicolon:
|
||||
res += ';'
|
||||
return res
|
||||
|
||||
def describe_signature(self, signode: TextElement, mode: str,
|
||||
env: "BuildEnvironment", options: Dict) -> None:
|
||||
@ -1340,6 +1345,8 @@ class ASTDeclaration(ASTBaseBase):
|
||||
else:
|
||||
assert False
|
||||
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
|
||||
if self.semicolon:
|
||||
mainDeclNode += nodes.Text(';')
|
||||
|
||||
|
||||
class SymbolLookupResult:
|
||||
@ -2742,7 +2749,7 @@ class DefinitionParser(BaseParser):
|
||||
declSpecs = self._parse_decl_specs(outer=outer, typed=False)
|
||||
decl = self._parse_declarator(named=True, paramMode=outer,
|
||||
typed=False)
|
||||
self.assert_end()
|
||||
self.assert_end(allowSemicolon=True)
|
||||
except DefinitionError as exUntyped:
|
||||
desc = "If just a name"
|
||||
prevErrors.append((exUntyped, desc))
|
||||
@ -2875,7 +2882,12 @@ class DefinitionParser(BaseParser):
|
||||
declaration = self._parse_type(named=True, outer='type')
|
||||
else:
|
||||
assert False
|
||||
return ASTDeclaration(objectType, directiveType, declaration)
|
||||
if objectType != 'macro':
|
||||
self.skip_ws()
|
||||
semicolon = self.skip_string(';')
|
||||
else:
|
||||
semicolon = False
|
||||
return ASTDeclaration(objectType, directiveType, declaration, semicolon)
|
||||
|
||||
def parse_namespace_object(self) -> ASTNestedName:
|
||||
return self._parse_nested_name()
|
||||
|
10
tests/roots/test-domain-c/semicolon.rst
Normal file
10
tests/roots/test-domain-c/semicolon.rst
Normal file
@ -0,0 +1,10 @@
|
||||
.. c:member:: int member;
|
||||
.. c:var:: int var;
|
||||
.. c:function:: void f();
|
||||
.. .. c:macro:: NO_SEMICOLON;
|
||||
.. c:struct:: Struct;
|
||||
.. c:union:: Union;
|
||||
.. c:enum:: Enum;
|
||||
.. c:enumerator:: Enumerator;
|
||||
.. c:type:: Type;
|
||||
.. c:type:: int TypeDef;
|
@ -27,10 +27,8 @@ def parse(name, string):
|
||||
return ast
|
||||
|
||||
|
||||
def check(name, input, idDict, output=None):
|
||||
def _check(name, input, idDict, output):
|
||||
# first a simple check of the AST
|
||||
if output is None:
|
||||
output = input
|
||||
ast = parse(name, input)
|
||||
res = str(ast)
|
||||
if res != output:
|
||||
@ -77,6 +75,16 @@ def check(name, input, idDict, output=None):
|
||||
raise DefinitionError("")
|
||||
|
||||
|
||||
def check(name, input, idDict, output=None):
|
||||
if output is None:
|
||||
output = input
|
||||
# First, check without semicolon
|
||||
_check(name, input, idDict, output)
|
||||
if name != 'macro':
|
||||
# Second, check with semicolon
|
||||
_check(name, input + ' ;', idDict, output + ';')
|
||||
|
||||
|
||||
def test_expressions():
|
||||
def exprCheck(expr, output=None):
|
||||
class Config:
|
||||
@ -469,8 +477,9 @@ def test_build_domain_c(app, status, warning):
|
||||
ws = filter_warnings(warning, "index")
|
||||
assert len(ws) == 0
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
|
||||
def test_build_domain_c(app, status, warning):
|
||||
def test_build_domain_c_namespace(app, status, warning):
|
||||
app.builder.build_all()
|
||||
ws = filter_warnings(warning, "namespace")
|
||||
assert len(ws) == 0
|
||||
@ -478,6 +487,7 @@ def test_build_domain_c(app, status, warning):
|
||||
for id_ in ('NS.NSVar', 'NULLVar', 'ZeroVar', 'NS2.NS3.NS2NS3Var', 'PopVar'):
|
||||
assert 'id="c.{}"'.format(id_) in t
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
|
||||
def test_build_domain_c_anon_dup_decl(app, status, warning):
|
||||
app.builder.build_all()
|
||||
@ -487,6 +497,13 @@ def test_build_domain_c_anon_dup_decl(app, status, warning):
|
||||
assert "WARNING: c:identifier reference target not found: @b" in ws[1]
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
|
||||
def test_build_domain_c_semicolon(app, status, warning):
|
||||
app.builder.build_all()
|
||||
ws = filter_warnings(warning, "semicolon")
|
||||
assert len(ws) == 0
|
||||
|
||||
|
||||
def test_cfunction(app):
|
||||
text = (".. c:function:: PyObject* "
|
||||
"PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)")
|
||||
|
Loading…
Reference in New Issue
Block a user