summaryrefslogtreecommitdiff
path: root/tests/test_domain_c.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_domain_c.py')
-rw-r--r--tests/test_domain_c.py163
1 files changed, 93 insertions, 70 deletions
diff --git a/tests/test_domain_c.py b/tests/test_domain_c.py
index ef4858786..d59c4fc1c 100644
--- a/tests/test_domain_c.py
+++ b/tests/test_domain_c.py
@@ -15,16 +15,20 @@ import pytest
from sphinx import addnodes
from sphinx.addnodes import desc
-from sphinx.domains.c import DefinitionError, DefinitionParser, Symbol, _id_prefix, _max_id
+from sphinx.domains.c import (DefinitionError, DefinitionParser, Symbol, _id_prefix,
+ _macroKeywords, _max_id)
from sphinx.ext.intersphinx import load_mappings, normalize_intersphinx_mapping
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
+class Config:
+ c_id_attributes = ["id_attr", 'LIGHTGBM_C_EXPORT']
+ c_paren_attributes = ["paren_attr"]
+ c_extra_keywords = _macroKeywords
+
+
def parse(name, string):
- class Config:
- c_id_attributes = ["id_attr", 'LIGHTGBM_C_EXPORT']
- c_paren_attributes = ["paren_attr"]
parser = DefinitionParser(string, location=None, config=Config())
parser.allowFallbackExpressionParsing = False
ast = parser.parse_declaration(name, name)
@@ -112,11 +116,8 @@ def check(name, input, idDict, output=None, key=None, asTextOutput=None):
asTextOutput + ';' if asTextOutput is not None else None)
-def test_expressions():
+def test_domain_c_ast_expressions():
def exprCheck(expr, output=None):
- class Config:
- c_id_attributes = ["id_attr"]
- c_paren_attributes = ["paren_attr"]
parser = DefinitionParser(expr, location=None, config=Config())
parser.allowFallbackExpressionParsing = False
ast = parser.parse_expression()
@@ -155,7 +156,8 @@ def test_expressions():
# primary
exprCheck('true')
exprCheck('false')
- ints = ['5', '0', '075', '0x0123456789ABCDEF', '0XF', '0b1', '0B1']
+ ints = ['5', '0', '075', '0x0123456789ABCDEF', '0XF', '0b1', '0B1',
+ "0b0'1'0", "00'1'2", "0x0'1'2", "1'2'3"]
unsignedSuffix = ['', 'u', 'U']
longSuffix = ['', 'l', 'L', 'll', 'LL']
for i in ints:
@@ -170,14 +172,18 @@ def test_expressions():
'5e42', '5e+42', '5e-42',
'5.', '5.e42', '5.e+42', '5.e-42',
'.5', '.5e42', '.5e+42', '.5e-42',
- '5.0', '5.0e42', '5.0e+42', '5.0e-42']:
+ '5.0', '5.0e42', '5.0e+42', '5.0e-42',
+ "1'2'3e7'8'9", "1'2'3.e7'8'9",
+ ".4'5'6e7'8'9", "1'2'3.4'5'6e7'8'9"]:
expr = e + suffix
exprCheck(expr)
for e in [
'ApF', 'Ap+F', 'Ap-F',
'A.', 'A.pF', 'A.p+F', 'A.p-F',
'.A', '.ApF', '.Ap+F', '.Ap-F',
- 'A.B', 'A.BpF', 'A.Bp+F', 'A.Bp-F']:
+ 'A.B', 'A.BpF', 'A.Bp+F', 'A.Bp-F',
+ "A'B'Cp1'2'3", "A'B'C.p1'2'3",
+ ".D'E'Fp1'2'3", "A'B'C.D'E'Fp1'2'3"]:
expr = "0x" + e + suffix
exprCheck(expr)
exprCheck('"abc\\"cba"') # string
@@ -269,7 +275,7 @@ def test_expressions():
exprCheck('a or_eq 5')
-def test_type_definitions():
+def test_domain_c_ast_type_definitions():
check('type', "{key}T", {1: "T"})
check('type', "{key}bool *b", {1: 'b'}, key='typedef')
@@ -290,7 +296,7 @@ def test_type_definitions():
{1: 'gpio_callback_t'}, key='typedef')
-def test_macro_definitions():
+def test_domain_c_ast_macro_definitions():
check('macro', 'M', {1: 'M'})
check('macro', 'M()', {1: 'M'})
check('macro', 'M(arg)', {1: 'M'})
@@ -306,7 +312,7 @@ def test_macro_definitions():
check('macro', 'M(arg1, arg2..., arg3)', {1: 'M'})
-def test_member_definitions():
+def test_domain_c_ast_member_definitions():
check('member', 'void a', {1: 'a'})
check('member', '_Bool a', {1: 'a'})
check('member', 'bool a', {1: 'a'})
@@ -364,7 +370,7 @@ def test_member_definitions():
check('member', 'int b : 3', {1: 'b'})
-def test_function_definitions():
+def test_domain_c_ast_function_definitions():
check('function', 'void f()', {1: 'f'})
check('function', 'void f(int)', {1: 'f'})
check('function', 'void f(int i)', {1: 'f'})
@@ -424,29 +430,29 @@ def test_function_definitions():
check('function', 'void f(void (*p)(int, double), int i)', {1: 'f'})
-def test_nested_name():
+def test_domain_c_ast_nested_name():
check('struct', '{key}.A', {1: "A"})
check('struct', '{key}.A.B', {1: "A.B"})
check('function', 'void f(.A a)', {1: "f"})
check('function', 'void f(.A.B a)', {1: "f"})
-def test_struct_definitions():
+def test_domain_c_ast_struct_definitions():
check('struct', '{key}A', {1: 'A'})
-def test_union_definitions():
+def test_domain_c_ast_union_definitions():
check('union', '{key}A', {1: 'A'})
-def test_enum_definitions():
+def test_domain_c_ast_enum_definitions():
check('enum', '{key}A', {1: 'A'})
check('enumerator', '{key}A', {1: 'A'})
check('enumerator', '{key}A = 42', {1: 'A'})
-def test_anon_definitions():
+def test_domain_c_ast_anon_definitions():
check('struct', '@a', {1: "@a"}, asTextOutput='struct [anonymous]')
check('union', '@a', {1: "@a"}, asTextOutput='union [anonymous]')
check('enum', '@a', {1: "@a"}, asTextOutput='enum [anonymous]')
@@ -454,7 +460,7 @@ def test_anon_definitions():
check('struct', '@a.A', {1: "@a.A"}, asTextOutput='struct [anonymous].A')
-def test_initializers():
+def test_domain_c_ast_initializers():
idsMember = {1: 'v'}
idsFunction = {1: 'f'}
# no init
@@ -473,7 +479,7 @@ def test_initializers():
# TODO: designator-list
-def test_attributes():
+def test_domain_c_ast_attributes():
# style: C++
check('member', '[[]] int f', {1: 'f'})
check('member', '[ [ ] ] int f', {1: 'f'},
@@ -522,6 +528,16 @@ def test_attributes():
check('function', 'LIGHTGBM_C_EXPORT int LGBM_BoosterFree(int handle)',
{1: 'LGBM_BoosterFree'})
+
+def test_extra_keywords():
+ with pytest.raises(DefinitionError,
+ match='Expected identifier, got user-defined keyword: complex.'):
+ parse('function', 'void f(int complex)')
+ with pytest.raises(DefinitionError,
+ match='Expected identifier, got user-defined keyword: complex.'):
+ parse('function', 'void complex(void)')
+
+
# def test_print():
# # used for getting all the ids out for checking
# for a in ids:
@@ -566,14 +582,14 @@ def extract_role_links(app, filename):
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
-def test_build_domain_c(app, status, warning):
+def test_domain_c_build(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "index")
assert len(ws) == 0
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
-def test_build_domain_c_namespace(app, status, warning):
+def test_domain_c_build_namespace(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "namespace")
assert len(ws) == 0
@@ -583,7 +599,7 @@ def test_build_domain_c_namespace(app, status, warning):
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
-def test_build_domain_c_anon_dup_decl(app, status, warning):
+def test_domain_c_build_anon_dup_decl(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "anon-dup-decl")
assert len(ws) == 2
@@ -592,7 +608,7 @@ def test_build_domain_c_anon_dup_decl(app, status, warning):
@pytest.mark.sphinx(confoverrides={'nitpicky': True})
-def test_build_domain_c_semicolon(app, warning):
+def test_domain_c_build_semicolon(app, warning):
text = """
.. c:member:: int member;
.. c:var:: int var;
@@ -611,7 +627,7 @@ def test_build_domain_c_semicolon(app, warning):
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
-def test_build_function_param_target(app, warning):
+def test_domain_c_build_function_param_target(app, warning):
# the anchor for function parameters should be the function
app.builder.build_all()
ws = filter_warnings(warning, "function_param_target")
@@ -624,12 +640,19 @@ def test_build_function_param_target(app, warning):
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
-def test_build_ns_lookup(app, warning):
+def test_domain_c_build_ns_lookup(app, warning):
app.builder.build_all()
ws = filter_warnings(warning, "ns_lookup")
assert len(ws) == 0
+@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
+def test_domain_c_build_field_role(app, status, warning):
+ app.builder.build_all()
+ ws = filter_warnings(warning, "field-role")
+ assert len(ws) == 0
+
+
def _get_obj(app, queryName):
domain = app.env.get_domain('c')
for name, dispname, objectType, docname, anchor, prio in domain.get_objects():
@@ -638,49 +661,8 @@ def _get_obj(app, queryName):
return (queryName, "not", "found")
-def test_cfunction(app):
- text = (".. c:function:: PyObject* "
- "PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)")
- doctree = restructuredtext.parse(app, text)
- assert_node(doctree[1], addnodes.desc, desctype="function",
- domain="c", objtype="function", noindex=False)
-
- entry = _get_obj(app, 'PyType_GenericAlloc')
- assert entry == ('index', 'c.PyType_GenericAlloc', 'function')
-
-
-def test_cmember(app):
- text = ".. c:member:: PyObject* PyTypeObject.tp_bases"
- doctree = restructuredtext.parse(app, text)
- assert_node(doctree[1], addnodes.desc, desctype="member",
- domain="c", objtype="member", noindex=False)
-
- entry = _get_obj(app, 'PyTypeObject.tp_bases')
- assert entry == ('index', 'c.PyTypeObject.tp_bases', 'member')
-
-
-def test_cvar(app):
- text = ".. c:var:: PyObject* PyClass_Type"
- doctree = restructuredtext.parse(app, text)
- assert_node(doctree[1], addnodes.desc, desctype="var",
- domain="c", objtype="var", noindex=False)
-
- entry = _get_obj(app, 'PyClass_Type')
- assert entry == ('index', 'c.PyClass_Type', 'member')
-
-
-def test_noindexentry(app):
- text = (".. c:function:: void f()\n"
- ".. c:function:: void g()\n"
- " :noindexentry:\n")
- doctree = restructuredtext.parse(app, text)
- assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
- assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C function)', 'c.f', '', None)])
- assert_node(doctree[2], addnodes.index, entries=[])
-
-
@pytest.mark.sphinx(testroot='domain-c-intersphinx', confoverrides={'nitpicky': True})
-def test_intersphinx(tempdir, app, status, warning):
+def test_domain_c_build_intersphinx(tempdir, app, status, warning):
# a splitting of test_ids_vs_tags0 into the primary directives in a remote project,
# and then the references in the test project
origSource = """\
@@ -728,3 +710,44 @@ _var c:member 1 index.html#c.$ -
app.builder.build_all()
ws = filter_warnings(warning, "index")
assert len(ws) == 0
+
+
+def test_domain_c_parse_cfunction(app):
+ text = (".. c:function:: PyObject* "
+ "PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)")
+ doctree = restructuredtext.parse(app, text)
+ assert_node(doctree[1], addnodes.desc, desctype="function",
+ domain="c", objtype="function", noindex=False)
+
+ entry = _get_obj(app, 'PyType_GenericAlloc')
+ assert entry == ('index', 'c.PyType_GenericAlloc', 'function')
+
+
+def test_domain_c_parse_cmember(app):
+ text = ".. c:member:: PyObject* PyTypeObject.tp_bases"
+ doctree = restructuredtext.parse(app, text)
+ assert_node(doctree[1], addnodes.desc, desctype="member",
+ domain="c", objtype="member", noindex=False)
+
+ entry = _get_obj(app, 'PyTypeObject.tp_bases')
+ assert entry == ('index', 'c.PyTypeObject.tp_bases', 'member')
+
+
+def test_domain_c_parse_cvar(app):
+ text = ".. c:var:: PyObject* PyClass_Type"
+ doctree = restructuredtext.parse(app, text)
+ assert_node(doctree[1], addnodes.desc, desctype="var",
+ domain="c", objtype="var", noindex=False)
+
+ entry = _get_obj(app, 'PyClass_Type')
+ assert entry == ('index', 'c.PyClass_Type', 'member')
+
+
+def test_domain_c_parse_noindexentry(app):
+ text = (".. c:function:: void f()\n"
+ ".. c:function:: void g()\n"
+ " :noindexentry:\n")
+ doctree = restructuredtext.parse(app, text)
+ assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
+ assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C function)', 'c.f', '', None)])
+ assert_node(doctree[2], addnodes.index, entries=[])