summaryrefslogtreecommitdiff
path: root/tests/test_domain_cpp.py
diff options
context:
space:
mode:
authorJean-François B <2589111+jfbu@users.noreply.github.com>2022-08-06 18:31:14 +0200
committerJean-François B <2589111+jfbu@users.noreply.github.com>2022-08-06 18:31:14 +0200
commit5c82449eca73ef448eb7fdfbcc061cb91d70c18c (patch)
treec4a8394dd9105ba73e2df12c3c5e26cbae501d54 /tests/test_domain_cpp.py
parent6f530ca3ea305a4c4e077a237fc7196e959a4bb4 (diff)
parent59056aa7816ebae81aa6842290aa7a6ece14d1bd (diff)
downloadsphinx-git-5c82449eca73ef448eb7fdfbcc061cb91d70c18c.tar.gz
Merge branch '5.x'
Diffstat (limited to 'tests/test_domain_cpp.py')
-rw-r--r--tests/test_domain_cpp.py91
1 files changed, 88 insertions, 3 deletions
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index ee8da3d39..5e9bc6aa3 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -841,9 +841,9 @@ def test_domain_cpp_ast_templates():
check('class', 'abc::ns::foo{{id_0, id_1, ...id_2}} {key}xyz::bar',
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
check('class', 'abc::ns::foo{{id_0, id_1, id_2}} {key}xyz::bar<id_0, id_1, id_2>',
- {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE'})
+ {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
check('class', 'abc::ns::foo{{id_0, id_1, ...id_2}} {key}xyz::bar<id_0, id_1, id_2...>',
- {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE'})
+ {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
check('class', 'template<> Concept{{U}} {key}A<int>::B', {2: 'IEI0EX7ConceptI1UEEN1AIiE1BE'})
@@ -876,6 +876,9 @@ def test_domain_cpp_ast_templates():
# defaulted constrained type parameters
check('type', 'template<C T = int&> {key}A', {2: 'I_1CE1A'}, key='using')
+ # pack expansion after non-type template parameter
+ check('type', 'template<int (X::*)(bool)...> {key}A', {2: 'I_DpM1XFibEE1A'}, key='using')
+
def test_domain_cpp_ast_placeholder_types():
check('function', 'void f(Sortable auto &v)', {1: 'f__SortableR', 2: '1fR8Sortable'})
@@ -901,7 +904,7 @@ def test_domain_cpp_ast_requires_clauses():
'template<typename T> requires R<T> ' +
'template<typename U> requires S<T> ' +
'void A<T>::f() requires B',
- {4: 'I0EIQ1RI1TEEI0EIQaa1SI1TE1BEN1AI1TE1fEvv'})
+ {4: 'I0EIQ1RI1TEEI0EIQaa1SI1TE1BEN1A1fEvv'})
check('function',
'template<template<typename T> requires R<T> typename X> ' +
'void f()',
@@ -1040,6 +1043,38 @@ def test_domain_cpp_ast_xref_parsing():
check('T f()')
+@pytest.mark.parametrize(
+ 'param,is_pack',
+ [('typename', False),
+ ('typename T', False),
+ ('typename...', True),
+ ('typename... T', True),
+ ('int', False),
+ ('int N', False),
+ ('int* N', False),
+ ('int& N', False),
+ ('int&... N', True),
+ ('int*... N', True),
+ ('int...', True),
+ ('int... N', True),
+ ('auto', False),
+ ('auto...', True),
+ ('int X::*', False),
+ ('int X::*...', True),
+ ('int (X::*)(bool)', False),
+ ('int (X::*x)(bool)', False),
+ ('int (X::*)(bool)...', True),
+ ('template<typename> class', False),
+ ('template<typename> class...', True),
+ ])
+def test_domain_cpp_template_parameters_is_pack(param: str, is_pack: bool):
+ def parse_template_parameter(param: str):
+ ast = parse('type', 'template<' + param + '> X')
+ return ast.templatePrefix.templates[0].params[0]
+ ast = parse_template_parameter(param)
+ assert ast.isPack == is_pack
+
+
# def test_print():
# # used for getting all the ids out for checking
# for a in ids:
@@ -1395,3 +1430,53 @@ def test_domain_cpp_parse_mix_decl_duplicate(app, warning):
assert "index.rst:3: WARNING: Duplicate C++ declaration, also defined at index:1." in ws[2]
assert "Declaration is '.. cpp:struct:: A'." in ws[3]
assert ws[4] == ""
+
+
+# For some reason, using the default testroot of "root" leads to the contents of
+# `test-root/objects.txt` polluting the symbol table depending on the test
+# execution order. Using a testroot of "config" seems to avoid that problem.
+@pytest.mark.sphinx(testroot='config')
+def test_domain_cpp_normalize_unspecialized_template_args(make_app, app_params):
+ args, kwargs = app_params
+
+ text1 = (".. cpp:class:: template <typename T> A\n")
+ text2 = (".. cpp:class:: template <typename T> template <typename U> A<T>::B\n")
+
+ app1 = make_app(*args, **kwargs)
+ restructuredtext.parse(app=app1, text=text1, docname='text1')
+ root1 = app1.env.domaindata['cpp']['root_symbol']
+
+ assert root1.dump(1) == (
+ ' ::\n'
+ ' template<typename T> \n'
+ ' A: {class} template<typename T> A\t(text1)\n'
+ ' T: {templateParam} typename T\t(text1)\n'
+ )
+
+ app2 = make_app(*args, **kwargs)
+ restructuredtext.parse(app=app2, text=text2, docname='text2')
+ root2 = app2.env.domaindata['cpp']['root_symbol']
+
+ assert root2.dump(1) == (
+ ' ::\n'
+ ' template<typename T> \n'
+ ' A\n'
+ ' T\n'
+ ' template<typename U> \n'
+ ' B: {class} template<typename T> template<typename U> A<T>::B\t(text2)\n'
+ ' U: {templateParam} typename U\t(text2)\n'
+ )
+
+ root2.merge_with(root1, ['text1'], app2.env)
+
+ assert root2.dump(1) == (
+ ' ::\n'
+ ' template<typename T> \n'
+ ' A: {class} template<typename T> A\t(text1)\n'
+ ' T: {templateParam} typename T\t(text1)\n'
+ ' template<typename U> \n'
+ ' B: {class} template<typename T> template<typename U> A<T>::B\t(text2)\n'
+ ' U: {templateParam} typename U\t(text2)\n'
+ )
+ warning = app2._warning.getvalue()
+ assert 'Internal C++ domain error during symbol merging' not in warning