2020-03-05 11:06:15 -06:00
|
|
|
"""Tests the C Domain"""
|
2021-01-11 01:16:06 -06:00
|
|
|
|
2024-11-22 15:54:26 -06:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2021-11-30 14:57:30 -06:00
|
|
|
import itertools
|
2024-08-15 15:42:25 -05:00
|
|
|
import xml.etree.ElementTree as ET
|
2021-01-11 01:16:06 -06:00
|
|
|
import zlib
|
2024-11-22 15:54:26 -06:00
|
|
|
from typing import TYPE_CHECKING
|
2020-10-13 05:30:13 -05:00
|
|
|
|
2020-11-11 05:00:27 -06:00
|
|
|
import pytest
|
|
|
|
|
2020-03-05 11:06:15 -06:00
|
|
|
from sphinx import addnodes
|
2023-05-11 08:28:57 -05:00
|
|
|
from sphinx.addnodes import (
|
|
|
|
desc,
|
|
|
|
desc_content,
|
|
|
|
desc_name,
|
|
|
|
desc_parameter,
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_sig_name,
|
|
|
|
desc_sig_space,
|
|
|
|
desc_signature,
|
|
|
|
desc_signature_line,
|
|
|
|
pending_xref,
|
|
|
|
)
|
2025-01-06 18:15:11 -06:00
|
|
|
from sphinx.domains.c._ids import _id_prefix, _macro_keywords, _max_id
|
2024-01-18 21:21:03 -06:00
|
|
|
from sphinx.domains.c._parser import DefinitionParser
|
|
|
|
from sphinx.domains.c._symbol import Symbol
|
2024-07-22 07:32:44 -05:00
|
|
|
from sphinx.ext.intersphinx import load_mappings, validate_intersphinx_mapping
|
2020-03-05 11:06:15 -06:00
|
|
|
from sphinx.testing import restructuredtext
|
|
|
|
from sphinx.testing.util import assert_node
|
2024-01-18 21:21:03 -06:00
|
|
|
from sphinx.util.cfamily import DefinitionError
|
2023-05-11 08:28:57 -05:00
|
|
|
from sphinx.writers.text import STDINDENT
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2024-11-22 15:54:26 -06:00
|
|
|
if TYPE_CHECKING:
|
|
|
|
from io import StringIO
|
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2021-06-16 15:08:30 -05:00
|
|
|
class Config:
|
2024-08-11 08:58:56 -05:00
|
|
|
c_id_attributes = ['id_attr', 'LIGHTGBM_C_EXPORT']
|
|
|
|
c_paren_attributes = ['paren_attr']
|
2025-01-06 18:15:11 -06:00
|
|
|
c_extra_keywords = _macro_keywords
|
2021-06-16 15:08:30 -05:00
|
|
|
|
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
def parse(name, string):
|
2020-04-13 03:09:41 -05:00
|
|
|
parser = DefinitionParser(string, location=None, config=Config())
|
2020-03-12 10:59:30 -05:00
|
|
|
parser.allowFallbackExpressionParsing = False
|
|
|
|
ast = parser.parse_declaration(name, name)
|
|
|
|
parser.assert_end()
|
|
|
|
return ast
|
|
|
|
|
|
|
|
|
2024-12-09 09:10:18 -06:00
|
|
|
def _check(name, input, id_dict, output, key, as_text_output):
|
2020-05-16 05:40:20 -05:00
|
|
|
if key is None:
|
|
|
|
key = name
|
|
|
|
key += ' '
|
2024-10-18 21:07:28 -05:00
|
|
|
if name in {'function', 'member'}:
|
2024-12-09 09:10:18 -06:00
|
|
|
input_actual = input
|
|
|
|
output_ast = output
|
|
|
|
output_as_text = output
|
2020-05-16 05:40:20 -05:00
|
|
|
else:
|
2024-12-09 09:10:18 -06:00
|
|
|
input_actual = input.format(key='')
|
|
|
|
output_ast = output.format(key='')
|
|
|
|
output_as_text = output.format(key=key)
|
|
|
|
if as_text_output is not None:
|
|
|
|
output_as_text = as_text_output
|
2020-05-16 05:40:20 -05:00
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
# first a simple check of the AST
|
2024-12-09 09:10:18 -06:00
|
|
|
ast = parse(name, input_actual)
|
2020-03-12 10:59:30 -05:00
|
|
|
res = str(ast)
|
2024-12-09 09:10:18 -06:00
|
|
|
if res != output_ast:
|
2024-03-14 05:05:40 -05:00
|
|
|
print()
|
2024-08-11 08:58:56 -05:00
|
|
|
print('Input: ', input)
|
|
|
|
print('Result: ', res)
|
2024-12-09 09:10:18 -06:00
|
|
|
print('Expected: ', output_ast)
|
2023-08-13 14:07:28 -05:00
|
|
|
raise DefinitionError
|
2024-12-09 09:10:18 -06:00
|
|
|
root_symbol = Symbol(None, None, None, None, None)
|
|
|
|
symbol = root_symbol.add_declaration(ast, docname='TestDoc', line=42)
|
|
|
|
parent_node = addnodes.desc()
|
2020-03-12 10:59:30 -05:00
|
|
|
signode = addnodes.desc_signature(input, '')
|
2024-12-09 09:10:18 -06:00
|
|
|
parent_node += signode
|
2020-03-12 10:59:30 -05:00
|
|
|
ast.describe_signature(signode, 'lastIsName', symbol, options={})
|
2024-12-09 09:10:18 -06:00
|
|
|
res_as_text = parent_node.astext()
|
|
|
|
if res_as_text != output_as_text:
|
2024-03-14 05:05:40 -05:00
|
|
|
print()
|
2024-08-11 08:58:56 -05:00
|
|
|
print('Input: ', input)
|
2024-12-09 09:10:18 -06:00
|
|
|
print('astext(): ', res_as_text)
|
|
|
|
print('Expected: ', output_as_text)
|
2023-08-13 14:07:28 -05:00
|
|
|
raise DefinitionError
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2024-12-09 09:10:18 -06:00
|
|
|
id_expected = [None]
|
2020-03-12 10:59:30 -05:00
|
|
|
for i in range(1, _max_id + 1):
|
2024-12-09 09:10:18 -06:00
|
|
|
if i in id_dict:
|
|
|
|
id_expected.append(id_dict[i])
|
2020-03-12 10:59:30 -05:00
|
|
|
else:
|
2024-12-09 09:10:18 -06:00
|
|
|
id_expected.append(id_expected[i - 1])
|
|
|
|
id_actual = [None]
|
2020-03-12 10:59:30 -05:00
|
|
|
for i in range(1, _max_id + 1):
|
2020-11-15 02:03:26 -06:00
|
|
|
# try:
|
2020-03-12 10:59:30 -05:00
|
|
|
id = ast.get_id(version=i)
|
|
|
|
assert id is not None
|
2024-12-09 09:10:18 -06:00
|
|
|
id_actual.append(id[len(_id_prefix[i]) :])
|
2020-11-15 02:03:26 -06:00
|
|
|
# except NoOldIdError:
|
2024-12-09 09:10:18 -06:00
|
|
|
# id_actual.append(None)
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
res = [True]
|
|
|
|
for i in range(1, _max_id + 1):
|
2024-12-09 09:10:18 -06:00
|
|
|
res.append(id_expected[i] == id_actual[i])
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
if not all(res):
|
2024-08-11 08:58:56 -05:00
|
|
|
print('input: %s' % input.rjust(20))
|
2020-03-12 10:59:30 -05:00
|
|
|
for i in range(1, _max_id + 1):
|
|
|
|
if res[i]:
|
|
|
|
continue
|
2024-08-11 08:58:56 -05:00
|
|
|
print('Error in id version %d.' % i)
|
2024-12-09 09:10:18 -06:00
|
|
|
print('result: %s' % id_actual[i])
|
|
|
|
print('expected: %s' % id_expected[i])
|
|
|
|
# print(root_symbol.dump(0))
|
2023-08-13 14:07:28 -05:00
|
|
|
raise DefinitionError
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2024-12-09 09:10:18 -06:00
|
|
|
def check(name, input, id_dict, output=None, key=None, as_text_output=None):
|
2020-04-24 04:38:22 -05:00
|
|
|
if output is None:
|
|
|
|
output = input
|
|
|
|
# First, check without semicolon
|
2024-12-09 09:10:18 -06:00
|
|
|
_check(name, input, id_dict, output, key, as_text_output)
|
2020-04-24 04:38:22 -05:00
|
|
|
if name != 'macro':
|
|
|
|
# Second, check with semicolon
|
2024-08-11 08:58:56 -05:00
|
|
|
_check(
|
|
|
|
name,
|
|
|
|
input + ' ;',
|
2024-12-09 09:10:18 -06:00
|
|
|
id_dict,
|
2024-08-11 08:58:56 -05:00
|
|
|
output + ';',
|
|
|
|
key,
|
2024-12-09 09:10:18 -06:00
|
|
|
as_text_output + ';' if as_text_output is not None else None,
|
2024-08-11 08:58:56 -05:00
|
|
|
)
|
2020-04-24 04:38:22 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_expressions():
|
2024-12-09 09:10:18 -06:00
|
|
|
def expr_check(expr, output=None):
|
2020-04-13 03:09:41 -05:00
|
|
|
parser = DefinitionParser(expr, location=None, config=Config())
|
2020-03-14 12:18:10 -05:00
|
|
|
parser.allowFallbackExpressionParsing = False
|
|
|
|
ast = parser.parse_expression()
|
|
|
|
parser.assert_end()
|
|
|
|
# first a simple check of the AST
|
|
|
|
if output is None:
|
|
|
|
output = expr
|
|
|
|
res = str(ast)
|
|
|
|
if res != output:
|
2024-03-14 05:05:40 -05:00
|
|
|
print()
|
2024-08-11 08:58:56 -05:00
|
|
|
print('Input: ', input)
|
|
|
|
print('Result: ', res)
|
|
|
|
print('Expected: ', output)
|
2023-08-13 14:07:28 -05:00
|
|
|
raise DefinitionError
|
2024-12-09 09:10:18 -06:00
|
|
|
display_string = ast.get_display_string()
|
|
|
|
if res != display_string:
|
2020-06-02 11:14:04 -05:00
|
|
|
# note: if the expression contains an anon name then this will trigger a falsely
|
2024-03-14 05:05:40 -05:00
|
|
|
print()
|
2024-08-11 08:58:56 -05:00
|
|
|
print('Input: ', expr)
|
|
|
|
print('Result: ', res)
|
2024-12-09 09:10:18 -06:00
|
|
|
print('Display: ', display_string)
|
2023-08-13 14:07:28 -05:00
|
|
|
raise DefinitionError
|
2020-06-02 11:14:04 -05:00
|
|
|
|
2020-03-14 12:18:10 -05:00
|
|
|
# type expressions
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('int*')
|
|
|
|
expr_check('int *const*')
|
|
|
|
expr_check('int *volatile*')
|
|
|
|
expr_check('int *restrict*')
|
|
|
|
expr_check('int *(*)(double)')
|
|
|
|
expr_check('const int*')
|
|
|
|
expr_check('__int64')
|
|
|
|
expr_check('unsigned __int64')
|
2020-03-14 12:18:10 -05:00
|
|
|
|
|
|
|
# actual expressions
|
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
# primary
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('true')
|
|
|
|
expr_check('false')
|
2024-08-11 08:58:56 -05:00
|
|
|
ints = [
|
|
|
|
'5',
|
|
|
|
'0',
|
|
|
|
'075',
|
|
|
|
'0x0123456789ABCDEF',
|
|
|
|
'0XF',
|
|
|
|
'0b1',
|
|
|
|
'0B1',
|
|
|
|
"0b0'1'0",
|
|
|
|
"00'1'2",
|
|
|
|
"0x0'1'2",
|
|
|
|
"1'2'3",
|
|
|
|
]
|
2024-12-09 09:10:18 -06:00
|
|
|
unsigned_suffix = ['', 'u', 'U']
|
|
|
|
long_suffix = ['', 'l', 'L', 'll', 'LL']
|
2020-03-12 10:59:30 -05:00
|
|
|
for i in ints:
|
2024-12-09 09:10:18 -06:00
|
|
|
for u in unsigned_suffix:
|
|
|
|
for l in long_suffix:
|
2020-03-12 10:59:30 -05:00
|
|
|
expr = i + u + l
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check(expr)
|
2020-03-12 10:59:30 -05:00
|
|
|
expr = i + l + u
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check(expr)
|
2024-10-18 21:07:28 -05:00
|
|
|
for suffix in ('', 'f', 'F', 'l', 'L'):
|
|
|
|
for e in (
|
2024-08-11 08:58:56 -05:00
|
|
|
'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',
|
|
|
|
"1'2'3e7'8'9",
|
|
|
|
"1'2'3.e7'8'9",
|
|
|
|
".4'5'6e7'8'9",
|
|
|
|
"1'2'3.4'5'6e7'8'9",
|
2024-10-18 21:07:28 -05:00
|
|
|
):
|
2020-03-12 10:59:30 -05:00
|
|
|
expr = e + suffix
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check(expr)
|
2024-10-18 21:07:28 -05:00
|
|
|
for e in (
|
2024-08-11 08:58:56 -05:00
|
|
|
'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'Cp1'2'3",
|
|
|
|
"A'B'C.p1'2'3",
|
|
|
|
".D'E'Fp1'2'3",
|
|
|
|
"A'B'C.D'E'Fp1'2'3",
|
2024-10-18 21:07:28 -05:00
|
|
|
):
|
2024-08-11 08:58:56 -05:00
|
|
|
expr = '0x' + e + suffix
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check(expr)
|
|
|
|
expr_check('"abc\\"cba"') # string
|
2020-03-12 10:59:30 -05:00
|
|
|
# character literals
|
2024-10-18 21:07:28 -05:00
|
|
|
for p in ('', 'u8', 'u', 'U', 'L'):
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check(p + "'a'")
|
|
|
|
expr_check(p + "'\\n'")
|
|
|
|
expr_check(p + "'\\012'")
|
|
|
|
expr_check(p + "'\\0'")
|
|
|
|
expr_check(p + "'\\x0a'")
|
|
|
|
expr_check(p + "'\\x0A'")
|
|
|
|
expr_check(p + "'\\u0a42'")
|
|
|
|
expr_check(p + "'\\u0A42'")
|
|
|
|
expr_check(p + "'\\U0001f34c'")
|
|
|
|
expr_check(p + "'\\U0001F34C'")
|
|
|
|
|
|
|
|
expr_check('(5)')
|
|
|
|
expr_check('C')
|
2020-03-12 10:59:30 -05:00
|
|
|
# postfix
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('A(2)')
|
|
|
|
expr_check('A[2]')
|
|
|
|
expr_check('a.b.c')
|
|
|
|
expr_check('a->b->c')
|
|
|
|
expr_check('i++')
|
|
|
|
expr_check('i--')
|
2020-03-12 10:59:30 -05:00
|
|
|
# unary
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('++5')
|
|
|
|
expr_check('--5')
|
|
|
|
expr_check('*5')
|
|
|
|
expr_check('&5')
|
|
|
|
expr_check('+5')
|
|
|
|
expr_check('-5')
|
|
|
|
expr_check('!5')
|
|
|
|
expr_check('not 5')
|
|
|
|
expr_check('~5')
|
|
|
|
expr_check('compl 5')
|
|
|
|
expr_check('sizeof(T)')
|
|
|
|
expr_check('sizeof -42')
|
|
|
|
expr_check('alignof(T)')
|
2020-03-12 10:59:30 -05:00
|
|
|
# cast
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('(int)2')
|
2020-03-12 10:59:30 -05:00
|
|
|
# binary op
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 || 42')
|
|
|
|
expr_check('5 or 42')
|
|
|
|
expr_check('5 && 42')
|
|
|
|
expr_check('5 and 42')
|
|
|
|
expr_check('5 | 42')
|
|
|
|
expr_check('5 bitor 42')
|
|
|
|
expr_check('5 ^ 42')
|
|
|
|
expr_check('5 xor 42')
|
|
|
|
expr_check('5 & 42')
|
|
|
|
expr_check('5 bitand 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['==', '!=']
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 == 42')
|
|
|
|
expr_check('5 != 42')
|
|
|
|
expr_check('5 not_eq 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['<=', '>=', '<', '>']
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 <= 42')
|
|
|
|
expr_check('5 >= 42')
|
|
|
|
expr_check('5 < 42')
|
|
|
|
expr_check('5 > 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['<<', '>>']
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 << 42')
|
|
|
|
expr_check('5 >> 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['+', '-']
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 + 42')
|
|
|
|
expr_check('5 - 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['*', '/', '%']
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('5 * 42')
|
|
|
|
expr_check('5 / 42')
|
|
|
|
expr_check('5 % 42')
|
2020-03-12 10:59:30 -05:00
|
|
|
# ['.*', '->*']
|
|
|
|
# conditional
|
|
|
|
# TODO
|
|
|
|
# assignment
|
2024-12-09 09:10:18 -06:00
|
|
|
expr_check('a = 5')
|
|
|
|
expr_check('a *= 5')
|
|
|
|
expr_check('a /= 5')
|
|
|
|
expr_check('a %= 5')
|
|
|
|
expr_check('a += 5')
|
|
|
|
expr_check('a -= 5')
|
|
|
|
expr_check('a >>= 5')
|
|
|
|
expr_check('a <<= 5')
|
|
|
|
expr_check('a &= 5')
|
|
|
|
expr_check('a and_eq 5')
|
|
|
|
expr_check('a ^= 5')
|
|
|
|
expr_check('a xor_eq 5')
|
|
|
|
expr_check('a |= 5')
|
|
|
|
expr_check('a or_eq 5')
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-08-14 08:59:11 -05:00
|
|
|
def test_domain_c_ast_fundamental_types():
|
|
|
|
def types():
|
|
|
|
def signed(t):
|
|
|
|
yield t
|
2021-08-15 14:31:31 -05:00
|
|
|
yield 'signed ' + t
|
|
|
|
yield 'unsigned ' + t
|
2021-08-14 08:59:11 -05:00
|
|
|
|
|
|
|
# integer types
|
|
|
|
# -------------
|
|
|
|
yield 'void'
|
|
|
|
yield from ('_Bool', 'bool')
|
|
|
|
yield from signed('char')
|
|
|
|
yield from signed('short')
|
2021-08-15 14:31:31 -05:00
|
|
|
yield from signed('short int')
|
2021-08-14 08:59:11 -05:00
|
|
|
yield from signed('int')
|
|
|
|
yield from ('signed', 'unsigned')
|
|
|
|
yield from signed('long')
|
|
|
|
yield from signed('long int')
|
|
|
|
yield from signed('long long')
|
|
|
|
yield from signed('long long int')
|
|
|
|
yield from ('__int128', '__uint128')
|
|
|
|
# extensions
|
|
|
|
for t in ('__int8', '__int16', '__int32', '__int64', '__int128'):
|
|
|
|
yield from signed(t)
|
|
|
|
|
|
|
|
# floating point types
|
|
|
|
# --------------------
|
|
|
|
yield from ('_Decimal32', '_Decimal64', '_Decimal128')
|
|
|
|
for f in ('float', 'double', 'long double'):
|
|
|
|
yield f
|
2024-08-11 08:58:56 -05:00
|
|
|
yield from (f + ' _Complex', f + ' complex')
|
|
|
|
yield from ('_Complex ' + f, 'complex ' + f)
|
|
|
|
yield from ('_Imaginary ' + f, 'imaginary ' + f)
|
2021-08-14 08:59:11 -05:00
|
|
|
# extensions
|
|
|
|
# https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html#Floating-Types
|
2024-08-11 08:58:56 -05:00
|
|
|
yield from (
|
|
|
|
'__float80',
|
|
|
|
'_Float64x',
|
|
|
|
'__float128',
|
|
|
|
'_Float128',
|
|
|
|
'__ibm128',
|
|
|
|
)
|
2021-08-14 08:59:11 -05:00
|
|
|
# https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html#Half-Precision
|
|
|
|
yield '__fp16'
|
|
|
|
|
|
|
|
# fixed-point types (extension)
|
|
|
|
# -----------------------------
|
|
|
|
# https://gcc.gnu.org/onlinedocs/gcc/Fixed-Point.html#Fixed-Point
|
2021-08-15 14:31:31 -05:00
|
|
|
for sat in ('', '_Sat '):
|
2021-08-14 09:03:54 -05:00
|
|
|
for t in ('_Fract', 'fract', '_Accum', 'accum'):
|
2021-08-15 14:31:31 -05:00
|
|
|
for size in ('short ', '', 'long ', 'long long '):
|
2021-08-14 08:59:11 -05:00
|
|
|
for tt in signed(size + t):
|
|
|
|
yield sat + tt
|
|
|
|
|
|
|
|
for t in types():
|
2024-08-11 08:58:56 -05:00
|
|
|
input = '{key}%s foo' % t
|
2021-08-15 14:31:31 -05:00
|
|
|
output = ' '.join(input.split())
|
|
|
|
check('type', input, {1: 'foo'}, key='typedef', output=output)
|
2021-11-30 14:57:30 -06:00
|
|
|
if ' ' in t:
|
|
|
|
# try permutations of all components
|
|
|
|
tcs = t.split()
|
|
|
|
for p in itertools.permutations(tcs):
|
2024-08-11 08:58:56 -05:00
|
|
|
input = '{key}%s foo' % ' '.join(p)
|
2021-11-30 14:57:30 -06:00
|
|
|
output = ' '.join(input.split())
|
2024-08-11 08:58:56 -05:00
|
|
|
check('type', input, {1: 'foo'}, key='typedef', output=output)
|
2021-08-14 08:59:11 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_type_definitions():
|
2024-08-11 08:58:56 -05:00
|
|
|
check('type', '{key}T', {1: 'T'})
|
|
|
|
|
|
|
|
check('type', '{key}bool *b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *const b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *const *b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *volatile *b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *restrict *b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *volatile const b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *volatile const b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool *volatile const *b', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}bool b[]', {1: 'b'}, key='typedef')
|
|
|
|
check('type', '{key}long long int foo', {1: 'foo'}, key='typedef')
|
2020-03-12 10:59:30 -05:00
|
|
|
# test decl specs on right
|
2024-08-11 08:58:56 -05:00
|
|
|
check('type', '{key}bool const b', {1: 'b'}, key='typedef')
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
# from breathe#267 (named function parameters for function pointers
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'type',
|
|
|
|
'{key}void (*gpio_callback_t)(struct device *port, uint32_t pin)',
|
|
|
|
{1: 'gpio_callback_t'},
|
|
|
|
key='typedef',
|
|
|
|
)
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_macro_definitions():
|
2020-03-12 10:59:30 -05:00
|
|
|
check('macro', 'M', {1: 'M'})
|
|
|
|
check('macro', 'M()', {1: 'M'})
|
|
|
|
check('macro', 'M(arg)', {1: 'M'})
|
|
|
|
check('macro', 'M(arg1, arg2)', {1: 'M'})
|
|
|
|
check('macro', 'M(arg1, arg2, arg3)', {1: 'M'})
|
|
|
|
check('macro', 'M(...)', {1: 'M'})
|
|
|
|
check('macro', 'M(arg, ...)', {1: 'M'})
|
|
|
|
check('macro', 'M(arg1, arg2, ...)', {1: 'M'})
|
|
|
|
check('macro', 'M(arg1, arg2, arg3, ...)', {1: 'M'})
|
2020-07-27 12:35:10 -05:00
|
|
|
# GNU extension
|
|
|
|
check('macro', 'M(arg1, arg2, arg3...)', {1: 'M'})
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
check('macro', 'M(arg1, arg2..., arg3)', {1: 'M'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_member_definitions():
|
2020-03-12 10:59:30 -05:00
|
|
|
check('member', 'void a', {1: 'a'})
|
|
|
|
check('member', '_Bool a', {1: 'a'})
|
|
|
|
check('member', 'bool a', {1: 'a'})
|
|
|
|
check('member', 'char a', {1: 'a'})
|
|
|
|
check('member', 'int a', {1: 'a'})
|
|
|
|
check('member', 'float a', {1: 'a'})
|
|
|
|
check('member', 'double a', {1: 'a'})
|
|
|
|
|
|
|
|
check('member', 'unsigned long a', {1: 'a'})
|
2020-03-14 18:08:27 -05:00
|
|
|
check('member', '__int64 a', {1: 'a'})
|
|
|
|
check('member', 'unsigned __int64 a', {1: 'a'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
check('member', 'int .a', {1: 'a'})
|
|
|
|
|
|
|
|
check('member', 'int *a', {1: 'a'})
|
|
|
|
check('member', 'int **a', {1: 'a'})
|
|
|
|
check('member', 'const int a', {1: 'a'})
|
|
|
|
check('member', 'volatile int a', {1: 'a'})
|
|
|
|
check('member', 'restrict int a', {1: 'a'})
|
|
|
|
check('member', 'volatile const int a', {1: 'a'})
|
|
|
|
check('member', 'restrict const int a', {1: 'a'})
|
|
|
|
check('member', 'restrict volatile int a', {1: 'a'})
|
|
|
|
check('member', 'restrict volatile const int a', {1: 'a'})
|
|
|
|
|
|
|
|
check('member', 'T t', {1: 't'})
|
|
|
|
|
|
|
|
check('member', 'int a[]', {1: 'a'})
|
|
|
|
|
|
|
|
check('member', 'int (*p)[]', {1: 'p'})
|
|
|
|
|
|
|
|
check('member', 'int a[42]', {1: 'a'})
|
|
|
|
check('member', 'int a = 42', {1: 'a'})
|
|
|
|
check('member', 'T a = {}', {1: 'a'})
|
|
|
|
check('member', 'T a = {1}', {1: 'a'})
|
|
|
|
check('member', 'T a = {1, 2}', {1: 'a'})
|
|
|
|
check('member', 'T a = {1, 2, 3}', {1: 'a'})
|
|
|
|
|
|
|
|
# test from issue #1539
|
|
|
|
check('member', 'CK_UTF8CHAR model[16]', {1: 'model'})
|
|
|
|
|
|
|
|
check('member', 'auto int a', {1: 'a'})
|
|
|
|
check('member', 'register int a', {1: 'a'})
|
|
|
|
check('member', 'extern int a', {1: 'a'})
|
|
|
|
check('member', 'static int a', {1: 'a'})
|
|
|
|
|
|
|
|
check('member', 'thread_local int a', {1: 'a'})
|
|
|
|
check('member', '_Thread_local int a', {1: 'a'})
|
|
|
|
check('member', 'extern thread_local int a', {1: 'a'})
|
2024-08-11 08:58:56 -05:00
|
|
|
check('member', 'thread_local extern int a', {1: 'a'}, 'extern thread_local int a')
|
2020-03-12 10:59:30 -05:00
|
|
|
check('member', 'static thread_local int a', {1: 'a'})
|
2024-08-11 08:58:56 -05:00
|
|
|
check('member', 'thread_local static int a', {1: 'a'}, 'static thread_local int a')
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
check('member', 'int b : 3', {1: 'b'})
|
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_function_definitions():
|
2020-03-12 10:59:30 -05:00
|
|
|
check('function', 'void f()', {1: 'f'})
|
|
|
|
check('function', 'void f(int)', {1: 'f'})
|
|
|
|
check('function', 'void f(int i)', {1: 'f'})
|
|
|
|
check('function', 'void f(int i, int j)', {1: 'f'})
|
|
|
|
check('function', 'void f(...)', {1: 'f'})
|
|
|
|
check('function', 'void f(int i, ...)', {1: 'f'})
|
|
|
|
check('function', 'void f(struct T)', {1: 'f'})
|
|
|
|
check('function', 'void f(struct T t)', {1: 'f'})
|
|
|
|
check('function', 'void f(union T)', {1: 'f'})
|
|
|
|
check('function', 'void f(union T t)', {1: 'f'})
|
|
|
|
check('function', 'void f(enum T)', {1: 'f'})
|
|
|
|
check('function', 'void f(enum T t)', {1: 'f'})
|
|
|
|
|
|
|
|
# test from issue #1539
|
|
|
|
check('function', 'void f(A x[])', {1: 'f'})
|
|
|
|
|
|
|
|
# test from issue #2377
|
|
|
|
check('function', 'void (*signal(int sig, void (*func)(int)))(int)', {1: 'signal'})
|
|
|
|
|
|
|
|
check('function', 'extern void f()', {1: 'f'})
|
|
|
|
check('function', 'static void f()', {1: 'f'})
|
|
|
|
check('function', 'inline void f()', {1: 'f'})
|
|
|
|
|
|
|
|
# tests derived from issue #1753 (skip to keep sanity)
|
2024-08-11 08:58:56 -05:00
|
|
|
check('function', 'void f(float *q(double))', {1: 'f'})
|
|
|
|
check('function', 'void f(float *(*q)(double))', {1: 'f'})
|
|
|
|
check('function', 'void f(float (*q)(double))', {1: 'f'})
|
|
|
|
check('function', 'int (*f(double d))(float)', {1: 'f'})
|
|
|
|
check('function', 'int (*f(bool b))[5]', {1: 'f'})
|
|
|
|
check('function', 'void f(int *const p)', {1: 'f'})
|
|
|
|
check('function', 'void f(int *volatile const p)', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
# from breathe#223
|
|
|
|
check('function', 'void f(struct E e)', {1: 'f'})
|
|
|
|
check('function', 'void f(enum E e)', {1: 'f'})
|
|
|
|
check('function', 'void f(union E e)', {1: 'f'})
|
|
|
|
|
2020-04-25 12:37:21 -05:00
|
|
|
# array declarators
|
|
|
|
check('function', 'void f(int arr[])', {1: 'f'})
|
|
|
|
check('function', 'void f(int arr[*])', {1: 'f'})
|
|
|
|
cvrs = ['', 'const', 'volatile', 'restrict', 'restrict volatile const']
|
|
|
|
for cvr in cvrs:
|
|
|
|
space = ' ' if len(cvr) != 0 else ''
|
2022-10-17 09:54:59 -05:00
|
|
|
check('function', f'void f(int arr[{cvr}*])', {1: 'f'})
|
|
|
|
check('function', f'void f(int arr[{cvr}])', {1: 'f'})
|
|
|
|
check('function', f'void f(int arr[{cvr}{space}42])', {1: 'f'})
|
|
|
|
check('function', f'void f(int arr[static{space}{cvr} 42])', {1: 'f'})
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'function',
|
|
|
|
f'void f(int arr[{cvr}{space}static 42])',
|
|
|
|
{1: 'f'},
|
|
|
|
output=f'void f(int arr[static{space}{cvr} 42])',
|
|
|
|
)
|
|
|
|
check(
|
|
|
|
'function',
|
|
|
|
'void f(int arr[const static volatile 42])',
|
|
|
|
{1: 'f'},
|
|
|
|
output='void f(int arr[static volatile const 42])',
|
|
|
|
)
|
2020-04-25 12:37:21 -05:00
|
|
|
|
2020-10-11 06:57:04 -05:00
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('function', 'void f(int for)')
|
|
|
|
|
2021-03-04 14:28:18 -06:00
|
|
|
# from #8960
|
|
|
|
check('function', 'void f(void (*p)(int, double), int i)', {1: 'f'})
|
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_nested_name():
|
2024-08-11 08:58:56 -05:00
|
|
|
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'})
|
2020-05-16 05:40:20 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_struct_definitions():
|
2020-05-16 05:40:20 -05:00
|
|
|
check('struct', '{key}A', {1: 'A'})
|
2020-03-14 18:36:46 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_union_definitions():
|
2020-05-16 05:40:20 -05:00
|
|
|
check('union', '{key}A', {1: 'A'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_enum_definitions():
|
2020-05-16 05:40:20 -05:00
|
|
|
check('enum', '{key}A', {1: 'A'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2020-05-16 05:40:20 -05:00
|
|
|
check('enumerator', '{key}A', {1: 'A'})
|
|
|
|
check('enumerator', '{key}A = 42', {1: 'A'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_anon_definitions():
|
2024-12-09 09:10:18 -06:00
|
|
|
check('struct', '@a', {1: '@a'}, as_text_output='struct [anonymous]')
|
|
|
|
check('union', '@a', {1: '@a'}, as_text_output='union [anonymous]')
|
|
|
|
check('enum', '@a', {1: '@a'}, as_text_output='enum [anonymous]')
|
|
|
|
check('struct', '@1', {1: '@1'}, as_text_output='struct [anonymous]')
|
|
|
|
check('struct', '@a.A', {1: '@a.A'}, as_text_output='struct [anonymous].A')
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_initializers():
|
2024-12-09 09:10:18 -06:00
|
|
|
ids_member = {1: 'v'}
|
|
|
|
ids_function = {1: 'f'}
|
2020-03-12 10:59:30 -05:00
|
|
|
# no init
|
2024-12-09 09:10:18 -06:00
|
|
|
check('member', 'T v', ids_member)
|
|
|
|
check('function', 'void f(T v)', ids_function)
|
2020-03-12 10:59:30 -05:00
|
|
|
# with '=', assignment-expression
|
2024-12-09 09:10:18 -06:00
|
|
|
check('member', 'T v = 42', ids_member)
|
|
|
|
check('function', 'void f(T v = 42)', ids_function)
|
2020-03-12 10:59:30 -05:00
|
|
|
# with '=', braced-init
|
2024-12-09 09:10:18 -06:00
|
|
|
check('member', 'T v = {}', ids_member)
|
|
|
|
check('function', 'void f(T v = {})', ids_function)
|
|
|
|
check('member', 'T v = {42, 42, 42}', ids_member)
|
|
|
|
check('function', 'void f(T v = {42, 42, 42})', ids_function)
|
|
|
|
check('member', 'T v = {42, 42, 42,}', ids_member)
|
|
|
|
check('function', 'void f(T v = {42, 42, 42,})', ids_function)
|
2020-03-14 12:18:10 -05:00
|
|
|
# TODO: designator-list
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_ast_attributes():
|
2020-03-12 10:59:30 -05:00
|
|
|
# style: C++
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', '[[]] int f', {1: 'f'})
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'member',
|
|
|
|
'[ [ ] ] int f',
|
|
|
|
{1: 'f'},
|
|
|
|
# this will fail when the proper grammar is implemented
|
|
|
|
output='[[ ]] int f',
|
|
|
|
)
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', '[[a]] int f', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
# style: GNU
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', '__attribute__(()) int f', {1: 'f'})
|
|
|
|
check('member', '__attribute__((a)) int f', {1: 'f'})
|
|
|
|
check('member', '__attribute__((a, b)) int f', {1: 'f'})
|
2020-06-20 02:55:35 -05:00
|
|
|
check('member', '__attribute__((optimize(3))) int f', {1: 'f'})
|
|
|
|
check('member', '__attribute__((format(printf, 1, 2))) int f', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
# style: user-defined id
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', 'id_attr int f', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
# style: user-defined paren
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', 'paren_attr() int f', {1: 'f'})
|
|
|
|
check('member', 'paren_attr(a) int f', {1: 'f'})
|
2020-11-15 02:03:26 -06:00
|
|
|
check('member', 'paren_attr("") int f', {1: 'f'})
|
2020-04-13 03:09:41 -05:00
|
|
|
check('member', 'paren_attr(()[{}][]{}) int f', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr(() int f')
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr([) int f')
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr({) int f')
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr([)]) int f')
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr((])) int f')
|
|
|
|
with pytest.raises(DefinitionError):
|
|
|
|
parse('member', 'paren_attr({]}) int f')
|
|
|
|
|
|
|
|
# position: decl specs
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'function',
|
|
|
|
'static inline __attribute__(()) void f()',
|
|
|
|
{1: 'f'},
|
|
|
|
output='__attribute__(()) static inline void f()',
|
|
|
|
)
|
2020-08-13 11:39:28 -05:00
|
|
|
check('function', '[[attr1]] [[attr2]] void f()', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
# position: declarator
|
2022-04-17 10:17:19 -05:00
|
|
|
check('member', 'int *[[attr1]] [[attr2]] i', {1: 'i'})
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'member',
|
|
|
|
'int *const [[attr1]] [[attr2]] volatile i',
|
|
|
|
{1: 'i'},
|
|
|
|
output='int *[[attr1]] [[attr2]] volatile const i',
|
|
|
|
)
|
2022-04-17 10:17:19 -05:00
|
|
|
check('member', 'int *[[attr1]] [[attr2]] *i', {1: 'i'})
|
2020-08-13 11:39:28 -05:00
|
|
|
# position: parameters
|
|
|
|
check('function', 'void f() [[attr1]] [[attr2]]', {1: 'f'})
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2022-04-17 10:27:30 -05:00
|
|
|
# position: enumerator
|
|
|
|
check('enumerator', '{key}Foo [[attr1]] [[attr2]]', {1: 'Foo'})
|
|
|
|
check('enumerator', '{key}Foo [[attr1]] [[attr2]] = 42', {1: 'Foo'})
|
|
|
|
|
2020-04-13 03:09:41 -05:00
|
|
|
# issue michaeljones/breathe#500
|
2024-08-11 08:58:56 -05:00
|
|
|
check(
|
|
|
|
'function',
|
|
|
|
'LIGHTGBM_C_EXPORT int LGBM_BoosterFree(int handle)',
|
|
|
|
{1: 'LGBM_BoosterFree'},
|
|
|
|
)
|
2020-03-12 10:59:30 -05:00
|
|
|
|
2021-06-16 15:08:30 -05:00
|
|
|
|
|
|
|
def test_extra_keywords():
|
2024-08-11 08:58:56 -05:00
|
|
|
with pytest.raises(DefinitionError, match='Expected identifier in nested name'):
|
2021-06-16 15:08:30 -05:00
|
|
|
parse('function', 'void complex(void)')
|
|
|
|
|
|
|
|
|
2020-03-12 10:59:30 -05:00
|
|
|
# def test_print():
|
|
|
|
# # used for getting all the ids out for checking
|
|
|
|
# for a in ids:
|
|
|
|
# print(a)
|
2023-08-13 14:07:28 -05:00
|
|
|
# raise DefinitionError
|
2020-03-12 10:59:30 -05:00
|
|
|
|
|
|
|
|
2024-07-23 09:35:55 -05:00
|
|
|
def split_warnings(warning: StringIO):
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = warning.getvalue().split('\n')
|
2020-10-11 08:23:11 -05:00
|
|
|
assert len(ws) >= 1
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ws[-1] == ''
|
2020-10-11 08:23:11 -05:00
|
|
|
return ws[:-1]
|
|
|
|
|
|
|
|
|
2024-07-23 09:35:55 -05:00
|
|
|
def filter_warnings(warning: StringIO, file):
|
|
|
|
lines = split_warnings(warning)
|
2024-08-11 08:58:56 -05:00
|
|
|
res = [
|
|
|
|
l
|
|
|
|
for l in lines
|
|
|
|
if 'domain-c' in l
|
|
|
|
and f'{file}.rst' in l
|
|
|
|
and "WARNING: document isn't included in any toctree" not in l
|
|
|
|
]
|
2022-10-17 09:54:59 -05:00
|
|
|
print(f"Filtered warnings for file '{file}':")
|
2020-03-12 10:59:30 -05:00
|
|
|
for w in res:
|
|
|
|
print(w)
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
2020-10-13 05:30:13 -05:00
|
|
|
def extract_role_links(app, filename):
|
2022-04-26 21:04:19 -05:00
|
|
|
t = (app.outdir / filename).read_text(encoding='utf8')
|
2024-08-11 08:58:56 -05:00
|
|
|
lis = [l for l in t.split('\n') if l.startswith('<li')]
|
2020-10-13 05:30:13 -05:00
|
|
|
entries = []
|
|
|
|
for l in lis:
|
2024-08-15 15:42:25 -05:00
|
|
|
li = ET.fromstring(l) # NoQA: S314 # using known data in tests
|
2024-12-09 09:10:18 -06:00
|
|
|
a_list = list(li.iter('a'))
|
|
|
|
assert len(a_list) == 1
|
|
|
|
a = a_list[0]
|
2020-10-13 05:30:13 -05:00
|
|
|
target = a.attrib['href'].lstrip('#')
|
|
|
|
title = a.attrib['title']
|
|
|
|
assert len(a) == 1
|
|
|
|
code = a[0]
|
|
|
|
assert code.tag == 'code'
|
|
|
|
text = ''.join(code.itertext())
|
|
|
|
entries.append((target, title, text))
|
|
|
|
return entries
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'index')
|
2020-03-12 10:59:30 -05:00
|
|
|
assert len(ws) == 0
|
2020-03-05 11:06:15 -06:00
|
|
|
|
2020-04-24 04:38:22 -05:00
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_namespace(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'namespace')
|
2020-04-12 07:13:54 -05:00
|
|
|
assert len(ws) == 0
|
2024-08-11 08:58:56 -05:00
|
|
|
t = (app.outdir / 'namespace.html').read_text(encoding='utf8')
|
2020-04-12 07:13:54 -05:00
|
|
|
for id_ in ('NS.NSVar', 'NULLVar', 'ZeroVar', 'NS2.NS3.NS2NS3Var', 'PopVar'):
|
2022-10-17 09:54:59 -05:00
|
|
|
assert f'id="c.{id_}"' in t
|
2020-03-05 11:06:15 -06:00
|
|
|
|
2020-04-24 04:38:22 -05:00
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_anon_dup_decl(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'anon-dup-decl')
|
2020-03-25 14:07:16 -05:00
|
|
|
assert len(ws) == 2
|
2024-08-11 08:58:56 -05:00
|
|
|
assert 'WARNING: c:identifier reference target not found: @a' in ws[0]
|
|
|
|
assert 'WARNING: c:identifier reference target not found: @b' in ws[1]
|
2020-03-25 14:07:16 -05:00
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_semicolon(app):
|
2020-10-11 08:23:11 -05:00
|
|
|
text = """
|
|
|
|
.. 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;
|
|
|
|
"""
|
|
|
|
restructuredtext.parse(app, text)
|
2024-07-23 09:35:55 -05:00
|
|
|
ws = split_warnings(app.warning)
|
2020-04-24 04:38:22 -05:00
|
|
|
assert len(ws) == 0
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_function_param_target(app):
|
2020-10-13 05:30:13 -05:00
|
|
|
# the anchor for function parameters should be the function
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'function_param_target')
|
2020-10-13 05:30:13 -05:00
|
|
|
assert len(ws) == 0
|
2024-08-11 08:58:56 -05:00
|
|
|
entries = extract_role_links(app, 'function_param_target.html')
|
2020-10-13 05:30:13 -05:00
|
|
|
assert entries == [
|
2021-02-24 08:27:23 -06:00
|
|
|
('c.function_param_target.f', 'i', 'i'),
|
|
|
|
('c.function_param_target.f', 'f.i', 'f.i'),
|
2020-10-13 05:30:13 -05:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_ns_lookup(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'ns_lookup')
|
2021-01-10 04:21:23 -06:00
|
|
|
assert len(ws) == 0
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c', confoverrides={'nitpicky': True})
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_field_role(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'field-role')
|
2021-06-03 09:42:00 -05:00
|
|
|
assert len(ws) == 0
|
|
|
|
|
|
|
|
|
2024-12-09 09:10:18 -06:00
|
|
|
def _get_obj(app, query_name):
|
2024-09-17 21:50:27 -05:00
|
|
|
domain = app.env.domains.c_domain
|
2024-12-09 09:10:18 -06:00
|
|
|
for name, _dispname, object_type, docname, anchor, _prio in domain.get_objects():
|
|
|
|
if name == query_name:
|
|
|
|
return docname, anchor, object_type
|
|
|
|
return query_name, 'not', 'found'
|
2020-09-14 14:01:41 -05:00
|
|
|
|
2020-11-15 02:03:26 -06:00
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html', testroot='domain-c-intersphinx', confoverrides={'nitpicky': True}
|
|
|
|
)
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_build_intersphinx(tmp_path, app):
|
2020-10-11 08:23:11 -05:00
|
|
|
# a splitting of test_ids_vs_tags0 into the primary directives in a remote project,
|
|
|
|
# and then the references in the test project
|
2024-12-09 09:10:18 -06:00
|
|
|
orig_source = """\
|
2021-01-11 01:16:06 -06:00
|
|
|
.. c:member:: int _member
|
|
|
|
.. c:var:: int _var
|
|
|
|
.. c:function:: void _function()
|
|
|
|
.. c:macro:: _macro
|
|
|
|
.. c:struct:: _struct
|
|
|
|
.. c:union:: _union
|
|
|
|
.. c:enum:: _enum
|
|
|
|
|
|
|
|
.. c:enumerator:: _enumerator
|
|
|
|
|
|
|
|
.. c:type:: _type
|
|
|
|
.. c:function:: void _functionParam(int param)
|
2025-01-02 17:25:30 -06:00
|
|
|
"""
|
2023-07-27 18:39:12 -05:00
|
|
|
inv_file = tmp_path / 'inventory'
|
2024-08-11 08:58:56 -05:00
|
|
|
inv_file.write_bytes(
|
|
|
|
b"""\
|
2021-01-11 01:16:06 -06:00
|
|
|
# Sphinx inventory version 2
|
|
|
|
# Project: C Intersphinx Test
|
2024-07-23 09:35:55 -05:00
|
|
|
# Version:
|
2021-01-11 01:16:06 -06:00
|
|
|
# The remainder of this file is compressed using zlib.
|
2024-08-11 08:58:56 -05:00
|
|
|
"""
|
|
|
|
+ zlib.compress(b"""\
|
2021-01-11 01:16:06 -06:00
|
|
|
_enum c:enum 1 index.html#c.$ -
|
|
|
|
_enum._enumerator c:enumerator 1 index.html#c.$ -
|
|
|
|
_enumerator c:enumerator 1 index.html#c._enum.$ -
|
|
|
|
_function c:function 1 index.html#c.$ -
|
|
|
|
_functionParam c:function 1 index.html#c.$ -
|
|
|
|
_functionParam.param c:functionParam 1 index.html#c._functionParam -
|
|
|
|
_macro c:macro 1 index.html#c.$ -
|
|
|
|
_member c:member 1 index.html#c.$ -
|
|
|
|
_struct c:struct 1 index.html#c.$ -
|
|
|
|
_type c:type 1 index.html#c.$ -
|
|
|
|
_union c:union 1 index.html#c.$ -
|
|
|
|
_var c:member 1 index.html#c.$ -
|
2024-08-11 08:58:56 -05:00
|
|
|
""")
|
2025-01-02 17:25:30 -06:00
|
|
|
)
|
2021-01-11 01:16:06 -06:00
|
|
|
app.config.intersphinx_mapping = {
|
2024-07-22 06:59:59 -05:00
|
|
|
'local': ('https://localhost/intersphinx/c/', str(inv_file)),
|
2021-01-11 01:16:06 -06:00
|
|
|
}
|
|
|
|
app.config.intersphinx_cache_limit = 0
|
|
|
|
# load the inventory and check if it's done correctly
|
2024-07-22 07:32:44 -05:00
|
|
|
validate_intersphinx_mapping(app, app.config)
|
2021-01-11 01:16:06 -06:00
|
|
|
load_mappings(app)
|
|
|
|
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2024-08-11 08:58:56 -05:00
|
|
|
ws = filter_warnings(app.warning, 'index')
|
2021-01-11 01:16:06 -06:00
|
|
|
assert len(ws) == 0
|
2021-06-03 12:35:14 -05:00
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root')
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_parse_cfunction(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = (
|
|
|
|
'.. c:function:: PyObject* '
|
|
|
|
'PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)'
|
|
|
|
)
|
2021-06-03 12:35:14 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
2021-06-03 12:35:14 -05:00
|
|
|
|
|
|
|
entry = _get_obj(app, 'PyType_GenericAlloc')
|
|
|
|
assert entry == ('index', 'c.PyType_GenericAlloc', 'function')
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root')
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_parse_cmember(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:member:: PyObject* PyTypeObject.tp_bases'
|
2021-06-03 12:35:14 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='member',
|
|
|
|
domain='c',
|
|
|
|
objtype='member',
|
|
|
|
no_index=False,
|
|
|
|
)
|
2021-06-03 12:35:14 -05:00
|
|
|
|
|
|
|
entry = _get_obj(app, 'PyTypeObject.tp_bases')
|
|
|
|
assert entry == ('index', 'c.PyTypeObject.tp_bases', 'member')
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root')
|
2021-06-03 12:35:14 -05:00
|
|
|
def test_domain_c_parse_cvar(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:var:: PyObject* PyClass_Type'
|
2021-06-03 12:35:14 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='var',
|
|
|
|
domain='c',
|
|
|
|
objtype='var',
|
|
|
|
no_index=False,
|
|
|
|
)
|
2021-06-03 12:35:14 -05:00
|
|
|
|
|
|
|
entry = _get_obj(app, 'PyClass_Type')
|
|
|
|
assert entry == ('index', 'c.PyClass_Type', 'member')
|
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root')
|
2023-07-28 16:30:26 -05:00
|
|
|
def test_domain_c_parse_no_index_entry(app):
|
2024-11-02 21:50:31 -05:00
|
|
|
text = '.. c:function:: void f()\n.. c:function:: void g()\n :no-index-entry:\n'
|
2021-06-03 12:35:14 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
|
|
|
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree[0],
|
|
|
|
addnodes.index,
|
|
|
|
entries=[('single', 'f (C function)', 'c.f', '', None)],
|
|
|
|
)
|
2021-06-03 12:35:14 -05:00
|
|
|
assert_node(doctree[2], addnodes.index, entries=[])
|
2023-05-11 08:28:57 -05:00
|
|
|
|
|
|
|
|
2024-08-11 08:58:56 -05:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'c_maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_c_maximum_signature_line_length_equal(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str name)'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'name'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=False
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'c_maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_c_maximum_signature_line_length_force_single(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str names)\n :single-line-parameter-list:'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'names'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=False
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'c_maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_c_maximum_signature_line_length_break(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str names)'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'names'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
assert_node(doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=True)
|
|
|
|
|
|
|
|
|
2024-08-11 08:58:56 -05:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_maximum_signature_line_length_equal(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str name)'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'name'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=False
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_maximum_signature_line_length_force_single(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str names)\n :single-line-parameter-list:'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'names'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=False
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_cfunction_signature_with_maximum_signature_line_length_break(app):
|
2024-08-11 08:58:56 -05:00
|
|
|
text = '.. c:function:: str hello(str names)'
|
2023-05-11 08:28:57 -05:00
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'names'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
assert_node(doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=True)
|
|
|
|
|
|
|
|
|
2024-08-11 08:58:56 -05:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'html',
|
2024-08-12 16:34:03 -05:00
|
|
|
testroot='root',
|
2024-08-11 08:58:56 -05:00
|
|
|
confoverrides={
|
|
|
|
'c_maximum_signature_line_length': len('str hello(str name)'),
|
|
|
|
'maximum_signature_line_length': 1,
|
|
|
|
},
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
def test_c_maximum_signature_line_length_overrides_global(app):
|
|
|
|
text = '.. c:function:: str hello(str name)'
|
|
|
|
doctree = restructuredtext.parse(app, text)
|
2024-08-11 08:58:56 -05:00
|
|
|
assert_node(
|
|
|
|
doctree,
|
|
|
|
(
|
|
|
|
addnodes.index,
|
|
|
|
[
|
|
|
|
desc,
|
|
|
|
(
|
|
|
|
[
|
|
|
|
desc_signature,
|
|
|
|
([
|
|
|
|
desc_signature_line,
|
|
|
|
(
|
|
|
|
pending_xref,
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_name, [desc_sig_name, 'hello']],
|
|
|
|
desc_parameterlist,
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
],
|
|
|
|
desc_content,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1],
|
|
|
|
addnodes.desc,
|
|
|
|
desctype='function',
|
|
|
|
domain='c',
|
|
|
|
objtype='function',
|
|
|
|
no_index=False,
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3],
|
|
|
|
[
|
|
|
|
desc_parameterlist,
|
|
|
|
desc_parameter,
|
|
|
|
(
|
|
|
|
[pending_xref, [desc_sig_name, 'str']],
|
|
|
|
desc_sig_space,
|
|
|
|
[desc_sig_name, 'name'],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
assert_node(
|
|
|
|
doctree[1][0][0][3], desc_parameterlist, multi_line_parameter_list=False
|
|
|
|
)
|
2023-05-11 08:28:57 -05:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx('html', testroot='domain-c-c_maximum_signature_line_length')
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_c_maximum_signature_line_length_in_html(app):
|
2023-05-11 08:28:57 -05:00
|
|
|
app.build()
|
|
|
|
content = (app.outdir / 'index.html').read_text(encoding='utf-8')
|
|
|
|
expected = """\
|
|
|
|
|
|
|
|
<dl>
|
|
|
|
<dd>\
|
|
|
|
<span class="n"><span class="pre">str</span></span>\
|
|
|
|
<span class="w"> </span>\
|
|
|
|
<span class="n"><span class="pre">name</span></span>,\
|
|
|
|
</dd>
|
|
|
|
</dl>
|
|
|
|
|
|
|
|
<span class="sig-paren">)</span>\
|
2023-08-11 23:21:16 -05:00
|
|
|
<a class="headerlink" href="#c.hello" title="Link to this definition">¶</a>\
|
2023-05-11 08:28:57 -05:00
|
|
|
<br />\
|
|
|
|
</dt>
|
|
|
|
"""
|
|
|
|
assert expected in content
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
2024-08-11 08:58:56 -05:00
|
|
|
'text',
|
|
|
|
testroot='domain-c-c_maximum_signature_line_length',
|
2023-05-11 08:28:57 -05:00
|
|
|
)
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_domain_c_c_maximum_signature_line_length_in_text(app):
|
2023-05-11 08:28:57 -05:00
|
|
|
app.build()
|
|
|
|
content = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
2024-08-11 08:58:56 -05:00
|
|
|
param_line_fmt = STDINDENT * ' ' + '{}\n'
|
2023-05-11 08:28:57 -05:00
|
|
|
|
2024-08-11 08:58:56 -05:00
|
|
|
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('str name,'))
|
2023-05-11 08:28:57 -05:00
|
|
|
|
|
|
|
assert expected_parameter_list_hello in content
|