diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2021-01-24 16:34:47 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2021-01-24 16:34:47 +0900 |
commit | 51d500833e391c182f536e83a5d62d5e90ce8ca9 (patch) | |
tree | fb854309b759773feb83e7e4bbc91e3ed3cb2b00 /sphinx/domains/cpp.py | |
parent | 375fb52fe402d46d633e321ce8f20c1aa61c49b9 (diff) | |
parent | 41ee2d6e6595d0eefb4a2b752fd79a3451382d5a (diff) | |
download | sphinx-git-51d500833e391c182f536e83a5d62d5e90ce8ca9.tar.gz |
Merge branch '3.x' into 7774_remove_develop.rst
Diffstat (limited to 'sphinx/domains/cpp.py')
-rw-r--r-- | sphinx/domains/cpp.py | 397 |
1 files changed, 234 insertions, 163 deletions
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 1783db491..25e6f1421 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -4,14 +4,13 @@ The C++ language domain. - :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re -from typing import ( - Any, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar, Union, Optional -) +from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, Type, + TypeVar, Union) from docutils import nodes from docutils.nodes import Element, Node, TextElement, system_message @@ -30,19 +29,17 @@ from sphinx.roles import SphinxRole, XRefRole from sphinx.transforms import SphinxTransform from sphinx.transforms.post_transforms import ReferencesResolver from sphinx.util import logging -from sphinx.util.cfamily import ( - NoOldIdError, ASTBaseBase, ASTAttribute, verify_description_mode, StringifyTransform, - BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral, - identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re, - hex_literal_re, binary_literal_re, integers_literal_suffix_re, - float_literal_re, float_literal_suffix_re, - char_literal_re -) +from sphinx.util.cfamily import (ASTAttribute, ASTBaseBase, ASTBaseParenExprList, BaseParser, + DefinitionError, NoOldIdError, StringifyTransform, + UnsupportedMultiCharacterCharLiteral, anon_identifier_re, + binary_literal_re, char_literal_re, float_literal_re, + float_literal_suffix_re, hex_literal_re, identifier_re, + integer_literal_re, integers_literal_suffix_re, + octal_literal_re, verify_description_mode) from sphinx.util.docfields import Field, GroupedField from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import make_refnode - logger = logging.getLogger(__name__) T = TypeVar('T') @@ -140,7 +137,7 @@ T = TypeVar('T') visibility storage-class-specifier function-specifier "friend" "constexpr" "volatile" "const" trailing-type-specifier # where trailing-type-specifier can no be cv-qualifier - # Inside e.g., template paramters a strict subset is used + # Inside e.g., template parameters a strict subset is used # (see type-specifier-seq) trailing-type-specifier -> simple-type-specifier -> @@ -1595,6 +1592,15 @@ class ASTOperator(ASTBase): identifier = str(self) if mode == 'lastIsName': signode += addnodes.desc_name(identifier, identifier) + elif mode == 'markType': + targetText = prefix + identifier + templateArgs + pnode = addnodes.pending_xref('', refdomain='cpp', + reftype='identifier', + reftarget=targetText, modname=None, + classname=None) + pnode['cpp:parent_key'] = symbol.get_lookup_key() + pnode += nodes.Text(identifier) + signode += pnode else: signode += addnodes.desc_addname(identifier, identifier) @@ -1835,7 +1841,7 @@ class ASTFunctionParameter(ASTBase): # this is not part of the normal name mangling in C++ if symbol: # the anchor will be our parent - return symbol.parent.declaration.get_id(version, prefixed=None) + return symbol.parent.declaration.get_id(version, prefixed=False) # else, do the usual if self.ellipsis: return 'z' @@ -1878,7 +1884,8 @@ class ASTNoexceptSpec(ASTBase): class ASTParametersQualifiers(ASTBase): def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool, refQual: str, exceptionSpec: ASTNoexceptSpec, trailingReturn: "ASTType", - override: bool, final: bool, initializer: str) -> None: + override: bool, final: bool, attrs: List[ASTAttribute], + initializer: str) -> None: self.args = args self.volatile = volatile self.const = const @@ -1887,6 +1894,7 @@ class ASTParametersQualifiers(ASTBase): self.trailingReturn = trailingReturn self.override = override self.final = final + self.attrs = attrs self.initializer = initializer @property @@ -1946,6 +1954,9 @@ class ASTParametersQualifiers(ASTBase): res.append(' final') if self.override: res.append(' override') + for attr in self.attrs: + res.append(' ') + res.append(transform(attr)) if self.initializer: res.append(' = ') res.append(self.initializer) @@ -1987,6 +1998,9 @@ class ASTParametersQualifiers(ASTBase): _add_anno(signode, 'final') if self.override: _add_anno(signode, 'override') + for attr in self.attrs: + signode += nodes.Text(' ') + attr.describe_signature(signode) if self.initializer: _add_text(signode, '= ' + str(self.initializer)) @@ -2742,7 +2756,7 @@ class ASTPackExpansionExpr(ASTExpression): signode += nodes.Text('...') -class ASTParenExprList(ASTBase): +class ASTParenExprList(ASTBaseParenExprList): def __init__(self, exprs: List[Union[ASTExpression, ASTBracedInitList]]) -> None: self.exprs = exprs @@ -3781,6 +3795,16 @@ class Symbol: debug_lookup = False # overridden by the corresponding config value debug_show_tree = False # overridden by the corresponding config value + def __copy__(self): + assert False # shouldn't happen + + def __deepcopy__(self, memo): + if self.parent: + assert False # shouldn't happen + else: + # the domain base class makes a copy of the initial data, which is fine + return Symbol(None, None, None, None, None, None, None) + @staticmethod def debug_print(*args: Any) -> None: print(Symbol.debug_indent_string * Symbol.debug_indent, end="") @@ -3806,7 +3830,8 @@ class Symbol: def __init__(self, parent: "Symbol", identOrOp: Union[ASTIdentifier, ASTOperator], templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction], - templateArgs: Any, declaration: ASTDeclaration, docname: str) -> None: + templateArgs: Any, declaration: ASTDeclaration, + docname: str, line: int) -> None: self.parent = parent # declarations in a single directive are linked together self.siblingAbove = None # type: Symbol @@ -3816,6 +3841,7 @@ class Symbol: self.templateArgs = templateArgs # identifier<templateArgs> self.declaration = declaration self.docname = docname + self.line = line self.isRedeclaration = False self._assert_invariants() @@ -3831,15 +3857,18 @@ class Symbol: # Do symbol addition after self._children has been initialised. self._add_template_and_function_params() - def _fill_empty(self, declaration: ASTDeclaration, docname: str) -> None: + def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> None: self._assert_invariants() - assert not self.declaration - assert not self.docname - assert declaration - assert docname + assert self.declaration is None + assert self.docname is None + assert self.line is None + assert declaration is not None + assert docname is not None + assert line is not None self.declaration = declaration self.declaration.symbol = self self.docname = docname + self.line = line self._assert_invariants() # and symbol addition should be done as well self._add_template_and_function_params() @@ -3863,7 +3892,7 @@ class Symbol: decl = None nne = ASTNestedNameElement(tp.get_identifier(), None) nn = ASTNestedName([nne], [False], rooted=False) - self._add_symbols(nn, [], decl, self.docname) + self._add_symbols(nn, [], decl, self.docname, self.line) # add symbols for function parameters, if any if self.declaration is not None and self.declaration.function_params is not None: for fp in self.declaration.function_params: @@ -3876,7 +3905,7 @@ class Symbol: decl = ASTDeclaration('functionParam', None, None, None, None, fp, None) assert not nn.rooted assert len(nn.names) == 1 - self._add_symbols(nn, [], decl, self.docname) + self._add_symbols(nn, [], decl, self.docname, self.line) if Symbol.debug_lookup: Symbol.debug_indent -= 1 @@ -3894,6 +3923,7 @@ class Symbol: if sChild.declaration and sChild.docname == docname: sChild.declaration = None sChild.docname = None + sChild.line = None if sChild.siblingAbove is not None: sChild.siblingAbove.siblingBelow = sChild.siblingBelow if sChild.siblingBelow is not None: @@ -3906,8 +3936,7 @@ class Symbol: def get_all_symbols(self) -> Iterator[Any]: yield self for sChild in self._children: - for s in sChild.get_all_symbols(): - yield s + yield from sChild.get_all_symbols() @property def children_recurse_anon(self) -> Generator["Symbol", None, None]: @@ -4088,7 +4117,7 @@ class Symbol: Symbol.debug_print("self:") print(self.to_string(Symbol.debug_indent + 1), end="") Symbol.debug_print("nestedName: ", nestedName) - Symbol.debug_print("templateDecls: ", templateDecls) + Symbol.debug_print("templateDecls: ", ",".join(str(t) for t in templateDecls)) Symbol.debug_print("strictTemplateParamArgLists:", strictTemplateParamArgLists) Symbol.debug_print("ancestorLookupType:", ancestorLookupType) Symbol.debug_print("templateShorthand: ", templateShorthand) @@ -4204,7 +4233,7 @@ class Symbol: identOrOp, templateParams, templateArgs) def _add_symbols(self, nestedName: ASTNestedName, templateDecls: List[Any], - declaration: ASTDeclaration, docname: str) -> "Symbol": + declaration: ASTDeclaration, docname: str, line: int) -> "Symbol": # Used for adding a whole path of symbols, where the last may or may not # be an actual declaration. @@ -4212,10 +4241,10 @@ class Symbol: Symbol.debug_indent += 1 Symbol.debug_print("_add_symbols:") Symbol.debug_indent += 1 - Symbol.debug_print("tdecls:", templateDecls) - Symbol.debug_print("nn: ", nestedName) - Symbol.debug_print("decl: ", declaration) - Symbol.debug_print("doc: ", docname) + Symbol.debug_print("tdecls:", ",".join(str(t) for t in templateDecls)) + Symbol.debug_print("nn: ", nestedName) + Symbol.debug_print("decl: ", declaration) + Symbol.debug_print("location: {}:{}".format(docname, line)) def onMissingQualifiedSymbol(parentSymbol: "Symbol", identOrOp: Union[ASTIdentifier, ASTOperator], @@ -4232,7 +4261,7 @@ class Symbol: return Symbol(parent=parentSymbol, identOrOp=identOrOp, templateParams=templateParams, templateArgs=templateArgs, declaration=None, - docname=None) + docname=None, line=None) lookupResult = self._symbol_lookup(nestedName, templateDecls, onMissingQualifiedSymbol, @@ -4253,14 +4282,14 @@ class Symbol: Symbol.debug_print("identOrOp: ", lookupResult.identOrOp) Symbol.debug_print("templateArgs: ", lookupResult.templateArgs) Symbol.debug_print("declaration: ", declaration) - Symbol.debug_print("docname: ", docname) + Symbol.debug_print("location: {}:{}".format(docname, line)) Symbol.debug_indent -= 1 symbol = Symbol(parent=lookupResult.parentSymbol, identOrOp=lookupResult.identOrOp, templateParams=lookupResult.templateParams, templateArgs=lookupResult.templateArgs, declaration=declaration, - docname=docname) + docname=docname, line=line) if Symbol.debug_lookup: Symbol.debug_indent -= 2 return symbol @@ -4273,7 +4302,7 @@ class Symbol: if not declaration: if Symbol.debug_lookup: - Symbol.debug_print("no delcaration") + Symbol.debug_print("no declaration") Symbol.debug_indent -= 2 # good, just a scope creation # TODO: what if we have more than one symbol? @@ -4309,7 +4338,7 @@ class Symbol: templateParams=lookupResult.templateParams, templateArgs=lookupResult.templateArgs, declaration=declaration, - docname=docname) + docname=docname, line=line) if Symbol.debug_lookup: Symbol.debug_print("end: creating candidate symbol") return symbol @@ -4341,6 +4370,11 @@ class Symbol: if Symbol.debug_lookup: Symbol.debug_print("candId:", candId) for symbol in withDecl: + # but all existing must be functions as well, + # otherwise we declare it to be a duplicate + if symbol.declaration.objectType != 'function': + handleDuplicateDeclaration(symbol, candSymbol) + # (not reachable) oldId = symbol.declaration.get_newest_id() if Symbol.debug_lookup: Symbol.debug_print("oldId: ", oldId) @@ -4351,7 +4385,11 @@ class Symbol: # if there is an empty symbol, fill that one if len(noDecl) == 0: if Symbol.debug_lookup: - Symbol.debug_print("no match, no empty, candSybmol is not None?:", candSymbol is not None) # NOQA + Symbol.debug_print("no match, no empty") + if candSymbol is not None: + Symbol.debug_print("result is already created candSymbol") + else: + Symbol.debug_print("result is makeCandSymbol()") Symbol.debug_indent -= 2 if candSymbol is not None: return candSymbol @@ -4372,7 +4410,7 @@ class Symbol: # .. namespace:: Test # .. namespace:: nullptr # .. class:: Test - symbol._fill_empty(declaration, docname) + symbol._fill_empty(declaration, docname, line) return symbol def merge_with(self, other: "Symbol", docnames: List[str], @@ -4451,13 +4489,15 @@ class Symbol: continue if otherChild.declaration and otherChild.docname in docnames: if not ourChild.declaration: - ourChild._fill_empty(otherChild.declaration, otherChild.docname) + ourChild._fill_empty(otherChild.declaration, + otherChild.docname, otherChild.line) elif ourChild.docname != otherChild.docname: name = str(ourChild.declaration) - msg = __("Duplicate declaration, also defined in '%s'.\n" - "Declaration is '%s'.") - msg = msg % (ourChild.docname, name) - logger.warning(msg, location=otherChild.docname) + msg = __("Duplicate C++ declaration, also defined at %s:%s.\n" + "Declaration is '.. cpp:%s:: %s'.") + msg = msg % (ourChild.docname, ourChild.line, + ourChild.declaration.directiveType, name) + logger.warning(msg, location=(otherChild.docname, otherChild.line)) else: # Both have declarations, and in the same docname. # This can apparently happen, it should be safe to @@ -4481,23 +4521,25 @@ class Symbol: else: templateDecls = [] res = self._add_symbols(nestedName, templateDecls, - declaration=None, docname=None) + declaration=None, docname=None, line=None) if Symbol.debug_lookup: Symbol.debug_indent -= 1 return res - def add_declaration(self, declaration: ASTDeclaration, docname: str) -> "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:") - assert declaration - assert docname + assert declaration is not None + assert docname is not None + assert line is not None nestedName = declaration.name if declaration.templatePrefix: templateDecls = declaration.templatePrefix.templates else: templateDecls = [] - res = self._add_symbols(nestedName, templateDecls, declaration, docname) + res = self._add_symbols(nestedName, templateDecls, declaration, docname, line) if Symbol.debug_lookup: Symbol.debug_indent -= 1 return res @@ -4692,7 +4734,8 @@ class Symbol: templateParams=lookupResult.templateParams, templateArgs=lookupResult.templateArgs, declaration=declaration, - docname='fakeDocnameForQuery') + docname='fakeDocnameForQuery', + line=42) queryId = declaration.get_newest_id() for symbol in symbols: if symbol.declaration is None: @@ -4882,7 +4925,7 @@ class DefinitionParser(BaseParser): raise self._make_multi_error([ (eFold, "If fold expression"), (eExpr, "If parenthesized expression") - ], "Error in fold expression or parenthesized expression.") + ], "Error in fold expression or parenthesized expression.") from eExpr return ASTParenExpr(res) # now it definitely is a fold expression if self.skip_string(')'): @@ -5066,7 +5109,7 @@ class DefinitionParser(BaseParser): errors = [] errors.append((eType, "If type")) errors.append((eExpr, "If expression")) - raise self._make_multi_error(errors, header) + raise self._make_multi_error(errors, header) from eExpr else: # a primary expression or a type pos = self.pos try: @@ -5093,7 +5136,7 @@ class DefinitionParser(BaseParser): errors = [] errors.append((eOuter, "If primary expression")) errors.append((eInner, "If type")) - raise self._make_multi_error(errors, header) + raise self._make_multi_error(errors, header) from eInner # and now parse postfixes postFixes = [] # type: List[ASTPostfixOp] @@ -5253,7 +5296,8 @@ class DefinitionParser(BaseParser): errs = [] errs.append((exCast, "If type cast expression")) errs.append((exUnary, "If unary expression")) - raise self._make_multi_error(errs, "Error in cast expression.") + raise self._make_multi_error(errs, + "Error in cast expression.") from exUnary else: return self._parse_unary_expression() @@ -5504,7 +5548,7 @@ class DefinitionParser(BaseParser): self.pos = pos prevErrors.append((e, "If non-type argument")) header = "Error in parsing template argument list." - raise self._make_multi_error(prevErrors, header) + raise self._make_multi_error(prevErrors, header) from e if parsedEnd: assert not parsedComma break @@ -5697,6 +5741,13 @@ class DefinitionParser(BaseParser): override = self.skip_word_and_ws( 'override') # they can be permuted + attrs = [] + while True: + attr = self._parse_attribute() + if attr is None: + break + attrs.append(attr) + self.skip_ws() initializer = None if self.skip_string('='): @@ -5713,7 +5764,7 @@ class DefinitionParser(BaseParser): return ASTParametersQualifiers( args, volatile, const, refQual, exceptionSpec, trailingReturn, - override, final, initializer) + override, final, attrs, initializer) def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple: """Just parse the simple ones.""" @@ -5949,7 +6000,7 @@ class DefinitionParser(BaseParser): self.pos = pos prevErrors.append((exNoPtrParen, "If parenthesis in noptr-declarator")) header = "Error in declarator" - raise self._make_multi_error(prevErrors, header) + raise self._make_multi_error(prevErrors, header) from exNoPtrParen if typed: # pointer to member pos = self.pos try: @@ -5988,7 +6039,7 @@ class DefinitionParser(BaseParser): self.pos = pos prevErrors.append((e, "If declarator-id")) header = "Error in declarator or parameters-and-qualifiers" - raise self._make_multi_error(prevErrors, header) + raise self._make_multi_error(prevErrors, header) from e def _parse_initializer(self, outer: str = None, allowFallback: bool = True ) -> ASTInitializer: @@ -6096,7 +6147,7 @@ class DefinitionParser(BaseParser): header = "Error when parsing function declaration." else: assert False - raise self._make_multi_error(prevErrors, header) + raise self._make_multi_error(prevErrors, header) from exTyped else: # For testing purposes. # do it again to get the proper traceback (how do you @@ -6163,7 +6214,7 @@ class DefinitionParser(BaseParser): errs.append((eType, "If default template argument is a type")) msg = "Error in non-type template parameter" msg += " or constrained template parameter." - raise self._make_multi_error(errs, msg) + raise self._make_multi_error(errs, msg) from eType def _parse_type_using(self) -> ASTTypeUsing: name = self._parse_nested_name() @@ -6238,23 +6289,19 @@ class DefinitionParser(BaseParser): # ========================================================================== - def _parse_template_parameter_list(self) -> ASTTemplateParams: - # only: '<' parameter-list '>' - # we assume that 'template' has just been parsed - templateParams = [] # type: List[ASTTemplateParam] + def _parse_template_paramter(self) -> ASTTemplateParam: self.skip_ws() - if not self.skip_string("<"): - self.fail("Expected '<' after 'template'") - prevErrors = [] - while 1: - self.skip_ws() - if self.skip_word('template'): - # declare a tenplate template parameter - nestedParams = self._parse_template_parameter_list() - else: - nestedParams = None - self.skip_ws() + if self.skip_word('template'): + # declare a tenplate template parameter + nestedParams = self._parse_template_parameter_list() + else: + nestedParams = None + + pos = self.pos + try: + # Unconstrained type parameter or template type parameter key = None + self.skip_ws() if self.skip_word_and_ws('typename'): key = 'typename' elif self.skip_word_and_ws('class'): @@ -6262,52 +6309,79 @@ class DefinitionParser(BaseParser): elif nestedParams: self.fail("Expected 'typename' or 'class' after " "template template parameter list.") - if key: - # declare a type or template type parameter - self.skip_ws() - parameterPack = self.skip_string('...') - self.skip_ws() - if self.match(identifier_re): - identifier = ASTIdentifier(self.matched_text) - else: - identifier = None - self.skip_ws() - if not parameterPack and self.skip_string('='): - default = self._parse_type(named=False, outer=None) - else: - default = None - data = ASTTemplateKeyParamPackIdDefault(key, identifier, - parameterPack, default) - if nestedParams: - # template type - templateParams.append( - ASTTemplateParamTemplateType(nestedParams, data)) - else: - # type - templateParams.append(ASTTemplateParamType(data)) else: - # declare a non-type parameter, or constrained type parameter - pos = self.pos - try: - param = self._parse_type_with_init('maybe', 'templateParam') - templateParams.append(ASTTemplateParamNonType(param)) - except DefinitionError as e: - msg = "If non-type template parameter or constrained template parameter" - prevErrors.append((e, msg)) - self.pos = pos + self.fail("Expected 'typename' or 'class' in tbe " + "beginning of template type parameter.") + self.skip_ws() + parameterPack = self.skip_string('...') + self.skip_ws() + if self.match(identifier_re): + identifier = ASTIdentifier(self.matched_text) + else: + identifier = None + self.skip_ws() + if not parameterPack and self.skip_string('='): + default = self._parse_type(named=False, outer=None) + else: + default = None + if self.current_char not in ',>': + self.fail('Expected "," or ">" after (template) type parameter.') + data = ASTTemplateKeyParamPackIdDefault(key, identifier, + parameterPack, default) + if nestedParams: + return ASTTemplateParamTemplateType(nestedParams, data) + else: + return ASTTemplateParamType(data) + except DefinitionError as eType: + if nestedParams: + raise + try: + # non-type parameter or constrained type parameter + self.pos = pos + param = self._parse_type_with_init('maybe', 'templateParam') + return ASTTemplateParamNonType(param) + except DefinitionError as eNonType: + self.pos = pos + header = "Error when parsing template parameter." + errs = [] + errs.append( + (eType, "If unconstrained type parameter or template type parameter")) + errs.append( + (eNonType, "If constrained type parameter or non-type parameter")) + raise self._make_multi_error(errs, header) + + def _parse_template_parameter_list(self) -> ASTTemplateParams: + # only: '<' parameter-list '>' + # we assume that 'template' has just been parsed + templateParams = [] # type: List[ASTTemplateParam] + self.skip_ws() + if not self.skip_string("<"): + self.fail("Expected '<' after 'template'") + while 1: + pos = self.pos + err = None + try: + param = self._parse_template_paramter() + templateParams.append(param) + except DefinitionError as eParam: + self.pos = pos + err = eParam self.skip_ws() if self.skip_string('>'): return ASTTemplateParams(templateParams) elif self.skip_string(','): - prevErrors = [] continue else: header = "Error in template parameter list." + errs = [] + if err: + errs.append((err, "If parameter")) try: - self.fail('Expected "=", ",", or ">".') + self.fail('Expected "," or ">".') except DefinitionError as e: - prevErrors.append((e, "")) - raise self._make_multi_error(prevErrors, header) + errs.append((e, "If no parameter")) + print(errs) + raise self._make_multi_error(errs, header) def _parse_template_introduction(self) -> ASTTemplateIntroduction: pos = self.pos @@ -6510,7 +6584,7 @@ class DefinitionParser(BaseParser): self.pos = pos prevErrors.append((e, "If type alias or template alias")) header = "Error in type declaration." - raise self._make_multi_error(prevErrors, header) + raise self._make_multi_error(prevErrors, header) from e elif objectType == 'concept': declaration = self._parse_concept() elif objectType == 'member': @@ -6576,7 +6650,7 @@ class DefinitionParser(BaseParser): errs.append((e1, "If shorthand ref")) errs.append((e2, "If full function ref")) msg = "Error in cross-reference." - raise self._make_multi_error(errs, msg) + raise self._make_multi_error(errs, msg) from e2 def parse_expression(self) -> Union[ASTExpression, ASTType]: pos = self.pos @@ -6597,7 +6671,7 @@ class DefinitionParser(BaseParser): errs = [] errs.append((exExpr, "If expression")) errs.append((exType, "If type")) - raise self._make_multi_error(errs, header) + raise self._make_multi_error(errs, header) from exType def _make_phony_error_name() -> ASTNestedName: @@ -6605,7 +6679,7 @@ def _make_phony_error_name() -> ASTNestedName: return ASTNestedName([nne], [False], rooted=False) -class CPPObject(ObjectDescription): +class CPPObject(ObjectDescription[ASTDeclaration]): """Description of a C++ language object.""" doc_field_types = [ @@ -6622,8 +6696,10 @@ class CPPObject(ObjectDescription): names=('returns', 'return')), ] - option_spec = dict(ObjectDescription.option_spec) - option_spec['tparam-line-spec'] = directives.flag + option_spec = { + 'noindexentry': directives.flag, + 'tparam-line-spec': directives.flag, + } def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None: assert ast.objectType == 'enumerator' @@ -6665,7 +6741,7 @@ class CPPObject(ObjectDescription): Symbol(parent=targetSymbol, identOrOp=symbol.identOrOp, templateParams=None, templateArgs=None, declaration=declClone, - docname=self.env.docname) + docname=self.env.docname, line=self.get_source_info()[1]) def add_target_and_index(self, ast: ASTDeclaration, sig: str, signode: TextElement) -> None: @@ -6698,7 +6774,7 @@ class CPPObject(ObjectDescription): if decl.objectType == 'concept': isInConcept = True break - if not isInConcept: + if not isInConcept and 'noindexentry' not in self.options: strippedName = name for prefix in self.env.config.cpp_index_common_prefix: if name.startswith(prefix): @@ -6762,10 +6838,12 @@ class CPPObject(ObjectDescription): parentSymbol = env.temp_data['cpp:parent_symbol'] parentDecl = parentSymbol.declaration if parentDecl is not None and parentDecl.objectType == 'function': - logger.warning("C++ declarations inside functions are not supported." + - " Parent function is " + - str(parentSymbol.get_full_nested_name()), - location=self.get_source_info()) + msg = "C++ declarations inside functions are not supported." \ + " Parent function: {}\nDirective name: {}\nDirective arg: {}" + logger.warning(msg.format( + str(parentSymbol.get_full_nested_name()), + self.name, self.arguments[0] + ), location=self.get_source_info()) name = _make_phony_error_name() symbol = parentSymbol.add_name(name) env.temp_data['cpp:last_symbol'] = symbol @@ -6777,7 +6855,7 @@ class CPPObject(ObjectDescription): return super().run() def handle_signature(self, sig: str, signode: desc_signature) -> ASTDeclaration: - parentSymbol = self.env.temp_data['cpp:parent_symbol'] + parentSymbol = self.env.temp_data['cpp:parent_symbol'] # type: Symbol parser = DefinitionParser(sig, location=signode, config=self.env.config) try: @@ -6790,10 +6868,11 @@ class CPPObject(ObjectDescription): name = _make_phony_error_name() symbol = parentSymbol.add_name(name) self.env.temp_data['cpp:last_symbol'] = symbol - raise ValueError + raise ValueError from e try: - symbol = parentSymbol.add_declaration(ast, docname=self.env.docname) + symbol = parentSymbol.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 @@ -6806,7 +6885,11 @@ class CPPObject(ObjectDescription): # Assume we are actually in the old symbol, # instead of the newly created duplicate. self.env.temp_data['cpp:last_symbol'] = e.symbol - logger.warning("Duplicate declaration, %s", sig, location=signode) + msg = __("Duplicate C++ declaration, also defined at %s:%s.\n" + "Declaration is '.. cpp:%s:: %s'.") + msg = msg % (e.symbol.docname, e.symbol.line, + self.display_object_type, sig) + logger.warning(msg, location=signode) if ast.objectType == 'enumerator': self._add_enumerator_to_parent(ast) @@ -6976,8 +7059,8 @@ class AliasNode(nodes.Element): assert parentKey is not None self.parentKey = parentKey - def copy(self: T) -> T: - return self.__class__(self.sig, env=None, parentKey=self.parentKey) # type: ignore + def copy(self) -> 'AliasNode': + return self.__class__(self.sig, env=None, parentKey=self.parentKey) class AliasTransform(SphinxTransform): @@ -7081,7 +7164,6 @@ class CPPAliasObject(ObjectDescription): node['domain'] = self.domain # 'desctype' is a backwards compatible attribute node['objtype'] = node['desctype'] = self.objtype - node['noindex'] = True self.names = [] # type: List[str] signatures = self.get_signatures() @@ -7178,14 +7260,18 @@ class CPPDomain(Domain): name = 'cpp' label = 'C++' object_types = { - 'class': ObjType(_('class'), 'class', 'type', 'identifier'), - 'union': ObjType(_('union'), 'union', 'type', 'identifier'), - 'function': ObjType(_('function'), 'function', 'func', 'type', 'identifier'), - 'member': ObjType(_('member'), 'member', 'var'), - 'type': ObjType(_('type'), 'type', 'identifier'), - 'concept': ObjType(_('concept'), 'concept', 'identifier'), - 'enum': ObjType(_('enum'), 'enum', 'type', 'identifier'), - 'enumerator': ObjType(_('enumerator'), 'enumerator') + 'class': ObjType(_('class'), 'class', 'struct', 'identifier', 'type'), + 'union': ObjType(_('union'), 'union', 'identifier', 'type'), + 'function': ObjType(_('function'), 'func', 'identifier', 'type'), + 'member': ObjType(_('member'), 'member', 'var', 'identifier'), + 'type': ObjType(_('type'), 'identifier', 'type'), + 'concept': ObjType(_('concept'), 'concept', 'identifier'), + 'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'), + 'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'), + # generated object types + 'functionParam': ObjType(_('function parameter'), 'identifier', 'member', 'var'), # noqa + 'templateParam': ObjType(_('template parameter'), + 'identifier', 'class', 'struct', 'union', 'member', 'var', 'type'), # noqa } directives = { @@ -7225,7 +7311,7 @@ class CPPDomain(Domain): 'texpr': CPPExprRole(asCode=False) } initial_data = { - 'root_symbol': Symbol(None, None, None, None, None, None), + 'root_symbol': Symbol(None, None, None, None, None, None, None), 'names': {} # full name for indexing -> docname } @@ -7273,13 +7359,9 @@ class CPPDomain(Domain): ourNames = self.data['names'] for name, docname in otherdata['names'].items(): if docname in docnames: - if name in ourNames: - msg = __("Duplicate declaration, also defined in '%s'.\n" - "Name of declaration is '%s'.") - msg = msg % (ourNames[name], name) - logger.warning(msg, location=docname) - else: + if name not in ourNames: ourNames[name] = docname + # no need to warn on duplicates, the symbol merge already does that if Symbol.debug_show_tree: print("\tresult:") print(self.data['root_symbol'].dump(1)) @@ -7366,30 +7448,19 @@ class CPPDomain(Domain): if typ.startswith('cpp:'): typ = typ[4:] - origTyp = typ - if typ == 'func': - typ = 'function' - if typ == 'struct': - typ = 'class' declTyp = s.declaration.objectType def checkType() -> bool: - if typ == 'any' or typ == 'identifier': + if typ == 'any': return True - if declTyp == 'templateParam': - # TODO: perhaps this should be strengthened one day - return True - if declTyp == 'functionParam': - if typ == 'var' or typ == 'member': - return True objtypes = self.objtypes_for_role(typ) if objtypes: return declTyp in objtypes - print("Type is %s (originally: %s), declType is %s" % (typ, origTyp, declTyp)) + print("Type is %s, declaration type is %s" % (typ, declTyp)) assert False if not checkType(): logger.warning("cpp:%s targets a %s (%s).", - origTyp, s.declaration.objectType, + typ, s.declaration.objectType, s.get_full_nested_name(), location=node) @@ -7419,10 +7490,10 @@ class CPPDomain(Domain): if env.config.add_function_parentheses and typ == 'any': addParen += 1 # and now this stuff for operator() - if (env.config.add_function_parentheses and typ == 'function' and + if (env.config.add_function_parentheses and typ == 'func' and title.endswith('operator()')): addParen += 1 - if ((typ == 'any' or typ == 'function') and + if ((typ == 'any' or typ == 'func') and title.endswith('operator') and displayName.endswith('operator()')): addParen += 1 @@ -7431,7 +7502,7 @@ class CPPDomain(Domain): if env.config.add_function_parentheses: if typ == 'any' and displayName.endswith('()'): addParen += 1 - elif typ == 'function': + elif typ == 'func': if title.endswith('()') and not displayName.endswith('()'): title = title[:-2] else: |