diff options
author | Jean-François B <2589111+jfbu@users.noreply.github.com> | 2022-08-06 18:31:14 +0200 |
---|---|---|
committer | Jean-François B <2589111+jfbu@users.noreply.github.com> | 2022-08-06 18:31:14 +0200 |
commit | 5c82449eca73ef448eb7fdfbcc061cb91d70c18c (patch) | |
tree | c4a8394dd9105ba73e2df12c3c5e26cbae501d54 /tests/test_domain_cpp.py | |
parent | 6f530ca3ea305a4c4e077a237fc7196e959a4bb4 (diff) | |
parent | 59056aa7816ebae81aa6842290aa7a6ece14d1bd (diff) | |
download | sphinx-git-5c82449eca73ef448eb7fdfbcc061cb91d70c18c.tar.gz |
Merge branch '5.x'
Diffstat (limited to 'tests/test_domain_cpp.py')
-rw-r--r-- | tests/test_domain_cpp.py | 91 |
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 |