From f195c4ae8767ad41f23dc39a75fb0cc8a39bcb4e Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 19 Jan 2024 02:20:43 +0000 Subject: [PATCH] Various C++ domain performance improvements (#11895) Authored-by: Jakob Lykke Andersen Co-authored-by: Jakob Lykke Andersen --- sphinx/domains/cpp.py | 24 ++++++++++++++-- .../roots/test-domain-cpp/operator-lookup.rst | 28 +++++++++++++++++++ tests/test_domains/test_domain_cpp.py | 13 +++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tests/roots/test-domain-cpp/operator-lookup.rst diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 9c00d8748..00f6a1b29 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1706,6 +1706,9 @@ class ASTFallbackExpr(ASTExpression): ################################################################################ class ASTOperator(ASTBase): + def __eq__(self, other: object) -> bool: + raise NotImplementedError(repr(self)) + def is_anon(self) -> bool: return False @@ -1754,6 +1757,11 @@ class ASTOperatorBuildIn(ASTOperator): def __init__(self, op: str) -> None: self.op = op + def __eq__(self, other: object) -> bool: + if not isinstance(other, ASTOperatorBuildIn): + return NotImplemented + return self.op == other.op + def get_id(self, version: int) -> str: if version == 1: ids = _id_operator_v1 @@ -1784,6 +1792,11 @@ class ASTOperatorLiteral(ASTOperator): def __init__(self, identifier: ASTIdentifier) -> None: self.identifier = identifier + def __eq__(self, other: object) -> bool: + if not isinstance(other, ASTOperatorLiteral): + return NotImplemented + return self.identifier == other.identifier + def get_id(self, version: int) -> str: if version == 1: raise NoOldIdError @@ -1803,6 +1816,11 @@ class ASTOperatorType(ASTOperator): def __init__(self, type: ASTType) -> None: self.type = type + def __eq__(self, other: object) -> bool: + if not isinstance(other, ASTOperatorType): + return NotImplemented + return self.type == other.type + def get_id(self, version: int) -> str: if version == 1: return 'castto-%s-operator' % self.type.get_id(version) @@ -4437,7 +4455,8 @@ class Symbol: return ASTNestedName(names, templates, rooted=False) def _find_first_named_symbol(self, identOrOp: ASTIdentifier | ASTOperator, - templateParams: Any, templateArgs: ASTTemplateArgs | None, + templateParams: ASTTemplateParams | ASTTemplateIntroduction, + templateArgs: ASTTemplateArgs | None, templateShorthand: bool, matchSelf: bool, recurseInAnon: bool, correctPrimaryTemplateArgs: bool, ) -> Symbol | None: @@ -4453,7 +4472,8 @@ class Symbol: return None def _find_named_symbols(self, identOrOp: ASTIdentifier | ASTOperator, - templateParams: Any, templateArgs: ASTTemplateArgs, + templateParams: ASTTemplateParams | ASTTemplateIntroduction, + templateArgs: ASTTemplateArgs, templateShorthand: bool, matchSelf: bool, recurseInAnon: bool, correctPrimaryTemplateArgs: bool, searchInSiblings: bool) -> Iterator[Symbol]: diff --git a/tests/roots/test-domain-cpp/operator-lookup.rst b/tests/roots/test-domain-cpp/operator-lookup.rst new file mode 100644 index 000000000..671b91b0f --- /dev/null +++ b/tests/roots/test-domain-cpp/operator-lookup.rst @@ -0,0 +1,28 @@ +When doing name resolution there are 4 different idenOrOps: + +- identifier +- built-in operator +- user-defined literal +- type conversion + +.. cpp:function:: int g() +.. cpp:function:: int operator+(int, int) +.. cpp:function:: int operator""_lit() + +.. cpp:class:: B + + .. cpp:function:: operator int() + + Functions that can't be found: + + - :cpp:func:`int h()` + - :cpp:func:`int operator+(bool, bool)` + - :cpp:func:`int operator""_udl()` + - :cpp:func:`operator bool()` + + Functions that should be found: + + - :cpp:func:`int g()` + - :cpp:func:`int operator+(int, int)` + - :cpp:func:`int operator""_lit()` + - :cpp:func:`operator int()` diff --git a/tests/test_domains/test_domain_cpp.py b/tests/test_domains/test_domain_cpp.py index 51b1545f2..bd9498bc6 100644 --- a/tests/test_domains/test_domain_cpp.py +++ b/tests/test_domains/test_domain_cpp.py @@ -1366,6 +1366,19 @@ def test_domain_cpp_build_field_role(app, status, warning): assert len(ws) == 0 +@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'nitpicky': True}) +def test_domain_cpp_build_operator_lookup(app, status, warning): + app.builder.build_all() + ws = filter_warnings(warning, "operator-lookup") + assert len(ws) == 5 + # TODO: the first one should not happen + assert ":10: WARNING: cpp:identifier reference target not found: _lit" in ws[0] + assert ":18: WARNING: cpp:func reference target not found: int h" in ws[1] + assert ":19: WARNING: cpp:func reference target not found: int operator+(bool, bool)" in ws[2] + assert ":20: WARNING: cpp:func reference target not found: int operator\"\"_udl" in ws[3] + assert ":21: WARNING: cpp:func reference target not found: operator bool" in ws[4] + + @pytest.mark.sphinx(testroot='domain-cpp-intersphinx', confoverrides={'nitpicky': True}) def test_domain_cpp_build_intersphinx(tmp_path, app, status, warning): origSource = """\