mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, add support for overload-specific references.
The "any" and "func" roles now accepts full function declarations. Fixes #1552
This commit is contained in:
parent
3348b9255f
commit
1c035d7203
18
CHANGES
18
CHANGES
@ -167,13 +167,17 @@ Features added
|
|||||||
* #4785: napoleon: Add strings to translation file for localisation
|
* #4785: napoleon: Add strings to translation file for localisation
|
||||||
* #4927: Display a warning when invalid values are passed to linenothreshold
|
* #4927: Display a warning when invalid values are passed to linenothreshold
|
||||||
option of highlight directive
|
option of highlight directive
|
||||||
* C++, add a ``cpp:texpr`` role as a sibling to ``cpp:expr``.
|
* C++:
|
||||||
* C++, add support for unions.
|
|
||||||
* C++, add support for anonymous entities using names staring with ``@``.
|
- Add a ``cpp:texpr`` role as a sibling to ``cpp:expr``.
|
||||||
Fixes #3593 and #2683.
|
- Add support for unions.
|
||||||
* #5147: C++, add support for (most) character literals.
|
- #3593, #2683: add support for anonymous entities using names staring with ``@``.
|
||||||
* C++, cross-referencing entities inside primary templates is supported,
|
- #5147: add support for (most) character literals.
|
||||||
and now properly documented.
|
- Cross-referencing entities inside primary templates is supported,
|
||||||
|
and now properly documented.
|
||||||
|
- #1552: add new cross-referencing format for ``cpp:any`` and ``cpp:func`` roles,
|
||||||
|
for referencing specific function overloads.
|
||||||
|
|
||||||
* #3606: MathJax should be loaded with async attribute
|
* #3606: MathJax should be loaded with async attribute
|
||||||
* html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs:
|
* html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs:
|
||||||
#4193)
|
#4193)
|
||||||
|
@ -1005,20 +1005,46 @@ These roles link to the given declaration types:
|
|||||||
When a custom title is not needed it may be useful to use the roles for inline expressions,
|
When a custom title is not needed it may be useful to use the roles for inline expressions,
|
||||||
:rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping.
|
:rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping.
|
||||||
|
|
||||||
.. admonition:: Note on References to Overloaded Functions
|
|
||||||
|
|
||||||
It is currently impossible to link to a specific version of an overloaded
|
|
||||||
function. Currently the C++ domain is the first domain that has basic
|
|
||||||
support for overloaded functions and until there is more data for comparison
|
|
||||||
we don't want to select a bad syntax to reference a specific overload.
|
|
||||||
Currently Sphinx will link to the first overloaded version of the function.
|
|
||||||
|
|
||||||
Declarations without template parameters and template arguments
|
Declarations without template parameters and template arguments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For linking to non-templated declarations the name must be a nested name, e.g.,
|
For linking to non-templated declarations the name must be a nested name, e.g.,
|
||||||
``f`` or ``MyClass::f``.
|
``f`` or ``MyClass::f``.
|
||||||
|
|
||||||
|
|
||||||
|
Overloaded (member) functions
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When a (member) function is referenced using just its name, the reference
|
||||||
|
will point to an arbitrary matching overload.
|
||||||
|
The :rst:role:`cpp:any` and :rst:role:`cpp:func` roles will an alternative
|
||||||
|
format, which simply is a complete function declaration.
|
||||||
|
This will resolve to the exact matching overload.
|
||||||
|
As example, consider the following class declaration:
|
||||||
|
|
||||||
|
.. cpp:namespace-push:: overload_example
|
||||||
|
.. cpp:class:: C
|
||||||
|
|
||||||
|
.. cpp:function:: void f(double d) const
|
||||||
|
.. cpp:function:: void f(double d)
|
||||||
|
.. cpp:function:: void f(int i)
|
||||||
|
.. cpp:function:: void f()
|
||||||
|
|
||||||
|
References using the :rst:role:`cpp:func` role:
|
||||||
|
|
||||||
|
- Arbitrary overload: ``C::f``, :cpp:func:`C::f`
|
||||||
|
- Also arbitrary overload: ``C::f()``, :cpp:func:`C::f()`
|
||||||
|
- Specific overload: ``void C::f()``, :cpp:func:`void C::f()`
|
||||||
|
- Specific overload: ``void C::f(int)``, :cpp:func:`void C::f(int)`
|
||||||
|
- Specific overload: ``void C::f(double)``, :cpp:func:`void C::f(double)`
|
||||||
|
- Specific overload: ``void C::f(double) const``, :cpp:func:`void C::f(double) const`
|
||||||
|
|
||||||
|
Note that the :confval:`add_function_parentheses` configuration variable
|
||||||
|
does not influence specific overload references.
|
||||||
|
|
||||||
|
.. cpp:namespace-pop::
|
||||||
|
|
||||||
|
|
||||||
Templated declarations
|
Templated declarations
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -622,20 +622,6 @@ class ASTBase(UnicodeMixin):
|
|||||||
"""Clone a definition expression node."""
|
"""Clone a definition expression node."""
|
||||||
return deepcopy(self)
|
return deepcopy(self)
|
||||||
|
|
||||||
def get_name(self):
|
|
||||||
# type: () -> unicode
|
|
||||||
"""Return the name.
|
|
||||||
|
|
||||||
Returns either `None` or a node with a name you might call
|
|
||||||
:meth:`split_owner` on.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError(repr(self))
|
|
||||||
|
|
||||||
def prefix_nested_name(self, prefix):
|
|
||||||
# type: (unicode) -> unicode
|
|
||||||
"""Prefix a name node (a node returned by :meth:`get_name`)."""
|
|
||||||
raise NotImplementedError(repr(self))
|
|
||||||
|
|
||||||
def _stringify(self, transform):
|
def _stringify(self, transform):
|
||||||
# type: (Callable[[Any], unicode]) -> unicode
|
# type: (Callable[[Any], unicode]) -> unicode
|
||||||
raise NotImplementedError(repr(self))
|
raise NotImplementedError(repr(self))
|
||||||
@ -1875,7 +1861,7 @@ class ASTTemplateIntroduction(ASTBase):
|
|||||||
class ASTTemplateDeclarationPrefix(ASTBase):
|
class ASTTemplateDeclarationPrefix(ASTBase):
|
||||||
def __init__(self, templates):
|
def __init__(self, templates):
|
||||||
# type: (List[Any]) -> None
|
# type: (List[Any]) -> None
|
||||||
# template is None means it's an explicit instantiation of a variable
|
# templates is None means it's an explicit instantiation of a variable
|
||||||
self.templates = templates
|
self.templates = templates
|
||||||
|
|
||||||
def get_id(self, version):
|
def get_id(self, version):
|
||||||
@ -3606,6 +3592,16 @@ class ASTNamespace(ASTBase):
|
|||||||
self.templatePrefix = templatePrefix
|
self.templatePrefix = templatePrefix
|
||||||
|
|
||||||
|
|
||||||
|
class SymbolLookupResult(object):
|
||||||
|
def __init__(self, symbols, parentSymbol, identOrOp, templateParams, templateArgs):
|
||||||
|
# type: (Iterator[Symbol], Symbol, Union[ASTIdentifier, ASTOperator], Any, ASTTemplateArgs) -> None # NOQA
|
||||||
|
self.symbols = symbols
|
||||||
|
self.parentSymbol = parentSymbol
|
||||||
|
self.identOrOp = identOrOp
|
||||||
|
self.templateParams = templateParams
|
||||||
|
self.templateArgs = templateArgs
|
||||||
|
|
||||||
|
|
||||||
class Symbol(object):
|
class Symbol(object):
|
||||||
def _assert_invariants(self):
|
def _assert_invariants(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
@ -3644,6 +3640,7 @@ class Symbol(object):
|
|||||||
self.isRedeclaration = False
|
self.isRedeclaration = False
|
||||||
self._assert_invariants()
|
self._assert_invariants()
|
||||||
|
|
||||||
|
# Remember to modify Symbol.remove if modifications to the parent change.
|
||||||
self._children = [] # type: List[Symbol]
|
self._children = [] # type: List[Symbol]
|
||||||
self._anonChildren = [] # type: List[Symbol]
|
self._anonChildren = [] # type: List[Symbol]
|
||||||
# note: _children includes _anonChildren
|
# note: _children includes _anonChildren
|
||||||
@ -3682,6 +3679,13 @@ class Symbol(object):
|
|||||||
templateParams=None, templateArgs=None,
|
templateParams=None, templateArgs=None,
|
||||||
declaration=decl, docname=docname)
|
declaration=decl, docname=docname)
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
if self.parent is None:
|
||||||
|
return
|
||||||
|
assert self in self.parent._children
|
||||||
|
self.parent._children.remove(self)
|
||||||
|
self.parent = None
|
||||||
|
|
||||||
def _fill_empty(self, declaration, docname):
|
def _fill_empty(self, declaration, docname):
|
||||||
# type: (ASTDeclaration, unicode) -> None
|
# type: (ASTDeclaration, unicode) -> None
|
||||||
self._assert_invariants()
|
self._assert_invariants()
|
||||||
@ -3745,16 +3749,35 @@ class Symbol(object):
|
|||||||
templates.append(False)
|
templates.append(False)
|
||||||
return ASTNestedName(names, templates, rooted=False)
|
return ASTNestedName(names, templates, rooted=False)
|
||||||
|
|
||||||
def _find_named_symbol(self,
|
def _find_first_named_symbol(
|
||||||
identOrOp, # type: Union[ASTIdentifier, ASTOperator]
|
self,
|
||||||
templateParams, # type: Any
|
identOrOp, # type: Union[ASTIdentifier, ASTOperator]
|
||||||
templateArgs, # type: ASTTemplateArgs
|
templateParams, # type: Any
|
||||||
templateShorthand, # type: bool
|
templateArgs, # type: ASTTemplateArgs
|
||||||
matchSelf, # type: bool
|
templateShorthand, # type: bool
|
||||||
recurseInAnon, # type: bool
|
matchSelf, # type: bool
|
||||||
correctPrimaryTemplateArgs # type: bool
|
recurseInAnon, # type: bool
|
||||||
):
|
correctPrimaryTemplateArgs # type: bool
|
||||||
|
): # NOQA
|
||||||
# type: (...) -> Symbol
|
# type: (...) -> Symbol
|
||||||
|
res = self._find_named_symbols(identOrOp, templateParams, templateArgs,
|
||||||
|
templateShorthand, matchSelf, recurseInAnon,
|
||||||
|
correctPrimaryTemplateArgs)
|
||||||
|
try:
|
||||||
|
return next(res)
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _find_named_symbols(self,
|
||||||
|
identOrOp, # type: Union[ASTIdentifier, ASTOperator]
|
||||||
|
templateParams, # type: Any
|
||||||
|
templateArgs, # type: ASTTemplateArgs
|
||||||
|
templateShorthand, # type: bool
|
||||||
|
matchSelf, # type: bool
|
||||||
|
recurseInAnon, # type: bool
|
||||||
|
correctPrimaryTemplateArgs # type: bool
|
||||||
|
):
|
||||||
|
# type: (...) -> Iterator[Symbol]
|
||||||
|
|
||||||
def isSpecialization():
|
def isSpecialization():
|
||||||
# the names of the template parameters must be given exactly as args
|
# the names of the template parameters must be given exactly as args
|
||||||
@ -3807,12 +3830,11 @@ class Symbol(object):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
if matchSelf and matches(self):
|
if matchSelf and matches(self):
|
||||||
return self
|
yield self
|
||||||
children = self.children_recurse_anon if recurseInAnon else self._children
|
children = self.children_recurse_anon if recurseInAnon else self._children
|
||||||
for s in children:
|
for s in children:
|
||||||
if matches(s):
|
if matches(s):
|
||||||
return s
|
yield s
|
||||||
return None
|
|
||||||
|
|
||||||
def _symbol_lookup(
|
def _symbol_lookup(
|
||||||
self,
|
self,
|
||||||
@ -3827,7 +3849,7 @@ class Symbol(object):
|
|||||||
recurseInAnon, # type: bool
|
recurseInAnon, # type: bool
|
||||||
correctPrimaryTemplateArgs # type: bool
|
correctPrimaryTemplateArgs # type: bool
|
||||||
):
|
):
|
||||||
# type: (...) -> Tuple[Symbol, Symbol, Union[ASTIdentifier, ASTOperator], Any, ASTTemplateArgs] # NOQA
|
# type: (...) -> SymbolLookupResult
|
||||||
# ancestorLookupType: if not None, specifies the target type of the lookup
|
# ancestorLookupType: if not None, specifies the target type of the lookup
|
||||||
|
|
||||||
if strictTemplateParamArgLists:
|
if strictTemplateParamArgLists:
|
||||||
@ -3885,7 +3907,7 @@ class Symbol(object):
|
|||||||
else:
|
else:
|
||||||
templateParams = None
|
templateParams = None
|
||||||
|
|
||||||
symbol = parentSymbol._find_named_symbol(
|
symbol = parentSymbol._find_first_named_symbol(
|
||||||
identOrOp,
|
identOrOp,
|
||||||
templateParams, templateArgs,
|
templateParams, templateArgs,
|
||||||
templateShorthand=templateShorthand,
|
templateShorthand=templateShorthand,
|
||||||
@ -3896,7 +3918,7 @@ class Symbol(object):
|
|||||||
symbol = onMissingQualifiedSymbol(parentSymbol, identOrOp,
|
symbol = onMissingQualifiedSymbol(parentSymbol, identOrOp,
|
||||||
templateParams, templateArgs)
|
templateParams, templateArgs)
|
||||||
if symbol is None:
|
if symbol is None:
|
||||||
return None, None, None, None, None
|
return None
|
||||||
# We have now matched part of a nested name, and need to match more
|
# We have now matched part of a nested name, and need to match more
|
||||||
# so even if we should matchSelf before, we definitely shouldn't
|
# so even if we should matchSelf before, we definitely shouldn't
|
||||||
# even more. (see also issue #2666)
|
# even more. (see also issue #2666)
|
||||||
@ -3914,13 +3936,12 @@ class Symbol(object):
|
|||||||
assert iTemplateDecl == len(templateDecls)
|
assert iTemplateDecl == len(templateDecls)
|
||||||
templateParams = None
|
templateParams = None
|
||||||
|
|
||||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
symbols = parentSymbol._find_named_symbols(
|
||||||
templateParams, templateArgs,
|
identOrOp, templateParams, templateArgs,
|
||||||
templateShorthand=templateShorthand,
|
templateShorthand=templateShorthand, matchSelf=matchSelf,
|
||||||
matchSelf=matchSelf,
|
recurseInAnon=recurseInAnon, correctPrimaryTemplateArgs=False)
|
||||||
recurseInAnon=recurseInAnon,
|
return SymbolLookupResult(symbols, parentSymbol,
|
||||||
correctPrimaryTemplateArgs=False)
|
identOrOp, templateParams, templateArgs)
|
||||||
return symbol, parentSymbol, identOrOp, templateParams, templateArgs
|
|
||||||
|
|
||||||
def _add_symbols(self, nestedName, templateDecls, declaration, docname):
|
def _add_symbols(self, nestedName, templateDecls, declaration, docname):
|
||||||
# type: (ASTNestedName, List[Any], ASTDeclaration, unicode) -> Symbol
|
# type: (ASTNestedName, List[Any], ASTDeclaration, unicode) -> Symbol
|
||||||
@ -3934,15 +3955,20 @@ class Symbol(object):
|
|||||||
templateArgs=templateArgs, declaration=None,
|
templateArgs=templateArgs, declaration=None,
|
||||||
docname=None)
|
docname=None)
|
||||||
|
|
||||||
symbol, parentSymbol, identOrOp, templateParams, templateArgs = \
|
lookupResult = self._symbol_lookup(nestedName, templateDecls,
|
||||||
self._symbol_lookup(nestedName, templateDecls,
|
onMissingQualifiedSymbol,
|
||||||
onMissingQualifiedSymbol,
|
strictTemplateParamArgLists=True,
|
||||||
strictTemplateParamArgLists=True,
|
ancestorLookupType=None,
|
||||||
ancestorLookupType=None,
|
templateShorthand=False,
|
||||||
templateShorthand=False,
|
matchSelf=False,
|
||||||
matchSelf=False,
|
recurseInAnon=True,
|
||||||
recurseInAnon=True,
|
correctPrimaryTemplateArgs=True)
|
||||||
correctPrimaryTemplateArgs=True)
|
assert lookupResult is not None # we create symbols all the way, so that can't happen
|
||||||
|
# TODO: actually do the iteration over results, though let's find a test case first
|
||||||
|
try:
|
||||||
|
symbol = next(lookupResult.symbols)
|
||||||
|
except StopIteration:
|
||||||
|
symbol = None
|
||||||
|
|
||||||
if symbol:
|
if symbol:
|
||||||
if not declaration:
|
if not declaration:
|
||||||
@ -3958,9 +3984,10 @@ class Symbol(object):
|
|||||||
return symbol
|
return symbol
|
||||||
# It may simply be a function overload, so let's compare ids.
|
# It may simply be a function overload, so let's compare ids.
|
||||||
isRedeclaration = True
|
isRedeclaration = True
|
||||||
candSymbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
candSymbol = Symbol(parent=lookupResult.parentSymbol,
|
||||||
templateParams=templateParams,
|
identOrOp=lookupResult.identOrOp,
|
||||||
templateArgs=templateArgs,
|
templateParams=lookupResult.templateParams,
|
||||||
|
templateArgs=lookupResult.templateArgs,
|
||||||
declaration=declaration,
|
declaration=declaration,
|
||||||
docname=docname)
|
docname=docname)
|
||||||
if declaration.objectType == "function":
|
if declaration.objectType == "function":
|
||||||
@ -3978,9 +4005,10 @@ class Symbol(object):
|
|||||||
candSymbol.isRedeclaration = True
|
candSymbol.isRedeclaration = True
|
||||||
raise _DuplicateSymbolError(symbol, declaration)
|
raise _DuplicateSymbolError(symbol, declaration)
|
||||||
else:
|
else:
|
||||||
symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
symbol = Symbol(parent=lookupResult.parentSymbol,
|
||||||
templateParams=templateParams,
|
identOrOp=lookupResult.identOrOp,
|
||||||
templateArgs=templateArgs,
|
templateParams=lookupResult.templateParams,
|
||||||
|
templateArgs=lookupResult.templateArgs,
|
||||||
declaration=declaration,
|
declaration=declaration,
|
||||||
docname=docname)
|
docname=docname)
|
||||||
return symbol
|
return symbol
|
||||||
@ -3989,13 +4017,12 @@ class Symbol(object):
|
|||||||
# type: (Symbol, List[unicode], BuildEnvironment) -> None
|
# type: (Symbol, List[unicode], BuildEnvironment) -> None
|
||||||
assert other is not None
|
assert other is not None
|
||||||
for otherChild in other._children:
|
for otherChild in other._children:
|
||||||
ourChild = self._find_named_symbol(identOrOp=otherChild.identOrOp,
|
ourChild = self._find_first_named_symbol(
|
||||||
templateParams=otherChild.templateParams,
|
identOrOp=otherChild.identOrOp,
|
||||||
templateArgs=otherChild.templateArgs,
|
templateParams=otherChild.templateParams,
|
||||||
templateShorthand=False,
|
templateArgs=otherChild.templateArgs,
|
||||||
matchSelf=False,
|
templateShorthand=False, matchSelf=False,
|
||||||
recurseInAnon=False,
|
recurseInAnon=False, correctPrimaryTemplateArgs=False)
|
||||||
correctPrimaryTemplateArgs=False)
|
|
||||||
if ourChild is None:
|
if ourChild is None:
|
||||||
# TODO: hmm, should we prune by docnames?
|
# TODO: hmm, should we prune by docnames?
|
||||||
self._children.append(otherChild)
|
self._children.append(otherChild)
|
||||||
@ -4054,12 +4081,12 @@ class Symbol(object):
|
|||||||
for name, templateParams in key:
|
for name, templateParams in key:
|
||||||
identOrOp = name.identOrOp
|
identOrOp = name.identOrOp
|
||||||
templateArgs = name.templateArgs
|
templateArgs = name.templateArgs
|
||||||
s = s._find_named_symbol(identOrOp,
|
s = s._find_first_named_symbol(identOrOp,
|
||||||
templateParams, templateArgs,
|
templateParams, templateArgs,
|
||||||
templateShorthand=False,
|
templateShorthand=False,
|
||||||
matchSelf=False,
|
matchSelf=False,
|
||||||
recurseInAnon=False,
|
recurseInAnon=False,
|
||||||
correctPrimaryTemplateArgs=False)
|
correctPrimaryTemplateArgs=False)
|
||||||
if not s:
|
if not s:
|
||||||
return None
|
return None
|
||||||
return s
|
return s
|
||||||
@ -4077,30 +4104,76 @@ class Symbol(object):
|
|||||||
# Is there another case where it would be good?
|
# Is there another case where it would be good?
|
||||||
return None
|
return None
|
||||||
|
|
||||||
symbol, parentSymbol, identOrOp, templateParams, templateArgs = \
|
lookupResult = self._symbol_lookup(nestedName, templateDecls,
|
||||||
self._symbol_lookup(nestedName, templateDecls,
|
onMissingQualifiedSymbol,
|
||||||
onMissingQualifiedSymbol,
|
strictTemplateParamArgLists=False,
|
||||||
strictTemplateParamArgLists=False,
|
ancestorLookupType=typ,
|
||||||
ancestorLookupType=typ,
|
templateShorthand=templateShorthand,
|
||||||
templateShorthand=templateShorthand,
|
matchSelf=matchSelf,
|
||||||
matchSelf=matchSelf,
|
recurseInAnon=recurseInAnon,
|
||||||
recurseInAnon=recurseInAnon,
|
correctPrimaryTemplateArgs=False)
|
||||||
correctPrimaryTemplateArgs=False)
|
if lookupResult is None:
|
||||||
|
# if it was a part of the qualification that could not be found
|
||||||
if symbol is not None:
|
|
||||||
return symbol
|
|
||||||
# if it was a part of the qualification that could not be found:
|
|
||||||
if parentSymbol is None:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# TODO: hmm, what if multiple symbols match?
|
||||||
|
try:
|
||||||
|
return next(lookupResult.symbols)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
# try without template params and args
|
# try without template params and args
|
||||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
symbol = lookupResult.parentSymbol._find_first_named_symbol(
|
||||||
None, None,
|
lookupResult.identOrOp, None, None,
|
||||||
templateShorthand=templateShorthand,
|
templateShorthand=templateShorthand, matchSelf=matchSelf,
|
||||||
matchSelf=matchSelf,
|
recurseInAnon=recurseInAnon, correctPrimaryTemplateArgs=False)
|
||||||
recurseInAnon=recurseInAnon,
|
|
||||||
correctPrimaryTemplateArgs=False)
|
|
||||||
return symbol
|
return symbol
|
||||||
|
|
||||||
|
def find_declaration(self, declaration, typ, templateShorthand,
|
||||||
|
matchSelf, recurseInAnon):
|
||||||
|
# type: (ASTDeclaration, unicode, bool, bool, bool) -> Symbol
|
||||||
|
# templateShorthand: missing template parameter lists for templates is ok
|
||||||
|
nestedName = declaration.name
|
||||||
|
if declaration.templatePrefix:
|
||||||
|
templateDecls = declaration.templatePrefix.templates
|
||||||
|
else:
|
||||||
|
templateDecls = []
|
||||||
|
|
||||||
|
def onMissingQualifiedSymbol(parentSymbol, identOrOp, templateParams, templateArgs):
|
||||||
|
# type: (Symbol, Union[ASTIdentifier, ASTOperator], Any, ASTTemplateArgs) -> Symbol
|
||||||
|
return None
|
||||||
|
|
||||||
|
lookupResult = self._symbol_lookup(nestedName, templateDecls,
|
||||||
|
onMissingQualifiedSymbol,
|
||||||
|
strictTemplateParamArgLists=False,
|
||||||
|
ancestorLookupType=typ,
|
||||||
|
templateShorthand=templateShorthand,
|
||||||
|
matchSelf=matchSelf,
|
||||||
|
recurseInAnon=recurseInAnon,
|
||||||
|
correctPrimaryTemplateArgs=False)
|
||||||
|
|
||||||
|
if lookupResult is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
symbols = list(lookupResult.symbols)
|
||||||
|
if len(symbols) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
querySymbol = Symbol(parent=lookupResult.parentSymbol,
|
||||||
|
identOrOp=lookupResult.identOrOp,
|
||||||
|
templateParams=lookupResult.templateParams,
|
||||||
|
templateArgs=lookupResult.templateArgs,
|
||||||
|
declaration=declaration,
|
||||||
|
docname='fakeDocnameForQuery')
|
||||||
|
queryId = declaration.get_newest_id()
|
||||||
|
for symbol in symbols:
|
||||||
|
candId = symbol.declaration.get_newest_id()
|
||||||
|
if candId == queryId:
|
||||||
|
querySymbol.remove()
|
||||||
|
return symbol
|
||||||
|
querySymbol.remove()
|
||||||
|
return None
|
||||||
|
|
||||||
def to_string(self, indent):
|
def to_string(self, indent):
|
||||||
# type: (int) -> unicode
|
# type: (int) -> unicode
|
||||||
res = ['\t' * indent] # type: List[unicode]
|
res = ['\t' * indent] # type: List[unicode]
|
||||||
@ -5825,9 +5898,13 @@ class DefinitionParser(object):
|
|||||||
else:
|
else:
|
||||||
return ASTTemplateDeclarationPrefix(templates)
|
return ASTTemplateDeclarationPrefix(templates)
|
||||||
|
|
||||||
def _check_template_consistency(self, nestedName, templatePrefix,
|
def _check_template_consistency(self,
|
||||||
fullSpecShorthand, isMember=False):
|
nestedName, # type: ASTNestedName
|
||||||
# type: (Any, Any, Any, bool) -> ASTTemplateDeclarationPrefix
|
templatePrefix, # type: ASTTemplateDeclarationPrefix
|
||||||
|
fullSpecShorthand, # type: bool
|
||||||
|
isMember=False # type: bool
|
||||||
|
):
|
||||||
|
# type: (...) -> ASTTemplateDeclarationPrefix
|
||||||
numArgs = nestedName.num_templates()
|
numArgs = nestedName.num_templates()
|
||||||
isMemberInstantiation = False
|
isMemberInstantiation = False
|
||||||
if not templatePrefix:
|
if not templatePrefix:
|
||||||
@ -5931,17 +6008,33 @@ class DefinitionParser(object):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def parse_xref_object(self):
|
def parse_xref_object(self):
|
||||||
# type: () -> ASTNamespace
|
# type: () -> Tuple[Any, bool]
|
||||||
templatePrefix = self._parse_template_declaration_prefix(objectType="xref")
|
pos = self.pos
|
||||||
name = self._parse_nested_name()
|
try:
|
||||||
# if there are '()' left, just skip them
|
templatePrefix = self._parse_template_declaration_prefix(objectType="xref")
|
||||||
self.skip_ws()
|
name = self._parse_nested_name()
|
||||||
self.skip_string('()')
|
# if there are '()' left, just skip them
|
||||||
templatePrefix = self._check_template_consistency(name, templatePrefix,
|
self.skip_ws()
|
||||||
fullSpecShorthand=True)
|
self.skip_string('()')
|
||||||
res = ASTNamespace(name, templatePrefix)
|
templatePrefix = self._check_template_consistency(name, templatePrefix,
|
||||||
res.objectType = 'xref' # type: ignore
|
fullSpecShorthand=True)
|
||||||
return res
|
res1 = ASTNamespace(name, templatePrefix)
|
||||||
|
res1.objectType = 'xref' # type: ignore
|
||||||
|
return res1, True
|
||||||
|
except DefinitionError as e1:
|
||||||
|
try:
|
||||||
|
self.pos = pos
|
||||||
|
res2 = self.parse_declaration('function')
|
||||||
|
# if there are '()' left, just skip them
|
||||||
|
self.skip_ws()
|
||||||
|
self.skip_string('()')
|
||||||
|
return res2, False
|
||||||
|
except DefinitionError as e2:
|
||||||
|
errs = []
|
||||||
|
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)
|
||||||
|
|
||||||
def parse_expression(self):
|
def parse_expression(self):
|
||||||
pos = self.pos
|
pos = self.pos
|
||||||
@ -6542,7 +6635,7 @@ class CPPDomain(Domain):
|
|||||||
target += '()'
|
target += '()'
|
||||||
parser = DefinitionParser(target, warner, env.config)
|
parser = DefinitionParser(target, warner, env.config)
|
||||||
try:
|
try:
|
||||||
ast = parser.parse_xref_object()
|
ast, isShorthand = parser.parse_xref_object()
|
||||||
parser.assert_end()
|
parser.assert_end()
|
||||||
except DefinitionError as e:
|
except DefinitionError as e:
|
||||||
def findWarning(e): # as arg to stop flake8 from complaining
|
def findWarning(e): # as arg to stop flake8 from complaining
|
||||||
@ -6573,14 +6666,21 @@ class CPPDomain(Domain):
|
|||||||
else:
|
else:
|
||||||
parentSymbol = rootSymbol
|
parentSymbol = rootSymbol
|
||||||
|
|
||||||
name = ast.nestedName
|
if isShorthand:
|
||||||
if ast.templatePrefix:
|
ns = ast # type: ASTNamespace
|
||||||
templateDecls = ast.templatePrefix.templates
|
name = ns.nestedName
|
||||||
|
if ns.templatePrefix:
|
||||||
|
templateDecls = ns.templatePrefix.templates
|
||||||
|
else:
|
||||||
|
templateDecls = []
|
||||||
|
s = parentSymbol.find_name(name, templateDecls, typ,
|
||||||
|
templateShorthand=True,
|
||||||
|
matchSelf=True, recurseInAnon=True)
|
||||||
else:
|
else:
|
||||||
templateDecls = []
|
decl = ast # type: ASTDeclaration
|
||||||
s = parentSymbol.find_name(name, templateDecls, typ,
|
s = parentSymbol.find_declaration(decl, typ,
|
||||||
templateShorthand=True,
|
templateShorthand=True,
|
||||||
matchSelf=True, recurseInAnon=True)
|
matchSelf=True, recurseInAnon=True)
|
||||||
if s is None or s.declaration is None:
|
if s is None or s.declaration is None:
|
||||||
txtName = text_type(name)
|
txtName = text_type(name)
|
||||||
if txtName.startswith('std::') or txtName == 'std':
|
if txtName.startswith('std::') or txtName == 'std':
|
||||||
@ -6609,8 +6709,11 @@ class CPPDomain(Domain):
|
|||||||
s.get_full_nested_name()))
|
s.get_full_nested_name()))
|
||||||
|
|
||||||
declaration = s.declaration
|
declaration = s.declaration
|
||||||
fullNestedName = s.get_full_nested_name()
|
if isShorthand:
|
||||||
displayName = fullNestedName.get_display_string().lstrip(':')
|
fullNestedName = s.get_full_nested_name()
|
||||||
|
displayName = fullNestedName.get_display_string().lstrip(':')
|
||||||
|
else:
|
||||||
|
displayName = decl.get_display_string()
|
||||||
docname = s.docname
|
docname = s.docname
|
||||||
assert docname
|
assert docname
|
||||||
|
|
||||||
@ -6622,19 +6725,33 @@ class CPPDomain(Domain):
|
|||||||
# are requested. Then the Sphinx machinery will add another pair.
|
# are requested. Then the Sphinx machinery will add another pair.
|
||||||
# Also, if it's an 'any' ref that resolves to a function, we need to add
|
# Also, if it's an 'any' ref that resolves to a function, we need to add
|
||||||
# parens as well.
|
# parens as well.
|
||||||
|
# However, if it's a non-shorthand function ref, for a function that
|
||||||
|
# takes no arguments, then we may need to add parens again as well.
|
||||||
addParen = 0
|
addParen = 0
|
||||||
if not node.get('refexplicit', False) and declaration.objectType == 'function':
|
if not node.get('refexplicit', False) and declaration.objectType == 'function':
|
||||||
# this is just the normal haxing for 'any' roles
|
if isShorthand:
|
||||||
if env.config.add_function_parentheses and typ == 'any':
|
# this is just the normal haxing for 'any' roles
|
||||||
addParen += 1
|
if env.config.add_function_parentheses and typ == 'any':
|
||||||
# and now this stuff for operator()
|
addParen += 1
|
||||||
if (env.config.add_function_parentheses and typ == 'function' and
|
# and now this stuff for operator()
|
||||||
title.endswith('operator()')):
|
if (env.config.add_function_parentheses and typ == 'function' and
|
||||||
addParen += 1
|
title.endswith('operator()')):
|
||||||
if ((typ == 'any' or typ == 'function') and
|
addParen += 1
|
||||||
title.endswith('operator') and
|
if ((typ == 'any' or typ == 'function') and
|
||||||
displayName.endswith('operator()')):
|
title.endswith('operator') and
|
||||||
addParen += 1
|
displayName.endswith('operator()')):
|
||||||
|
addParen += 1
|
||||||
|
else:
|
||||||
|
# our job here is to essentially nullify add_function_parentheses
|
||||||
|
if env.config.add_function_parentheses:
|
||||||
|
if typ == 'any' and displayName.endswith('()'):
|
||||||
|
addParen += 1
|
||||||
|
elif typ == 'function':
|
||||||
|
if title.endswith('()') and not displayName.endswith('()'):
|
||||||
|
title = title[:-2]
|
||||||
|
else:
|
||||||
|
if displayName.endswith('()'):
|
||||||
|
addParen += 1
|
||||||
if addParen > 0:
|
if addParen > 0:
|
||||||
title += '()' * addParen
|
title += '()' * addParen
|
||||||
# and reconstruct the title again
|
# and reconstruct the title again
|
||||||
|
Loading…
Reference in New Issue
Block a user