From 3e2f89b82080543c32d48c737d05b88121802e2e Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 30 Dec 2024 02:09:50 +0000 Subject: [PATCH] Enable automatic formatting for ``sphinx/domains/c/`` --- .ruff.toml | 5 - sphinx/domains/c/__init__.py | 512 +++++++++++++++++++++-------------- sphinx/domains/c/_ast.py | 451 ++++++++++++++++++------------ sphinx/domains/c/_ids.py | 84 +++++- sphinx/domains/c/_parser.py | 235 ++++++++++------ sphinx/domains/c/_symbol.py | 408 +++++++++++++++------------- 6 files changed, 1033 insertions(+), 662 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index b1cd1334b15..4497d2a92b3 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -394,11 +394,6 @@ preview = true quote-style = "single" exclude = [ "sphinx/builders/latex/constants.py", - "sphinx/domains/c/_parser.py", - "sphinx/domains/c/_ids.py", - "sphinx/domains/c/__init__.py", - "sphinx/domains/c/_symbol.py", - "sphinx/domains/c/_ast.py", "sphinx/domains/changeset.py", "sphinx/domains/citation.py", "sphinx/domains/cpp/_parser.py", diff --git a/sphinx/domains/c/__init__.py b/sphinx/domains/c/__init__.py index 28d77227eee..29837a9a924 100644 --- a/sphinx/domains/c/__init__.py +++ b/sphinx/domains/c/__init__.py @@ -101,7 +101,7 @@ def _make_phony_error_name() -> ASTNestedName: - return ASTNestedName([ASTIdentifier("PhonyNameDueToError")], rooted=False) + return ASTNestedName([ASTIdentifier('PhonyNameDueToError')], rooted=False) class CObject(ObjectDescription[ASTDeclaration]): @@ -125,38 +125,44 @@ def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None: symbol = ast.symbol assert symbol assert symbol.ident is not None - parentSymbol = symbol.parent - assert parentSymbol - if parentSymbol.parent is None: + parent_symbol = symbol.parent + assert parent_symbol + if parent_symbol.parent is None: # TODO: we could warn, but it is somewhat equivalent to # enumeratorss, without the enum return # no parent - parentDecl = parentSymbol.declaration - if parentDecl is None: + parent_decl = parent_symbol.declaration + if parent_decl is None: # the parent is not explicitly declared # TODO: we could warn, but? return - if parentDecl.objectType != 'enum': + if parent_decl.objectType != 'enum': # TODO: maybe issue a warning, enumerators in non-enums is weird, # but it is somewhat equivalent to enumeratorss, without the enum return - if parentDecl.directiveType != 'enum': + if parent_decl.directiveType != 'enum': return - targetSymbol = parentSymbol.parent - s = targetSymbol.find_identifier(symbol.ident, matchSelf=False, recurseInAnon=True, - searchInSiblings=False) + target_symbol = parent_symbol.parent + s = target_symbol.find_identifier( + symbol.ident, matchSelf=False, recurseInAnon=True, searchInSiblings=False + ) if s is not None: # something is already declared with that name return - declClone = symbol.declaration.clone() - declClone.enumeratorScopedSymbol = symbol - Symbol(parent=targetSymbol, ident=symbol.ident, - declaration=declClone, - docname=self.env.docname, line=self.get_source_info()[1]) - - def add_target_and_index(self, ast: ASTDeclaration, sig: str, - signode: TextElement) -> None: + decl_clone = symbol.declaration.clone() + decl_clone.enumeratorScopedSymbol = symbol + Symbol( + parent=target_symbol, + ident=symbol.ident, + declaration=decl_clone, + docname=self.env.docname, + line=self.get_source_info()[1], + ) + + def add_target_and_index( + self, ast: ASTDeclaration, sig: str, signode: TextElement + ) -> None: ids = [] for i in range(1, _max_id + 1): try: @@ -166,14 +172,14 @@ def add_target_and_index(self, ast: ASTDeclaration, sig: str, assert i < _max_id # let's keep the newest first ids.reverse() - newestId = ids[0] - assert newestId # shouldn't be None + newest_id = ids[0] + assert newest_id # shouldn't be None name = ast.symbol.get_full_nested_name().get_display_string().lstrip('.') - if newestId not in self.state.document.ids: + if newest_id not in self.state.document.ids: # always add the newest id - assert newestId - signode['ids'].append(newestId) + assert newest_id + signode['ids'].append(newest_id) # only add compatibility ids when there are no conflicts for id in ids[1:]: if not id: # is None when the element didn't exist in that version @@ -184,8 +190,14 @@ def add_target_and_index(self, ast: ASTDeclaration, sig: str, self.state.document.note_explicit_target(signode) if 'no-index-entry' not in self.options: - indexText = self.get_index_text(name) - self.indexnode['entries'].append(('single', indexText, newestId, '', None)) + index_text = self.get_index_text(name) + self.indexnode['entries'].append(( + 'single', + index_text, + newest_id, + '', + None, + )) @property def object_type(self) -> str: @@ -201,8 +213,9 @@ def get_index_text(self, name: str) -> str: def parse_definition(self, parser: DefinitionParser) -> ASTDeclaration: return parser.parse_declaration(self.object_type, self.objtype) - def describe_signature(self, signode: TextElement, ast: ASTDeclaration, - options: dict) -> None: + def describe_signature( + self, signode: TextElement, ast: ASTDeclaration, options: dict + ) -> None: ast.describe_signature(signode, 'lastIsName', self.env, options) def run(self) -> list[Node]: @@ -219,11 +232,13 @@ def run(self) -> list[Node]: return super().run() def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration: - parentSymbol: Symbol = self.env.temp_data['c:parent_symbol'] + parent_symbol: Symbol = self.env.temp_data['c:parent_symbol'] - max_len = (self.env.config.c_maximum_signature_line_length - or self.env.config.maximum_signature_line_length - or 0) + max_len = ( + self.env.config.c_maximum_signature_line_length + or self.env.config.maximum_signature_line_length + or 0 + ) signode['multi_line_parameter_list'] = ( 'single-line-parameter-list' not in self.options and (len(sig) > max_len > 0) @@ -238,13 +253,14 @@ def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration: # It is easier to assume some phony name than handling the error in # the possibly inner declarations. name = _make_phony_error_name() - symbol = parentSymbol.add_name(name) + symbol = parent_symbol.add_name(name) self.env.temp_data['c:last_symbol'] = symbol raise ValueError from e try: - symbol = parentSymbol.add_declaration( - ast, docname=self.env.docname, line=self.get_source_info()[1]) + symbol = parent_symbol.add_declaration( + ast, docname=self.env.docname, line=self.get_source_info()[1] + ) # append the new declaration to the sibling list assert symbol.siblingAbove is None assert symbol.siblingBelow is None @@ -257,8 +273,10 @@ def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration: # Assume we are actually in the old symbol, # instead of the newly created duplicate. self.env.temp_data['c:last_symbol'] = e.symbol - msg = __("Duplicate C declaration, also defined at %s:%s.\n" - "Declaration is '.. c:%s:: %s'.") + msg = __( + 'Duplicate C declaration, also defined at %s:%s.\n' + "Declaration is '.. c:%s:: %s'." + ) logger.warning( msg, e.symbol.docname, @@ -278,12 +296,12 @@ def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration: return ast def before_content(self) -> None: - lastSymbol: Symbol = self.env.temp_data['c:last_symbol'] - assert lastSymbol + last_symbol: Symbol = self.env.temp_data['c:last_symbol'] + assert last_symbol self.oldParentSymbol = self.env.temp_data['c:parent_symbol'] self.oldParentKey: LookupKey = self.env.ref_context['c:parent_key'] - self.env.temp_data['c:parent_symbol'] = lastSymbol - self.env.ref_context['c:parent_key'] = lastSymbol.get_lookup_key() + self.env.temp_data['c:parent_symbol'] = last_symbol + self.env.ref_context['c:parent_key'] = last_symbol.get_lookup_key() def after_content(self) -> None: self.env.temp_data['c:parent_symbol'] = self.oldParentSymbol @@ -301,16 +319,31 @@ def display_object_type(self) -> str: _function_doc_field_types = [ - TypedField('parameter', label=_('Parameters'), - names=('param', 'parameter', 'arg', 'argument'), - typerolename='expr', typenames=('type',)), - GroupedField('retval', label=_('Return values'), - names=('retvals', 'retval'), - can_collapse=True), - Field('returnvalue', label=_('Returns'), has_arg=False, - names=('returns', 'return')), - Field('returntype', label=_('Return type'), has_arg=False, - names=('rtype',)), + TypedField( + 'parameter', + label=_('Parameters'), + names=('param', 'parameter', 'arg', 'argument'), + typerolename='expr', + typenames=('type',), + ), + GroupedField( + 'retval', + label=_('Return values'), + names=('retvals', 'retval'), + can_collapse=True, + ), + Field( + 'returnvalue', + label=_('Returns'), + has_arg=False, + names=('returns', 'return'), + ), + Field( + 'returntype', + label=_('Return type'), + has_arg=False, + names=('rtype',), + ), ] @@ -359,21 +392,21 @@ class CNamespaceObject(SphinxDirective): option_spec: ClassVar[OptionSpec] = {} def run(self) -> list[Node]: - rootSymbol = self.env.domaindata['c']['root_symbol'] + root_symbol = self.env.domaindata['c']['root_symbol'] if self.arguments[0].strip() in {'NULL', '0', 'nullptr'}: - symbol = rootSymbol + symbol = root_symbol stack: list[Symbol] = [] else: - parser = DefinitionParser(self.arguments[0], - location=self.get_location(), - config=self.env.config) + parser = DefinitionParser( + self.arguments[0], location=self.get_location(), config=self.env.config + ) try: name = parser.parse_namespace_object() parser.assert_end() except DefinitionError as e: logger.warning(e, location=self.get_location()) name = _make_phony_error_name() - symbol = rootSymbol.add_name(name) + symbol = root_symbol.add_name(name) stack = [symbol] self.env.temp_data['c:parent_symbol'] = symbol self.env.temp_data['c:namespace_stack'] = stack @@ -391,19 +424,19 @@ class CNamespacePushObject(SphinxDirective): def run(self) -> list[Node]: if self.arguments[0].strip() in {'NULL', '0', 'nullptr'}: return [] - parser = DefinitionParser(self.arguments[0], - location=self.get_location(), - config=self.env.config) + parser = DefinitionParser( + self.arguments[0], location=self.get_location(), config=self.env.config + ) try: name = parser.parse_namespace_object() parser.assert_end() except DefinitionError as e: logger.warning(e, location=self.get_location()) name = _make_phony_error_name() - oldParent = self.env.temp_data.get('c:parent_symbol', None) - if not oldParent: - oldParent = self.env.domaindata['c']['root_symbol'] - symbol = oldParent.add_name(name) + old_parent = self.env.temp_data.get('c:parent_symbol', None) + if not old_parent: + old_parent = self.env.domaindata['c']['root_symbol'] + symbol = old_parent.add_name(name) stack = self.env.temp_data.get('c:namespace_stack', []) stack.append(symbol) self.env.temp_data['c:parent_symbol'] = symbol @@ -422,8 +455,10 @@ class CNamespacePopObject(SphinxDirective): def run(self) -> list[Node]: stack = self.env.temp_data.get('c:namespace_stack', None) if not stack or len(stack) == 0: - logger.warning("C namespace pop on empty stack. Defaulting to global scope.", - location=self.get_location()) + logger.warning( + 'C namespace pop on empty stack. Defaulting to global scope.', + location=self.get_location(), + ) stack = [] else: stack.pop() @@ -461,16 +496,27 @@ def __init__( self.parentKey = parentKey def copy(self) -> AliasNode: - return self.__class__(self.sig, self.aliasOptions, self.document, - env=None, parentKey=self.parentKey) + return self.__class__( + self.sig, + self.aliasOptions, + self.document, + env=None, + parentKey=self.parentKey, + ) class AliasTransform(SphinxTransform): default_priority = ReferencesResolver.default_priority - 1 - def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool, - aliasOptions: dict, renderOptions: dict, - document: Any) -> list[Node]: + def _render_symbol( + self, + s: Symbol, + maxdepth: int, + skip_this: bool, + alias_options: dict, + render_options: dict, + document: Any, + ) -> list[Node]: if maxdepth == 0: recurse = True elif maxdepth == 1: @@ -480,14 +526,16 @@ def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool, recurse = True nodes: list[Node] = [] - if not skipThis: + if not skip_this: signode = addnodes.desc_signature('', '') nodes.append(signode) - s.declaration.describe_signature(signode, 'markName', self.env, renderOptions) + s.declaration.describe_signature( + signode, 'markName', self.env, render_options + ) if recurse: - if skipThis: - childContainer: list[Node] | addnodes.desc = nodes + if skip_this: + child_container: list[Node] | addnodes.desc = nodes else: content = addnodes.desc_content() desc = addnodes.desc() @@ -497,28 +545,31 @@ def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool, # 'desctype' is a backwards compatible attribute desc['objtype'] = desc['desctype'] = 'alias' desc['no-index'] = True - childContainer = desc + child_container = desc - for sChild in s.children: - if sChild.declaration is None: + for s_child in s.children: + if s_child.declaration is None: continue - childNodes = self._render_symbol( - sChild, maxdepth=maxdepth, skipThis=False, - aliasOptions=aliasOptions, renderOptions=renderOptions, - document=document) - childContainer.extend(childNodes) - - if not skipThis and len(desc.children) != 0: + child_nodes = self._render_symbol( + s_child, + maxdepth=maxdepth, + skip_this=False, + alias_options=alias_options, + render_options=render_options, + document=document, + ) + child_container.extend(child_nodes) + + if not skip_this and len(desc.children) != 0: nodes.append(content) return nodes def apply(self, **kwargs: Any) -> None: for node in self.document.findall(AliasNode): sig = node.sig - parentKey = node.parentKey + parent_key = node.parentKey try: - parser = DefinitionParser(sig, location=node, - config=self.env.config) + parser = DefinitionParser(sig, location=node, config=self.env.config) name = parser.parse_xref_object() except DefinitionError as e: logger.warning(e, location=node) @@ -532,25 +583,26 @@ def apply(self, **kwargs: Any) -> None: node.replace_self(signode) continue - rootSymbol: Symbol = self.env.domains.c_domain.data['root_symbol'] - parentSymbol: Symbol | None = rootSymbol.direct_lookup(parentKey) - if not parentSymbol: - logger.debug("Target: %s", sig) - logger.debug("ParentKey: %s", parentKey) - logger.debug(rootSymbol.dump(1)) - assert parentSymbol # should be there - - s = parentSymbol.find_declaration( - name, 'any', - matchSelf=True, recurseInAnon=True) + root_symbol: Symbol = self.env.domains.c_domain.data['root_symbol'] + parent_symbol: Symbol | None = root_symbol.direct_lookup(parent_key) + if not parent_symbol: + logger.debug('Target: %s', sig) + logger.debug('ParentKey: %s', parent_key) + logger.debug(root_symbol.dump(1)) + assert parent_symbol # should be there + + s = parent_symbol.find_declaration( + name, 'any', matchSelf=True, recurseInAnon=True + ) if s is None: signode = addnodes.desc_signature(sig, '') node.append(signode) signode.clear() signode += addnodes.desc_name(sig, sig) - logger.warning("Could not find C declaration for alias '%s'.", name, - location=node) + logger.warning( + "Could not find C declaration for alias '%s'.", name, location=node + ) node.replace_self(signode) continue # Declarations like .. var:: int Missing::var @@ -563,15 +615,21 @@ def apply(self, **kwargs: Any) -> None: signode += addnodes.desc_name(sig, sig) logger.warning( - "Can not render C declaration for alias '%s'. No such declaration.", name, - location=node) + "Can not render C declaration for alias '%s'. No such declaration.", + name, + location=node, + ) node.replace_self(signode) continue - nodes = self._render_symbol(s, maxdepth=node.aliasOptions['maxdepth'], - skipThis=node.aliasOptions['noroot'], - aliasOptions=node.aliasOptions, - renderOptions={}, document=node.document) + nodes = self._render_symbol( + s, + maxdepth=node.aliasOptions['maxdepth'], + skip_this=node.aliasOptions['noroot'], + alias_options=node.aliasOptions, + render_options={}, + document=node.document, + ) node.replace_self(nodes) @@ -600,30 +658,40 @@ def run(self) -> list[Node]: node['no-index'] = True self.names: list[str] = [] - aliasOptions = { + alias_options = { 'maxdepth': self.options.get('maxdepth', 1), 'noroot': 'noroot' in self.options, } - if aliasOptions['noroot'] and aliasOptions['maxdepth'] == 1: - logger.warning("Error in C alias declaration." - " Requested 'noroot' but 'maxdepth' 1." - " When skipping the root declaration," - " need 'maxdepth' 0 for infinite or at least 2.", - location=self.get_location()) + if alias_options['noroot'] and alias_options['maxdepth'] == 1: + logger.warning( + 'Error in C alias declaration.' + " Requested 'noroot' but 'maxdepth' 1." + ' When skipping the root declaration,' + " need 'maxdepth' 0 for infinite or at least 2.", + location=self.get_location(), + ) for sig in self.get_signatures(): - node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env)) + node.append( + AliasNode(sig, alias_options, self.state.document, env=self.env) + ) return [node] class CXRefRole(XRefRole): - def process_link(self, env: BuildEnvironment, refnode: Element, - has_explicit_title: bool, title: str, target: str) -> tuple[str, str]: + def process_link( + self, + env: BuildEnvironment, + refnode: Element, + has_explicit_title: bool, + title: str, + target: str, + ) -> tuple[str, str]: refnode.attributes.update(env.ref_context) if not has_explicit_title: # major hax: replace anon names via simple string manipulation. # Can this actually fail? - title = anon_identifier_re.sub("[anonymous]", str(title)) + title = anon_identifier_re.sub('[anonymous]', str(title)) if not has_explicit_title: target = target.lstrip('~') # only has a meaning for the title @@ -633,7 +701,7 @@ def process_link(self, env: BuildEnvironment, refnode: Element, title = title[1:] dot = title.rfind('.') if dot != -1: - title = title[dot + 1:] + title = title[dot + 1 :] return title, target @@ -649,23 +717,29 @@ def __init__(self, asCode: bool) -> None: def run(self) -> tuple[list[Node], list[system_message]]: text = self.text.replace('\n', ' ') - parser = DefinitionParser(text, location=self.get_location(), - config=self.env.config) + parser = DefinitionParser( + text, location=self.get_location(), config=self.env.config + ) # attempt to mimic XRefRole classes, except that... try: ast = parser.parse_expression() except DefinitionError as ex: - logger.warning('Unparseable C expression: %r\n%s', text, ex, - location=self.get_location()) + logger.warning( + 'Unparseable C expression: %r\n%s', + text, + ex, + location=self.get_location(), + ) # see below - return [addnodes.desc_inline('c', text, text, classes=[self.class_type])], [] - parentSymbol = self.env.temp_data.get('c:parent_symbol', None) - if parentSymbol is None: - parentSymbol = self.env.domaindata['c']['root_symbol'] + node = addnodes.desc_inline('c', text, text, classes=[self.class_type]) + return [node], [] + parent_symbol = self.env.temp_data.get('c:parent_symbol', None) + if parent_symbol is None: + parent_symbol = self.env.domaindata['c']['root_symbol'] # ...most if not all of these classes should really apply to the individual references, # not the container node signode = addnodes.desc_inline('c', classes=[self.class_type]) - ast.describe_signature(signode, 'markType', self.env, parentSymbol) + ast.describe_signature(signode, 'markType', self.env, parent_symbol) return [signode], [] @@ -677,16 +751,18 @@ class CDomain(Domain): object_types = { # 'identifier' is the one used for xrefs generated in signatures, not in roles 'member': ObjType(_('member'), 'var', 'member', 'data', 'identifier'), - 'var': ObjType(_('variable'), 'var', 'member', 'data', 'identifier'), - 'function': ObjType(_('function'), 'func', 'identifier', 'type'), - 'macro': ObjType(_('macro'), 'macro', 'identifier'), - 'struct': ObjType(_('struct'), 'struct', 'identifier', 'type'), - 'union': ObjType(_('union'), 'union', 'identifier', 'type'), - 'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'), - 'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'), - 'type': ObjType(_('type'), 'identifier', 'type'), + 'var': ObjType(_('variable'), 'var', 'member', 'data', 'identifier'), + 'function': ObjType(_('function'), 'func', 'identifier', 'type'), + 'macro': ObjType(_('macro'), 'macro', 'identifier'), + 'struct': ObjType(_('struct'), 'struct', 'identifier', 'type'), + 'union': ObjType(_('union'), 'union', 'identifier', 'type'), + 'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'), + 'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'), + 'type': ObjType(_('type'), 'identifier', 'type'), # generated object types - 'functionParam': ObjType(_('function parameter'), 'identifier', 'var', 'member', 'data'), # NoQA: E501 + 'functionParam': ObjType( + _('function parameter'), 'identifier', 'var', 'member', 'data' + ), # NoQA: E501 } directives = { @@ -727,126 +803,156 @@ class CDomain(Domain): def clear_doc(self, docname: str) -> None: if Symbol.debug_show_tree: - logger.debug("clear_doc: %s", docname) - logger.debug("\tbefore:") + logger.debug('clear_doc: %s', docname) + logger.debug('\tbefore:') logger.debug(self.data['root_symbol'].dump(1)) - logger.debug("\tbefore end") + logger.debug('\tbefore end') - rootSymbol = self.data['root_symbol'] - rootSymbol.clear_doc(docname) + root_symbol = self.data['root_symbol'] + root_symbol.clear_doc(docname) if Symbol.debug_show_tree: - logger.debug("\tafter:") + logger.debug('\tafter:') logger.debug(self.data['root_symbol'].dump(1)) - logger.debug("\tafter end") - logger.debug("clear_doc end: %s", docname) + logger.debug('\tafter end') + logger.debug('clear_doc end: %s', docname) - def process_doc(self, env: BuildEnvironment, docname: str, - document: nodes.document) -> None: + def process_doc( + self, env: BuildEnvironment, docname: str, document: nodes.document + ) -> None: if Symbol.debug_show_tree: - logger.debug("process_doc: %s", docname) + logger.debug('process_doc: %s', docname) logger.debug(self.data['root_symbol'].dump(0)) - logger.debug("process_doc end: %s", docname) + logger.debug('process_doc end: %s', docname) def process_field_xref(self, pnode: pending_xref) -> None: pnode.attributes.update(self.env.ref_context) def merge_domaindata(self, docnames: Set[str], otherdata: dict[str, Any]) -> None: if Symbol.debug_show_tree: - logger.debug("merge_domaindata:") - logger.debug("\tself:") + logger.debug('merge_domaindata:') + logger.debug('\tself:') logger.debug(self.data['root_symbol'].dump(1)) - logger.debug("\tself end") - logger.debug("\tother:") + logger.debug('\tself end') + logger.debug('\tother:') logger.debug(otherdata['root_symbol'].dump(1)) - logger.debug("\tother end") - logger.debug("merge_domaindata end") + logger.debug('\tother end') + logger.debug('merge_domaindata end') - self.data['root_symbol'].merge_with(otherdata['root_symbol'], - docnames, self.env) - ourObjects = self.data['objects'] + self.data['root_symbol'].merge_with( + otherdata['root_symbol'], docnames, self.env + ) + our_objects = self.data['objects'] for fullname, (fn, id_, objtype) in otherdata['objects'].items(): if fn in docnames: - if fullname not in ourObjects: - ourObjects[fullname] = (fn, id_, objtype) + if fullname not in our_objects: + our_objects[fullname] = (fn, id_, objtype) # no need to warn on duplicates, the symbol merge already does that def _resolve_xref_inner( - self, env: BuildEnvironment, fromdocname: str, builder: Builder, - typ: str, target: str, node: pending_xref, contnode: Element + self, + env: BuildEnvironment, + fromdocname: str, + builder: Builder, + typ: str, + target: str, + node: pending_xref, + contnode: Element, ) -> tuple[nodes.reference, str] | tuple[None, None]: parser = DefinitionParser(target, location=node, config=env.config) try: name = parser.parse_xref_object() except DefinitionError as e: - logger.warning('Unparseable C cross-reference: %r\n%s', target, e, - location=node) + logger.warning( + 'Unparseable C cross-reference: %r\n%s', target, e, location=node + ) return None, None - parentKey: LookupKey = node.get("c:parent_key", None) - rootSymbol = self.data['root_symbol'] - if parentKey: - parentSymbol: Symbol = rootSymbol.direct_lookup(parentKey) - if not parentSymbol: - logger.debug("Target: %s", target) - logger.debug("ParentKey: %s", parentKey) - logger.debug(rootSymbol.dump(1)) - assert parentSymbol # should be there + parent_key: LookupKey = node.get('c:parent_key', None) + root_symbol = self.data['root_symbol'] + if parent_key: + parent_symbol: Symbol = root_symbol.direct_lookup(parent_key) + if not parent_symbol: + logger.debug('Target: %s', target) + logger.debug('ParentKey: %s', parent_key) + logger.debug(root_symbol.dump(1)) + assert parent_symbol # should be there else: - parentSymbol = rootSymbol - s = parentSymbol.find_declaration(name, typ, - matchSelf=True, recurseInAnon=True) + parent_symbol = root_symbol + s = parent_symbol.find_declaration( + name, typ, matchSelf=True, recurseInAnon=True + ) if s is None or s.declaration is None: return None, None # TODO: check role type vs. object type declaration = s.declaration - displayName = name.get_display_string() + display_name = name.get_display_string() docname = s.docname assert docname - return make_refnode(builder, fromdocname, docname, - declaration.get_newest_id(), contnode, displayName, - ), declaration.objectType + return make_refnode( + builder, + fromdocname, + docname, + declaration.get_newest_id(), + contnode, + display_name, + ), declaration.objectType - def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder, - typ: str, target: str, node: pending_xref, - contnode: Element) -> nodes.reference | None: - return self._resolve_xref_inner(env, fromdocname, builder, typ, - target, node, contnode)[0] - - def resolve_any_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder, - target: str, node: pending_xref, contnode: Element, - ) -> list[tuple[str, nodes.reference]]: + def resolve_xref( + self, + env: BuildEnvironment, + fromdocname: str, + builder: Builder, + typ: str, + target: str, + node: pending_xref, + contnode: Element, + ) -> nodes.reference | None: + return self._resolve_xref_inner( + env, fromdocname, builder, typ, target, node, contnode + )[0] + + def resolve_any_xref( + self, + env: BuildEnvironment, + fromdocname: str, + builder: Builder, + target: str, + node: pending_xref, + contnode: Element, + ) -> list[tuple[str, nodes.reference]]: with logging.suppress_logging(): - retnode, objtype = self._resolve_xref_inner(env, fromdocname, builder, - 'any', target, node, contnode) + retnode, objtype = self._resolve_xref_inner( + env, fromdocname, builder, 'any', target, node, contnode + ) if retnode: return [('c:' + self.role_for_objtype(objtype), retnode)] return [] def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]: - rootSymbol = self.data['root_symbol'] - for symbol in rootSymbol.get_all_symbols(): + root_symbol = self.data['root_symbol'] + for symbol in root_symbol.get_all_symbols(): if symbol.declaration is None: continue assert symbol.docname - fullNestedName = symbol.get_full_nested_name() - name = str(fullNestedName).lstrip('.') - dispname = fullNestedName.get_display_string().lstrip('.') - objectType = symbol.declaration.objectType + full_nested_name = symbol.get_full_nested_name() + name = str(full_nested_name).lstrip('.') + dispname = full_nested_name.get_display_string().lstrip('.') + object_type = symbol.declaration.objectType docname = symbol.docname - newestId = symbol.declaration.get_newest_id() - yield name, dispname, objectType, docname, newestId, 1 + newest_id = symbol.declaration.get_newest_id() + yield name, dispname, object_type, docname, newest_id, 1 def setup(app: Sphinx) -> ExtensionMetadata: app.add_domain(CDomain) - app.add_config_value("c_id_attributes", [], 'env', types={list, tuple}) - app.add_config_value("c_paren_attributes", [], 'env', types={list, tuple}) - app.add_config_value("c_extra_keywords", _macroKeywords, 'env', types={set, list}) + app.add_config_value('c_id_attributes', [], 'env', types={list, tuple}) + app.add_config_value('c_paren_attributes', [], 'env', types={list, tuple}) + app.add_config_value('c_extra_keywords', _macroKeywords, 'env', types={set, list}) app.add_config_value( - "c_maximum_signature_line_length", None, 'env', types={int, type(None)} + 'c_maximum_signature_line_length', None, 'env', types={int, type(None)} ) app.add_post_transform(AliasTransform) diff --git a/sphinx/domains/c/_ast.py b/sphinx/domains/c/_ast.py index 5a7640c8ba8..583e9c7bb1a 100644 --- a/sphinx/domains/c/_ast.py +++ b/sphinx/domains/c/_ast.py @@ -26,20 +26,27 @@ from sphinx.util.cfamily import StringifyTransform DeclarationType: TypeAlias = Union[ # NoQA: UP007 - "ASTStruct", "ASTUnion", "ASTEnum", "ASTEnumerator", - "ASTType", "ASTTypeWithInit", "ASTMacro", + 'ASTStruct', + 'ASTUnion', + 'ASTEnum', + 'ASTEnumerator', + 'ASTType', + 'ASTTypeWithInit', + 'ASTMacro', ] class ASTBase(ASTBaseBase): - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: raise NotImplementedError(repr(self)) # Names ################################################################################ + class ASTIdentifier(ASTBaseBase): def __init__(self, name: str) -> None: if not isinstance(name, str) or len(name) == 0: @@ -66,25 +73,35 @@ def __str__(self) -> str: return self.name def get_display_string(self) -> str: - return "[anonymous]" if self.is_anonymous else self.name + return '[anonymous]' if self.is_anonymous else self.name def _stringify(self, transform: StringifyTransform) -> str: return transform(self.get_display_string()) - def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironment, - prefix: str, symbol: Symbol) -> None: + 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_anonymous: - node = addnodes.desc_sig_name(text="[anonymous]") + node = addnodes.desc_sig_name(text='[anonymous]') else: node = addnodes.desc_sig_name(self.name, self.name) if mode == 'markType': target_text = prefix + self.name - pnode = addnodes.pending_xref('', refdomain='c', - reftype='identifier', - reftarget=target_text, modname=None, - classname=None) + pnode = addnodes.pending_xref( + '', + refdomain='c', + reftype='identifier', + reftarget=target_text, + modname=None, + classname=None, + ) pnode['c:parent_key'] = symbol.get_lookup_key() pnode += node signode += pnode @@ -101,7 +118,8 @@ def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironm def identifier(self) -> str: warnings.warn( '`ASTIdentifier.identifier` is deprecated, use `ASTIdentifier.name` instead', - DeprecationWarning, stacklevel=2, + DeprecationWarning, + stacklevel=2, ) return self.name @@ -134,18 +152,19 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return res - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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?" + 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?" + unreachable = 'Can this happen?' raise AssertionError(unreachable) # TODO signode += nodes.Text('.') n = self.names[i] @@ -197,6 +216,7 @@ def describe_signature(self, signode: TextElement, mode: str, # Expressions ################################################################################ + class ASTExpression(ASTBase): pass @@ -204,6 +224,7 @@ class ASTExpression(ASTBase): # Primary expressions ################################################################################ + class ASTLiteral(ASTExpression): pass @@ -226,8 +247,9 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return 'false' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: txt = str(self) signode += addnodes.desc_sig_keyword(txt, txt) @@ -247,8 +269,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return self.data - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: txt = str(self) signode += addnodes.desc_sig_literal_number(txt, txt) @@ -266,10 +289,7 @@ def __init__(self, prefix: str, data: str) -> None: def __eq__(self, other: object) -> bool: if not isinstance(other, ASTCharLiteral): return NotImplemented - return ( - self.prefix == other.prefix - and self.value == other.value - ) + return self.prefix == other.prefix and self.value == other.value def __hash__(self) -> int: return hash((self.prefix, self.value)) @@ -280,8 +300,9 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return self.prefix + "'" + self.data + "'" - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: txt = str(self) signode += addnodes.desc_sig_literal_char(txt, txt) @@ -301,8 +322,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return self.data - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: txt = str(self) signode += addnodes.desc_sig_literal_string(txt, txt) @@ -326,8 +348,9 @@ def _stringify(self, transform: StringifyTransform) -> str: 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: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: self.name.describe_signature(signode, mode, env, symbol) @@ -349,8 +372,9 @@ def _stringify(self, transform: StringifyTransform) -> str: 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: + 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(')', ')') @@ -359,6 +383,7 @@ def describe_signature(self, signode: TextElement, mode: str, # Postfix expressions ################################################################################ + class ASTPostfixOp(ASTBase): pass @@ -378,8 +403,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return transform(self.lst) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: self.lst.describe_signature(signode, mode, env, symbol) @@ -398,8 +424,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return '[' + transform(self.expr) + ']' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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(']', ']') @@ -409,8 +436,9 @@ class ASTPostfixInc(ASTPostfixOp): def _stringify(self, transform: StringifyTransform) -> str: return '++' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: signode += addnodes.desc_sig_operator('++', '++') @@ -418,8 +446,9 @@ class ASTPostfixDec(ASTPostfixOp): def _stringify(self, transform: StringifyTransform) -> str: return '--' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: signode += addnodes.desc_sig_operator('--', '--') @@ -438,8 +467,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return '->' + transform(self.name) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -458,10 +488,14 @@ def __hash__(self) -> int: return hash((self.prefix, self.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: + 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) @@ -470,6 +504,7 @@ def describe_signature(self, signode: TextElement, mode: str, # Unary expressions ################################################################################ + class ASTUnaryOpExpr(ASTExpression): def __init__(self, op: str, expr: ASTExpression) -> None: self.op = op @@ -485,12 +520,13 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: if self.op[0] in 'cn': - return self.op + " " + transform(self.expr) + 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: + 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() @@ -512,10 +548,11 @@ def __hash__(self) -> int: return hash(self.typ) def _stringify(self, transform: StringifyTransform) -> str: - return "sizeof(" + transform(self.typ) + ")" + return 'sizeof(' + transform(self.typ) + ')' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -535,10 +572,11 @@ def __hash__(self) -> int: return hash(self.expr) def _stringify(self, transform: StringifyTransform) -> str: - return "sizeof " + transform(self.expr) + return 'sizeof ' + transform(self.expr) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -557,10 +595,11 @@ def __hash__(self) -> int: return hash(self.typ) def _stringify(self, transform: StringifyTransform) -> str: - return "alignof(" + transform(self.typ) + ")" + return 'alignof(' + transform(self.typ) + ')' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -570,6 +609,7 @@ def describe_signature(self, signode: TextElement, mode: str, # Other expressions ################################################################################ + class ASTCastExpr(ASTExpression): def __init__(self, typ: ASTType, expr: ASTExpression) -> None: self.typ = typ @@ -578,10 +618,7 @@ def __init__(self, typ: ASTType, expr: ASTExpression) -> None: def __eq__(self, other: object) -> bool: if not isinstance(other, ASTCastExpr): return NotImplemented - return ( - self.typ == other.typ - and self.expr == other.expr - ) + return self.typ == other.typ and self.expr == other.expr def __hash__(self) -> int: return hash((self.typ, self.expr)) @@ -593,8 +630,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.expr)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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(')', ')') @@ -611,10 +649,7 @@ def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None: def __eq__(self, other: object) -> bool: if not isinstance(other, ASTBinOpExpr): return NotImplemented - return ( - self.exprs == other.exprs - and self.ops == other.ops - ) + return self.exprs == other.exprs and self.ops == other.ops def __hash__(self) -> int: return hash((self.exprs, self.ops)) @@ -629,8 +664,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.exprs[i])) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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() @@ -653,10 +689,7 @@ def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None: def __eq__(self, other: object) -> bool: if not isinstance(other, ASTAssignmentExpr): return NotImplemented - return ( - self.exprs == other.exprs - and self.ops == other.ops - ) + return self.exprs == other.exprs and self.ops == other.ops def __hash__(self) -> int: return hash((self.exprs, self.ops)) @@ -671,8 +704,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.exprs[i])) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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() @@ -703,8 +737,9 @@ def _stringify(self, transform: StringifyTransform) -> str: def get_id(self, version: int) -> str: return str(self.expr) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: signode += nodes.literal(self.expr, self.expr) @@ -712,6 +747,7 @@ def describe_signature(self, signode: TextElement, mode: str, # Types ################################################################################ + class ASTTrailingTypeSpec(ASTBase): pass @@ -732,8 +768,9 @@ def __hash__(self) -> int: def _stringify(self, transform: StringifyTransform) -> str: return ' '.join(self.names) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: first = True for n in self.names: if not first: @@ -751,10 +788,7 @@ def __init__(self, prefix: str, nestedName: ASTNestedName) -> None: def __eq__(self, other: object) -> bool: if not isinstance(other, ASTTrailingTypeSpecName): return NotImplemented - return ( - self.prefix == other.prefix - and self.nestedName == other.nestedName - ) + return self.prefix == other.prefix and self.nestedName == other.nestedName def __hash__(self) -> int: return hash((self.prefix, self.nestedName)) @@ -771,8 +805,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.nestedName)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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() @@ -802,8 +837,9 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return transform(self.arg) - def describe_signature(self, signode: Any, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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('...', '...') @@ -812,7 +848,9 @@ def describe_signature(self, signode: Any, mode: str, class ASTParameters(ASTBase): - def __init__(self, args: list[ASTFunctionParameter], attrs: ASTAttributeList) -> None: + def __init__( + self, args: list[ASTFunctionParameter], attrs: ASTAttributeList + ) -> None: self.args = args self.attrs = attrs @@ -843,8 +881,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.attrs)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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 @@ -852,7 +891,9 @@ def describe_signature(self, signode: TextElement, mode: str, 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) + 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 @@ -881,8 +922,16 @@ def describe_signature(self, signode: TextElement, mode: str, class ASTDeclSpecsSimple(ASTBaseBase): - def __init__(self, storage: str, threadLocal: str, inline: bool, - restrict: bool, volatile: bool, const: bool, attrs: ASTAttributeList) -> None: + 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 @@ -918,13 +967,15 @@ def __hash__(self) -> int: 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) + 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] = [] @@ -970,10 +1021,13 @@ def _add(modifiers: list[Node], text: str) -> None: class ASTDeclSpecs(ASTBase): - def __init__(self, outer: str, - leftSpecs: ASTDeclSpecsSimple, - rightSpecs: ASTDeclSpecsSimple, - trailing: ASTTrailingTypeSpec) -> None: + 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 @@ -1007,17 +1061,18 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(l) if self.trailingTypeSpec: if len(res) > 0: - res.append(" ") + res.append(' ') res.append(transform(self.trailingTypeSpec)) r = str(self.rightSpecs) if len(r) > 0: if len(res) > 0: - res.append(" ") + res.append(' ') res.append(r) - return "".join(res) + return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: verify_description_mode(mode) modifiers: list[Node] = [] @@ -1028,8 +1083,7 @@ def describe_signature(self, signode: TextElement, mode: str, if self.trailingTypeSpec: if len(modifiers) > 0: signode += addnodes.desc_sig_space() - self.trailingTypeSpec.describe_signature(signode, mode, env, - symbol=symbol) + self.trailingTypeSpec.describe_signature(signode, mode, env, symbol=symbol) modifiers = [] self.rightSpecs.describe_signature(modifiers) if len(modifiers) > 0: @@ -1041,9 +1095,17 @@ def describe_signature(self, signode: TextElement, mode: str, # Declarator ################################################################################ + class ASTArray(ASTBase): - def __init__(self, static: bool, const: bool, volatile: bool, restrict: bool, - vla: bool, size: ASTExpression) -> None: + 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 @@ -1093,8 +1155,9 @@ def _stringify(self, transform: StringifyTransform) -> str: el.append(transform(self.size)) return '[' + ' '.join(el) + ']' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: verify_description_mode(mode) signode += addnodes.desc_sig_punctuation('[', '[') add_space = False @@ -1136,8 +1199,9 @@ def require_space_after_declSpecs(self) -> bool: class ASTDeclaratorNameParam(ASTDeclarator): - def __init__(self, declId: ASTNestedName, - arrayOps: list[ASTArray], param: ASTParameters) -> None: + def __init__( + self, declId: ASTNestedName, arrayOps: list[ASTArray], param: ASTParameters + ) -> None: self.declId = declId self.arrayOps = arrayOps self.param = param @@ -1176,8 +1240,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.param)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -1213,12 +1278,13 @@ def _stringify(self, transform: StringifyTransform) -> str: res = [] if self.declId: res.append(transform(self.declId)) - res.append(" : ") + res.append(' : ') res.append(transform(self.size)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -1229,8 +1295,14 @@ def describe_signature(self, signode: TextElement, mode: str, class ASTDeclaratorPtr(ASTDeclarator): - def __init__(self, next: ASTDeclarator, restrict: bool, volatile: bool, const: bool, - attrs: ASTAttributeList) -> None: + def __init__( + self, + next: ASTDeclarator, + restrict: bool, + volatile: bool, + const: bool, + attrs: ASTAttributeList, + ) -> None: assert next self.next = next self.restrict = restrict @@ -1261,9 +1333,13 @@ 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() + 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 = ['*'] @@ -1286,8 +1362,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.next)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -1347,18 +1424,20 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.next)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) + self.next.describe_signature(signode, 'noneIsName', env, symbol) # Initializer ################################################################################ + class ASTParenExprList(ASTBaseParenExprList): def __init__(self, exprs: list[ASTExpression]) -> None: self.exprs = exprs @@ -1375,8 +1454,9 @@ 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: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: verify_description_mode(mode) signode += addnodes.desc_sig_punctuation('(', '(') first = True @@ -1408,8 +1488,9 @@ def _stringify(self, transform: StringifyTransform) -> str: trailing_comma = ',' if self.trailingComma else '' return f'{{{exprs}{trailing_comma}}}' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + def describe_signature( + self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol + ) -> None: verify_description_mode(mode) signode += addnodes.desc_sig_punctuation('{', '{') first = True @@ -1426,8 +1507,9 @@ def describe_signature(self, signode: TextElement, mode: str, class ASTInitializer(ASTBase): - def __init__(self, value: ASTBracedInitList | ASTExpression, - hasAssign: bool = True) -> None: + def __init__( + self, value: ASTBracedInitList | ASTExpression, hasAssign: bool = True + ) -> None: self.value = value self.hasAssign = hasAssign @@ -1446,8 +1528,9 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return val - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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() @@ -1497,12 +1580,12 @@ def get_type_declaration_prefix(self) -> str: else: return 'type' - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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): + 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'. @@ -1538,8 +1621,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.init)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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: @@ -1547,8 +1631,9 @@ def describe_signature(self, signode: TextElement, mode: str, class ASTMacroParameter(ASTBase): - def __init__(self, arg: ASTNestedName | None, ellipsis: bool = False, - variadic: bool = False) -> None: + def __init__( + self, arg: ASTNestedName | None, ellipsis: bool = False, variadic: bool = False + ) -> None: self.arg = arg self.ellipsis = ellipsis self.variadic = variadic @@ -1573,8 +1658,9 @@ def _stringify(self, transform: StringifyTransform) -> str: else: return transform(self.arg) - def describe_signature(self, signode: Any, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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('...', '...') @@ -1586,7 +1672,9 @@ def describe_signature(self, signode: Any, mode: str, class ASTMacro(ASTBase): - def __init__(self, ident: ASTNestedName, args: list[ASTMacroParameter] | None) -> None: + def __init__( + self, ident: ASTNestedName, args: list[ASTMacroParameter] | None + ) -> None: self.ident = ident self.args = args @@ -1619,8 +1707,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(')') return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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: @@ -1651,8 +1740,9 @@ def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: def _stringify(self, transform: StringifyTransform) -> str: return transform(self.name) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -1675,8 +1765,9 @@ def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: def _stringify(self, transform: StringifyTransform) -> str: return transform(self.name) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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) @@ -1699,15 +1790,17 @@ def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: def _stringify(self, transform: StringifyTransform) -> str: return transform(self.name) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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: + def __init__( + self, name: ASTNestedName, init: ASTInitializer | None, attrs: ASTAttributeList + ) -> None: self.name = name self.init = init self.attrs = attrs @@ -1737,8 +1830,9 @@ def _stringify(self, transform: StringifyTransform) -> str: res.append(transform(self.init)) return ''.join(res) - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, symbol: Symbol) -> None: + 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: @@ -1749,9 +1843,13 @@ def describe_signature(self, signode: TextElement, mode: str, class ASTDeclaration(ASTBaseBase): - def __init__(self, objectType: str, directiveType: str | None, - declaration: DeclarationType | ASTFunctionParameter, - semicolon: bool = False) -> None: + def __init__( + self, + objectType: str, + directiveType: str | None, + declaration: DeclarationType | ASTFunctionParameter, + semicolon: bool = False, + ) -> None: self.objectType = objectType self.directiveType = directiveType self.declaration = declaration @@ -1788,8 +1886,12 @@ def __hash__(self) -> int: )) def clone(self) -> ASTDeclaration: - return ASTDeclaration(self.objectType, self.directiveType, - self.declaration.clone(), self.semicolon) + return ASTDeclaration( + self.objectType, + self.directiveType, + self.declaration.clone(), + self.semicolon, + ) @property def name(self) -> ASTNestedName: @@ -1823,8 +1925,13 @@ def _stringify(self, transform: StringifyTransform) -> str: res += ';' return res - def describe_signature(self, signode: TextElement, mode: str, - env: BuildEnvironment, options: dict[str, bool]) -> None: + 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. diff --git a/sphinx/domains/c/_ids.py b/sphinx/domains/c/_ids.py index cd617be9015..c05d255c84c 100644 --- a/sphinx/domains/c/_ids.py +++ b/sphinx/domains/c/_ids.py @@ -4,18 +4,41 @@ # https://en.cppreference.com/w/c/keyword _keywords = [ - 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', - 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', 'int', 'long', - 'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', - 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', - '_Alignas', '_Alignof', '_Atomic', '_Bool', '_Complex', + 'auto', + 'break', + 'case', 'char', 'const', 'continue', + 'default', 'do', 'double', + 'else', 'enum', 'extern', + 'float', 'for', + 'goto', + 'if', 'inline', 'int', + 'long', + 'register', 'restrict', 'return', + 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', + 'typedef', + 'union', 'unsigned', + 'void', 'volatile', + 'while', + '_Alignas', '_Alignof', '_Atomic', + '_Bool', + '_Complex', '_Decimal32', '_Decimal64', '_Decimal128', - '_Generic', '_Imaginary', '_Noreturn', '_Static_assert', '_Thread_local', -] + '_Generic', + '_Imaginary', + '_Noreturn', + '_Static_assert', + '_Thread_local', +] # fmt: skip # These are only keyword'y when the corresponding headers are included. # They are used as default value for c_extra_keywords. _macroKeywords = [ - 'alignas', 'alignof', 'bool', 'complex', 'imaginary', 'noreturn', 'static_assert', + 'alignas', + 'alignof', + 'bool', + 'complex', + 'imaginary', + 'noreturn', + 'static_assert', 'thread_local', ] @@ -33,20 +56,49 @@ ['*', '/', '%'], ['.*', '->*'], ] -_expression_unary_ops = ["++", "--", "*", "&", "+", "-", "!", "not", "~", "compl"] -_expression_assignment_ops = ["=", "*=", "/=", "%=", "+=", "-=", - ">>=", "<<=", "&=", "and_eq", "^=", "xor_eq", "|=", "or_eq"] +_expression_unary_ops = [ + '++', + '--', + '*', + '&', + '+', + '-', + '!', + 'not', + '~', + 'compl', +] +_expression_assignment_ops = [ + '=', + '*=', + '/=', + '%=', + '+=', + '-=', + '>>=', + '<<=', + '&=', + 'and_eq', + '^=', + 'xor_eq', + '|=', + 'or_eq', +] _max_id = 1 _id_prefix = [None, 'c.', 'Cv2.'] # Ids are used in lookup keys which are used across pickled files, # so when _max_id changes, make sure to update the ENV_VERSION. -_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'" - r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.DOTALL) +_string_re = re.compile( + r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'" + r'|"([^"\\]*(?:\\.[^"\\]*)*)")', + re.DOTALL, +) # bool, complex, and imaginary are macro "keywords", so they are handled separately -_simple_type_specifiers_re = re.compile(r""" +_simple_type_specifiers_re = re.compile( + r""" \b( void|_Bool |signed|unsigned @@ -62,4 +114,6 @@ |__fp16 # extension |_Sat|_Fract|fract|_Accum|accum # extension )\b -""", re.VERBOSE) + """, + re.VERBOSE, +) diff --git a/sphinx/domains/c/_parser.py b/sphinx/domains/c/_parser.py index 8c8d930dddd..8bc95b8d1e8 100644 --- a/sphinx/domains/c/_parser.py +++ b/sphinx/domains/c/_parser.py @@ -105,7 +105,7 @@ def _parse_string(self) -> str | None: escape = False while True: if self.eof: - self.fail("Unexpected end during inside string.") + self.fail('Unexpected end during inside string.') elif self.current_char == '"' and not escape: self.pos += 1 break @@ -114,7 +114,7 @@ def _parse_string(self) -> str | None: else: escape = False self.pos += 1 - return self.definition[start_pos:self.pos] + return self.definition[start_pos : self.pos] def _parse_literal(self) -> ASTLiteral | None: # -> integer-literal @@ -130,12 +130,16 @@ def _parse_literal(self) -> ASTLiteral | None: pos = self.pos if self.match(float_literal_re): self.match(float_literal_suffix_re) - return ASTNumberLiteral(self.definition[pos:self.pos]) - for regex in (binary_literal_re, hex_literal_re, - integer_literal_re, octal_literal_re): + return ASTNumberLiteral(self.definition[pos : self.pos]) + for regex in ( + binary_literal_re, + hex_literal_re, + integer_literal_re, + octal_literal_re, + ): if self.match(regex): self.match(integers_literal_suffix_re) - return ASTNumberLiteral(self.definition[pos:self.pos]) + return ASTNumberLiteral(self.definition[pos : self.pos]) string = self._parse_string() if string is not None: @@ -148,10 +152,14 @@ def _parse_literal(self) -> ASTLiteral | None: try: return ASTCharLiteral(prefix, data) except UnicodeDecodeError as e: - self.fail("Can not handle character literal. Internal error was: %s" % e) + self.fail( + 'Can not handle character literal. Internal error was: %s' % e + ) except UnsupportedMultiCharacterCharLiteral: - self.fail("Can not handle character literal" - " resulting in multiple decoded characters.") + self.fail( + 'Can not handle character literal' + ' resulting in multiple decoded characters.' + ) return None def _parse_paren_expression(self) -> ASTExpression | None: @@ -181,8 +189,9 @@ def _parse_primary_expression(self) -> ASTExpression | None: return ASTIdExpression(nn) return None - def _parse_initializer_list(self, name: str, open: str, close: str, - ) -> tuple[list[ASTExpression] | None, bool | None]: + def _parse_initializer_list( + self, name: str, open: str, close: str + ) -> tuple[list[ASTExpression] | None, bool | None]: # Parse open and close with the actual initializer-list in between # -> initializer-clause '...'[opt] # | initializer-list ',' initializer-clause '...'[opt] @@ -218,8 +227,9 @@ def _parse_paren_expression_list(self) -> ASTParenExprList | None: # # expression-list # -> initializer-list - exprs, trailing_comma = self._parse_initializer_list("parenthesized expression-list", - '(', ')') + exprs, trailing_comma = self._parse_initializer_list( + 'parenthesized expression-list', '(', ')' + ) if exprs is None: return None return ASTParenExprList(exprs) @@ -227,7 +237,9 @@ def _parse_paren_expression_list(self) -> ASTParenExprList | None: def _parse_braced_init_list(self) -> ASTBracedInitList | None: # -> '{' initializer-list ','[opt] '}' # | '{' '}' - exprs, trailing_comma = self._parse_initializer_list("braced-init-list", '{', '}') + exprs, trailing_comma = self._parse_initializer_list( + 'braced-init-list', '{', '}' + ) if exprs is None: return None return ASTBracedInitList(exprs, trailing_comma) @@ -331,10 +343,11 @@ def _parse_cast_expression(self) -> ASTExpression: return self._parse_unary_expression() except DefinitionError as ex_unary: errs = [] - errs.append((ex_cast, "If type cast expression")) - errs.append((ex_unary, "If unary expression")) - raise self._make_multi_error(errs, - "Error in cast expression.") from ex_unary + errs.append((ex_cast, 'If type cast expression')) + errs.append((ex_unary, 'If unary expression')) + raise self._make_multi_error( + errs, 'Error in cast expression.' + ) from ex_unary else: return self._parse_unary_expression() @@ -352,11 +365,15 @@ def _parse_logical_or_expression(self) -> ASTExpression: # pm = cast .*, ->* def _parse_bin_op_expr(self: DefinitionParser, op_id: int) -> ASTExpression: if op_id + 1 == len(_expression_bin_ops): + def parser() -> ASTExpression: return self._parse_cast_expression() + else: + def parser() -> ASTExpression: return _parse_bin_op_expr(self, op_id + 1) + exprs = [] ops = [] exprs.append(parser()) @@ -387,9 +404,12 @@ def parser() -> ASTExpression: if not one_more: break return ASTBinOpExpr(exprs, ops) # type: ignore[return-value] + return _parse_bin_op_expr(self, 0) - def _parse_conditional_expression_tail(self, or_expr_head: Any) -> ASTExpression | None: + def _parse_conditional_expression_tail( + self, or_expr_head: Any + ) -> ASTExpression | None: # -> "?" expression ":" assignment-expression return None @@ -436,9 +456,8 @@ def _parse_expression(self) -> ASTExpression: return self._parse_assignment_expression() def _parse_expression_fallback( - self, end: list[str], - parser: Callable[[], ASTExpression], - allow: bool = True) -> ASTExpression: + self, end: list[str], parser: Callable[[], ASTExpression], allow: bool = True + ) -> ASTExpression: # Stupidly "parse" an expression. # 'end' should be a list of characters which ends the expression. @@ -451,8 +470,10 @@ def _parse_expression_fallback( # and for testing we may want to globally disable it if not allow or not self.allowFallbackExpressionParsing: raise - self.warn("Parsing of expression failed. Using fallback parser." - " Error was:\n%s" % e) + self.warn( + 'Parsing of expression failed. Using fallback parser.' + ' Error was:\n%s' % e + ) self.pos = prev_pos # and then the fallback scanning assert end is not None @@ -473,9 +494,10 @@ def _parse_expression_fallback( symbols.pop() self.pos += 1 if len(end) > 0 and self.eof: - self.fail("Could not find end of expression starting at %d." - % start_pos) - value = self.definition[start_pos:self.pos].strip() + self.fail( + 'Could not find end of expression starting at %d.' % start_pos + ) + value = self.definition[start_pos : self.pos].strip() return ASTFallbackExpr(value.strip()) def _parse_nested_name(self) -> ASTNestedName: @@ -488,20 +510,20 @@ def _parse_nested_name(self) -> ASTNestedName: while 1: self.skip_ws() if not self.match(identifier_re): - self.fail("Expected identifier in nested name.") + self.fail('Expected identifier in nested name.') identifier = self.matched_text # make sure there isn't a keyword if identifier in _keywords: - self.fail("Expected identifier in nested name, " - "got keyword: %s" % identifier) + self.fail( + 'Expected identifier in nested name, got keyword: %s' % identifier + ) if self.matched_text in self.config.c_extra_keywords: msg = ( 'Expected identifier, got user-defined keyword: %s.' ' Remove it from c_extra_keywords to allow it as identifier.\n' 'Currently c_extra_keywords is %s.' ) - self.fail(msg % (self.matched_text, - str(self.config.c_extra_keywords))) + self.fail(msg % (self.matched_text, str(self.config.c_extra_keywords))) ident = ASTIdentifier(identifier) names.append(ident) @@ -582,13 +604,15 @@ def _parse_parameters(self, param_mode: str) -> ASTParameters | None: continue if self.skip_string(')'): break - self.fail(f'Expecting "," or ")" in parameters, got "{self.current_char}".') + self.fail( + f'Expecting "," or ")" in parameters, got "{self.current_char}".' + ) attrs = self._parse_attribute_list() return ASTParameters(args, attrs) def _parse_decl_specs_simple( - self, outer: str | None, typed: bool, + self, outer: str | None, typed: bool ) -> ASTDeclSpecsSimple: """Just parse the simple ones.""" storage = None @@ -644,8 +668,15 @@ def _parse_decl_specs_simple( attrs.append(attr) continue break - return ASTDeclSpecsSimple(storage, thread_local, inline, - restrict, volatile, const, ASTAttributeList(attrs)) + return ASTDeclSpecsSimple( + storage, + thread_local, + inline, + restrict, + volatile, + const, + ASTAttributeList(attrs), + ) def _parse_decl_specs(self, outer: str | None, typed: bool = True) -> ASTDeclSpecs: if outer: @@ -662,23 +693,25 @@ def _parse_decl_specs(self, outer: str | None, typed: bool = True) -> ASTDeclSpe return ASTDeclSpecs(outer, left_specs, right_specs, trailing) def _parse_declarator_name_suffix( - self, named: bool | str, param_mode: str, typed: bool, + self, named: bool | str, param_mode: str, typed: bool ) -> ASTDeclarator: assert named in {True, False, 'single'} # now we should parse the name, and then suffixes if named == 'single': if self.match(identifier_re): if self.matched_text in _keywords: - self.fail("Expected identifier, " - "got keyword: %s" % self.matched_text) + self.fail( + 'Expected identifier, got keyword: %s' % self.matched_text + ) if self.matched_text in self.config.c_extra_keywords: msg = ( 'Expected identifier, got user-defined keyword: %s. ' 'Remove it from c_extra_keywords to allow it as identifier.\n' 'Currently c_extra_keywords is %s.' ) - self.fail(msg % (self.matched_text, - str(self.config.c_extra_keywords))) + self.fail( + msg % (self.matched_text, str(self.config.c_extra_keywords)) + ) identifier = ASTIdentifier(self.matched_text) decl_id = ASTNestedName([identifier], rooted=False) else: @@ -726,6 +759,7 @@ def _parse_declarator_name_suffix( def parser() -> ASTExpression: return self._parse_expression() + size = self._parse_expression_fallback([']'], parser) self.skip_ws() if not self.skip_string(']'): @@ -741,15 +775,14 @@ def parser() -> ASTExpression: if self.skip_string(':'): size = self._parse_constant_expression() return ASTDeclaratorNameBitField(declId=decl_id, size=size) - return ASTDeclaratorNameParam(declId=decl_id, arrayOps=array_ops, - param=param) + return ASTDeclaratorNameParam(declId=decl_id, arrayOps=array_ops, param=param) - def _parse_declarator(self, named: bool | str, param_mode: str, - typed: bool = True) -> ASTDeclarator: + def _parse_declarator( + self, named: bool | str, param_mode: str, typed: bool = True + ) -> ASTDeclarator: # 'typed' here means 'parse return type stuff' if param_mode not in {'type', 'function'}: - raise Exception( - "Internal error, unknown param_mode '%s'." % param_mode) + raise Exception("Internal error, unknown param_mode '%s'." % param_mode) prev_errors = [] self.skip_ws() if typed and self.skip_string('*'): @@ -777,20 +810,23 @@ def _parse_declarator(self, named: bool | str, param_mode: str, continue break next = self._parse_declarator(named, param_mode, typed) - return ASTDeclaratorPtr(next=next, - restrict=restrict, volatile=volatile, const=const, - attrs=ASTAttributeList(attrs)) + return ASTDeclaratorPtr( + next=next, + restrict=restrict, + volatile=volatile, + const=const, + attrs=ASTAttributeList(attrs), + ) if typed and self.current_char == '(': # note: peeking, not skipping # maybe this is the beginning of params, try that first, # otherwise assume it's noptr->declarator > ( ptr-declarator ) pos = self.pos try: # assume this is params - res = self._parse_declarator_name_suffix(named, param_mode, - typed) + res = self._parse_declarator_name_suffix(named, param_mode, typed) return res except DefinitionError as ex_param_qual: - msg = "If declarator-id with parameters" + msg = 'If declarator-id with parameters' if param_mode == 'function': msg += " (e.g., 'void f(int arg)')" prev_errors.append((ex_param_qual, msg)) @@ -803,30 +839,33 @@ def _parse_declarator(self, named: bool | str, param_mode: str, # inside, right? inner = self._parse_declarator(named, param_mode, typed) if not self.skip_string(')'): - self.fail("Expected ')' in \"( ptr-declarator )\"") - next = self._parse_declarator(named=False, - param_mode="type", - typed=typed) + self.fail('Expected \')\' in "( ptr-declarator )"') + next = self._parse_declarator( + named=False, param_mode='type', typed=typed + ) return ASTDeclaratorParen(inner=inner, next=next) except DefinitionError as ex_no_ptr_paren: self.pos = pos - msg = "If parenthesis in noptr-declarator" + msg = 'If parenthesis in noptr-declarator' if param_mode == 'function': msg += " (e.g., 'void (*f(int arg))(double)')" prev_errors.append((ex_no_ptr_paren, msg)) - header = "Error in declarator" - raise self._make_multi_error(prev_errors, header) from ex_no_ptr_paren + header = 'Error in declarator' + raise self._make_multi_error( + prev_errors, header + ) from ex_no_ptr_paren pos = self.pos try: return self._parse_declarator_name_suffix(named, param_mode, typed) except DefinitionError as e: self.pos = pos - prev_errors.append((e, "If declarator-id")) - header = "Error in declarator or parameters" + prev_errors.append((e, 'If declarator-id')) + header = 'Error in declarator or parameters' raise self._make_multi_error(prev_errors, header) from e - def _parse_initializer(self, outer: str | None = None, allow_fallback: bool = True, - ) -> ASTInitializer | None: + def _parse_initializer( + self, outer: str | None = None, allow_fallback: bool = True + ) -> ASTInitializer | None: self.skip_ws() if outer == 'member' and False: # NoQA: SIM223 # TODO braced_init = self._parse_braced_init_list() @@ -845,13 +884,16 @@ def _parse_initializer(self, outer: str | None = None, allow_fallback: bool = Tr elif outer is None: # function parameter fallback_end = [',', ')'] else: - self.fail("Internal error, initializer for outer '%s' not " - "implemented." % outer) + self.fail( + "Internal error, initializer for outer '%s' not implemented." % outer + ) def parser() -> ASTExpression: return self._parse_assignment_expression() - value = self._parse_expression_fallback(fallback_end, parser, allow=allow_fallback) + value = self._parse_expression_fallback( + fallback_end, parser, allow=allow_fallback + ) return ASTInitializer(value) def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType: @@ -871,11 +913,10 @@ def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType: # first try without the type try: decl_specs = self._parse_decl_specs(outer=outer, typed=False) - decl = self._parse_declarator(named=True, param_mode=outer, - typed=False) + decl = self._parse_declarator(named=True, param_mode=outer, typed=False) self.assert_end(allowSemicolon=True) except DefinitionError as ex_untyped: - desc = "If just a name" + desc = 'If just a name' prev_errors.append((ex_untyped, desc)) self.pos = start_pos try: @@ -883,14 +924,14 @@ def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType: decl = self._parse_declarator(named=True, param_mode=outer) except DefinitionError as ex_typed: self.pos = start_pos - desc = "If typedef-like declaration" + desc = 'If typedef-like declaration' prev_errors.append((ex_typed, desc)) # Retain the else branch for easier debugging. # TODO: it would be nice to save the previous stacktrace # and output it here. if True: - header = "Type must be either just a name or a " - header += "typedef-like declaration." + header = 'Type must be either just a name or a ' + header += 'typedef-like declaration.' raise self._make_multi_error(prev_errors, header) from ex_typed else: # NoQA: RET506 # For testing purposes. @@ -900,8 +941,9 @@ def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType: self.pos = start_pos typed = True decl_specs = self._parse_decl_specs(outer=outer, typed=typed) - decl = self._parse_declarator(named=True, param_mode=outer, - typed=typed) + decl = self._parse_declarator( + named=True, param_mode=outer, typed=typed + ) elif outer == 'function': decl_specs = self._parse_decl_specs(outer=outer) decl = self._parse_declarator(named=True, param_mode=outer) @@ -913,7 +955,9 @@ def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType: decl = self._parse_declarator(named=named, param_mode=param_mode) return ASTType(decl_specs, decl) - def _parse_type_with_init(self, named: bool | str, outer: str | None) -> ASTTypeWithInit: + def _parse_type_with_init( + self, named: bool | str, outer: str | None + ) -> ASTTypeWithInit: if outer: assert outer in {'type', 'member', 'function'} type = self._parse_type(outer=outer, named=named) @@ -924,7 +968,7 @@ def _parse_macro(self) -> ASTMacro: self.skip_ws() ident = self._parse_nested_name() if ident is None: - self.fail("Expected identifier in macro definition.") + self.fail('Expected identifier in macro definition.') self.skip_ws() if not self.skip_string_and_ws('('): return ASTMacro(ident, None) @@ -940,7 +984,7 @@ def _parse_macro(self) -> ASTMacro: self.fail('Expected ")" after "..." in macro parameters.') break if not self.match(identifier_re): - self.fail("Expected identifier in macro parameters.") + self.fail('Expected identifier in macro parameters.') nn = ASTNestedName([ASTIdentifier(self.matched_text)], rooted=False) # Allow named variadic args: # https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html @@ -989,12 +1033,31 @@ def parser() -> ASTExpression: def parse_declaration(self, objectType: str, directiveType: str) -> ASTDeclaration: object_type = objectType directive_type = directiveType - if object_type not in {'function', 'member', - 'macro', 'struct', 'union', 'enum', 'enumerator', 'type'}: + if object_type not in { + 'function', + 'member', + 'macro', + 'struct', + 'union', + 'enum', + 'enumerator', + 'type', + }: raise Exception('Internal error, unknown objectType "%s".' % object_type) - if directive_type not in {'function', 'member', 'var', - 'macro', 'struct', 'union', 'enum', 'enumerator', 'type'}: - raise Exception('Internal error, unknown directiveType "%s".' % directive_type) + if directive_type not in { + 'function', + 'member', + 'var', + 'macro', + 'struct', + 'union', + 'enum', + 'enumerator', + 'type', + }: + raise Exception( + 'Internal error, unknown directiveType "%s".' % directive_type + ) declaration: DeclarationType | None = None if object_type == 'member': @@ -1047,9 +1110,9 @@ def parse_expression(self) -> ASTExpression | ASTType: self.skip_ws() self.assert_end() except DefinitionError as ex_type: - header = "Error when parsing (type) expression." + header = 'Error when parsing (type) expression.' errs = [] - errs.append((ex_expr, "If expression")) - errs.append((ex_type, "If type")) + errs.append((ex_expr, 'If expression')) + errs.append((ex_type, 'If type')) raise self._make_multi_error(errs, header) from ex_type return res diff --git a/sphinx/domains/c/_symbol.py b/sphinx/domains/c/_symbol.py index d98a57065ca..eb37a70e35f 100644 --- a/sphinx/domains/c/_symbol.py +++ b/sphinx/domains/c/_symbol.py @@ -27,12 +27,13 @@ def __init__(self, symbol: Symbol, declaration: ASTDeclaration) -> None: self.declaration = declaration def __str__(self) -> str: - return "Internal C duplicate symbol error:\n%s" % self.symbol.dump(0) + return 'Internal C duplicate symbol error:\n%s' % self.symbol.dump(0) class SymbolLookupResult: - def __init__(self, symbols: Sequence[Symbol], parentSymbol: Symbol, - ident: ASTIdentifier) -> None: + def __init__( + self, symbols: Sequence[Symbol], parentSymbol: Symbol, ident: ASTIdentifier + ) -> None: self.symbols = symbols self.parentSymbol = parentSymbol self.ident = ident @@ -43,13 +44,13 @@ def __init__(self, data: list[tuple[ASTIdentifier, str]]) -> None: self.data = data def __str__(self) -> str: - inner = ', '.join(f"({ident}, {id_})" for ident, id_ in self.data) + inner = ', '.join(f'({ident}, {id_})' for ident, id_ in self.data) return f'[{inner}]' class Symbol: debug_indent = 0 - debug_indent_string = " " + debug_indent_string = ' ' debug_lookup = False debug_show_tree = False @@ -65,7 +66,7 @@ def __deepcopy__(self, memo: Any) -> Symbol: @staticmethod def debug_print(*args: Any) -> None: msg = Symbol.debug_indent_string * Symbol.debug_indent - msg += "".join(str(e) for e in args) + msg += ''.join(str(e) for e in args) logger.debug(msg) def _assert_invariants(self) -> None: @@ -78,7 +79,7 @@ def _assert_invariants(self) -> None: assert self.docname def __setattr__(self, key: str, value: Any) -> None: - if key == "children": + if key == 'children': raise AssertionError return super().__setattr__(key, value) @@ -159,12 +160,15 @@ def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> N def _add_function_params(self) -> None: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("_add_function_params:") + Symbol.debug_print('_add_function_params:') # Note: we may be called from _fill_empty, so the symbols we want # to add may actually already be present (as empty symbols). # add symbols for function parameters, if any - if self.declaration is not None and self.declaration.function_params is not None: + if ( + self.declaration is not None + and self.declaration.function_params is not None + ): for p in self.declaration.function_params: if p.arg is None: continue @@ -205,8 +209,8 @@ def clear_doc(self, docname: str) -> None: def get_all_symbols(self) -> Iterator[Symbol]: yield self - for sChild in self._children: - yield from sChild.get_all_symbols() + for s_child in self._children: + yield from s_child.get_all_symbols() @property def children(self) -> Iterator[Symbol]: @@ -244,70 +248,74 @@ def get_full_nested_name(self) -> ASTNestedName: def _symbol_lookup( self, - nestedName: ASTNestedName, - onMissingQualifiedSymbol: Callable[[Symbol, ASTIdentifier], Symbol | None], - ancestorLookupType: str | None, - matchSelf: bool, - recurseInAnon: bool, - searchInSiblings: bool, + nested_name: ASTNestedName, + on_missing_qualified_symbol: Callable[[Symbol, ASTIdentifier], Symbol | None], + ancestor_lookup_type: str | None, + match_self: bool, + recurse_in_anon: bool, + search_in_siblings: bool, ) -> SymbolLookupResult | None: # TODO: further simplification from C++ to C - # ancestorLookupType: if not None, specifies the target type of the lookup + # ancestor_lookup_type: if not None, specifies the target type of the lookup if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("_symbol_lookup:") + Symbol.debug_print('_symbol_lookup:') Symbol.debug_indent += 1 - Symbol.debug_print("self:") + Symbol.debug_print('self:') logger.debug(self.to_string(Symbol.debug_indent + 1, addEndNewline=False)) - Symbol.debug_print("nestedName: ", nestedName) - Symbol.debug_print("ancestorLookupType:", ancestorLookupType) - Symbol.debug_print("matchSelf: ", matchSelf) - Symbol.debug_print("recurseInAnon: ", recurseInAnon) - Symbol.debug_print("searchInSiblings: ", searchInSiblings) + Symbol.debug_print('nested_name: ', nested_name) + Symbol.debug_print('ancestor_lookup_type:', ancestor_lookup_type) + Symbol.debug_print('match_self: ', match_self) + Symbol.debug_print('recurse_in_anon: ', recurse_in_anon) + Symbol.debug_print('search_in_siblings: ', search_in_siblings) - names = nestedName.names + names = nested_name.names # find the right starting point for lookup - parentSymbol = self - if nestedName.rooted: - while parentSymbol.parent is not None: - parentSymbol = parentSymbol.parent + parent_symbol = self + if nested_name.rooted: + while parent_symbol.parent is not None: + parent_symbol = parent_symbol.parent - if ancestorLookupType is not None: + if ancestor_lookup_type is not None: # walk up until we find the first identifier - firstName = names[0] - while parentSymbol.parent: - if firstName.name in parentSymbol._children_by_name: + first_name = names[0] + while parent_symbol.parent: + if first_name.name in parent_symbol._children_by_name: break - parentSymbol = parentSymbol.parent + parent_symbol = parent_symbol.parent if Symbol.debug_lookup: - Symbol.debug_print("starting point:") - logger.debug(parentSymbol.to_string(Symbol.debug_indent + 1, addEndNewline=False)) + Symbol.debug_print('starting point:') + logger.debug( + parent_symbol.to_string(Symbol.debug_indent + 1, addEndNewline=False) + ) # and now the actual lookup for ident in names[:-1]: name = ident.name - if name in parentSymbol._children_by_name: - symbol = parentSymbol._children_by_name[name] + if name in parent_symbol._children_by_name: + symbol = parent_symbol._children_by_name[name] else: - symbol = onMissingQualifiedSymbol(parentSymbol, ident) + symbol = on_missing_qualified_symbol(parent_symbol, ident) if symbol is None: if Symbol.debug_lookup: Symbol.debug_indent -= 2 return None - parentSymbol = symbol + parent_symbol = symbol if Symbol.debug_lookup: - Symbol.debug_print("handle last name from:") - logger.debug(parentSymbol.to_string(Symbol.debug_indent + 1, addEndNewline=False)) + Symbol.debug_print('handle last name from:') + logger.debug( + parent_symbol.to_string(Symbol.debug_indent + 1, addEndNewline=False) + ) # handle the last name ident = names[-1] name = ident.name - symbol = parentSymbol._children_by_name.get(name) - if not symbol and recurseInAnon: - for child in parentSymbol._anon_children: + symbol = parent_symbol._children_by_name.get(name) + if not symbol and recurse_in_anon: + for child in parent_symbol._anon_children: if name in child._children_by_name: symbol = child._children_by_name[name] break @@ -316,11 +324,11 @@ def _symbol_lookup( Symbol.debug_indent -= 2 result = [symbol] if symbol else [] - return SymbolLookupResult(result, parentSymbol, ident) + return SymbolLookupResult(result, parent_symbol, ident) def _add_symbols( self, - nestedName: ASTNestedName, + nested_name: ASTNestedName, declaration: ASTDeclaration | None, docname: str | None, line: int | None, @@ -331,152 +339,172 @@ def _add_symbols( if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("_add_symbols:") + Symbol.debug_print('_add_symbols:') Symbol.debug_indent += 1 - Symbol.debug_print("nn: ", nestedName) - Symbol.debug_print("decl: ", declaration) - Symbol.debug_print(f"location: {docname}:{line}") + Symbol.debug_print('nn: ', nested_name) + Symbol.debug_print('decl: ', declaration) + Symbol.debug_print(f'location: {docname}:{line}') - def onMissingQualifiedSymbol(parentSymbol: Symbol, ident: ASTIdentifier) -> Symbol: + def on_missing_qualified_symbol( + parent_symbol: Symbol, ident: ASTIdentifier + ) -> Symbol: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("_add_symbols, onMissingQualifiedSymbol:") + Symbol.debug_print('_add_symbols, on_missing_qualified_symbol:') Symbol.debug_indent += 1 - Symbol.debug_print("ident: ", ident) + Symbol.debug_print('ident: ', ident) Symbol.debug_indent -= 2 - return Symbol(parent=parentSymbol, ident=ident, - declaration=None, docname=None, line=None) - - lookupResult = self._symbol_lookup(nestedName, - onMissingQualifiedSymbol, - ancestorLookupType=None, - matchSelf=False, - recurseInAnon=False, - searchInSiblings=False) - assert lookupResult is not None # we create symbols all the way, so that can't happen - symbols = list(lookupResult.symbols) + return Symbol( + parent=parent_symbol, + ident=ident, + declaration=None, + docname=None, + line=None, + ) + + lookup_result = self._symbol_lookup( + nested_name, + on_missing_qualified_symbol, + ancestor_lookup_type=None, + match_self=False, + recurse_in_anon=False, + search_in_siblings=False, + ) + # we create symbols all the way, so that can't happen + assert lookup_result is not None + symbols = list(lookup_result.symbols) if len(symbols) == 0: if Symbol.debug_lookup: - Symbol.debug_print("_add_symbols, result, no symbol:") + Symbol.debug_print('_add_symbols, result, no symbol:') Symbol.debug_indent += 1 - Symbol.debug_print("ident: ", lookupResult.ident) - Symbol.debug_print("declaration: ", declaration) - Symbol.debug_print(f"location: {docname}:{line}") + Symbol.debug_print('ident: ', lookup_result.ident) + Symbol.debug_print('declaration: ', declaration) + Symbol.debug_print(f'location: {docname}:{line}') Symbol.debug_indent -= 1 - symbol = Symbol(parent=lookupResult.parentSymbol, - ident=lookupResult.ident, - declaration=declaration, - docname=docname, line=line) + symbol = Symbol( + parent=lookup_result.parentSymbol, + ident=lookup_result.ident, + declaration=declaration, + docname=docname, + line=line, + ) if Symbol.debug_lookup: Symbol.debug_indent -= 2 return symbol if Symbol.debug_lookup: - Symbol.debug_print("_add_symbols, result, symbols:") + Symbol.debug_print('_add_symbols, result, symbols:') Symbol.debug_indent += 1 - Symbol.debug_print("number symbols:", len(symbols)) + Symbol.debug_print('number symbols:', len(symbols)) Symbol.debug_indent -= 1 if not declaration: if Symbol.debug_lookup: - Symbol.debug_print("no declaration") + Symbol.debug_print('no declaration') Symbol.debug_indent -= 2 # good, just a scope creation # TODO: what if we have more than one symbol? return symbols[0] - noDecl = [] - withDecl = [] - dupDecl = [] + no_decl = [] + with_decl = [] + dup_decl = [] for s in symbols: if s.declaration is None: - noDecl.append(s) + no_decl.append(s) elif s.isRedeclaration: - dupDecl.append(s) + dup_decl.append(s) else: - withDecl.append(s) + with_decl.append(s) if Symbol.debug_lookup: - Symbol.debug_print("#noDecl: ", len(noDecl)) - Symbol.debug_print("#withDecl:", len(withDecl)) - Symbol.debug_print("#dupDecl: ", len(dupDecl)) + Symbol.debug_print('#no_decl: ', len(no_decl)) + Symbol.debug_print('#with_decl:', len(with_decl)) + Symbol.debug_print('#dup_decl: ', len(dup_decl)) # With partial builds we may start with a large symbol tree stripped of declarations. - # Essentially any combination of noDecl, withDecl, and dupDecls seems possible. + # Essentially any combination of no_decl, with_decl, and dup_decls seems possible. # TODO: make partial builds fully work. What should happen when the primary symbol gets # deleted, and other duplicates exist? The full document should probably be rebuild. # First check if one of those with a declaration matches. # If it's a function, we need to compare IDs, # otherwise there should be only one symbol with a declaration. - def makeCandSymbol() -> Symbol: + def make_cand_symbol() -> Symbol: if Symbol.debug_lookup: - Symbol.debug_print("begin: creating candidate symbol") - symbol = Symbol(parent=lookupResult.parentSymbol, - ident=lookupResult.ident, - declaration=declaration, - docname=docname, line=line) + Symbol.debug_print('begin: creating candidate symbol') + symbol = Symbol( + parent=lookup_result.parentSymbol, + ident=lookup_result.ident, + declaration=declaration, + docname=docname, + line=line, + ) if Symbol.debug_lookup: - Symbol.debug_print("end: creating candidate symbol") + Symbol.debug_print('end: creating candidate symbol') return symbol - if len(withDecl) == 0: - candSymbol = None + if len(with_decl) == 0: + cand_symbol = None else: - candSymbol = makeCandSymbol() + cand_symbol = make_cand_symbol() - def handleDuplicateDeclaration(symbol: Symbol, candSymbol: Symbol) -> None: + def handle_duplicate_declaration( + symbol: Symbol, cand_symbol: Symbol + ) -> None: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("redeclaration") + Symbol.debug_print('redeclaration') Symbol.debug_indent -= 1 Symbol.debug_indent -= 2 # Redeclaration of the same symbol. # Let the new one be there, but raise an error to the client # so it can use the real symbol as subscope. # This will probably result in a duplicate id warning. - candSymbol.isRedeclaration = True + cand_symbol.isRedeclaration = True raise _DuplicateSymbolError(symbol, declaration) - if declaration.objectType != "function": - assert len(withDecl) <= 1 - handleDuplicateDeclaration(withDecl[0], candSymbol) + if declaration.objectType != 'function': + assert len(with_decl) <= 1 + handle_duplicate_declaration(with_decl[0], cand_symbol) # (not reachable) # a function, so compare IDs - candId = declaration.get_newest_id() + cand_id = declaration.get_newest_id() if Symbol.debug_lookup: - Symbol.debug_print("candId:", candId) - for symbol in withDecl: - oldId = symbol.declaration.get_newest_id() + Symbol.debug_print('cand_id:', cand_id) + for symbol in with_decl: + old_id = symbol.declaration.get_newest_id() if Symbol.debug_lookup: - Symbol.debug_print("oldId: ", oldId) - if candId == oldId: - handleDuplicateDeclaration(symbol, candSymbol) + Symbol.debug_print('old_id: ', old_id) + if cand_id == old_id: + handle_duplicate_declaration(symbol, cand_symbol) # (not reachable) # no candidate symbol found with matching ID # if there is an empty symbol, fill that one - if len(noDecl) == 0: + if len(no_decl) == 0: if Symbol.debug_lookup: Symbol.debug_print( - "no match, no empty, candSybmol is not None?:", candSymbol is not None, + 'no match, no empty, cand_sybmol is not None?:', + cand_symbol is not None, ) Symbol.debug_indent -= 2 - if candSymbol is not None: - return candSymbol + if cand_symbol is not None: + return cand_symbol else: - return makeCandSymbol() + return make_cand_symbol() else: if Symbol.debug_lookup: Symbol.debug_print( - "no match, but fill an empty declaration, candSybmol is not None?:", - candSymbol is not None) + 'no match, but fill an empty declaration, cand_sybmol is not None?:', + cand_symbol is not None, + ) Symbol.debug_indent -= 2 - if candSymbol is not None: - candSymbol.remove() - # assert len(noDecl) == 1 + if cand_symbol is not None: + cand_symbol.remove() + # assert len(no_decl) == 1 # TODO: enable assertion when we at some point find out how to do cleanup # for now, just take the first one, it should work fine ... right? - symbol = noDecl[0] + symbol = no_decl[0] # If someone first opened the scope, and then later # declares it, e.g, # .. namespace:: Test @@ -485,44 +513,48 @@ def handleDuplicateDeclaration(symbol: Symbol, candSymbol: Symbol) -> None: symbol._fill_empty(declaration, docname, line) return symbol - def merge_with(self, other: Symbol, docnames: list[str], - env: BuildEnvironment) -> None: + def merge_with( + self, other: Symbol, docnames: list[str], env: BuildEnvironment + ) -> None: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("merge_with:") + Symbol.debug_print('merge_with:') assert other is not None - for otherChild in other._children: - otherName = otherChild.ident.name - if otherName not in self._children_by_name: + for other_child in other._children: + other_name = other_child.ident.name + if other_name not in self._children_by_name: # TODO: hmm, should we prune by docnames? - otherChild.parent = self - self._add_child(otherChild) - otherChild._assert_invariants() + other_child.parent = self + self._add_child(other_child) + other_child._assert_invariants() continue - ourChild = self._children_by_name[otherName] - if otherChild.declaration and otherChild.docname in docnames: - if not ourChild.declaration: - ourChild._fill_empty(otherChild.declaration, - otherChild.docname, otherChild.line) - elif ourChild.docname != otherChild.docname: - name = str(ourChild.declaration) - msg = __("Duplicate C declaration, also defined at %s:%s.\n" - "Declaration is '.. c:%s:: %s'.") + our_child = self._children_by_name[other_name] + if other_child.declaration and other_child.docname in docnames: + if not our_child.declaration: + our_child._fill_empty( + other_child.declaration, other_child.docname, other_child.line + ) + elif our_child.docname != other_child.docname: + name = str(our_child.declaration) + msg = __( + 'Duplicate C declaration, also defined at %s:%s.\n' + "Declaration is '.. c:%s:: %s'." + ) logger.warning( msg, - ourChild.docname, - ourChild.line, - ourChild.declaration.directiveType, + our_child.docname, + our_child.line, + our_child.declaration.directiveType, name, - location=(otherChild.docname, otherChild.line), + location=(other_child.docname, other_child.line), ) else: # Both have declarations, and in the same docname. # This can apparently happen, it should be safe to # just ignore it, right? pass - ourChild.merge_with(otherChild, docnames, env) + our_child.merge_with(other_child, docnames, env) if Symbol.debug_lookup: Symbol.debug_indent -= 1 @@ -530,45 +562,52 @@ def merge_with(self, other: Symbol, docnames: list[str], def add_name(self, nestedName: ASTNestedName) -> Symbol: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("add_name:") + Symbol.debug_print('add_name:') res = self._add_symbols(nestedName, declaration=None, docname=None, line=None) if Symbol.debug_lookup: Symbol.debug_indent -= 1 return res - def add_declaration(self, declaration: ASTDeclaration, - docname: str, line: int) -> Symbol: + def add_declaration( + self, declaration: ASTDeclaration, docname: str, line: int + ) -> Symbol: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("add_declaration:") + Symbol.debug_print('add_declaration:') assert declaration is not None assert docname is not None assert line is not None - nestedName = declaration.name - res = self._add_symbols(nestedName, declaration, docname, line) + nested_name = declaration.name + res = self._add_symbols(nested_name, declaration, docname, line) if Symbol.debug_lookup: Symbol.debug_indent -= 1 return res - def find_identifier(self, ident: ASTIdentifier, - matchSelf: bool, recurseInAnon: bool, searchInSiblings: bool, - ) -> Symbol | None: + def find_identifier( + self, + ident: ASTIdentifier, + matchSelf: bool, + recurseInAnon: bool, + searchInSiblings: bool, + ) -> Symbol | None: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("find_identifier:") + Symbol.debug_print('find_identifier:') Symbol.debug_indent += 1 - Symbol.debug_print("ident: ", ident) - Symbol.debug_print("matchSelf: ", matchSelf) - Symbol.debug_print("recurseInAnon: ", recurseInAnon) - Symbol.debug_print("searchInSiblings:", searchInSiblings) + Symbol.debug_print('ident: ', ident) + Symbol.debug_print('matchSelf: ', matchSelf) + Symbol.debug_print('recurseInAnon: ', recurseInAnon) + Symbol.debug_print('searchInSiblings:', searchInSiblings) logger.debug(self.to_string(Symbol.debug_indent + 1, addEndNewline=False)) Symbol.debug_indent -= 2 current = self while current is not None: if Symbol.debug_lookup: Symbol.debug_indent += 2 - Symbol.debug_print("trying:") - logger.debug(current.to_string(Symbol.debug_indent + 1, addEndNewline=False)) + Symbol.debug_print('trying:') + logger.debug( + current.to_string(Symbol.debug_indent + 1, addEndNewline=False) + ) Symbol.debug_indent -= 2 if matchSelf and current.ident == ident: return current @@ -587,49 +626,53 @@ def find_identifier(self, ident: ASTIdentifier, def direct_lookup(self, key: LookupKey) -> Symbol | None: if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("direct_lookup:") + Symbol.debug_print('direct_lookup:') Symbol.debug_indent += 1 s = self for ident, id_ in key.data: s = s._children_by_name.get(ident.name) if Symbol.debug_lookup: - Symbol.debug_print("name: ", ident.name) - Symbol.debug_print("id: ", id_) + Symbol.debug_print('name: ', ident.name) + Symbol.debug_print('id: ', id_) if s is not None: - logger.debug(s.to_string(Symbol.debug_indent + 1, addEndNewline=False)) + logger.debug( + s.to_string(Symbol.debug_indent + 1, addEndNewline=False) + ) else: - Symbol.debug_print("not found") + Symbol.debug_print('not found') if s is None: break if Symbol.debug_lookup: Symbol.debug_indent -= 2 return s - def find_declaration(self, nestedName: ASTNestedName, typ: str, - matchSelf: bool, recurseInAnon: bool) -> Symbol | None: + def find_declaration( + self, nestedName: ASTNestedName, typ: str, matchSelf: bool, recurseInAnon: bool + ) -> Symbol | None: # templateShorthand: missing template parameter lists for templates is ok if Symbol.debug_lookup: Symbol.debug_indent += 1 - Symbol.debug_print("find_declaration:") + Symbol.debug_print('find_declaration:') - def onMissingQualifiedSymbol( - parentSymbol: Symbol, - ident: ASTIdentifier, + def on_missing_qualified_symbol( + parent_symbol: Symbol, ident: ASTIdentifier ) -> Symbol | None: return None - lookupResult = self._symbol_lookup(nestedName, - onMissingQualifiedSymbol, - ancestorLookupType=typ, - matchSelf=matchSelf, - recurseInAnon=recurseInAnon, - searchInSiblings=False) + lookup_result = self._symbol_lookup( + nestedName, + on_missing_qualified_symbol, + ancestor_lookup_type=typ, + match_self=matchSelf, + recurse_in_anon=recurseInAnon, + search_in_siblings=False, + ) if Symbol.debug_lookup: Symbol.debug_indent -= 1 - if lookupResult is None: + if lookup_result is None: return None - symbols = list(lookupResult.symbols) + symbols = list(lookup_result.symbols) if len(symbols) == 0: return None return symbols[0] @@ -644,7 +687,7 @@ def to_string(self, indent: int, *, addEndNewline: bool = True) -> str: else: res.append(str(self.declaration)) if self.declaration: - res.append(": ") + res.append(': ') if self.isRedeclaration: res.append('!!duplicate!! ') res.append(str(self.declaration)) @@ -657,4 +700,7 @@ def to_string(self, indent: int, *, addEndNewline: bool = True) -> str: return ''.join(res) def dump(self, indent: int) -> str: - return ''.join([self.to_string(indent), *(c.dump(indent + 1) for c in self._children)]) + return ''.join([ + self.to_string(indent), + *(c.dump(indent + 1) for c in self._children), + ])