You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1422 lines
52 KiB
1422 lines
52 KiB
8 months ago
|
from __future__ import annotations
|
||
|
|
||
|
from typing import TYPE_CHECKING, Any, Union, cast
|
||
|
|
||
|
from docutils import nodes
|
||
|
|
||
|
from sphinx import addnodes
|
||
|
from sphinx.domains.c._ids import _id_prefix, _max_id
|
||
|
from sphinx.util.cfamily import (
|
||
|
ASTAttributeList,
|
||
|
ASTBaseBase,
|
||
|
ASTBaseParenExprList,
|
||
|
StringifyTransform,
|
||
|
UnsupportedMultiCharacterCharLiteral,
|
||
|
verify_description_mode,
|
||
|
)
|
||
|
|
||
|
if TYPE_CHECKING:
|
||
|
|
||
|
from docutils.nodes import Element, Node, TextElement
|
||
|
|
||
|
from sphinx.domains.c._symbol import Symbol
|
||
|
from sphinx.environment import BuildEnvironment
|
||
|
|
||
|
DeclarationType = Union[
|
||
|
"ASTStruct", "ASTUnion", "ASTEnum", "ASTEnumerator",
|
||
|
"ASTType", "ASTTypeWithInit", "ASTMacro",
|
||
|
]
|
||
|
|
||
|
|
||
|
class ASTBase(ASTBaseBase):
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
raise NotImplementedError(repr(self))
|
||
|
|
||
|
|
||
|
# Names
|
||
|
################################################################################
|
||
|
|
||
|
class ASTIdentifier(ASTBaseBase):
|
||
|
def __init__(self, identifier: str) -> None:
|
||
|
assert identifier is not None
|
||
|
assert len(identifier) != 0
|
||
|
self.identifier = identifier
|
||
|
|
||
|
# ASTBaseBase already implements this method,
|
||
|
# but specialising it here improves performance
|
||
|
def __eq__(self, other: object) -> bool:
|
||
|
if type(other) is not ASTIdentifier:
|
||
|
return NotImplemented
|
||
|
return self.identifier == other.identifier
|
||
|
|
||
|
def is_anon(self) -> bool:
|
||
|
return self.identifier[0] == '@'
|
||
|
|
||
|
# and this is where we finally make a difference between __str__ and the display string
|
||
|
|
||
|
def __str__(self) -> str:
|
||
|
return self.identifier
|
||
|
|
||
|
def get_display_string(self) -> str:
|
||
|
return "[anonymous]" if self.is_anon() else self.identifier
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironment,
|
||
|
prefix: str, symbol: Symbol) -> None:
|
||
|
# note: slightly different signature of describe_signature due to the prefix
|
||
|
verify_description_mode(mode)
|
||
|
if self.is_anon():
|
||
|
node = addnodes.desc_sig_name(text="[anonymous]")
|
||
|
else:
|
||
|
node = addnodes.desc_sig_name(self.identifier, self.identifier)
|
||
|
if mode == 'markType':
|
||
|
targetText = prefix + self.identifier
|
||
|
pnode = addnodes.pending_xref('', refdomain='c',
|
||
|
reftype='identifier',
|
||
|
reftarget=targetText, modname=None,
|
||
|
classname=None)
|
||
|
pnode['c:parent_key'] = symbol.get_lookup_key()
|
||
|
pnode += node
|
||
|
signode += pnode
|
||
|
elif mode == 'lastIsName':
|
||
|
nameNode = addnodes.desc_name()
|
||
|
nameNode += node
|
||
|
signode += nameNode
|
||
|
elif mode == 'noneIsName':
|
||
|
signode += node
|
||
|
else:
|
||
|
raise Exception('Unknown description mode: %s' % mode)
|
||
|
|
||
|
|
||
|
class ASTNestedName(ASTBase):
|
||
|
def __init__(self, names: list[ASTIdentifier], rooted: bool) -> None:
|
||
|
assert len(names) > 0
|
||
|
self.names = names
|
||
|
self.rooted = rooted
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self
|
||
|
|
||
|
def get_id(self, version: int) -> str:
|
||
|
return '.'.join(str(n) for n in self.names)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = '.'.join(transform(n) for n in self.names)
|
||
|
if self.rooted:
|
||
|
return '.' + res
|
||
|
else:
|
||
|
return res
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
# just print the name part, with template args, not template params
|
||
|
if mode == 'noneIsName':
|
||
|
if self.rooted:
|
||
|
unreachable = "Can this happen?"
|
||
|
raise AssertionError(unreachable) # TODO
|
||
|
signode += nodes.Text('.')
|
||
|
for i in range(len(self.names)):
|
||
|
if i != 0:
|
||
|
unreachable = "Can this happen?"
|
||
|
raise AssertionError(unreachable) # TODO
|
||
|
signode += nodes.Text('.')
|
||
|
n = self.names[i]
|
||
|
n.describe_signature(signode, mode, env, '', symbol)
|
||
|
elif mode == 'param':
|
||
|
assert not self.rooted, str(self)
|
||
|
assert len(self.names) == 1
|
||
|
self.names[0].describe_signature(signode, 'noneIsName', env, '', symbol)
|
||
|
elif mode in ('markType', 'lastIsName', 'markName'):
|
||
|
# Each element should be a pending xref targeting the complete
|
||
|
# prefix.
|
||
|
prefix = ''
|
||
|
first = True
|
||
|
names = self.names[:-1] if mode == 'lastIsName' else self.names
|
||
|
# If lastIsName, then wrap all of the prefix in a desc_addname,
|
||
|
# else append directly to signode.
|
||
|
# TODO: also for C?
|
||
|
# NOTE: Breathe previously relied on the prefix being in the desc_addname node,
|
||
|
# so it can remove it in inner declarations.
|
||
|
dest = signode
|
||
|
if mode == 'lastIsName':
|
||
|
dest = addnodes.desc_addname()
|
||
|
if self.rooted:
|
||
|
prefix += '.'
|
||
|
if mode == 'lastIsName' and len(names) == 0:
|
||
|
signode += addnodes.desc_sig_punctuation('.', '.')
|
||
|
else:
|
||
|
dest += addnodes.desc_sig_punctuation('.', '.')
|
||
|
for i in range(len(names)):
|
||
|
ident = names[i]
|
||
|
if not first:
|
||
|
dest += addnodes.desc_sig_punctuation('.', '.')
|
||
|
prefix += '.'
|
||
|
first = False
|
||
|
txt_ident = str(ident)
|
||
|
if txt_ident != '':
|
||
|
ident.describe_signature(dest, 'markType', env, prefix, symbol)
|
||
|
prefix += txt_ident
|
||
|
if mode == 'lastIsName':
|
||
|
if len(self.names) > 1:
|
||
|
dest += addnodes.desc_sig_punctuation('.', '.')
|
||
|
signode += dest
|
||
|
self.names[-1].describe_signature(signode, mode, env, '', symbol)
|
||
|
else:
|
||
|
raise Exception('Unknown description mode: %s' % mode)
|
||
|
|
||
|
|
||
|
################################################################################
|
||
|
# Expressions
|
||
|
################################################################################
|
||
|
|
||
|
class ASTExpression(ASTBase):
|
||
|
pass
|
||
|
|
||
|
|
||
|
# Primary expressions
|
||
|
################################################################################
|
||
|
|
||
|
class ASTLiteral(ASTExpression):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class ASTBooleanLiteral(ASTLiteral):
|
||
|
def __init__(self, value: bool) -> None:
|
||
|
self.value = value
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
if self.value:
|
||
|
return 'true'
|
||
|
else:
|
||
|
return 'false'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
txt = str(self)
|
||
|
signode += addnodes.desc_sig_keyword(txt, txt)
|
||
|
|
||
|
|
||
|
class ASTNumberLiteral(ASTLiteral):
|
||
|
def __init__(self, data: str) -> None:
|
||
|
self.data = data
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return self.data
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
txt = str(self)
|
||
|
signode += addnodes.desc_sig_literal_number(txt, txt)
|
||
|
|
||
|
|
||
|
class ASTCharLiteral(ASTLiteral):
|
||
|
def __init__(self, prefix: str, data: str) -> None:
|
||
|
self.prefix = prefix # may be None when no prefix
|
||
|
self.data = data
|
||
|
decoded = data.encode().decode('unicode-escape')
|
||
|
if len(decoded) == 1:
|
||
|
self.value = ord(decoded)
|
||
|
else:
|
||
|
raise UnsupportedMultiCharacterCharLiteral(decoded)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
if self.prefix is None:
|
||
|
return "'" + self.data + "'"
|
||
|
else:
|
||
|
return self.prefix + "'" + self.data + "'"
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
txt = str(self)
|
||
|
signode += addnodes.desc_sig_literal_char(txt, txt)
|
||
|
|
||
|
|
||
|
class ASTStringLiteral(ASTLiteral):
|
||
|
def __init__(self, data: str) -> None:
|
||
|
self.data = data
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return self.data
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
txt = str(self)
|
||
|
signode += addnodes.desc_sig_literal_string(txt, txt)
|
||
|
|
||
|
|
||
|
class ASTIdExpression(ASTExpression):
|
||
|
def __init__(self, name: ASTNestedName) -> None:
|
||
|
# note: this class is basically to cast a nested name as an expression
|
||
|
self.name = name
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return transform(self.name)
|
||
|
|
||
|
def get_id(self, version: int) -> str:
|
||
|
return self.name.get_id(version)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
self.name.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTParenExpr(ASTExpression):
|
||
|
def __init__(self, expr: ASTExpression) -> None:
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return '(' + transform(self.expr) + ')'
|
||
|
|
||
|
def get_id(self, version: int) -> str:
|
||
|
return self.expr.get_id(version) # type: ignore[attr-defined]
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
self.expr.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
|
||
|
|
||
|
# Postfix expressions
|
||
|
################################################################################
|
||
|
|
||
|
class ASTPostfixOp(ASTBase):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class ASTPostfixCallExpr(ASTPostfixOp):
|
||
|
def __init__(self, lst: ASTParenExprList | ASTBracedInitList) -> None:
|
||
|
self.lst = lst
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return transform(self.lst)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
self.lst.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTPostfixArray(ASTPostfixOp):
|
||
|
def __init__(self, expr: ASTExpression) -> None:
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return '[' + transform(self.expr) + ']'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_punctuation('[', '[')
|
||
|
self.expr.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(']', ']')
|
||
|
|
||
|
|
||
|
class ASTPostfixInc(ASTPostfixOp):
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return '++'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_operator('++', '++')
|
||
|
|
||
|
|
||
|
class ASTPostfixDec(ASTPostfixOp):
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return '--'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_operator('--', '--')
|
||
|
|
||
|
|
||
|
class ASTPostfixMemberOfPointer(ASTPostfixOp):
|
||
|
def __init__(self, name: ASTNestedName) -> None:
|
||
|
self.name = name
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return '->' + transform(self.name)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_operator('->', '->')
|
||
|
self.name.describe_signature(signode, 'noneIsName', env, symbol)
|
||
|
|
||
|
|
||
|
class ASTPostfixExpr(ASTExpression):
|
||
|
def __init__(self, prefix: ASTExpression, postFixes: list[ASTPostfixOp]) -> None:
|
||
|
self.prefix = prefix
|
||
|
self.postFixes = postFixes
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return ''.join([transform(self.prefix), *(transform(p) for p in self.postFixes)])
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
self.prefix.describe_signature(signode, mode, env, symbol)
|
||
|
for p in self.postFixes:
|
||
|
p.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
# Unary expressions
|
||
|
################################################################################
|
||
|
|
||
|
class ASTUnaryOpExpr(ASTExpression):
|
||
|
def __init__(self, op: str, expr: ASTExpression) -> None:
|
||
|
self.op = op
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
if self.op[0] in 'cn':
|
||
|
return self.op + " " + transform(self.expr)
|
||
|
else:
|
||
|
return self.op + transform(self.expr)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
if self.op[0] in 'cn':
|
||
|
signode += addnodes.desc_sig_keyword(self.op, self.op)
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
else:
|
||
|
signode += addnodes.desc_sig_operator(self.op, self.op)
|
||
|
self.expr.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTSizeofType(ASTExpression):
|
||
|
def __init__(self, typ: ASTType) -> None:
|
||
|
self.typ = typ
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return "sizeof(" + transform(self.typ) + ")"
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_keyword('sizeof', 'sizeof')
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
self.typ.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
|
||
|
|
||
|
class ASTSizeofExpr(ASTExpression):
|
||
|
def __init__(self, expr: ASTExpression) -> None:
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return "sizeof " + transform(self.expr)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_keyword('sizeof', 'sizeof')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.expr.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTAlignofExpr(ASTExpression):
|
||
|
def __init__(self, typ: ASTType) -> None:
|
||
|
self.typ = typ
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return "alignof(" + transform(self.typ) + ")"
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_keyword('alignof', 'alignof')
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
self.typ.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
|
||
|
|
||
|
# Other expressions
|
||
|
################################################################################
|
||
|
|
||
|
class ASTCastExpr(ASTExpression):
|
||
|
def __init__(self, typ: ASTType, expr: ASTExpression) -> None:
|
||
|
self.typ = typ
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = ['(']
|
||
|
res.append(transform(self.typ))
|
||
|
res.append(')')
|
||
|
res.append(transform(self.expr))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
self.typ.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
self.expr.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTBinOpExpr(ASTBase):
|
||
|
def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None:
|
||
|
assert len(exprs) > 0
|
||
|
assert len(exprs) == len(ops) + 1
|
||
|
self.exprs = exprs
|
||
|
self.ops = ops
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append(transform(self.exprs[0]))
|
||
|
for i in range(1, len(self.exprs)):
|
||
|
res.append(' ')
|
||
|
res.append(self.ops[i - 1])
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.exprs[i]))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
self.exprs[0].describe_signature(signode, mode, env, symbol)
|
||
|
for i in range(1, len(self.exprs)):
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
op = self.ops[i - 1]
|
||
|
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'):
|
||
|
signode += addnodes.desc_sig_keyword(op, op)
|
||
|
else:
|
||
|
signode += addnodes.desc_sig_operator(op, op)
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.exprs[i].describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTAssignmentExpr(ASTExpression):
|
||
|
def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None:
|
||
|
assert len(exprs) > 0
|
||
|
assert len(exprs) == len(ops) + 1
|
||
|
self.exprs = exprs
|
||
|
self.ops = ops
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append(transform(self.exprs[0]))
|
||
|
for i in range(1, len(self.exprs)):
|
||
|
res.append(' ')
|
||
|
res.append(self.ops[i - 1])
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.exprs[i]))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
self.exprs[0].describe_signature(signode, mode, env, symbol)
|
||
|
for i in range(1, len(self.exprs)):
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
op = self.ops[i - 1]
|
||
|
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'):
|
||
|
signode += addnodes.desc_sig_keyword(op, op)
|
||
|
else:
|
||
|
signode += addnodes.desc_sig_operator(op, op)
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.exprs[i].describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTFallbackExpr(ASTExpression):
|
||
|
def __init__(self, expr: str) -> None:
|
||
|
self.expr = expr
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return self.expr
|
||
|
|
||
|
def get_id(self, version: int) -> str:
|
||
|
return str(self.expr)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
signode += nodes.literal(self.expr, self.expr)
|
||
|
|
||
|
|
||
|
################################################################################
|
||
|
# Types
|
||
|
################################################################################
|
||
|
|
||
|
class ASTTrailingTypeSpec(ASTBase):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||
|
def __init__(self, names: list[str]) -> None:
|
||
|
assert len(names) != 0
|
||
|
self.names = names
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return ' '.join(self.names)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
first = True
|
||
|
for n in self.names:
|
||
|
if not first:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
else:
|
||
|
first = False
|
||
|
signode += addnodes.desc_sig_keyword_type(n, n)
|
||
|
|
||
|
|
||
|
class ASTTrailingTypeSpecName(ASTTrailingTypeSpec):
|
||
|
def __init__(self, prefix: str, nestedName: ASTNestedName) -> None:
|
||
|
self.prefix = prefix
|
||
|
self.nestedName = nestedName
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.nestedName
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
if self.prefix:
|
||
|
res.append(self.prefix)
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.nestedName))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
if self.prefix:
|
||
|
signode += addnodes.desc_sig_keyword(self.prefix, self.prefix)
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.nestedName.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTFunctionParameter(ASTBase):
|
||
|
def __init__(self, arg: ASTTypeWithInit | None, ellipsis: bool = False) -> None:
|
||
|
self.arg = arg
|
||
|
self.ellipsis = ellipsis
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
# the anchor will be our parent
|
||
|
return symbol.parent.declaration.get_id(version, prefixed=False)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
if self.ellipsis:
|
||
|
return '...'
|
||
|
else:
|
||
|
return transform(self.arg)
|
||
|
|
||
|
def describe_signature(self, signode: Any, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
if self.ellipsis:
|
||
|
signode += addnodes.desc_sig_punctuation('...', '...')
|
||
|
else:
|
||
|
self.arg.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTParameters(ASTBase):
|
||
|
def __init__(self, args: list[ASTFunctionParameter], attrs: ASTAttributeList) -> None:
|
||
|
self.args = args
|
||
|
self.attrs = attrs
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
return self.args
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append('(')
|
||
|
first = True
|
||
|
for a in self.args:
|
||
|
if not first:
|
||
|
res.append(', ')
|
||
|
first = False
|
||
|
res.append(str(a))
|
||
|
res.append(')')
|
||
|
if len(self.attrs) != 0:
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.attrs))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
multi_line_parameter_list = False
|
||
|
test_node: Element = signode
|
||
|
while test_node.parent:
|
||
|
if not isinstance(test_node, addnodes.desc_signature):
|
||
|
test_node = test_node.parent
|
||
|
continue
|
||
|
multi_line_parameter_list = test_node.get('multi_line_parameter_list', False)
|
||
|
break
|
||
|
|
||
|
# only use the desc_parameterlist for the outer list, not for inner lists
|
||
|
if mode == 'lastIsName':
|
||
|
paramlist = addnodes.desc_parameterlist()
|
||
|
paramlist['multi_line_parameter_list'] = multi_line_parameter_list
|
||
|
for arg in self.args:
|
||
|
param = addnodes.desc_parameter('', '', noemph=True)
|
||
|
arg.describe_signature(param, 'param', env, symbol=symbol)
|
||
|
paramlist += param
|
||
|
signode += paramlist
|
||
|
else:
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
first = True
|
||
|
for arg in self.args:
|
||
|
if not first:
|
||
|
signode += addnodes.desc_sig_punctuation(',', ',')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
first = False
|
||
|
arg.describe_signature(signode, 'markType', env, symbol=symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
|
||
|
if len(self.attrs) != 0:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.attrs.describe_signature(signode)
|
||
|
|
||
|
|
||
|
class ASTDeclSpecsSimple(ASTBaseBase):
|
||
|
def __init__(self, storage: str, threadLocal: str, inline: bool,
|
||
|
restrict: bool, volatile: bool, const: bool, attrs: ASTAttributeList) -> None:
|
||
|
self.storage = storage
|
||
|
self.threadLocal = threadLocal
|
||
|
self.inline = inline
|
||
|
self.restrict = restrict
|
||
|
self.volatile = volatile
|
||
|
self.const = const
|
||
|
self.attrs = attrs
|
||
|
|
||
|
def mergeWith(self, other: ASTDeclSpecsSimple) -> ASTDeclSpecsSimple:
|
||
|
if not other:
|
||
|
return self
|
||
|
return ASTDeclSpecsSimple(self.storage or other.storage,
|
||
|
self.threadLocal or other.threadLocal,
|
||
|
self.inline or other.inline,
|
||
|
self.volatile or other.volatile,
|
||
|
self.const or other.const,
|
||
|
self.restrict or other.restrict,
|
||
|
self.attrs + other.attrs)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res: list[str] = []
|
||
|
if len(self.attrs) != 0:
|
||
|
res.append(transform(self.attrs))
|
||
|
if self.storage:
|
||
|
res.append(self.storage)
|
||
|
if self.threadLocal:
|
||
|
res.append(self.threadLocal)
|
||
|
if self.inline:
|
||
|
res.append('inline')
|
||
|
if self.restrict:
|
||
|
res.append('restrict')
|
||
|
if self.volatile:
|
||
|
res.append('volatile')
|
||
|
if self.const:
|
||
|
res.append('const')
|
||
|
return ' '.join(res)
|
||
|
|
||
|
def describe_signature(self, modifiers: list[Node]) -> None:
|
||
|
def _add(modifiers: list[Node], text: str) -> None:
|
||
|
if len(modifiers) != 0:
|
||
|
modifiers.append(addnodes.desc_sig_space())
|
||
|
modifiers.append(addnodes.desc_sig_keyword(text, text))
|
||
|
|
||
|
if len(modifiers) != 0 and len(self.attrs) != 0:
|
||
|
modifiers.append(addnodes.desc_sig_space())
|
||
|
tempNode = nodes.TextElement()
|
||
|
self.attrs.describe_signature(tempNode)
|
||
|
modifiers.extend(tempNode.children)
|
||
|
if self.storage:
|
||
|
_add(modifiers, self.storage)
|
||
|
if self.threadLocal:
|
||
|
_add(modifiers, self.threadLocal)
|
||
|
if self.inline:
|
||
|
_add(modifiers, 'inline')
|
||
|
if self.restrict:
|
||
|
_add(modifiers, 'restrict')
|
||
|
if self.volatile:
|
||
|
_add(modifiers, 'volatile')
|
||
|
if self.const:
|
||
|
_add(modifiers, 'const')
|
||
|
|
||
|
|
||
|
class ASTDeclSpecs(ASTBase):
|
||
|
def __init__(self, outer: str,
|
||
|
leftSpecs: ASTDeclSpecsSimple,
|
||
|
rightSpecs: ASTDeclSpecsSimple,
|
||
|
trailing: ASTTrailingTypeSpec) -> None:
|
||
|
# leftSpecs and rightSpecs are used for output
|
||
|
# allSpecs are used for id generation TODO: remove?
|
||
|
self.outer = outer
|
||
|
self.leftSpecs = leftSpecs
|
||
|
self.rightSpecs = rightSpecs
|
||
|
self.allSpecs = self.leftSpecs.mergeWith(self.rightSpecs)
|
||
|
self.trailingTypeSpec = trailing
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res: list[str] = []
|
||
|
l = transform(self.leftSpecs)
|
||
|
if len(l) > 0:
|
||
|
res.append(l)
|
||
|
if self.trailingTypeSpec:
|
||
|
if len(res) > 0:
|
||
|
res.append(" ")
|
||
|
res.append(transform(self.trailingTypeSpec))
|
||
|
r = str(self.rightSpecs)
|
||
|
if len(r) > 0:
|
||
|
if len(res) > 0:
|
||
|
res.append(" ")
|
||
|
res.append(r)
|
||
|
return "".join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
modifiers: list[Node] = []
|
||
|
|
||
|
self.leftSpecs.describe_signature(modifiers)
|
||
|
|
||
|
for m in modifiers:
|
||
|
signode += m
|
||
|
if self.trailingTypeSpec:
|
||
|
if len(modifiers) > 0:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.trailingTypeSpec.describe_signature(signode, mode, env,
|
||
|
symbol=symbol)
|
||
|
modifiers = []
|
||
|
self.rightSpecs.describe_signature(modifiers)
|
||
|
if len(modifiers) > 0:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
for m in modifiers:
|
||
|
signode += m
|
||
|
|
||
|
|
||
|
# Declarator
|
||
|
################################################################################
|
||
|
|
||
|
class ASTArray(ASTBase):
|
||
|
def __init__(self, static: bool, const: bool, volatile: bool, restrict: bool,
|
||
|
vla: bool, size: ASTExpression) -> None:
|
||
|
self.static = static
|
||
|
self.const = const
|
||
|
self.volatile = volatile
|
||
|
self.restrict = restrict
|
||
|
self.vla = vla
|
||
|
self.size = size
|
||
|
if vla:
|
||
|
assert size is None
|
||
|
if size is not None:
|
||
|
assert not vla
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
el = []
|
||
|
if self.static:
|
||
|
el.append('static')
|
||
|
if self.restrict:
|
||
|
el.append('restrict')
|
||
|
if self.volatile:
|
||
|
el.append('volatile')
|
||
|
if self.const:
|
||
|
el.append('const')
|
||
|
if self.vla:
|
||
|
return '[' + ' '.join(el) + '*]'
|
||
|
elif self.size:
|
||
|
el.append(transform(self.size))
|
||
|
return '[' + ' '.join(el) + ']'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
signode += addnodes.desc_sig_punctuation('[', '[')
|
||
|
addSpace = False
|
||
|
|
||
|
def _add(signode: TextElement, text: str) -> bool:
|
||
|
if addSpace:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
signode += addnodes.desc_sig_keyword(text, text)
|
||
|
return True
|
||
|
|
||
|
if self.static:
|
||
|
addSpace = _add(signode, 'static')
|
||
|
if self.restrict:
|
||
|
addSpace = _add(signode, 'restrict')
|
||
|
if self.volatile:
|
||
|
addSpace = _add(signode, 'volatile')
|
||
|
if self.const:
|
||
|
addSpace = _add(signode, 'const')
|
||
|
if self.vla:
|
||
|
signode += addnodes.desc_sig_punctuation('*', '*')
|
||
|
elif self.size:
|
||
|
if addSpace:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.size.describe_signature(signode, 'markType', env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(']', ']')
|
||
|
|
||
|
|
||
|
class ASTDeclarator(ASTBase):
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
raise NotImplementedError(repr(self))
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
raise NotImplementedError(repr(self))
|
||
|
|
||
|
def require_space_after_declSpecs(self) -> bool:
|
||
|
raise NotImplementedError(repr(self))
|
||
|
|
||
|
|
||
|
class ASTDeclaratorNameParam(ASTDeclarator):
|
||
|
def __init__(self, declId: ASTNestedName,
|
||
|
arrayOps: list[ASTArray], param: ASTParameters) -> None:
|
||
|
self.declId = declId
|
||
|
self.arrayOps = arrayOps
|
||
|
self.param = param
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.declId
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
return self.param.function_params
|
||
|
|
||
|
# ------------------------------------------------------------------------
|
||
|
|
||
|
def require_space_after_declSpecs(self) -> bool:
|
||
|
return self.declId is not None
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
if self.declId:
|
||
|
res.append(transform(self.declId))
|
||
|
res.extend(transform(op) for op in self.arrayOps)
|
||
|
if self.param:
|
||
|
res.append(transform(self.param))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
if self.declId:
|
||
|
self.declId.describe_signature(signode, mode, env, symbol)
|
||
|
for op in self.arrayOps:
|
||
|
op.describe_signature(signode, mode, env, symbol)
|
||
|
if self.param:
|
||
|
self.param.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTDeclaratorNameBitField(ASTDeclarator):
|
||
|
def __init__(self, declId: ASTNestedName, size: ASTExpression) -> None:
|
||
|
self.declId = declId
|
||
|
self.size = size
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.declId
|
||
|
|
||
|
# ------------------------------------------------------------------------
|
||
|
|
||
|
def require_space_after_declSpecs(self) -> bool:
|
||
|
return self.declId is not None
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
if self.declId:
|
||
|
res.append(transform(self.declId))
|
||
|
res.append(" : ")
|
||
|
res.append(transform(self.size))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
if self.declId:
|
||
|
self.declId.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
signode += addnodes.desc_sig_punctuation(':', ':')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.size.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTDeclaratorPtr(ASTDeclarator):
|
||
|
def __init__(self, next: ASTDeclarator, restrict: bool, volatile: bool, const: bool,
|
||
|
attrs: ASTAttributeList) -> None:
|
||
|
assert next
|
||
|
self.next = next
|
||
|
self.restrict = restrict
|
||
|
self.volatile = volatile
|
||
|
self.const = const
|
||
|
self.attrs = attrs
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.next.name
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
return self.next.function_params
|
||
|
|
||
|
def require_space_after_declSpecs(self) -> bool:
|
||
|
return self.const or self.volatile or self.restrict or \
|
||
|
len(self.attrs) > 0 or \
|
||
|
self.next.require_space_after_declSpecs()
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = ['*']
|
||
|
res.append(transform(self.attrs))
|
||
|
if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const):
|
||
|
res.append(' ')
|
||
|
if self.restrict:
|
||
|
res.append('restrict')
|
||
|
if self.volatile:
|
||
|
if self.restrict:
|
||
|
res.append(' ')
|
||
|
res.append('volatile')
|
||
|
if self.const:
|
||
|
if self.restrict or self.volatile:
|
||
|
res.append(' ')
|
||
|
res.append('const')
|
||
|
if self.const or self.volatile or self.restrict or len(self.attrs) > 0:
|
||
|
if self.next.require_space_after_declSpecs():
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.next))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
signode += addnodes.desc_sig_punctuation('*', '*')
|
||
|
self.attrs.describe_signature(signode)
|
||
|
if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const):
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
|
||
|
def _add_anno(signode: TextElement, text: str) -> None:
|
||
|
signode += addnodes.desc_sig_keyword(text, text)
|
||
|
|
||
|
if self.restrict:
|
||
|
_add_anno(signode, 'restrict')
|
||
|
if self.volatile:
|
||
|
if self.restrict:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
_add_anno(signode, 'volatile')
|
||
|
if self.const:
|
||
|
if self.restrict or self.volatile:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
_add_anno(signode, 'const')
|
||
|
if self.const or self.volatile or self.restrict or len(self.attrs) > 0:
|
||
|
if self.next.require_space_after_declSpecs():
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.next.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTDeclaratorParen(ASTDeclarator):
|
||
|
def __init__(self, inner: ASTDeclarator, next: ASTDeclarator) -> None:
|
||
|
assert inner
|
||
|
assert next
|
||
|
self.inner = inner
|
||
|
self.next = next
|
||
|
# TODO: we assume the name and params are in inner
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.inner.name
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
return self.inner.function_params
|
||
|
|
||
|
def require_space_after_declSpecs(self) -> bool:
|
||
|
return True
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = ['(']
|
||
|
res.append(transform(self.inner))
|
||
|
res.append(')')
|
||
|
res.append(transform(self.next))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
self.inner.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
self.next.describe_signature(signode, "noneIsName", env, symbol)
|
||
|
|
||
|
|
||
|
# Initializer
|
||
|
################################################################################
|
||
|
|
||
|
class ASTParenExprList(ASTBaseParenExprList):
|
||
|
def __init__(self, exprs: list[ASTExpression]) -> None:
|
||
|
self.exprs = exprs
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
exprs = [transform(e) for e in self.exprs]
|
||
|
return '(%s)' % ', '.join(exprs)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
signode += addnodes.desc_sig_punctuation('(', '(')
|
||
|
first = True
|
||
|
for e in self.exprs:
|
||
|
if not first:
|
||
|
signode += addnodes.desc_sig_punctuation(',', ',')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
else:
|
||
|
first = False
|
||
|
e.describe_signature(signode, mode, env, symbol)
|
||
|
signode += addnodes.desc_sig_punctuation(')', ')')
|
||
|
|
||
|
|
||
|
class ASTBracedInitList(ASTBase):
|
||
|
def __init__(self, exprs: list[ASTExpression], trailingComma: bool) -> None:
|
||
|
self.exprs = exprs
|
||
|
self.trailingComma = trailingComma
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
exprs = ', '.join(transform(e) for e in self.exprs)
|
||
|
trailingComma = ',' if self.trailingComma else ''
|
||
|
return f'{{{exprs}{trailingComma}}}'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
signode += addnodes.desc_sig_punctuation('{', '{')
|
||
|
first = True
|
||
|
for e in self.exprs:
|
||
|
if not first:
|
||
|
signode += addnodes.desc_sig_punctuation(',', ',')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
else:
|
||
|
first = False
|
||
|
e.describe_signature(signode, mode, env, symbol)
|
||
|
if self.trailingComma:
|
||
|
signode += addnodes.desc_sig_punctuation(',', ',')
|
||
|
signode += addnodes.desc_sig_punctuation('}', '}')
|
||
|
|
||
|
|
||
|
class ASTInitializer(ASTBase):
|
||
|
def __init__(self, value: ASTBracedInitList | ASTExpression,
|
||
|
hasAssign: bool = True) -> None:
|
||
|
self.value = value
|
||
|
self.hasAssign = hasAssign
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
val = transform(self.value)
|
||
|
if self.hasAssign:
|
||
|
return ' = ' + val
|
||
|
else:
|
||
|
return val
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
if self.hasAssign:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
signode += addnodes.desc_sig_punctuation('=', '=')
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.value.describe_signature(signode, 'markType', env, symbol)
|
||
|
|
||
|
|
||
|
class ASTType(ASTBase):
|
||
|
def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator) -> None:
|
||
|
assert declSpecs
|
||
|
assert decl
|
||
|
self.declSpecs = declSpecs
|
||
|
self.decl = decl
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.decl.name
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter]:
|
||
|
return self.decl.function_params
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
declSpecs = transform(self.declSpecs)
|
||
|
res.append(declSpecs)
|
||
|
if self.decl.require_space_after_declSpecs() and len(declSpecs) > 0:
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.decl))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def get_type_declaration_prefix(self) -> str:
|
||
|
if self.declSpecs.trailingTypeSpec:
|
||
|
return 'typedef'
|
||
|
else:
|
||
|
return 'type'
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.declSpecs.describe_signature(signode, 'markType', env, symbol)
|
||
|
if (self.decl.require_space_after_declSpecs() and
|
||
|
len(str(self.declSpecs)) > 0):
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
# for parameters that don't really declare new names we get 'markType',
|
||
|
# this should not be propagated, but be 'noneIsName'.
|
||
|
if mode == 'markType':
|
||
|
mode = 'noneIsName'
|
||
|
self.decl.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTTypeWithInit(ASTBase):
|
||
|
def __init__(self, type: ASTType, init: ASTInitializer) -> None:
|
||
|
self.type = type
|
||
|
self.init = init
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.type.name
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return self.type.get_id(version, objectType, symbol)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append(transform(self.type))
|
||
|
if self.init:
|
||
|
res.append(transform(self.init))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.type.describe_signature(signode, mode, env, symbol)
|
||
|
if self.init:
|
||
|
self.init.describe_signature(signode, mode, env, symbol)
|
||
|
|
||
|
|
||
|
class ASTMacroParameter(ASTBase):
|
||
|
def __init__(self, arg: ASTNestedName | None, ellipsis: bool = False,
|
||
|
variadic: bool = False) -> None:
|
||
|
self.arg = arg
|
||
|
self.ellipsis = ellipsis
|
||
|
self.variadic = variadic
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
if self.ellipsis:
|
||
|
return '...'
|
||
|
elif self.variadic:
|
||
|
return transform(self.arg) + '...'
|
||
|
else:
|
||
|
return transform(self.arg)
|
||
|
|
||
|
def describe_signature(self, signode: Any, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
if self.ellipsis:
|
||
|
signode += addnodes.desc_sig_punctuation('...', '...')
|
||
|
elif self.variadic:
|
||
|
name = str(self)
|
||
|
signode += addnodes.desc_sig_name(name, name)
|
||
|
else:
|
||
|
self.arg.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTMacro(ASTBase):
|
||
|
def __init__(self, ident: ASTNestedName, args: list[ASTMacroParameter] | None) -> None:
|
||
|
self.ident = ident
|
||
|
self.args = args
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
return self.ident
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append(transform(self.ident))
|
||
|
if self.args is not None:
|
||
|
res.append('(')
|
||
|
first = True
|
||
|
for arg in self.args:
|
||
|
if not first:
|
||
|
res.append(', ')
|
||
|
first = False
|
||
|
res.append(transform(arg))
|
||
|
res.append(')')
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.ident.describe_signature(signode, mode, env, symbol)
|
||
|
if self.args is None:
|
||
|
return
|
||
|
paramlist = addnodes.desc_parameterlist()
|
||
|
for arg in self.args:
|
||
|
param = addnodes.desc_parameter('', '', noemph=True)
|
||
|
arg.describe_signature(param, 'param', env, symbol=symbol)
|
||
|
paramlist += param
|
||
|
signode += paramlist
|
||
|
|
||
|
|
||
|
class ASTStruct(ASTBase):
|
||
|
def __init__(self, name: ASTNestedName) -> None:
|
||
|
self.name = name
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return transform(self.name)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTUnion(ASTBase):
|
||
|
def __init__(self, name: ASTNestedName) -> None:
|
||
|
self.name = name
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return transform(self.name)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTEnum(ASTBase):
|
||
|
def __init__(self, name: ASTNestedName) -> None:
|
||
|
self.name = name
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
return transform(self.name)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||
|
|
||
|
|
||
|
class ASTEnumerator(ASTBase):
|
||
|
def __init__(self, name: ASTNestedName, init: ASTInitializer | None,
|
||
|
attrs: ASTAttributeList) -> None:
|
||
|
self.name = name
|
||
|
self.init = init
|
||
|
self.attrs = attrs
|
||
|
|
||
|
def get_id(self, version: int, objectType: str, symbol: Symbol) -> str:
|
||
|
return symbol.get_full_nested_name().get_id(version)
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = []
|
||
|
res.append(transform(self.name))
|
||
|
if len(self.attrs) != 0:
|
||
|
res.append(' ')
|
||
|
res.append(transform(self.attrs))
|
||
|
if self.init:
|
||
|
res.append(transform(self.init))
|
||
|
return ''.join(res)
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, symbol: Symbol) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
self.name.describe_signature(signode, mode, env, symbol)
|
||
|
if len(self.attrs) != 0:
|
||
|
signode += addnodes.desc_sig_space()
|
||
|
self.attrs.describe_signature(signode)
|
||
|
if self.init:
|
||
|
self.init.describe_signature(signode, 'markType', env, symbol)
|
||
|
|
||
|
|
||
|
class ASTDeclaration(ASTBaseBase):
|
||
|
def __init__(self, objectType: str, directiveType: str | None,
|
||
|
declaration: DeclarationType | ASTFunctionParameter,
|
||
|
semicolon: bool = False) -> None:
|
||
|
self.objectType = objectType
|
||
|
self.directiveType = directiveType
|
||
|
self.declaration = declaration
|
||
|
self.semicolon = semicolon
|
||
|
|
||
|
self.symbol: Symbol | None = None
|
||
|
# set by CObject._add_enumerator_to_parent
|
||
|
self.enumeratorScopedSymbol: Symbol | None = None
|
||
|
|
||
|
# the cache assumes that by the time get_newest_id is called, no
|
||
|
# further changes will be made to this object
|
||
|
self._newest_id_cache: str | None = None
|
||
|
|
||
|
def clone(self) -> ASTDeclaration:
|
||
|
return ASTDeclaration(self.objectType, self.directiveType,
|
||
|
self.declaration.clone(), self.semicolon)
|
||
|
|
||
|
@property
|
||
|
def name(self) -> ASTNestedName:
|
||
|
decl = cast(DeclarationType, self.declaration)
|
||
|
return decl.name
|
||
|
|
||
|
@property
|
||
|
def function_params(self) -> list[ASTFunctionParameter] | None:
|
||
|
if self.objectType != 'function':
|
||
|
return None
|
||
|
decl = cast(ASTType, self.declaration)
|
||
|
return decl.function_params
|
||
|
|
||
|
def get_id(self, version: int, prefixed: bool = True) -> str:
|
||
|
if self.objectType == 'enumerator' and self.enumeratorScopedSymbol:
|
||
|
return self.enumeratorScopedSymbol.declaration.get_id(version, prefixed)
|
||
|
id_ = self.declaration.get_id(version, self.objectType, self.symbol)
|
||
|
if prefixed:
|
||
|
return _id_prefix[version] + id_
|
||
|
else:
|
||
|
return id_
|
||
|
|
||
|
def get_newest_id(self) -> str:
|
||
|
if self._newest_id_cache is None:
|
||
|
self._newest_id_cache = self.get_id(_max_id, True)
|
||
|
return self._newest_id_cache
|
||
|
|
||
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||
|
res = transform(self.declaration)
|
||
|
if self.semicolon:
|
||
|
res += ';'
|
||
|
return res
|
||
|
|
||
|
def describe_signature(self, signode: TextElement, mode: str,
|
||
|
env: BuildEnvironment, options: dict[str, bool]) -> None:
|
||
|
verify_description_mode(mode)
|
||
|
assert self.symbol
|
||
|
# The caller of the domain added a desc_signature node.
|
||
|
# Always enable multiline:
|
||
|
signode['is_multiline'] = True
|
||
|
# Put each line in a desc_signature_line node.
|
||
|
mainDeclNode = addnodes.desc_signature_line()
|
||
|
mainDeclNode.sphinx_line_type = 'declarator'
|
||
|
mainDeclNode['add_permalink'] = not self.symbol.isRedeclaration
|
||
|
signode += mainDeclNode
|
||
|
|
||
|
if self.objectType in {'member', 'function', 'macro'}:
|
||
|
pass
|
||
|
elif self.objectType == 'struct':
|
||
|
mainDeclNode += addnodes.desc_sig_keyword('struct', 'struct')
|
||
|
mainDeclNode += addnodes.desc_sig_space()
|
||
|
elif self.objectType == 'union':
|
||
|
mainDeclNode += addnodes.desc_sig_keyword('union', 'union')
|
||
|
mainDeclNode += addnodes.desc_sig_space()
|
||
|
elif self.objectType == 'enum':
|
||
|
mainDeclNode += addnodes.desc_sig_keyword('enum', 'enum')
|
||
|
mainDeclNode += addnodes.desc_sig_space()
|
||
|
elif self.objectType == 'enumerator':
|
||
|
mainDeclNode += addnodes.desc_sig_keyword('enumerator', 'enumerator')
|
||
|
mainDeclNode += addnodes.desc_sig_space()
|
||
|
elif self.objectType == 'type':
|
||
|
decl = cast(ASTType, self.declaration)
|
||
|
prefix = decl.get_type_declaration_prefix()
|
||
|
mainDeclNode += addnodes.desc_sig_keyword(prefix, prefix)
|
||
|
mainDeclNode += addnodes.desc_sig_space()
|
||
|
else:
|
||
|
raise AssertionError
|
||
|
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
|
||
|
if self.semicolon:
|
||
|
mainDeclNode += addnodes.desc_sig_punctuation(';', ';')
|