mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7673 from jakobandersen/cpp_test_with_astext
C++, fix rendering of rooted nested names
This commit is contained in:
commit
218415ac74
2
CHANGES
2
CHANGES
@ -104,6 +104,8 @@ Bugs fixed
|
|||||||
supporting images
|
supporting images
|
||||||
* #7610: incorrectly renders consecutive backslashes for docutils-0.16
|
* #7610: incorrectly renders consecutive backslashes for docutils-0.16
|
||||||
* #7646: handle errors on event handlers
|
* #7646: handle errors on event handlers
|
||||||
|
* C++, fix rendering and xrefs in nested names explicitly starting
|
||||||
|
in global scope, e.g., ``::A::B``.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -752,11 +752,17 @@ class ASTNestedName(ASTBase):
|
|||||||
names = self.names[:-1] if mode == 'lastIsName' else self.names
|
names = self.names[:-1] if mode == 'lastIsName' else self.names
|
||||||
# If lastIsName, then wrap all of the prefix in a desc_addname,
|
# If lastIsName, then wrap all of the prefix in a desc_addname,
|
||||||
# else append directly to signode.
|
# else append directly to signode.
|
||||||
# NOTE: Breathe relies on the prefix being in the desc_addname node,
|
# NOTE: Breathe previously relied on the prefix being in the desc_addname node,
|
||||||
# so it can remove it in inner declarations.
|
# so it can remove it in inner declarations.
|
||||||
dest = signode
|
dest = signode
|
||||||
if mode == 'lastIsName':
|
if mode == 'lastIsName':
|
||||||
dest = addnodes.desc_addname()
|
dest = addnodes.desc_addname()
|
||||||
|
if self.rooted:
|
||||||
|
prefix += '::'
|
||||||
|
if mode == 'lastIsName' and len(names) == 0:
|
||||||
|
signode += nodes.Text('::')
|
||||||
|
else:
|
||||||
|
dest += nodes.Text('::')
|
||||||
for i in range(len(names)):
|
for i in range(len(names)):
|
||||||
nne = names[i]
|
nne = names[i]
|
||||||
template = self.templates[i]
|
template = self.templates[i]
|
||||||
|
@ -33,15 +33,29 @@ def parse(name, string):
|
|||||||
return ast
|
return ast
|
||||||
|
|
||||||
|
|
||||||
def _check(name, input, idDict, output):
|
def _check(name, input, idDict, output, key, asTextOutput):
|
||||||
|
if key is None:
|
||||||
|
key = name
|
||||||
|
key += ' '
|
||||||
|
if name in ('function', 'member'):
|
||||||
|
inputActual = input
|
||||||
|
outputAst = output
|
||||||
|
outputAsText = output
|
||||||
|
else:
|
||||||
|
inputActual = input.format(key='')
|
||||||
|
outputAst = output.format(key='')
|
||||||
|
outputAsText = output.format(key=key)
|
||||||
|
if asTextOutput is not None:
|
||||||
|
outputAsText = asTextOutput
|
||||||
|
|
||||||
# first a simple check of the AST
|
# first a simple check of the AST
|
||||||
ast = parse(name, input)
|
ast = parse(name, inputActual)
|
||||||
res = str(ast)
|
res = str(ast)
|
||||||
if res != output:
|
if res != outputAst:
|
||||||
print("")
|
print("")
|
||||||
print("Input: ", input)
|
print("Input: ", input)
|
||||||
print("Result: ", res)
|
print("Result: ", res)
|
||||||
print("Expected: ", output)
|
print("Expected: ", outputAst)
|
||||||
raise DefinitionError("")
|
raise DefinitionError("")
|
||||||
rootSymbol = Symbol(None, None, None, None, None, None)
|
rootSymbol = Symbol(None, None, None, None, None, None)
|
||||||
symbol = rootSymbol.add_declaration(ast, docname="TestDoc")
|
symbol = rootSymbol.add_declaration(ast, docname="TestDoc")
|
||||||
@ -49,6 +63,13 @@ def _check(name, input, idDict, output):
|
|||||||
signode = addnodes.desc_signature(input, '')
|
signode = addnodes.desc_signature(input, '')
|
||||||
parentNode += signode
|
parentNode += signode
|
||||||
ast.describe_signature(signode, 'lastIsName', symbol, options={})
|
ast.describe_signature(signode, 'lastIsName', symbol, options={})
|
||||||
|
resAsText = parentNode.astext()
|
||||||
|
if resAsText != outputAsText:
|
||||||
|
print("")
|
||||||
|
print("Input: ", input)
|
||||||
|
print("astext(): ", resAsText)
|
||||||
|
print("Expected: ", outputAsText)
|
||||||
|
raise DefinitionError("")
|
||||||
|
|
||||||
idExpected = [None]
|
idExpected = [None]
|
||||||
for i in range(1, _max_id + 1):
|
for i in range(1, _max_id + 1):
|
||||||
@ -81,13 +102,14 @@ def _check(name, input, idDict, output):
|
|||||||
raise DefinitionError("")
|
raise DefinitionError("")
|
||||||
|
|
||||||
|
|
||||||
def check(name, input, idDict, output=None):
|
def check(name, input, idDict, output=None, key=None, asTextOutput=None):
|
||||||
if output is None:
|
if output is None:
|
||||||
output = input
|
output = input
|
||||||
# First, check without semicolon
|
# First, check without semicolon
|
||||||
_check(name, input, idDict, output)
|
_check(name, input, idDict, output, key, asTextOutput)
|
||||||
# Second, check with semicolon
|
# Second, check with semicolon
|
||||||
_check(name, input + ' ;', idDict, output + ';')
|
_check(name, input + ' ;', idDict, output + ';', key,
|
||||||
|
asTextOutput + ';' if asTextOutput is not None else None)
|
||||||
|
|
||||||
|
|
||||||
def test_fundamental_types():
|
def test_fundamental_types():
|
||||||
@ -113,10 +135,11 @@ def test_fundamental_types():
|
|||||||
def test_expressions():
|
def test_expressions():
|
||||||
def exprCheck(expr, id, id4=None):
|
def exprCheck(expr, id, id4=None):
|
||||||
ids = 'IE1CIA%s_1aE'
|
ids = 'IE1CIA%s_1aE'
|
||||||
idDict = {2: ids % expr, 3: ids % id}
|
# call .format() on the expr to unescape double curly braces
|
||||||
|
idDict = {2: ids % expr.format(), 3: ids % id}
|
||||||
if id4 is not None:
|
if id4 is not None:
|
||||||
idDict[4] = ids % id4
|
idDict[4] = ids % id4
|
||||||
check('class', 'template<> C<a[%s]>' % expr, idDict)
|
check('class', 'template<> {key}C<a[%s]>' % expr, idDict)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
cpp_id_attributes = ["id_attr"]
|
cpp_id_attributes = ["id_attr"]
|
||||||
@ -229,8 +252,8 @@ def test_expressions():
|
|||||||
exprCheck('new int()', 'nw_ipiE')
|
exprCheck('new int()', 'nw_ipiE')
|
||||||
exprCheck('new int(5, 42)', 'nw_ipiL5EL42EE')
|
exprCheck('new int(5, 42)', 'nw_ipiL5EL42EE')
|
||||||
exprCheck('::new int', 'nw_iE')
|
exprCheck('::new int', 'nw_iE')
|
||||||
exprCheck('new int{}', 'nw_iilE')
|
exprCheck('new int{{}}', 'nw_iilE')
|
||||||
exprCheck('new int{5, 42}', 'nw_iilL5EL42EE')
|
exprCheck('new int{{5, 42}}', 'nw_iilL5EL42EE')
|
||||||
# delete-expression
|
# delete-expression
|
||||||
exprCheck('delete p', 'dl1p')
|
exprCheck('delete p', 'dl1p')
|
||||||
exprCheck('delete [] p', 'da1p')
|
exprCheck('delete [] p', 'da1p')
|
||||||
@ -291,7 +314,7 @@ def test_expressions():
|
|||||||
exprCheck('a xor_eq 5', 'eO1aL5E')
|
exprCheck('a xor_eq 5', 'eO1aL5E')
|
||||||
exprCheck('a |= 5', 'oR1aL5E')
|
exprCheck('a |= 5', 'oR1aL5E')
|
||||||
exprCheck('a or_eq 5', 'oR1aL5E')
|
exprCheck('a or_eq 5', 'oR1aL5E')
|
||||||
exprCheck('a = {1, 2, 3}', 'aS1ailL1EL2EL3EE')
|
exprCheck('a = {{1, 2, 3}}', 'aS1ailL1EL2EL3EE')
|
||||||
# comma operator
|
# comma operator
|
||||||
exprCheck('a, 5', 'cm1aL5E')
|
exprCheck('a, 5', 'cm1aL5E')
|
||||||
|
|
||||||
@ -301,8 +324,8 @@ def test_expressions():
|
|||||||
check('function', 'template<> void f(A<B, 2> &v)',
|
check('function', 'template<> void f(A<B, 2> &v)',
|
||||||
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE", 4: "IE1fvR1AI1BXL2EEE"})
|
{2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE", 4: "IE1fvR1AI1BXL2EEE"})
|
||||||
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
|
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
|
||||||
check('class', "template<int T = 42> A", {2: "I_iE1A"})
|
check('class', "template<int T = 42> {key}A", {2: "I_iE1A"})
|
||||||
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
check('enumerator', '{key}A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
||||||
|
|
||||||
exprCheck('operator()()', 'clclE')
|
exprCheck('operator()()', 'clclE')
|
||||||
exprCheck('operator()<int>()', 'clclIiEE')
|
exprCheck('operator()<int>()', 'clclIiEE')
|
||||||
@ -312,58 +335,59 @@ def test_expressions():
|
|||||||
|
|
||||||
|
|
||||||
def test_type_definitions():
|
def test_type_definitions():
|
||||||
check("type", "public bool b", {1: "b", 2: "1b"}, "bool b")
|
check("type", "public bool b", {1: "b", 2: "1b"}, "{key}bool b", key='typedef')
|
||||||
check("type", "bool A::b", {1: "A::b", 2: "N1A1bE"})
|
check("type", "{key}bool A::b", {1: "A::b", 2: "N1A1bE"}, key='typedef')
|
||||||
check("type", "bool *b", {1: "b", 2: "1b"})
|
check("type", "{key}bool *b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool *const b", {1: "b", 2: "1b"})
|
check("type", "{key}bool *const b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool *volatile const b", {1: "b", 2: "1b"})
|
check("type", "{key}bool *volatile const b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool *volatile const b", {1: "b", 2: "1b"})
|
check("type", "{key}bool *volatile const b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool *volatile const *b", {1: "b", 2: "1b"})
|
check("type", "{key}bool *volatile const *b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool &b", {1: "b", 2: "1b"})
|
check("type", "{key}bool &b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "bool b[]", {1: "b", 2: "1b"})
|
check("type", "{key}bool b[]", {1: "b", 2: "1b"}, key='typedef')
|
||||||
check("type", "std::pair<int, int> coord", {1: "coord", 2: "5coord"})
|
check("type", "{key}std::pair<int, int> coord", {1: "coord", 2: "5coord"}, key='typedef')
|
||||||
check("type", "long long int foo", {1: "foo", 2: "3foo"})
|
check("type", "{key}long long int foo", {1: "foo", 2: "3foo"}, key='typedef')
|
||||||
check("type", 'std::vector<std::pair<std::string, long long>> module::blah',
|
check("type", '{key}std::vector<std::pair<std::string, long long>> module::blah',
|
||||||
{1: "module::blah", 2: "N6module4blahE"})
|
{1: "module::blah", 2: "N6module4blahE"}, key='typedef')
|
||||||
check("type", "std::function<void()> F", {1: "F", 2: "1F"})
|
check("type", "{key}std::function<void()> F", {1: "F", 2: "1F"}, key='typedef')
|
||||||
check("type", "std::function<R(A1, A2)> F", {1: "F", 2: "1F"})
|
check("type", "{key}std::function<R(A1, A2)> F", {1: "F", 2: "1F"}, key='typedef')
|
||||||
check("type", "std::function<R(A1, A2, A3)> F", {1: "F", 2: "1F"})
|
check("type", "{key}std::function<R(A1, A2, A3)> F", {1: "F", 2: "1F"}, key='typedef')
|
||||||
check("type", "std::function<R(A1, A2, A3, As...)> F", {1: "F", 2: "1F"})
|
check("type", "{key}std::function<R(A1, A2, A3, As...)> F", {1: "F", 2: "1F"}, key='typedef')
|
||||||
check("type", "MyContainer::const_iterator",
|
check("type", "{key}MyContainer::const_iterator",
|
||||||
{1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"})
|
{1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"})
|
||||||
check("type",
|
check("type",
|
||||||
"public MyContainer::const_iterator",
|
"public MyContainer::const_iterator",
|
||||||
{1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"},
|
{1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"},
|
||||||
output="MyContainer::const_iterator")
|
output="{key}MyContainer::const_iterator")
|
||||||
# test decl specs on right
|
# test decl specs on right
|
||||||
check("type", "bool const b", {1: "b", 2: "1b"})
|
check("type", "{key}bool const b", {1: "b", 2: "1b"}, key='typedef')
|
||||||
# test name in global scope
|
# test name in global scope
|
||||||
check("type", "bool ::B::b", {1: "B::b", 2: "N1B1bE"})
|
check("type", "{key}bool ::B::b", {1: "B::b", 2: "N1B1bE"}, key='typedef')
|
||||||
|
|
||||||
check('type', 'A = B', {2: '1A'})
|
check('type', '{key}A = B', {2: '1A'}, key='using')
|
||||||
check('type', 'A = decltype(b)', {2: '1A'})
|
check('type', '{key}A = decltype(b)', {2: '1A'}, key='using')
|
||||||
|
|
||||||
# from breathe#267 (named function parameters for function pointers
|
# from breathe#267 (named function parameters for function pointers
|
||||||
check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)',
|
check('type', '{key}void (*gpio_callback_t)(struct device *port, uint32_t pin)',
|
||||||
{1: 'gpio_callback_t', 2: '15gpio_callback_t'})
|
{1: 'gpio_callback_t', 2: '15gpio_callback_t'}, key='typedef')
|
||||||
check('type', 'void (*f)(std::function<void(int i)> g)', {1: 'f', 2: '1f'})
|
check('type', '{key}void (*f)(std::function<void(int i)> g)', {1: 'f', 2: '1f'},
|
||||||
|
key='typedef')
|
||||||
|
|
||||||
check('type', 'T = A::template B<int>::template C<double>', {2: '1T'})
|
check('type', '{key}T = A::template B<int>::template C<double>', {2: '1T'}, key='using')
|
||||||
|
|
||||||
check('type', 'T = Q<A::operator()>', {2: '1T'})
|
check('type', '{key}T = Q<A::operator()>', {2: '1T'}, key='using')
|
||||||
check('type', 'T = Q<A::operator()<int>>', {2: '1T'})
|
check('type', '{key}T = Q<A::operator()<int>>', {2: '1T'}, key='using')
|
||||||
check('type', 'T = Q<A::operator bool>', {2: '1T'})
|
check('type', '{key}T = Q<A::operator bool>', {2: '1T'}, key='using')
|
||||||
|
|
||||||
|
|
||||||
def test_concept_definitions():
|
def test_concept_definitions():
|
||||||
check('concept', 'template<typename Param> A::B::Concept',
|
check('concept', 'template<typename Param> {key}A::B::Concept',
|
||||||
{2: 'I0EN1A1B7ConceptE'})
|
{2: 'I0EN1A1B7ConceptE'})
|
||||||
check('concept', 'template<typename A, typename B, typename ...C> Foo',
|
check('concept', 'template<typename A, typename B, typename ...C> {key}Foo',
|
||||||
{2: 'I00DpE3Foo'})
|
{2: 'I00DpE3Foo'})
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
parse('concept', 'Foo')
|
parse('concept', '{key}Foo')
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
parse('concept', 'template<typename T> template<typename U> Foo')
|
parse('concept', 'template<typename T> template<typename U> {key}Foo')
|
||||||
|
|
||||||
|
|
||||||
def test_member_definitions():
|
def test_member_definitions():
|
||||||
@ -639,95 +663,102 @@ def test_operators():
|
|||||||
check('function', 'void operator[]()', {1: "subscript-operator", 2: "ixv"})
|
check('function', 'void operator[]()', {1: "subscript-operator", 2: "ixv"})
|
||||||
|
|
||||||
|
|
||||||
|
class test_nested_name():
|
||||||
|
check('class', '{key}::A', {1: "A", 2: "1A"})
|
||||||
|
check('class', '{key}::A::B', {1: "A::B", 2: "N1A1BE"})
|
||||||
|
check('function', 'void f(::A a)', {1: "f__A", 2: "1f1A"})
|
||||||
|
check('function', 'void f(::A::B a)', {1: "f__A::B", 2: "1fN1A1BE"})
|
||||||
|
|
||||||
|
|
||||||
def test_class_definitions():
|
def test_class_definitions():
|
||||||
check('class', 'public A', {1: "A", 2: "1A"}, output='A')
|
check('class', 'public A', {1: "A", 2: "1A"}, output='{key}A')
|
||||||
check('class', 'private A', {1: "A", 2: "1A"})
|
check('class', 'private {key}A', {1: "A", 2: "1A"})
|
||||||
check('class', 'A final', {1: 'A', 2: '1A'})
|
check('class', '{key}A final', {1: 'A', 2: '1A'})
|
||||||
|
|
||||||
# test bases
|
# test bases
|
||||||
check('class', 'A', {1: "A", 2: "1A"})
|
check('class', '{key}A', {1: "A", 2: "1A"})
|
||||||
check('class', 'A::B::C', {1: "A::B::C", 2: "N1A1B1CE"})
|
check('class', '{key}A::B::C', {1: "A::B::C", 2: "N1A1B1CE"})
|
||||||
check('class', 'A : B', {1: "A", 2: "1A"})
|
check('class', '{key}A : B', {1: "A", 2: "1A"})
|
||||||
check('class', 'A : private B', {1: "A", 2: "1A"})
|
check('class', '{key}A : private B', {1: "A", 2: "1A"})
|
||||||
check('class', 'A : public B', {1: "A", 2: "1A"})
|
check('class', '{key}A : public B', {1: "A", 2: "1A"})
|
||||||
check('class', 'A : B, C', {1: "A", 2: "1A"})
|
check('class', '{key}A : B, C', {1: "A", 2: "1A"})
|
||||||
check('class', 'A : B, protected C, D', {1: "A", 2: "1A"})
|
check('class', '{key}A : B, protected C, D', {1: "A", 2: "1A"})
|
||||||
check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : private virtual B')
|
check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='{key}A : private virtual B')
|
||||||
check('class', 'A : private virtual B', {1: 'A', 2: '1A'})
|
check('class', '{key}A : private virtual B', {1: 'A', 2: '1A'})
|
||||||
check('class', 'A : B, virtual C', {1: 'A', 2: '1A'})
|
check('class', '{key}A : B, virtual C', {1: 'A', 2: '1A'})
|
||||||
check('class', 'A : public virtual B', {1: 'A', 2: '1A'})
|
check('class', '{key}A : public virtual B', {1: 'A', 2: '1A'})
|
||||||
check('class', 'A : B, C...', {1: 'A', 2: '1A'})
|
check('class', '{key}A : B, C...', {1: 'A', 2: '1A'})
|
||||||
check('class', 'A : B..., C', {1: 'A', 2: '1A'})
|
check('class', '{key}A : B..., C', {1: 'A', 2: '1A'})
|
||||||
|
|
||||||
# from #4094
|
# from #4094
|
||||||
check('class', 'template<class, class = std::void_t<>> has_var', {2: 'I00E7has_var'})
|
check('class', 'template<class, class = std::void_t<>> {key}has_var', {2: 'I00E7has_var'})
|
||||||
check('class', 'template<class T> has_var<T, std::void_t<decltype(&T::var)>>',
|
check('class', 'template<class T> {key}has_var<T, std::void_t<decltype(&T::var)>>',
|
||||||
{2: 'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'})
|
{2: 'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'})
|
||||||
|
|
||||||
|
|
||||||
check('class', 'template<typename ...Ts> T<int (*)(Ts)...>',
|
check('class', 'template<typename ...Ts> {key}T<int (*)(Ts)...>',
|
||||||
{2: 'IDpE1TIJPFi2TsEEE'})
|
{2: 'IDpE1TIJPFi2TsEEE'})
|
||||||
check('class', 'template<int... Is> T<(Is)...>',
|
check('class', 'template<int... Is> {key}T<(Is)...>',
|
||||||
{2: 'I_DpiE1TIJX(Is)EEE', 3: 'I_DpiE1TIJX2IsEEE'})
|
{2: 'I_DpiE1TIJX(Is)EEE', 3: 'I_DpiE1TIJX2IsEEE'})
|
||||||
|
|
||||||
|
|
||||||
def test_union_definitions():
|
def test_union_definitions():
|
||||||
check('union', 'A', {2: "1A"})
|
check('union', '{key}A', {2: "1A"})
|
||||||
|
|
||||||
|
|
||||||
def test_enum_definitions():
|
def test_enum_definitions():
|
||||||
check('enum', 'A', {2: "1A"})
|
check('enum', '{key}A', {2: "1A"})
|
||||||
check('enum', 'A : std::underlying_type<B>::type', {2: "1A"})
|
check('enum', '{key}A : std::underlying_type<B>::type', {2: "1A"})
|
||||||
check('enum', 'A : unsigned int', {2: "1A"})
|
check('enum', '{key}A : unsigned int', {2: "1A"})
|
||||||
check('enum', 'public A', {2: "1A"}, output='A')
|
check('enum', 'public A', {2: "1A"}, output='{key}A')
|
||||||
check('enum', 'private A', {2: "1A"})
|
check('enum', 'private {key}A', {2: "1A"})
|
||||||
|
|
||||||
check('enumerator', 'A', {2: "1A"})
|
check('enumerator', '{key}A', {2: "1A"})
|
||||||
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
check('enumerator', '{key}A = std::numeric_limits<unsigned long>::max()', {2: "1A"})
|
||||||
|
|
||||||
|
|
||||||
def test_anon_definitions():
|
def test_anon_definitions():
|
||||||
check('class', '@a', {3: "Ut1_a"})
|
check('class', '@a', {3: "Ut1_a"}, asTextOutput='class [anonymous]')
|
||||||
check('union', '@a', {3: "Ut1_a"})
|
check('union', '@a', {3: "Ut1_a"}, asTextOutput='union [anonymous]')
|
||||||
check('enum', '@a', {3: "Ut1_a"})
|
check('enum', '@a', {3: "Ut1_a"}, asTextOutput='enum [anonymous]')
|
||||||
check('class', '@1', {3: "Ut1_1"})
|
check('class', '@1', {3: "Ut1_1"}, asTextOutput='class [anonymous]')
|
||||||
check('class', '@a::A', {3: "NUt1_a1AE"})
|
check('class', '@a::A', {3: "NUt1_a1AE"}, asTextOutput='class [anonymous]::A')
|
||||||
|
|
||||||
|
|
||||||
def test_templates():
|
def test_templates():
|
||||||
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> A<T>")
|
check('class', "A<T>", {2: "IE1AI1TE"}, output="template<> {key}A<T>")
|
||||||
# first just check which objects support templating
|
# first just check which objects support templating
|
||||||
check('class', "template<> A", {2: "IE1A"})
|
check('class', "template<> {key}A", {2: "IE1A"})
|
||||||
check('function', "template<> void A()", {2: "IE1Av", 4: "IE1Avv"})
|
check('function', "template<> void A()", {2: "IE1Av", 4: "IE1Avv"})
|
||||||
check('member', "template<> A a", {2: "IE1a"})
|
check('member', "template<> A a", {2: "IE1a"})
|
||||||
check('type', "template<> a = A", {2: "IE1a"})
|
check('type', "template<> {key}a = A", {2: "IE1a"}, key='using')
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
parse('enum', "template<> A")
|
parse('enum', "template<> A")
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
parse('enumerator', "template<> A")
|
parse('enumerator', "template<> A")
|
||||||
# then all the real tests
|
# then all the real tests
|
||||||
check('class', "template<typename T1, typename T2> A", {2: "I00E1A"})
|
check('class', "template<typename T1, typename T2> {key}A", {2: "I00E1A"})
|
||||||
check('type', "template<> a", {2: "IE1a"})
|
check('type', "template<> {key}a", {2: "IE1a"}, key='using')
|
||||||
|
|
||||||
check('class', "template<typename T> A", {2: "I0E1A"})
|
check('class', "template<typename T> {key}A", {2: "I0E1A"})
|
||||||
check('class', "template<class T> A", {2: "I0E1A"})
|
check('class', "template<class T> {key}A", {2: "I0E1A"})
|
||||||
check('class', "template<typename ...T> A", {2: "IDpE1A"})
|
check('class', "template<typename ...T> {key}A", {2: "IDpE1A"})
|
||||||
check('class', "template<typename...> A", {2: "IDpE1A"})
|
check('class', "template<typename...> {key}A", {2: "IDpE1A"})
|
||||||
check('class', "template<typename = Test> A", {2: "I0E1A"})
|
check('class', "template<typename = Test> {key}A", {2: "I0E1A"})
|
||||||
check('class', "template<typename T = Test> A", {2: "I0E1A"})
|
check('class', "template<typename T = Test> {key}A", {2: "I0E1A"})
|
||||||
|
|
||||||
check('class', "template<template<typename> typename T> A", {2: "II0E0E1A"})
|
check('class', "template<template<typename> typename T> {key}A", {2: "II0E0E1A"})
|
||||||
check('class', "template<template<typename> typename> A", {2: "II0E0E1A"})
|
check('class', "template<template<typename> typename> {key}A", {2: "II0E0E1A"})
|
||||||
check('class', "template<template<typename> typename ...T> A", {2: "II0EDpE1A"})
|
check('class', "template<template<typename> typename ...T> {key}A", {2: "II0EDpE1A"})
|
||||||
check('class', "template<template<typename> typename...> A", {2: "II0EDpE1A"})
|
check('class', "template<template<typename> typename...> {key}A", {2: "II0EDpE1A"})
|
||||||
|
|
||||||
check('class', "template<int> A", {2: "I_iE1A"})
|
check('class', "template<int> {key}A", {2: "I_iE1A"})
|
||||||
check('class', "template<int T> A", {2: "I_iE1A"})
|
check('class', "template<int T> {key}A", {2: "I_iE1A"})
|
||||||
check('class', "template<int... T> A", {2: "I_DpiE1A"})
|
check('class', "template<int... T> {key}A", {2: "I_DpiE1A"})
|
||||||
check('class', "template<int T = 42> A", {2: "I_iE1A"})
|
check('class', "template<int T = 42> {key}A", {2: "I_iE1A"})
|
||||||
check('class', "template<int = 42> A", {2: "I_iE1A"})
|
check('class', "template<int = 42> {key}A", {2: "I_iE1A"})
|
||||||
|
|
||||||
check('class', "template<> A<NS::B<>>", {2: "IE1AIN2NS1BIEEE"})
|
check('class', "template<> {key}A<NS::B<>>", {2: "IE1AIN2NS1BIEEE"})
|
||||||
|
|
||||||
# from #2058
|
# from #2058
|
||||||
check('function',
|
check('function',
|
||||||
@ -747,21 +778,21 @@ def test_templates():
|
|||||||
parse('enum', 'abc::ns::foo{id_0, id_1, id_2} A')
|
parse('enum', 'abc::ns::foo{id_0, id_1, id_2} A')
|
||||||
with pytest.raises(DefinitionError):
|
with pytest.raises(DefinitionError):
|
||||||
parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
|
parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
|
||||||
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar',
|
check('class', 'abc::ns::foo{{id_0, id_1, id_2}} {key}xyz::bar',
|
||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
||||||
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar',
|
check('class', 'abc::ns::foo{{id_0, id_1, ...id_2}} {key}xyz::bar',
|
||||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
||||||
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar<id_0, id_1, id_2>',
|
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_2EEN3xyz3barI4id_04id_14id_2EE'})
|
||||||
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar<id_0, id_1, id_2...>',
|
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_2EEN3xyz3barI4id_04id_1Dp4id_2EE'})
|
||||||
|
|
||||||
check('class', 'template<> Concept{U} A<int>::B', {2: 'IEI0EX7ConceptI1UEEN1AIiE1BE'})
|
check('class', 'template<> Concept{{U}} {key}A<int>::B', {2: 'IEI0EX7ConceptI1UEEN1AIiE1BE'})
|
||||||
|
|
||||||
check('type', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar = ghi::qux',
|
check('type', 'abc::ns::foo{{id_0, id_1, id_2}} {key}xyz::bar = ghi::qux',
|
||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}, key='using')
|
||||||
check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
|
check('type', 'abc::ns::foo{{id_0, id_1, ...id_2}} {key}xyz::bar = ghi::qux',
|
||||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}, key='using')
|
||||||
check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
|
check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
|
||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv',
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv',
|
||||||
4: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEvv'})
|
4: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEvv'})
|
||||||
@ -772,8 +803,8 @@ def test_templates():
|
|||||||
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
{2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
|
||||||
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
|
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
|
||||||
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
{2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
|
||||||
check('concept', 'Iterator{T, U} Another', {2: 'I00EX8IteratorI1T1UEE7Another'})
|
check('concept', 'Iterator{{T, U}} {key}Another', {2: 'I00EX8IteratorI1T1UEE7Another'})
|
||||||
check('concept', 'template<typename ...Pack> Numerics = (... && Numeric<Pack>)',
|
check('concept', 'template<typename ...Pack> {key}Numerics = (... && Numeric<Pack>)',
|
||||||
{2: 'IDpE8Numerics'})
|
{2: 'IDpE8Numerics'})
|
||||||
|
|
||||||
# explicit specializations of members
|
# explicit specializations of members
|
||||||
@ -785,7 +816,7 @@ def test_templates():
|
|||||||
output='template<> template<> int A<int>::B<int>::b') # same as above
|
output='template<> template<> int A<int>::B<int>::b') # same as above
|
||||||
|
|
||||||
# defaulted constrained type parameters
|
# defaulted constrained type parameters
|
||||||
check('type', 'template<C T = int&> A', {2: 'I_1CE1A'})
|
check('type', 'template<C T = int&> {key}A', {2: 'I_1CE1A'}, key='using')
|
||||||
|
|
||||||
|
|
||||||
def test_template_args():
|
def test_template_args():
|
||||||
@ -797,9 +828,10 @@ def test_template_args():
|
|||||||
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE",
|
3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE",
|
||||||
4: "I0E5allowvP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
4: "I0E5allowvP1FN4funcI1F1BXne1GL1EEE4typeE"})
|
||||||
# from #3542
|
# from #3542
|
||||||
check('type', "template<typename T> "
|
check('type', "template<typename T> {key}"
|
||||||
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
|
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
|
||||||
{2: "I0E21enable_if_not_array_t"})
|
{2: "I0E21enable_if_not_array_t"},
|
||||||
|
key='using')
|
||||||
|
|
||||||
|
|
||||||
def test_initializers():
|
def test_initializers():
|
||||||
|
Loading…
Reference in New Issue
Block a user