mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, support pack expansion in template argument lists
This commit is contained in:
parent
f9d36008e1
commit
c9fb5ab9ad
@ -1713,9 +1713,11 @@ class ASTTemplateArgConstant(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTTemplateArgs(ASTBase):
|
class ASTTemplateArgs(ASTBase):
|
||||||
def __init__(self, args: List[Union["ASTType", ASTTemplateArgConstant]]) -> None:
|
def __init__(self, args: List[Union["ASTType", ASTTemplateArgConstant]],
|
||||||
|
packExpansion: bool) -> None:
|
||||||
assert args is not None
|
assert args is not None
|
||||||
self.args = args
|
self.args = args
|
||||||
|
self.packExpansion = packExpansion
|
||||||
|
|
||||||
def get_id(self, version: int) -> str:
|
def get_id(self, version: int) -> str:
|
||||||
if version == 1:
|
if version == 1:
|
||||||
@ -1727,13 +1729,21 @@ class ASTTemplateArgs(ASTBase):
|
|||||||
|
|
||||||
res = []
|
res = []
|
||||||
res.append('I')
|
res.append('I')
|
||||||
for a in self.args:
|
if len(self.args) > 0:
|
||||||
res.append(a.get_id(version))
|
for a in self.args[:-1]:
|
||||||
|
res.append(a.get_id(version))
|
||||||
|
if self.packExpansion:
|
||||||
|
res.append('J')
|
||||||
|
res.append(self.args[-1].get_id(version))
|
||||||
|
if self.packExpansion:
|
||||||
|
res.append('E')
|
||||||
res.append('E')
|
res.append('E')
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
res = ', '.join(transform(a) for a in self.args)
|
res = ', '.join(transform(a) for a in self.args)
|
||||||
|
if self.packExpansion:
|
||||||
|
res += '...'
|
||||||
return '<' + res + '>'
|
return '<' + res + '>'
|
||||||
|
|
||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
@ -1746,6 +1756,8 @@ class ASTTemplateArgs(ASTBase):
|
|||||||
signode += nodes.Text(', ')
|
signode += nodes.Text(', ')
|
||||||
first = False
|
first = False
|
||||||
a.describe_signature(signode, 'markType', env, symbol=symbol)
|
a.describe_signature(signode, 'markType', env, symbol=symbol)
|
||||||
|
if self.packExpansion:
|
||||||
|
signode += nodes.Text('...')
|
||||||
signode += nodes.Text('>')
|
signode += nodes.Text('>')
|
||||||
|
|
||||||
|
|
||||||
@ -5351,13 +5363,21 @@ class DefinitionParser(BaseParser):
|
|||||||
return ASTOperatorType(type)
|
return ASTOperatorType(type)
|
||||||
|
|
||||||
def _parse_template_argument_list(self) -> ASTTemplateArgs:
|
def _parse_template_argument_list(self) -> ASTTemplateArgs:
|
||||||
|
# template-argument-list: (but we include the < and > here
|
||||||
|
# template-argument ...[opt]
|
||||||
|
# template-argument-list, template-argument ...[opt]
|
||||||
|
# template-argument:
|
||||||
|
# constant-expression
|
||||||
|
# type-id
|
||||||
|
# id-expression
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if not self.skip_string_and_ws('<'):
|
if not self.skip_string_and_ws('<'):
|
||||||
return None
|
return None
|
||||||
if self.skip_string('>'):
|
if self.skip_string('>'):
|
||||||
return ASTTemplateArgs([])
|
return ASTTemplateArgs([], False)
|
||||||
prevErrors = []
|
prevErrors = []
|
||||||
templateArgs = [] # type: List[Union[ASTType, ASTTemplateArgConstant]]
|
templateArgs = [] # type: List[Union[ASTType, ASTTemplateArgConstant]]
|
||||||
|
packExpansion = False
|
||||||
while 1:
|
while 1:
|
||||||
pos = self.pos
|
pos = self.pos
|
||||||
parsedComma = False
|
parsedComma = False
|
||||||
@ -5365,12 +5385,17 @@ class DefinitionParser(BaseParser):
|
|||||||
try:
|
try:
|
||||||
type = self._parse_type(named=False)
|
type = self._parse_type(named=False)
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.skip_string('>'):
|
if self.skip_string_and_ws('...'):
|
||||||
|
packExpansion = True
|
||||||
|
parsedEnd = True
|
||||||
|
if not self.skip_string('>'):
|
||||||
|
self.fail('Expected ">" after "..." in template argument list.')
|
||||||
|
elif self.skip_string('>'):
|
||||||
parsedEnd = True
|
parsedEnd = True
|
||||||
elif self.skip_string(','):
|
elif self.skip_string(','):
|
||||||
parsedComma = True
|
parsedComma = True
|
||||||
else:
|
else:
|
||||||
self.fail('Expected ">" or "," in template argument list.')
|
self.fail('Expected "...>", ">" or "," in template argument list.')
|
||||||
templateArgs.append(type)
|
templateArgs.append(type)
|
||||||
except DefinitionError as e:
|
except DefinitionError as e:
|
||||||
prevErrors.append((e, "If type argument"))
|
prevErrors.append((e, "If type argument"))
|
||||||
@ -5378,12 +5403,17 @@ class DefinitionParser(BaseParser):
|
|||||||
try:
|
try:
|
||||||
value = self._parse_constant_expression(inTemplate=True)
|
value = self._parse_constant_expression(inTemplate=True)
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.skip_string('>'):
|
if self.skip_string_and_ws('...'):
|
||||||
|
packExpansion = True
|
||||||
|
parsedEnd = True
|
||||||
|
if not self.skip_string('>'):
|
||||||
|
self.fail('Expected ">" after "..." in template argument list.')
|
||||||
|
elif self.skip_string('>'):
|
||||||
parsedEnd = True
|
parsedEnd = True
|
||||||
elif self.skip_string(','):
|
elif self.skip_string(','):
|
||||||
parsedComma = True
|
parsedComma = True
|
||||||
else:
|
else:
|
||||||
self.fail('Expected ">" or "," in template argument list.')
|
self.fail('Expected "...>", ">" or "," in template argument list.')
|
||||||
templateArgs.append(ASTTemplateArgConstant(value))
|
templateArgs.append(ASTTemplateArgConstant(value))
|
||||||
except DefinitionError as e:
|
except DefinitionError as e:
|
||||||
self.pos = pos
|
self.pos = pos
|
||||||
@ -5393,7 +5423,9 @@ class DefinitionParser(BaseParser):
|
|||||||
if parsedEnd:
|
if parsedEnd:
|
||||||
assert not parsedComma
|
assert not parsedComma
|
||||||
break
|
break
|
||||||
return ASTTemplateArgs(templateArgs)
|
else:
|
||||||
|
assert not packExpansion
|
||||||
|
return ASTTemplateArgs(templateArgs, packExpansion)
|
||||||
|
|
||||||
def _parse_nested_name(self, memberPointer: bool = False) -> ASTNestedName:
|
def _parse_nested_name(self, memberPointer: bool = False) -> ASTNestedName:
|
||||||
names = [] # type: List[ASTNestedNameElement]
|
names = [] # type: List[ASTNestedNameElement]
|
||||||
|
@ -629,6 +629,12 @@ def test_class_definitions():
|
|||||||
{2: 'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'})
|
{2: 'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'})
|
||||||
|
|
||||||
|
|
||||||
|
check('class', 'template<typename ...Ts> T<int (*)(Ts)...>',
|
||||||
|
{2: 'IDpE1TIJPFi2TsEEE'})
|
||||||
|
check('class', 'template<int... Is> T<(Is)...>',
|
||||||
|
{2: 'I_DpiE1TIJX(Is)EEE', 3: 'I_DpiE1TIJX2IsEEE'})
|
||||||
|
|
||||||
|
|
||||||
def test_union_definitions():
|
def test_union_definitions():
|
||||||
check('union', 'A', {2: "1A"})
|
check('union', 'A', {2: "1A"})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user