Sphinx 7.2.6__py3-none-any.whl → 7.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +8 -9
- sphinx/addnodes.py +31 -28
- sphinx/application.py +9 -15
- sphinx/builders/__init__.py +5 -6
- sphinx/builders/_epub_base.py +17 -9
- sphinx/builders/changes.py +10 -5
- sphinx/builders/dirhtml.py +4 -2
- sphinx/builders/dummy.py +3 -2
- sphinx/builders/epub3.py +5 -3
- sphinx/builders/gettext.py +24 -7
- sphinx/builders/html/__init__.py +88 -96
- sphinx/builders/html/_assets.py +16 -16
- sphinx/builders/html/transforms.py +4 -2
- sphinx/builders/latex/__init__.py +40 -33
- sphinx/builders/latex/nodes.py +6 -2
- sphinx/builders/latex/transforms.py +17 -8
- sphinx/builders/latex/util.py +1 -1
- sphinx/builders/linkcheck.py +86 -27
- sphinx/builders/manpage.py +8 -6
- sphinx/builders/singlehtml.py +5 -4
- sphinx/builders/texinfo.py +18 -14
- sphinx/builders/text.py +3 -2
- sphinx/builders/xml.py +5 -2
- sphinx/cmd/build.py +119 -76
- sphinx/cmd/make_mode.py +4 -9
- sphinx/cmd/quickstart.py +13 -16
- sphinx/config.py +432 -250
- sphinx/deprecation.py +23 -13
- sphinx/directives/__init__.py +8 -8
- sphinx/directives/code.py +7 -7
- sphinx/directives/other.py +23 -13
- sphinx/directives/patches.py +7 -6
- sphinx/domains/__init__.py +2 -2
- sphinx/domains/c/__init__.py +796 -0
- sphinx/domains/c/_ast.py +1421 -0
- sphinx/domains/c/_ids.py +65 -0
- sphinx/domains/c/_parser.py +1048 -0
- sphinx/domains/c/_symbol.py +700 -0
- sphinx/domains/changeset.py +11 -7
- sphinx/domains/citation.py +5 -2
- sphinx/domains/cpp/__init__.py +1089 -0
- sphinx/domains/cpp/_ast.py +3635 -0
- sphinx/domains/cpp/_ids.py +537 -0
- sphinx/domains/cpp/_parser.py +2117 -0
- sphinx/domains/cpp/_symbol.py +1092 -0
- sphinx/domains/index.py +6 -4
- sphinx/domains/javascript.py +16 -13
- sphinx/domains/math.py +9 -4
- sphinx/domains/python/__init__.py +890 -0
- sphinx/domains/python/_annotations.py +507 -0
- sphinx/domains/python/_object.py +426 -0
- sphinx/domains/rst.py +12 -7
- sphinx/domains/{std.py → std/__init__.py} +19 -16
- sphinx/environment/__init__.py +21 -19
- sphinx/environment/adapters/indexentries.py +2 -2
- sphinx/environment/adapters/toctree.py +10 -9
- sphinx/environment/collectors/__init__.py +6 -3
- sphinx/environment/collectors/asset.py +4 -3
- sphinx/environment/collectors/dependencies.py +3 -2
- sphinx/environment/collectors/metadata.py +6 -5
- sphinx/environment/collectors/title.py +3 -2
- sphinx/environment/collectors/toctree.py +5 -4
- sphinx/errors.py +13 -2
- sphinx/events.py +14 -9
- sphinx/ext/apidoc.py +9 -11
- sphinx/ext/autodoc/__init__.py +105 -71
- sphinx/ext/autodoc/directive.py +7 -6
- sphinx/ext/autodoc/importer.py +102 -36
- sphinx/ext/autodoc/mock.py +7 -5
- sphinx/ext/autodoc/preserve_defaults.py +4 -3
- sphinx/ext/autodoc/type_comment.py +2 -1
- sphinx/ext/autodoc/typehints.py +5 -4
- sphinx/ext/autosectionlabel.py +3 -2
- sphinx/ext/autosummary/__init__.py +21 -17
- sphinx/ext/autosummary/generate.py +9 -9
- sphinx/ext/coverage.py +26 -20
- sphinx/ext/doctest.py +38 -33
- sphinx/ext/duration.py +1 -0
- sphinx/ext/extlinks.py +4 -3
- sphinx/ext/githubpages.py +3 -2
- sphinx/ext/graphviz.py +10 -7
- sphinx/ext/ifconfig.py +5 -5
- sphinx/ext/imgconverter.py +6 -5
- sphinx/ext/imgmath.py +9 -8
- sphinx/ext/inheritance_diagram.py +31 -31
- sphinx/ext/intersphinx.py +140 -23
- sphinx/ext/linkcode.py +3 -2
- sphinx/ext/mathjax.py +2 -1
- sphinx/ext/napoleon/__init__.py +12 -7
- sphinx/ext/napoleon/docstring.py +34 -32
- sphinx/ext/todo.py +10 -7
- sphinx/ext/viewcode.py +12 -11
- sphinx/extension.py +18 -8
- sphinx/highlighting.py +39 -20
- sphinx/io.py +17 -8
- sphinx/jinja2glue.py +16 -15
- sphinx/locale/__init__.py +30 -23
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
- sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +904 -847
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
- sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +823 -766
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
- sphinx/locale/sphinx.pot +813 -755
- sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +865 -808
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +879 -822
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
- sphinx/parsers.py +7 -5
- sphinx/project.py +18 -11
- sphinx/pycode/__init__.py +6 -5
- sphinx/pycode/ast.py +23 -8
- sphinx/pycode/parser.py +6 -5
- sphinx/registry.py +12 -6
- sphinx/roles.py +103 -57
- sphinx/search/__init__.py +17 -18
- sphinx/search/da.py +2 -2
- sphinx/search/de.py +2 -2
- sphinx/search/en.py +1 -1
- sphinx/search/es.py +2 -2
- sphinx/search/fi.py +2 -2
- sphinx/search/fr.py +2 -2
- sphinx/search/hu.py +2 -2
- sphinx/search/it.py +2 -2
- sphinx/search/ja.py +13 -22
- sphinx/search/nl.py +2 -2
- sphinx/search/no.py +2 -2
- sphinx/search/pt.py +2 -2
- sphinx/search/ro.py +1 -1
- sphinx/search/ru.py +2 -2
- sphinx/search/sv.py +2 -2
- sphinx/search/tr.py +1 -1
- sphinx/search/zh.py +2 -3
- sphinx/templates/graphviz/graphviz.css +1 -1
- sphinx/testing/fixtures.py +41 -24
- sphinx/testing/path.py +1 -1
- sphinx/testing/util.py +142 -53
- sphinx/texinputs/sphinx.xdy +1 -1
- sphinx/texinputs/sphinxlatextables.sty +1 -1
- sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
- sphinx/themes/agogo/layout.html +4 -4
- sphinx/themes/agogo/static/agogo.css_t +1 -1
- sphinx/themes/agogo/theme.toml +22 -0
- sphinx/themes/basic/defindex.html +1 -1
- sphinx/themes/basic/domainindex.html +1 -1
- sphinx/themes/basic/genindex-single.html +1 -1
- sphinx/themes/basic/genindex-split.html +1 -1
- sphinx/themes/basic/genindex.html +1 -1
- sphinx/themes/basic/globaltoc.html +1 -1
- sphinx/themes/basic/layout.html +1 -1
- sphinx/themes/basic/localtoc.html +1 -1
- sphinx/themes/basic/page.html +1 -1
- sphinx/themes/basic/relations.html +1 -1
- sphinx/themes/basic/search.html +5 -20
- sphinx/themes/basic/searchbox.html +3 -3
- sphinx/themes/basic/searchfield.html +3 -3
- sphinx/themes/basic/sourcelink.html +1 -1
- sphinx/themes/basic/static/basic.css_t +1 -1
- sphinx/themes/basic/static/doctools.js +1 -1
- sphinx/themes/basic/static/language_data.js_t +2 -2
- sphinx/themes/basic/static/searchtools.js +105 -60
- sphinx/themes/basic/theme.toml +23 -0
- sphinx/themes/bizstyle/layout.html +1 -6
- sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
- sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
- sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
- sphinx/themes/bizstyle/theme.toml +12 -0
- sphinx/themes/classic/layout.html +1 -1
- sphinx/themes/classic/static/classic.css_t +1 -1
- sphinx/themes/classic/static/sidebar.js_t +1 -1
- sphinx/themes/classic/theme.toml +34 -0
- sphinx/themes/default/theme.toml +2 -0
- sphinx/themes/epub/epub-cover.html +1 -1
- sphinx/themes/epub/layout.html +1 -1
- sphinx/themes/epub/static/epub.css_t +1 -1
- sphinx/themes/epub/theme.toml +10 -0
- sphinx/themes/haiku/layout.html +3 -3
- sphinx/themes/haiku/static/haiku.css_t +2 -2
- sphinx/themes/haiku/theme.toml +16 -0
- sphinx/themes/nature/static/nature.css_t +1 -1
- sphinx/themes/nature/theme.toml +6 -0
- sphinx/themes/nonav/layout.html +1 -1
- sphinx/themes/nonav/static/nonav.css_t +1 -1
- sphinx/themes/nonav/theme.toml +10 -0
- sphinx/themes/pyramid/static/epub.css_t +1 -1
- sphinx/themes/pyramid/static/pyramid.css_t +1 -1
- sphinx/themes/pyramid/theme.toml +6 -0
- sphinx/themes/scrolls/artwork/logo.svg +1 -1
- sphinx/themes/scrolls/layout.html +2 -2
- sphinx/themes/scrolls/static/scrolls.css_t +1 -1
- sphinx/themes/scrolls/theme.toml +15 -0
- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
- sphinx/themes/sphinxdoc/theme.toml +6 -0
- sphinx/themes/traditional/static/traditional.css_t +1 -1
- sphinx/themes/traditional/theme.toml +9 -0
- sphinx/theming.py +427 -131
- sphinx/transforms/__init__.py +21 -24
- sphinx/transforms/compact_bullet_list.py +5 -5
- sphinx/transforms/i18n.py +30 -28
- sphinx/transforms/post_transforms/__init__.py +9 -7
- sphinx/transforms/post_transforms/code.py +4 -1
- sphinx/transforms/post_transforms/images.py +17 -13
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +15 -11
- sphinx/util/_io.py +34 -0
- sphinx/util/_pathlib.py +23 -18
- sphinx/util/build_phase.py +1 -0
- sphinx/util/cfamily.py +19 -11
- sphinx/util/console.py +101 -21
- sphinx/util/display.py +3 -2
- sphinx/util/docfields.py +12 -8
- sphinx/util/docutils.py +21 -35
- sphinx/util/exceptions.py +3 -2
- sphinx/util/fileutil.py +5 -5
- sphinx/util/http_date.py +9 -2
- sphinx/util/i18n.py +40 -9
- sphinx/util/inspect.py +317 -245
- sphinx/util/inventory.py +22 -5
- sphinx/util/logging.py +81 -7
- sphinx/util/matching.py +2 -1
- sphinx/util/math.py +1 -2
- sphinx/util/nodes.py +39 -29
- sphinx/util/osutil.py +25 -6
- sphinx/util/parallel.py +6 -1
- sphinx/util/requests.py +8 -5
- sphinx/util/rst.py +8 -6
- sphinx/util/tags.py +3 -3
- sphinx/util/template.py +8 -3
- sphinx/util/typing.py +76 -42
- sphinx/versioning.py +6 -2
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +17 -13
- sphinx/writers/latex.py +12 -12
- sphinx/writers/manpage.py +13 -7
- sphinx/writers/texinfo.py +13 -10
- sphinx/writers/text.py +13 -23
- sphinx/writers/xml.py +1 -1
- sphinx-7.2.6.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
- sphinx-7.3.0.dist-info/RECORD +581 -0
- sphinx/domains/c.py +0 -3906
- sphinx/domains/cpp.py +0 -8233
- sphinx/domains/python.py +0 -1769
- sphinx/themes/agogo/theme.conf +0 -20
- sphinx/themes/basic/theme.conf +0 -16
- sphinx/themes/bizstyle/theme.conf +0 -10
- sphinx/themes/classic/theme.conf +0 -32
- sphinx/themes/default/theme.conf +0 -2
- sphinx/themes/epub/theme.conf +0 -8
- sphinx/themes/haiku/theme.conf +0 -14
- sphinx/themes/nature/theme.conf +0 -4
- sphinx/themes/nonav/theme.conf +0 -8
- sphinx/themes/pyramid/theme.conf +0 -4
- sphinx/themes/scrolls/theme.conf +0 -13
- sphinx/themes/sphinxdoc/theme.conf +0 -4
- sphinx/themes/traditional/theme.conf +0 -7
- sphinx-7.2.6.dist-info/RECORD +0 -569
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,1089 @@
|
|
|
1
|
+
"""The C++ language domain."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
|
7
|
+
|
|
8
|
+
from docutils import nodes
|
|
9
|
+
from docutils.parsers.rst import directives
|
|
10
|
+
|
|
11
|
+
from sphinx import addnodes
|
|
12
|
+
from sphinx.directives import ObjectDescription
|
|
13
|
+
from sphinx.domains import Domain, ObjType
|
|
14
|
+
from sphinx.domains.cpp._ast import (
|
|
15
|
+
ASTDeclaration,
|
|
16
|
+
ASTIdentifier,
|
|
17
|
+
ASTNamespace,
|
|
18
|
+
ASTNestedName,
|
|
19
|
+
ASTNestedNameElement,
|
|
20
|
+
)
|
|
21
|
+
from sphinx.domains.cpp._ids import _max_id
|
|
22
|
+
from sphinx.domains.cpp._parser import DefinitionParser
|
|
23
|
+
from sphinx.domains.cpp._symbol import Symbol, _DuplicateSymbolError
|
|
24
|
+
from sphinx.errors import NoUri
|
|
25
|
+
from sphinx.locale import _, __
|
|
26
|
+
from sphinx.roles import SphinxRole, XRefRole
|
|
27
|
+
from sphinx.transforms import SphinxTransform
|
|
28
|
+
from sphinx.transforms.post_transforms import ReferencesResolver
|
|
29
|
+
from sphinx.util import logging
|
|
30
|
+
from sphinx.util.cfamily import (
|
|
31
|
+
DefinitionError,
|
|
32
|
+
NoOldIdError,
|
|
33
|
+
anon_identifier_re,
|
|
34
|
+
)
|
|
35
|
+
from sphinx.util.docfields import Field, GroupedField
|
|
36
|
+
from sphinx.util.docutils import SphinxDirective
|
|
37
|
+
from sphinx.util.nodes import make_refnode
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from collections.abc import Iterator
|
|
41
|
+
|
|
42
|
+
from docutils.nodes import Element, Node, TextElement, system_message
|
|
43
|
+
|
|
44
|
+
from sphinx.addnodes import desc_signature, pending_xref
|
|
45
|
+
from sphinx.application import Sphinx
|
|
46
|
+
from sphinx.builders import Builder
|
|
47
|
+
from sphinx.domains.cpp._symbol import LookupKey
|
|
48
|
+
from sphinx.environment import BuildEnvironment
|
|
49
|
+
from sphinx.util.typing import ExtensionMetadata, OptionSpec
|
|
50
|
+
|
|
51
|
+
logger = logging.getLogger(__name__)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _make_phony_error_name() -> ASTNestedName:
|
|
55
|
+
nne = ASTNestedNameElement(ASTIdentifier("PhonyNameDueToError"), None)
|
|
56
|
+
return ASTNestedName([nne], [False], rooted=False)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
60
|
+
"""Description of a C++ language object."""
|
|
61
|
+
|
|
62
|
+
doc_field_types: list[Field] = [
|
|
63
|
+
GroupedField('template parameter', label=_('Template Parameters'),
|
|
64
|
+
names=('tparam', 'template parameter'),
|
|
65
|
+
can_collapse=True),
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
option_spec: ClassVar[OptionSpec] = {
|
|
69
|
+
'no-index-entry': directives.flag,
|
|
70
|
+
'no-contents-entry': directives.flag,
|
|
71
|
+
'no-typesetting': directives.flag,
|
|
72
|
+
'noindexentry': directives.flag,
|
|
73
|
+
'nocontentsentry': directives.flag,
|
|
74
|
+
'tparam-line-spec': directives.flag,
|
|
75
|
+
'single-line-parameter-list': directives.flag,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None:
|
|
79
|
+
assert ast.objectType == 'enumerator'
|
|
80
|
+
# find the parent, if it exists && is an enum
|
|
81
|
+
# && it's unscoped,
|
|
82
|
+
# then add the name to the parent scope
|
|
83
|
+
symbol = ast.symbol
|
|
84
|
+
assert symbol
|
|
85
|
+
assert symbol.identOrOp is not None
|
|
86
|
+
assert symbol.templateParams is None
|
|
87
|
+
assert symbol.templateArgs is None
|
|
88
|
+
parentSymbol = symbol.parent
|
|
89
|
+
assert parentSymbol
|
|
90
|
+
if parentSymbol.parent is None:
|
|
91
|
+
# TODO: we could warn, but it is somewhat equivalent to unscoped
|
|
92
|
+
# enums, without the enum
|
|
93
|
+
return # no parent
|
|
94
|
+
parentDecl = parentSymbol.declaration
|
|
95
|
+
if parentDecl is None:
|
|
96
|
+
# the parent is not explicitly declared
|
|
97
|
+
# TODO: we could warn, but it could be a style to just assume
|
|
98
|
+
# enumerator parents to be scoped
|
|
99
|
+
return
|
|
100
|
+
if parentDecl.objectType != 'enum':
|
|
101
|
+
# TODO: maybe issue a warning, enumerators in non-enums is weird,
|
|
102
|
+
# but it is somewhat equivalent to unscoped enums, without the enum
|
|
103
|
+
return
|
|
104
|
+
if parentDecl.directiveType != 'enum':
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
targetSymbol = parentSymbol.parent
|
|
108
|
+
s = targetSymbol.find_identifier(symbol.identOrOp, matchSelf=False, recurseInAnon=True,
|
|
109
|
+
searchInSiblings=False)
|
|
110
|
+
if s is not None:
|
|
111
|
+
# something is already declared with that name
|
|
112
|
+
return
|
|
113
|
+
declClone = symbol.declaration.clone()
|
|
114
|
+
declClone.enumeratorScopedSymbol = symbol
|
|
115
|
+
Symbol(parent=targetSymbol, identOrOp=symbol.identOrOp,
|
|
116
|
+
templateParams=None, templateArgs=None,
|
|
117
|
+
declaration=declClone,
|
|
118
|
+
docname=self.env.docname, line=self.get_source_info()[1])
|
|
119
|
+
|
|
120
|
+
def add_target_and_index(self, ast: ASTDeclaration, sig: str,
|
|
121
|
+
signode: TextElement) -> None:
|
|
122
|
+
# general note: name must be lstrip(':')'ed, to remove "::"
|
|
123
|
+
ids = []
|
|
124
|
+
for i in range(1, _max_id + 1):
|
|
125
|
+
try:
|
|
126
|
+
id = ast.get_id(version=i)
|
|
127
|
+
ids.append(id)
|
|
128
|
+
except NoOldIdError:
|
|
129
|
+
assert i < _max_id
|
|
130
|
+
# let's keep the newest first
|
|
131
|
+
ids.reverse()
|
|
132
|
+
newestId = ids[0]
|
|
133
|
+
assert newestId # shouldn't be None
|
|
134
|
+
if not re.compile(r'^[a-zA-Z0-9_]*$').match(newestId):
|
|
135
|
+
logger.warning('Index id generation for C++ object "%s" failed, please '
|
|
136
|
+
'report as bug (id=%s).', ast, newestId,
|
|
137
|
+
location=self.get_location())
|
|
138
|
+
|
|
139
|
+
name = ast.symbol.get_full_nested_name().get_display_string().lstrip(':')
|
|
140
|
+
# Add index entry, but not if it's a declaration inside a concept
|
|
141
|
+
isInConcept = False
|
|
142
|
+
s = ast.symbol.parent
|
|
143
|
+
while s is not None:
|
|
144
|
+
decl = s.declaration
|
|
145
|
+
s = s.parent
|
|
146
|
+
if decl is None:
|
|
147
|
+
continue
|
|
148
|
+
if decl.objectType == 'concept':
|
|
149
|
+
isInConcept = True
|
|
150
|
+
break
|
|
151
|
+
if not isInConcept and 'no-index-entry' not in self.options:
|
|
152
|
+
strippedName = name
|
|
153
|
+
for prefix in self.env.config.cpp_index_common_prefix:
|
|
154
|
+
if name.startswith(prefix):
|
|
155
|
+
strippedName = strippedName[len(prefix):]
|
|
156
|
+
break
|
|
157
|
+
indexText = self.get_index_text(strippedName)
|
|
158
|
+
self.indexnode['entries'].append(('single', indexText, newestId, '', None))
|
|
159
|
+
|
|
160
|
+
if newestId not in self.state.document.ids:
|
|
161
|
+
# if the name is not unique, the first one will win
|
|
162
|
+
names = self.env.domaindata['cpp']['names']
|
|
163
|
+
if name not in names:
|
|
164
|
+
names[name] = ast.symbol.docname
|
|
165
|
+
# always add the newest id
|
|
166
|
+
assert newestId
|
|
167
|
+
signode['ids'].append(newestId)
|
|
168
|
+
# only add compatibility ids when there are no conflicts
|
|
169
|
+
for id in ids[1:]:
|
|
170
|
+
if not id: # is None when the element didn't exist in that version
|
|
171
|
+
continue
|
|
172
|
+
if id not in self.state.document.ids:
|
|
173
|
+
signode['ids'].append(id)
|
|
174
|
+
self.state.document.note_explicit_target(signode)
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def object_type(self) -> str:
|
|
178
|
+
raise NotImplementedError
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def display_object_type(self) -> str:
|
|
182
|
+
return self.object_type
|
|
183
|
+
|
|
184
|
+
def get_index_text(self, name: str) -> str:
|
|
185
|
+
return _('%s (C++ %s)') % (name, self.display_object_type)
|
|
186
|
+
|
|
187
|
+
def parse_definition(self, parser: DefinitionParser) -> ASTDeclaration:
|
|
188
|
+
return parser.parse_declaration(self.object_type, self.objtype)
|
|
189
|
+
|
|
190
|
+
def describe_signature(self, signode: desc_signature,
|
|
191
|
+
ast: ASTDeclaration, options: dict) -> None:
|
|
192
|
+
ast.describe_signature(signode, 'lastIsName', self.env, options)
|
|
193
|
+
|
|
194
|
+
def run(self) -> list[Node]:
|
|
195
|
+
env = self.state.document.settings.env # from ObjectDescription.run
|
|
196
|
+
if 'cpp:parent_symbol' not in env.temp_data:
|
|
197
|
+
root = env.domaindata['cpp']['root_symbol']
|
|
198
|
+
env.temp_data['cpp:parent_symbol'] = root
|
|
199
|
+
env.ref_context['cpp:parent_key'] = root.get_lookup_key()
|
|
200
|
+
|
|
201
|
+
# The lookup keys assume that no nested scopes exists inside overloaded functions.
|
|
202
|
+
# (see also #5191)
|
|
203
|
+
# Example:
|
|
204
|
+
# .. cpp:function:: void f(int)
|
|
205
|
+
# .. cpp:function:: void f(double)
|
|
206
|
+
#
|
|
207
|
+
# .. cpp:function:: void g()
|
|
208
|
+
#
|
|
209
|
+
# :cpp:any:`boom`
|
|
210
|
+
#
|
|
211
|
+
# So we disallow any signatures inside functions.
|
|
212
|
+
parentSymbol = env.temp_data['cpp:parent_symbol']
|
|
213
|
+
parentDecl = parentSymbol.declaration
|
|
214
|
+
if parentDecl is not None and parentDecl.objectType == 'function':
|
|
215
|
+
msg = ("C++ declarations inside functions are not supported. "
|
|
216
|
+
f"Parent function: {parentSymbol.get_full_nested_name()}\n"
|
|
217
|
+
f"Directive name: {self.name}\nDirective arg: {self.arguments[0]}")
|
|
218
|
+
logger.warning(msg, location=self.get_location())
|
|
219
|
+
name = _make_phony_error_name()
|
|
220
|
+
symbol = parentSymbol.add_name(name)
|
|
221
|
+
env.temp_data['cpp:last_symbol'] = symbol
|
|
222
|
+
return []
|
|
223
|
+
# When multiple declarations are made in the same directive
|
|
224
|
+
# they need to know about each other to provide symbol lookup for function parameters.
|
|
225
|
+
# We use last_symbol to store the latest added declaration in a directive.
|
|
226
|
+
env.temp_data['cpp:last_symbol'] = None
|
|
227
|
+
return super().run()
|
|
228
|
+
|
|
229
|
+
def handle_signature(self, sig: str, signode: desc_signature) -> ASTDeclaration:
|
|
230
|
+
parentSymbol: Symbol = self.env.temp_data['cpp:parent_symbol']
|
|
231
|
+
|
|
232
|
+
max_len = (self.env.config.cpp_maximum_signature_line_length
|
|
233
|
+
or self.env.config.maximum_signature_line_length
|
|
234
|
+
or 0)
|
|
235
|
+
signode['multi_line_parameter_list'] = (
|
|
236
|
+
'single-line-parameter-list' not in self.options
|
|
237
|
+
and (len(sig) > max_len > 0)
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
parser = DefinitionParser(sig, location=signode, config=self.env.config)
|
|
241
|
+
try:
|
|
242
|
+
ast = self.parse_definition(parser)
|
|
243
|
+
parser.assert_end()
|
|
244
|
+
except DefinitionError as e:
|
|
245
|
+
logger.warning(e, location=signode)
|
|
246
|
+
# It is easier to assume some phony name than handling the error in
|
|
247
|
+
# the possibly inner declarations.
|
|
248
|
+
name = _make_phony_error_name()
|
|
249
|
+
symbol = parentSymbol.add_name(name)
|
|
250
|
+
self.env.temp_data['cpp:last_symbol'] = symbol
|
|
251
|
+
raise ValueError from e
|
|
252
|
+
|
|
253
|
+
try:
|
|
254
|
+
symbol = parentSymbol.add_declaration(
|
|
255
|
+
ast, docname=self.env.docname, line=self.get_source_info()[1])
|
|
256
|
+
# append the new declaration to the sibling list
|
|
257
|
+
assert symbol.siblingAbove is None
|
|
258
|
+
assert symbol.siblingBelow is None
|
|
259
|
+
symbol.siblingAbove = self.env.temp_data['cpp:last_symbol']
|
|
260
|
+
if symbol.siblingAbove is not None:
|
|
261
|
+
assert symbol.siblingAbove.siblingBelow is None
|
|
262
|
+
symbol.siblingAbove.siblingBelow = symbol
|
|
263
|
+
self.env.temp_data['cpp:last_symbol'] = symbol
|
|
264
|
+
except _DuplicateSymbolError as e:
|
|
265
|
+
# Assume we are actually in the old symbol,
|
|
266
|
+
# instead of the newly created duplicate.
|
|
267
|
+
self.env.temp_data['cpp:last_symbol'] = e.symbol
|
|
268
|
+
msg = __("Duplicate C++ declaration, also defined at %s:%s.\n"
|
|
269
|
+
"Declaration is '.. cpp:%s:: %s'.")
|
|
270
|
+
msg = msg % (e.symbol.docname, e.symbol.line,
|
|
271
|
+
self.display_object_type, sig)
|
|
272
|
+
logger.warning(msg, location=signode)
|
|
273
|
+
|
|
274
|
+
if ast.objectType == 'enumerator':
|
|
275
|
+
self._add_enumerator_to_parent(ast)
|
|
276
|
+
|
|
277
|
+
# note: handle_signature may be called multiple time per directive,
|
|
278
|
+
# if it has multiple signatures, so don't mess with the original options.
|
|
279
|
+
options = dict(self.options)
|
|
280
|
+
options['tparam-line-spec'] = 'tparam-line-spec' in self.options
|
|
281
|
+
self.describe_signature(signode, ast, options)
|
|
282
|
+
return ast
|
|
283
|
+
|
|
284
|
+
def before_content(self) -> None:
|
|
285
|
+
lastSymbol: Symbol = self.env.temp_data['cpp:last_symbol']
|
|
286
|
+
assert lastSymbol
|
|
287
|
+
self.oldParentSymbol = self.env.temp_data['cpp:parent_symbol']
|
|
288
|
+
self.oldParentKey: LookupKey = self.env.ref_context['cpp:parent_key']
|
|
289
|
+
self.env.temp_data['cpp:parent_symbol'] = lastSymbol
|
|
290
|
+
self.env.ref_context['cpp:parent_key'] = lastSymbol.get_lookup_key()
|
|
291
|
+
self.env.temp_data['cpp:domain_name'] = (
|
|
292
|
+
*self.env.temp_data.get('cpp:domain_name', ()),
|
|
293
|
+
lastSymbol.identOrOp._stringify(str),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def after_content(self) -> None:
|
|
297
|
+
self.env.temp_data['cpp:parent_symbol'] = self.oldParentSymbol
|
|
298
|
+
self.env.ref_context['cpp:parent_key'] = self.oldParentKey
|
|
299
|
+
self.env.temp_data['cpp:domain_name'] = self.env.temp_data['cpp:domain_name'][:-1]
|
|
300
|
+
|
|
301
|
+
def _object_hierarchy_parts(self, sig_node: desc_signature) -> tuple[str, ...]:
|
|
302
|
+
return tuple(s.identOrOp._stringify(str) for s in
|
|
303
|
+
self.env.temp_data['cpp:last_symbol'].get_full_nested_name().names)
|
|
304
|
+
|
|
305
|
+
def _toc_entry_name(self, sig_node: desc_signature) -> str:
|
|
306
|
+
if not sig_node.get('_toc_parts'):
|
|
307
|
+
return ''
|
|
308
|
+
|
|
309
|
+
config = self.env.app.config
|
|
310
|
+
objtype = sig_node.parent.get('objtype')
|
|
311
|
+
if config.add_function_parentheses and objtype in {'function', 'method'}:
|
|
312
|
+
parens = '()'
|
|
313
|
+
else:
|
|
314
|
+
parens = ''
|
|
315
|
+
*parents, name = sig_node['_toc_parts']
|
|
316
|
+
if config.toc_object_entries_show_parents == 'domain':
|
|
317
|
+
return '::'.join((*self.env.temp_data.get('cpp:domain_name', ()), name + parens))
|
|
318
|
+
if config.toc_object_entries_show_parents == 'hide':
|
|
319
|
+
return name + parens
|
|
320
|
+
if config.toc_object_entries_show_parents == 'all':
|
|
321
|
+
return '::'.join([*parents, name + parens])
|
|
322
|
+
return ''
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class CPPTypeObject(CPPObject):
|
|
326
|
+
object_type = 'type'
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
class CPPConceptObject(CPPObject):
|
|
330
|
+
object_type = 'concept'
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class CPPMemberObject(CPPObject):
|
|
334
|
+
object_type = 'member'
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class CPPFunctionObject(CPPObject):
|
|
338
|
+
object_type = 'function'
|
|
339
|
+
|
|
340
|
+
doc_field_types = [
|
|
341
|
+
*CPPObject.doc_field_types,
|
|
342
|
+
GroupedField(
|
|
343
|
+
"parameter",
|
|
344
|
+
label=_("Parameters"),
|
|
345
|
+
names=("param", "parameter", "arg", "argument"),
|
|
346
|
+
can_collapse=True,
|
|
347
|
+
),
|
|
348
|
+
GroupedField(
|
|
349
|
+
"exceptions",
|
|
350
|
+
label=_("Throws"),
|
|
351
|
+
rolename="expr",
|
|
352
|
+
names=("throws", "throw", "exception"),
|
|
353
|
+
can_collapse=True,
|
|
354
|
+
),
|
|
355
|
+
GroupedField(
|
|
356
|
+
"retval",
|
|
357
|
+
label=_("Return values"),
|
|
358
|
+
names=("retvals", "retval"),
|
|
359
|
+
can_collapse=True,
|
|
360
|
+
),
|
|
361
|
+
Field("returnvalue", label=_("Returns"), has_arg=False, names=("returns", "return")),
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class CPPClassObject(CPPObject):
|
|
366
|
+
object_type = 'class'
|
|
367
|
+
|
|
368
|
+
@property
|
|
369
|
+
def display_object_type(self) -> str:
|
|
370
|
+
# the distinction between class and struct is only cosmetic
|
|
371
|
+
assert self.objtype in ('class', 'struct')
|
|
372
|
+
return self.objtype
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
class CPPUnionObject(CPPObject):
|
|
376
|
+
object_type = 'union'
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
class CPPEnumObject(CPPObject):
|
|
380
|
+
object_type = 'enum'
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
class CPPEnumeratorObject(CPPObject):
|
|
384
|
+
object_type = 'enumerator'
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class CPPNamespaceObject(SphinxDirective):
|
|
388
|
+
"""
|
|
389
|
+
This directive is just to tell Sphinx that we're documenting stuff in
|
|
390
|
+
namespace foo.
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
has_content = False
|
|
394
|
+
required_arguments = 1
|
|
395
|
+
optional_arguments = 0
|
|
396
|
+
final_argument_whitespace = True
|
|
397
|
+
option_spec: ClassVar[OptionSpec] = {}
|
|
398
|
+
|
|
399
|
+
def run(self) -> list[Node]:
|
|
400
|
+
rootSymbol = self.env.domaindata['cpp']['root_symbol']
|
|
401
|
+
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
|
|
402
|
+
symbol = rootSymbol
|
|
403
|
+
stack: list[Symbol] = []
|
|
404
|
+
else:
|
|
405
|
+
parser = DefinitionParser(self.arguments[0],
|
|
406
|
+
location=self.get_location(),
|
|
407
|
+
config=self.config)
|
|
408
|
+
try:
|
|
409
|
+
ast = parser.parse_namespace_object()
|
|
410
|
+
parser.assert_end()
|
|
411
|
+
except DefinitionError as e:
|
|
412
|
+
logger.warning(e, location=self.get_location())
|
|
413
|
+
name = _make_phony_error_name()
|
|
414
|
+
ast = ASTNamespace(name, None)
|
|
415
|
+
symbol = rootSymbol.add_name(ast.nestedName, ast.templatePrefix)
|
|
416
|
+
stack = [symbol]
|
|
417
|
+
self.env.temp_data['cpp:parent_symbol'] = symbol
|
|
418
|
+
self.env.temp_data['cpp:namespace_stack'] = stack
|
|
419
|
+
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
420
|
+
return []
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class CPPNamespacePushObject(SphinxDirective):
|
|
424
|
+
has_content = False
|
|
425
|
+
required_arguments = 1
|
|
426
|
+
optional_arguments = 0
|
|
427
|
+
final_argument_whitespace = True
|
|
428
|
+
option_spec: ClassVar[OptionSpec] = {}
|
|
429
|
+
|
|
430
|
+
def run(self) -> list[Node]:
|
|
431
|
+
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
|
|
432
|
+
return []
|
|
433
|
+
parser = DefinitionParser(self.arguments[0],
|
|
434
|
+
location=self.get_location(),
|
|
435
|
+
config=self.config)
|
|
436
|
+
try:
|
|
437
|
+
ast = parser.parse_namespace_object()
|
|
438
|
+
parser.assert_end()
|
|
439
|
+
except DefinitionError as e:
|
|
440
|
+
logger.warning(e, location=self.get_location())
|
|
441
|
+
name = _make_phony_error_name()
|
|
442
|
+
ast = ASTNamespace(name, None)
|
|
443
|
+
oldParent = self.env.temp_data.get('cpp:parent_symbol', None)
|
|
444
|
+
if not oldParent:
|
|
445
|
+
oldParent = self.env.domaindata['cpp']['root_symbol']
|
|
446
|
+
symbol = oldParent.add_name(ast.nestedName, ast.templatePrefix)
|
|
447
|
+
stack = self.env.temp_data.get('cpp:namespace_stack', [])
|
|
448
|
+
stack.append(symbol)
|
|
449
|
+
self.env.temp_data['cpp:parent_symbol'] = symbol
|
|
450
|
+
self.env.temp_data['cpp:namespace_stack'] = stack
|
|
451
|
+
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
452
|
+
return []
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
class CPPNamespacePopObject(SphinxDirective):
|
|
456
|
+
has_content = False
|
|
457
|
+
required_arguments = 0
|
|
458
|
+
optional_arguments = 0
|
|
459
|
+
final_argument_whitespace = True
|
|
460
|
+
option_spec: ClassVar[OptionSpec] = {}
|
|
461
|
+
|
|
462
|
+
def run(self) -> list[Node]:
|
|
463
|
+
stack = self.env.temp_data.get('cpp:namespace_stack', None)
|
|
464
|
+
if not stack or len(stack) == 0:
|
|
465
|
+
logger.warning("C++ namespace pop on empty stack. Defaulting to global scope.",
|
|
466
|
+
location=self.get_location())
|
|
467
|
+
stack = []
|
|
468
|
+
else:
|
|
469
|
+
stack.pop()
|
|
470
|
+
if len(stack) > 0:
|
|
471
|
+
symbol = stack[-1]
|
|
472
|
+
else:
|
|
473
|
+
symbol = self.env.domaindata['cpp']['root_symbol']
|
|
474
|
+
self.env.temp_data['cpp:parent_symbol'] = symbol
|
|
475
|
+
self.env.temp_data['cpp:namespace_stack'] = stack
|
|
476
|
+
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
477
|
+
return []
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
class AliasNode(nodes.Element):
|
|
481
|
+
def __init__(self, sig: str, aliasOptions: dict,
|
|
482
|
+
env: BuildEnvironment | None = None,
|
|
483
|
+
parentKey: LookupKey | None = None) -> None:
|
|
484
|
+
super().__init__()
|
|
485
|
+
self.sig = sig
|
|
486
|
+
self.aliasOptions = aliasOptions
|
|
487
|
+
if env is not None:
|
|
488
|
+
if 'cpp:parent_symbol' not in env.temp_data:
|
|
489
|
+
root = env.domaindata['cpp']['root_symbol']
|
|
490
|
+
env.temp_data['cpp:parent_symbol'] = root
|
|
491
|
+
env.ref_context['cpp:parent_key'] = root.get_lookup_key()
|
|
492
|
+
self.parentKey = env.ref_context['cpp:parent_key']
|
|
493
|
+
else:
|
|
494
|
+
assert parentKey is not None
|
|
495
|
+
self.parentKey = parentKey
|
|
496
|
+
|
|
497
|
+
def copy(self) -> AliasNode:
|
|
498
|
+
return self.__class__(self.sig, self.aliasOptions,
|
|
499
|
+
env=None, parentKey=self.parentKey)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
class AliasTransform(SphinxTransform):
|
|
503
|
+
default_priority = ReferencesResolver.default_priority - 1
|
|
504
|
+
|
|
505
|
+
def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool,
|
|
506
|
+
aliasOptions: dict, renderOptions: dict,
|
|
507
|
+
document: Any) -> list[Node]:
|
|
508
|
+
if maxdepth == 0:
|
|
509
|
+
recurse = True
|
|
510
|
+
elif maxdepth == 1:
|
|
511
|
+
recurse = False
|
|
512
|
+
else:
|
|
513
|
+
maxdepth -= 1
|
|
514
|
+
recurse = True
|
|
515
|
+
|
|
516
|
+
nodes: list[Node] = []
|
|
517
|
+
if not skipThis:
|
|
518
|
+
signode = addnodes.desc_signature('', '')
|
|
519
|
+
nodes.append(signode)
|
|
520
|
+
s.declaration.describe_signature(signode, 'markName', self.env, renderOptions)
|
|
521
|
+
|
|
522
|
+
if recurse:
|
|
523
|
+
if skipThis:
|
|
524
|
+
childContainer: list[Node] | addnodes.desc = nodes
|
|
525
|
+
else:
|
|
526
|
+
content = addnodes.desc_content()
|
|
527
|
+
desc = addnodes.desc()
|
|
528
|
+
content.append(desc)
|
|
529
|
+
desc.document = document
|
|
530
|
+
desc['domain'] = 'cpp'
|
|
531
|
+
# 'desctype' is a backwards compatible attribute
|
|
532
|
+
desc['objtype'] = desc['desctype'] = 'alias'
|
|
533
|
+
desc['no-index'] = True
|
|
534
|
+
childContainer = desc
|
|
535
|
+
|
|
536
|
+
for sChild in s._children:
|
|
537
|
+
if sChild.declaration is None:
|
|
538
|
+
continue
|
|
539
|
+
if sChild.declaration.objectType in ("templateParam", "functionParam"):
|
|
540
|
+
continue
|
|
541
|
+
childNodes = self._render_symbol(
|
|
542
|
+
sChild, maxdepth=maxdepth, skipThis=False,
|
|
543
|
+
aliasOptions=aliasOptions, renderOptions=renderOptions,
|
|
544
|
+
document=document)
|
|
545
|
+
childContainer.extend(childNodes)
|
|
546
|
+
|
|
547
|
+
if not skipThis and len(desc.children) != 0:
|
|
548
|
+
nodes.append(content)
|
|
549
|
+
return nodes
|
|
550
|
+
|
|
551
|
+
def apply(self, **kwargs: Any) -> None:
|
|
552
|
+
for node in self.document.findall(AliasNode):
|
|
553
|
+
sig = node.sig
|
|
554
|
+
parentKey = node.parentKey
|
|
555
|
+
try:
|
|
556
|
+
parser = DefinitionParser(sig, location=node,
|
|
557
|
+
config=self.env.config)
|
|
558
|
+
ast, isShorthand = parser.parse_xref_object()
|
|
559
|
+
parser.assert_end()
|
|
560
|
+
except DefinitionError as e:
|
|
561
|
+
logger.warning(e, location=node)
|
|
562
|
+
ast, isShorthand = None, None
|
|
563
|
+
|
|
564
|
+
if ast is None:
|
|
565
|
+
# could not be parsed, so stop here
|
|
566
|
+
signode = addnodes.desc_signature(sig, '')
|
|
567
|
+
signode.clear()
|
|
568
|
+
signode += addnodes.desc_name(sig, sig)
|
|
569
|
+
node.replace_self(signode)
|
|
570
|
+
continue
|
|
571
|
+
|
|
572
|
+
rootSymbol: Symbol = self.env.domains['cpp'].data['root_symbol']
|
|
573
|
+
parentSymbol: Symbol = rootSymbol.direct_lookup(parentKey)
|
|
574
|
+
if not parentSymbol:
|
|
575
|
+
logger.debug("Target: %s", sig)
|
|
576
|
+
logger.debug("ParentKey: %s", parentKey)
|
|
577
|
+
logger.debug(rootSymbol.dump(1))
|
|
578
|
+
assert parentSymbol # should be there
|
|
579
|
+
|
|
580
|
+
symbols: list[Symbol] = []
|
|
581
|
+
if isShorthand:
|
|
582
|
+
assert isinstance(ast, ASTNamespace)
|
|
583
|
+
ns = ast
|
|
584
|
+
name = ns.nestedName
|
|
585
|
+
if ns.templatePrefix:
|
|
586
|
+
templateDecls = ns.templatePrefix.templates
|
|
587
|
+
else:
|
|
588
|
+
templateDecls = []
|
|
589
|
+
symbols, failReason = parentSymbol.find_name(
|
|
590
|
+
nestedName=name,
|
|
591
|
+
templateDecls=templateDecls,
|
|
592
|
+
typ='any',
|
|
593
|
+
templateShorthand=True,
|
|
594
|
+
matchSelf=True, recurseInAnon=True,
|
|
595
|
+
searchInSiblings=False)
|
|
596
|
+
if symbols is None:
|
|
597
|
+
symbols = []
|
|
598
|
+
else:
|
|
599
|
+
assert isinstance(ast, ASTDeclaration)
|
|
600
|
+
decl = ast
|
|
601
|
+
name = decl.name
|
|
602
|
+
s = parentSymbol.find_declaration(decl, 'any',
|
|
603
|
+
templateShorthand=True,
|
|
604
|
+
matchSelf=True, recurseInAnon=True)
|
|
605
|
+
if s is not None:
|
|
606
|
+
symbols.append(s)
|
|
607
|
+
|
|
608
|
+
symbols = [s for s in symbols if s.declaration is not None]
|
|
609
|
+
|
|
610
|
+
if len(symbols) == 0:
|
|
611
|
+
signode = addnodes.desc_signature(sig, '')
|
|
612
|
+
node.append(signode)
|
|
613
|
+
signode.clear()
|
|
614
|
+
signode += addnodes.desc_name(sig, sig)
|
|
615
|
+
|
|
616
|
+
logger.warning("Can not find C++ declaration for alias '%s'." % ast,
|
|
617
|
+
location=node)
|
|
618
|
+
node.replace_self(signode)
|
|
619
|
+
else:
|
|
620
|
+
nodes = []
|
|
621
|
+
renderOptions = {
|
|
622
|
+
'tparam-line-spec': False,
|
|
623
|
+
}
|
|
624
|
+
for s in symbols:
|
|
625
|
+
assert s.declaration is not None
|
|
626
|
+
res = self._render_symbol(
|
|
627
|
+
s, maxdepth=node.aliasOptions['maxdepth'],
|
|
628
|
+
skipThis=node.aliasOptions['noroot'],
|
|
629
|
+
aliasOptions=node.aliasOptions,
|
|
630
|
+
renderOptions=renderOptions,
|
|
631
|
+
document=node.document)
|
|
632
|
+
nodes.extend(res)
|
|
633
|
+
node.replace_self(nodes)
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
class CPPAliasObject(ObjectDescription):
|
|
637
|
+
option_spec: ClassVar[OptionSpec] = {
|
|
638
|
+
'maxdepth': directives.nonnegative_int,
|
|
639
|
+
'noroot': directives.flag,
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
def run(self) -> list[Node]:
|
|
643
|
+
"""
|
|
644
|
+
On purpose this doesn't call the ObjectDescription version, but is based on it.
|
|
645
|
+
Each alias signature may expand into multiple real signatures (an overload set).
|
|
646
|
+
The code is therefore based on the ObjectDescription version.
|
|
647
|
+
"""
|
|
648
|
+
if ':' in self.name:
|
|
649
|
+
self.domain, self.objtype = self.name.split(':', 1)
|
|
650
|
+
else:
|
|
651
|
+
self.domain, self.objtype = '', self.name
|
|
652
|
+
|
|
653
|
+
node = addnodes.desc()
|
|
654
|
+
node.document = self.state.document
|
|
655
|
+
node['domain'] = self.domain
|
|
656
|
+
# 'desctype' is a backwards compatible attribute
|
|
657
|
+
node['objtype'] = node['desctype'] = self.objtype
|
|
658
|
+
|
|
659
|
+
self.names: list[str] = []
|
|
660
|
+
aliasOptions = {
|
|
661
|
+
'maxdepth': self.options.get('maxdepth', 1),
|
|
662
|
+
'noroot': 'noroot' in self.options,
|
|
663
|
+
}
|
|
664
|
+
if aliasOptions['noroot'] and aliasOptions['maxdepth'] == 1:
|
|
665
|
+
logger.warning("Error in C++ alias declaration."
|
|
666
|
+
" Requested 'noroot' but 'maxdepth' 1."
|
|
667
|
+
" When skipping the root declaration,"
|
|
668
|
+
" need 'maxdepth' 0 for infinite or at least 2.",
|
|
669
|
+
location=self.get_location())
|
|
670
|
+
signatures = self.get_signatures()
|
|
671
|
+
for sig in signatures:
|
|
672
|
+
node.append(AliasNode(sig, aliasOptions, env=self.env))
|
|
673
|
+
|
|
674
|
+
contentnode = addnodes.desc_content()
|
|
675
|
+
node.append(contentnode)
|
|
676
|
+
self.before_content()
|
|
677
|
+
self.state.nested_parse(self.content, self.content_offset, contentnode)
|
|
678
|
+
self.env.temp_data['object'] = None
|
|
679
|
+
self.after_content()
|
|
680
|
+
return [node]
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
class CPPXRefRole(XRefRole):
|
|
684
|
+
def process_link(self, env: BuildEnvironment, refnode: Element, has_explicit_title: bool,
|
|
685
|
+
title: str, target: str) -> tuple[str, str]:
|
|
686
|
+
refnode.attributes.update(env.ref_context)
|
|
687
|
+
|
|
688
|
+
if not has_explicit_title:
|
|
689
|
+
# major hax: replace anon names via simple string manipulation.
|
|
690
|
+
# Can this actually fail?
|
|
691
|
+
title = anon_identifier_re.sub("[anonymous]", str(title))
|
|
692
|
+
|
|
693
|
+
if refnode['reftype'] == 'any':
|
|
694
|
+
# Assume the removal part of fix_parens for :any: refs.
|
|
695
|
+
# The addition part is done with the reference is resolved.
|
|
696
|
+
if not has_explicit_title and title.endswith('()'):
|
|
697
|
+
title = title[:-2]
|
|
698
|
+
if target.endswith('()'):
|
|
699
|
+
target = target[:-2]
|
|
700
|
+
# TODO: should this really be here?
|
|
701
|
+
if not has_explicit_title:
|
|
702
|
+
target = target.lstrip('~') # only has a meaning for the title
|
|
703
|
+
# if the first character is a tilde, don't display the module/class
|
|
704
|
+
# parts of the contents
|
|
705
|
+
if title[:1] == '~':
|
|
706
|
+
title = title[1:]
|
|
707
|
+
dcolon = title.rfind('::')
|
|
708
|
+
if dcolon != -1:
|
|
709
|
+
title = title[dcolon + 2:]
|
|
710
|
+
return title, target
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
class CPPExprRole(SphinxRole):
|
|
714
|
+
def __init__(self, asCode: bool) -> None:
|
|
715
|
+
super().__init__()
|
|
716
|
+
if asCode:
|
|
717
|
+
# render the expression as inline code
|
|
718
|
+
self.class_type = 'cpp-expr'
|
|
719
|
+
else:
|
|
720
|
+
# render the expression as inline text
|
|
721
|
+
self.class_type = 'cpp-texpr'
|
|
722
|
+
|
|
723
|
+
def run(self) -> tuple[list[Node], list[system_message]]:
|
|
724
|
+
text = self.text.replace('\n', ' ')
|
|
725
|
+
parser = DefinitionParser(text,
|
|
726
|
+
location=self.get_location(),
|
|
727
|
+
config=self.config)
|
|
728
|
+
# attempt to mimic XRefRole classes, except that...
|
|
729
|
+
try:
|
|
730
|
+
ast = parser.parse_expression()
|
|
731
|
+
except DefinitionError as ex:
|
|
732
|
+
logger.warning('Unparseable C++ expression: %r\n%s', text, ex,
|
|
733
|
+
location=self.get_location())
|
|
734
|
+
# see below
|
|
735
|
+
return [addnodes.desc_inline('cpp', text, text, classes=[self.class_type])], []
|
|
736
|
+
parentSymbol = self.env.temp_data.get('cpp:parent_symbol', None)
|
|
737
|
+
if parentSymbol is None:
|
|
738
|
+
parentSymbol = self.env.domaindata['cpp']['root_symbol']
|
|
739
|
+
# ...most if not all of these classes should really apply to the individual references,
|
|
740
|
+
# not the container node
|
|
741
|
+
signode = addnodes.desc_inline('cpp', classes=[self.class_type])
|
|
742
|
+
ast.describe_signature(signode, 'markType', self.env, parentSymbol)
|
|
743
|
+
return [signode], []
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
class CPPDomain(Domain):
|
|
747
|
+
"""C++ language domain.
|
|
748
|
+
|
|
749
|
+
There are two 'object type' attributes being used::
|
|
750
|
+
|
|
751
|
+
- Each object created from directives gets an assigned .objtype from ObjectDescription.run.
|
|
752
|
+
This is simply the directive name.
|
|
753
|
+
- Each declaration (see the distinction in the directives dict below) has a nested .ast of
|
|
754
|
+
type ASTDeclaration. That object has .objectType which corresponds to the keys in the
|
|
755
|
+
object_types dict below. They are the core different types of declarations in C++ that
|
|
756
|
+
one can document.
|
|
757
|
+
"""
|
|
758
|
+
|
|
759
|
+
name = 'cpp'
|
|
760
|
+
label = 'C++'
|
|
761
|
+
object_types = {
|
|
762
|
+
'class': ObjType(_('class'), 'class', 'struct', 'identifier', 'type'),
|
|
763
|
+
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
|
|
764
|
+
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
|
|
765
|
+
'member': ObjType(_('member'), 'member', 'var', 'identifier'),
|
|
766
|
+
'type': ObjType(_('type'), 'identifier', 'type'),
|
|
767
|
+
'concept': ObjType(_('concept'), 'concept', 'identifier'),
|
|
768
|
+
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
|
|
769
|
+
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
|
|
770
|
+
# generated object types
|
|
771
|
+
'functionParam': ObjType(_('function parameter'), 'identifier', 'member', 'var'), # NoQA: E501
|
|
772
|
+
'templateParam': ObjType(_('template parameter'),
|
|
773
|
+
'identifier', 'class', 'struct', 'union', 'member', 'var', 'type'), # NoQA: E501
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
directives = {
|
|
777
|
+
# declarations
|
|
778
|
+
'class': CPPClassObject,
|
|
779
|
+
'struct': CPPClassObject,
|
|
780
|
+
'union': CPPUnionObject,
|
|
781
|
+
'function': CPPFunctionObject,
|
|
782
|
+
'member': CPPMemberObject,
|
|
783
|
+
'var': CPPMemberObject,
|
|
784
|
+
'type': CPPTypeObject,
|
|
785
|
+
'concept': CPPConceptObject,
|
|
786
|
+
'enum': CPPEnumObject,
|
|
787
|
+
'enum-struct': CPPEnumObject,
|
|
788
|
+
'enum-class': CPPEnumObject,
|
|
789
|
+
'enumerator': CPPEnumeratorObject,
|
|
790
|
+
# scope control
|
|
791
|
+
'namespace': CPPNamespaceObject,
|
|
792
|
+
'namespace-push': CPPNamespacePushObject,
|
|
793
|
+
'namespace-pop': CPPNamespacePopObject,
|
|
794
|
+
# other
|
|
795
|
+
'alias': CPPAliasObject,
|
|
796
|
+
}
|
|
797
|
+
roles = {
|
|
798
|
+
'any': CPPXRefRole(),
|
|
799
|
+
'class': CPPXRefRole(),
|
|
800
|
+
'struct': CPPXRefRole(),
|
|
801
|
+
'union': CPPXRefRole(),
|
|
802
|
+
'func': CPPXRefRole(fix_parens=True),
|
|
803
|
+
'member': CPPXRefRole(),
|
|
804
|
+
'var': CPPXRefRole(),
|
|
805
|
+
'type': CPPXRefRole(),
|
|
806
|
+
'concept': CPPXRefRole(),
|
|
807
|
+
'enum': CPPXRefRole(),
|
|
808
|
+
'enumerator': CPPXRefRole(),
|
|
809
|
+
'expr': CPPExprRole(asCode=True),
|
|
810
|
+
'texpr': CPPExprRole(asCode=False),
|
|
811
|
+
}
|
|
812
|
+
initial_data = {
|
|
813
|
+
'root_symbol': Symbol(None, None, None, None, None, None, None),
|
|
814
|
+
'names': {}, # full name for indexing -> docname
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
def clear_doc(self, docname: str) -> None:
|
|
818
|
+
if Symbol.debug_show_tree:
|
|
819
|
+
logger.debug("clear_doc: %s", docname)
|
|
820
|
+
logger.debug("\tbefore:")
|
|
821
|
+
logger.debug(self.data['root_symbol'].dump(1))
|
|
822
|
+
logger.debug("\tbefore end")
|
|
823
|
+
|
|
824
|
+
rootSymbol = self.data['root_symbol']
|
|
825
|
+
rootSymbol.clear_doc(docname)
|
|
826
|
+
|
|
827
|
+
if Symbol.debug_show_tree:
|
|
828
|
+
logger.debug("\tafter:")
|
|
829
|
+
logger.debug(self.data['root_symbol'].dump(1))
|
|
830
|
+
logger.debug("\tafter end")
|
|
831
|
+
logger.debug("clear_doc end: %s", docname)
|
|
832
|
+
for name, nDocname in list(self.data['names'].items()):
|
|
833
|
+
if nDocname == docname:
|
|
834
|
+
del self.data['names'][name]
|
|
835
|
+
|
|
836
|
+
def process_doc(self, env: BuildEnvironment, docname: str,
|
|
837
|
+
document: nodes.document) -> None:
|
|
838
|
+
if Symbol.debug_show_tree:
|
|
839
|
+
logger.debug("process_doc: %s", docname)
|
|
840
|
+
logger.debug(self.data['root_symbol'].dump(0))
|
|
841
|
+
logger.debug("process_doc end: %s", docname)
|
|
842
|
+
|
|
843
|
+
def process_field_xref(self, pnode: pending_xref) -> None:
|
|
844
|
+
pnode.attributes.update(self.env.ref_context)
|
|
845
|
+
|
|
846
|
+
def merge_domaindata(self, docnames: list[str], otherdata: dict[str, Any]) -> None:
|
|
847
|
+
if Symbol.debug_show_tree:
|
|
848
|
+
logger.debug("merge_domaindata:")
|
|
849
|
+
logger.debug("\tself:")
|
|
850
|
+
logger.debug(self.data['root_symbol'].dump(1))
|
|
851
|
+
logger.debug("\tself end")
|
|
852
|
+
logger.debug("\tother:")
|
|
853
|
+
logger.debug(otherdata['root_symbol'].dump(1))
|
|
854
|
+
logger.debug("\tother end")
|
|
855
|
+
|
|
856
|
+
self.data['root_symbol'].merge_with(otherdata['root_symbol'],
|
|
857
|
+
docnames, self.env)
|
|
858
|
+
ourNames = self.data['names']
|
|
859
|
+
for name, docname in otherdata['names'].items():
|
|
860
|
+
if docname in docnames:
|
|
861
|
+
if name not in ourNames:
|
|
862
|
+
ourNames[name] = docname
|
|
863
|
+
# no need to warn on duplicates, the symbol merge already does that
|
|
864
|
+
if Symbol.debug_show_tree:
|
|
865
|
+
logger.debug("\tresult:")
|
|
866
|
+
logger.debug(self.data['root_symbol'].dump(1))
|
|
867
|
+
logger.debug("\tresult end")
|
|
868
|
+
logger.debug("merge_domaindata end")
|
|
869
|
+
|
|
870
|
+
def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
|
|
871
|
+
typ: str, target: str, node: pending_xref,
|
|
872
|
+
contnode: Element) -> tuple[Element | None, str | None]:
|
|
873
|
+
# add parens again for those that could be functions
|
|
874
|
+
if typ in ('any', 'func'):
|
|
875
|
+
target += '()'
|
|
876
|
+
parser = DefinitionParser(target, location=node, config=env.config)
|
|
877
|
+
try:
|
|
878
|
+
ast, isShorthand = parser.parse_xref_object()
|
|
879
|
+
except DefinitionError as e:
|
|
880
|
+
# as arg to stop flake8 from complaining
|
|
881
|
+
def findWarning(e: Exception) -> tuple[str, Exception]:
|
|
882
|
+
if typ != 'any' and typ != 'func':
|
|
883
|
+
return target, e
|
|
884
|
+
# hax on top of the paren hax to try to get correct errors
|
|
885
|
+
parser2 = DefinitionParser(target[:-2],
|
|
886
|
+
location=node,
|
|
887
|
+
config=env.config)
|
|
888
|
+
try:
|
|
889
|
+
parser2.parse_xref_object()
|
|
890
|
+
except DefinitionError as e2:
|
|
891
|
+
return target[:-2], e2
|
|
892
|
+
# strange, that we don't get the error now, use the original
|
|
893
|
+
return target, e
|
|
894
|
+
t, ex = findWarning(e)
|
|
895
|
+
logger.warning('Unparseable C++ cross-reference: %r\n%s', t, ex,
|
|
896
|
+
location=node)
|
|
897
|
+
return None, None
|
|
898
|
+
parentKey: LookupKey = node.get("cpp:parent_key", None)
|
|
899
|
+
rootSymbol = self.data['root_symbol']
|
|
900
|
+
if parentKey:
|
|
901
|
+
parentSymbol: Symbol = rootSymbol.direct_lookup(parentKey)
|
|
902
|
+
if not parentSymbol:
|
|
903
|
+
logger.debug("Target: %s", target)
|
|
904
|
+
logger.debug("ParentKey: %s", parentKey.data)
|
|
905
|
+
logger.debug(rootSymbol.dump(1))
|
|
906
|
+
assert parentSymbol # should be there
|
|
907
|
+
else:
|
|
908
|
+
parentSymbol = rootSymbol
|
|
909
|
+
|
|
910
|
+
if isShorthand:
|
|
911
|
+
assert isinstance(ast, ASTNamespace)
|
|
912
|
+
ns = ast
|
|
913
|
+
name = ns.nestedName
|
|
914
|
+
if ns.templatePrefix:
|
|
915
|
+
templateDecls = ns.templatePrefix.templates
|
|
916
|
+
else:
|
|
917
|
+
templateDecls = []
|
|
918
|
+
# let's be conservative with the sibling lookup for now
|
|
919
|
+
searchInSiblings = (not name.rooted) and len(name.names) == 1
|
|
920
|
+
symbols, failReason = parentSymbol.find_name(
|
|
921
|
+
name, templateDecls, typ,
|
|
922
|
+
templateShorthand=True,
|
|
923
|
+
matchSelf=True, recurseInAnon=True,
|
|
924
|
+
searchInSiblings=searchInSiblings)
|
|
925
|
+
if symbols is None:
|
|
926
|
+
if typ == 'identifier':
|
|
927
|
+
if failReason == 'templateParamInQualified':
|
|
928
|
+
# this is an xref we created as part of a signature,
|
|
929
|
+
# so don't warn for names nested in template parameters
|
|
930
|
+
raise NoUri(str(name), typ)
|
|
931
|
+
s = None
|
|
932
|
+
else:
|
|
933
|
+
# just refer to the arbitrarily first symbol
|
|
934
|
+
s = symbols[0]
|
|
935
|
+
else:
|
|
936
|
+
assert isinstance(ast, ASTDeclaration)
|
|
937
|
+
decl = ast
|
|
938
|
+
name = decl.name
|
|
939
|
+
s = parentSymbol.find_declaration(decl, typ,
|
|
940
|
+
templateShorthand=True,
|
|
941
|
+
matchSelf=True, recurseInAnon=True)
|
|
942
|
+
if s is None or s.declaration is None:
|
|
943
|
+
txtName = str(name)
|
|
944
|
+
if txtName.startswith('std::') or txtName == 'std':
|
|
945
|
+
raise NoUri(txtName, typ)
|
|
946
|
+
return None, None
|
|
947
|
+
|
|
948
|
+
if typ.startswith('cpp:'):
|
|
949
|
+
typ = typ[4:]
|
|
950
|
+
declTyp = s.declaration.objectType
|
|
951
|
+
|
|
952
|
+
def checkType() -> bool:
|
|
953
|
+
if typ == 'any':
|
|
954
|
+
return True
|
|
955
|
+
objtypes = self.objtypes_for_role(typ)
|
|
956
|
+
if objtypes:
|
|
957
|
+
return declTyp in objtypes
|
|
958
|
+
logger.debug(f"Type is {typ}, declaration type is {declTyp}") # NoQA: G004
|
|
959
|
+
raise AssertionError
|
|
960
|
+
if not checkType():
|
|
961
|
+
logger.warning("cpp:%s targets a %s (%s).",
|
|
962
|
+
typ, s.declaration.objectType,
|
|
963
|
+
s.get_full_nested_name(),
|
|
964
|
+
location=node)
|
|
965
|
+
|
|
966
|
+
declaration = s.declaration
|
|
967
|
+
if isShorthand:
|
|
968
|
+
fullNestedName = s.get_full_nested_name()
|
|
969
|
+
displayName = fullNestedName.get_display_string().lstrip(':')
|
|
970
|
+
else:
|
|
971
|
+
displayName = decl.get_display_string()
|
|
972
|
+
docname = s.docname
|
|
973
|
+
assert docname
|
|
974
|
+
|
|
975
|
+
# the non-identifier refs are cross-references, which should be processed:
|
|
976
|
+
# - fix parenthesis due to operator() and add_function_parentheses
|
|
977
|
+
if typ != "identifier":
|
|
978
|
+
title = contnode.pop(0).astext()
|
|
979
|
+
# If it's operator(), we need to add '()' if explicit function parens
|
|
980
|
+
# are requested. Then the Sphinx machinery will add another pair.
|
|
981
|
+
# Also, if it's an 'any' ref that resolves to a function, we need to add
|
|
982
|
+
# parens as well.
|
|
983
|
+
# However, if it's a non-shorthand function ref, for a function that
|
|
984
|
+
# takes no arguments, then we may need to add parens again as well.
|
|
985
|
+
addParen = 0
|
|
986
|
+
if not node.get('refexplicit', False) and declaration.objectType == 'function':
|
|
987
|
+
if isShorthand:
|
|
988
|
+
# this is just the normal haxing for 'any' roles
|
|
989
|
+
if env.config.add_function_parentheses and typ == 'any':
|
|
990
|
+
addParen += 1
|
|
991
|
+
# and now this stuff for operator()
|
|
992
|
+
if (env.config.add_function_parentheses and typ == 'func' and
|
|
993
|
+
title.endswith('operator()')):
|
|
994
|
+
addParen += 1
|
|
995
|
+
if (typ in ('any', 'func') and
|
|
996
|
+
title.endswith('operator') and
|
|
997
|
+
displayName.endswith('operator()')):
|
|
998
|
+
addParen += 1
|
|
999
|
+
else:
|
|
1000
|
+
# our job here is to essentially nullify add_function_parentheses
|
|
1001
|
+
if env.config.add_function_parentheses:
|
|
1002
|
+
if typ == 'any' and displayName.endswith('()'):
|
|
1003
|
+
addParen += 1
|
|
1004
|
+
elif typ == 'func':
|
|
1005
|
+
if title.endswith('()') and not displayName.endswith('()'):
|
|
1006
|
+
title = title[:-2]
|
|
1007
|
+
else:
|
|
1008
|
+
if displayName.endswith('()'):
|
|
1009
|
+
addParen += 1
|
|
1010
|
+
if addParen > 0:
|
|
1011
|
+
title += '()' * addParen
|
|
1012
|
+
# and reconstruct the title again
|
|
1013
|
+
contnode += nodes.Text(title)
|
|
1014
|
+
res = make_refnode(builder, fromdocname, docname,
|
|
1015
|
+
declaration.get_newest_id(), contnode, displayName,
|
|
1016
|
+
), declaration.objectType
|
|
1017
|
+
return res
|
|
1018
|
+
|
|
1019
|
+
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
|
|
1020
|
+
typ: str, target: str, node: pending_xref, contnode: Element,
|
|
1021
|
+
) -> Element | None:
|
|
1022
|
+
return self._resolve_xref_inner(env, fromdocname, builder, typ,
|
|
1023
|
+
target, node, contnode)[0]
|
|
1024
|
+
|
|
1025
|
+
def resolve_any_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
|
|
1026
|
+
target: str, node: pending_xref, contnode: Element,
|
|
1027
|
+
) -> list[tuple[str, Element]]:
|
|
1028
|
+
with logging.suppress_logging():
|
|
1029
|
+
retnode, objtype = self._resolve_xref_inner(env, fromdocname, builder,
|
|
1030
|
+
'any', target, node, contnode)
|
|
1031
|
+
if retnode:
|
|
1032
|
+
if objtype == 'templateParam':
|
|
1033
|
+
return [('cpp:templateParam', retnode)]
|
|
1034
|
+
else:
|
|
1035
|
+
return [('cpp:' + self.role_for_objtype(objtype), retnode)]
|
|
1036
|
+
return []
|
|
1037
|
+
|
|
1038
|
+
def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
|
|
1039
|
+
rootSymbol = self.data['root_symbol']
|
|
1040
|
+
for symbol in rootSymbol.get_all_symbols():
|
|
1041
|
+
if symbol.declaration is None:
|
|
1042
|
+
continue
|
|
1043
|
+
assert symbol.docname
|
|
1044
|
+
fullNestedName = symbol.get_full_nested_name()
|
|
1045
|
+
name = str(fullNestedName).lstrip(':')
|
|
1046
|
+
dispname = fullNestedName.get_display_string().lstrip(':')
|
|
1047
|
+
objectType = symbol.declaration.objectType
|
|
1048
|
+
docname = symbol.docname
|
|
1049
|
+
newestId = symbol.declaration.get_newest_id()
|
|
1050
|
+
yield (name, dispname, objectType, docname, newestId, 1)
|
|
1051
|
+
|
|
1052
|
+
def get_full_qualified_name(self, node: Element) -> str | None:
|
|
1053
|
+
target = node.get('reftarget', None)
|
|
1054
|
+
if target is None:
|
|
1055
|
+
return None
|
|
1056
|
+
parentKey: LookupKey = node.get("cpp:parent_key", None)
|
|
1057
|
+
if parentKey is None or len(parentKey.data) <= 0:
|
|
1058
|
+
return None
|
|
1059
|
+
|
|
1060
|
+
rootSymbol = self.data['root_symbol']
|
|
1061
|
+
parentSymbol = rootSymbol.direct_lookup(parentKey)
|
|
1062
|
+
parentName = parentSymbol.get_full_nested_name()
|
|
1063
|
+
return f'{parentName}::{target}'
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
1067
|
+
app.add_domain(CPPDomain)
|
|
1068
|
+
app.add_config_value("cpp_index_common_prefix", [], 'env')
|
|
1069
|
+
app.add_config_value("cpp_id_attributes", [], 'env')
|
|
1070
|
+
app.add_config_value("cpp_paren_attributes", [], 'env')
|
|
1071
|
+
app.add_config_value("cpp_maximum_signature_line_length", None, 'env', types={int, None})
|
|
1072
|
+
app.add_post_transform(AliasTransform)
|
|
1073
|
+
|
|
1074
|
+
# debug stuff
|
|
1075
|
+
app.add_config_value("cpp_debug_lookup", False, '')
|
|
1076
|
+
app.add_config_value("cpp_debug_show_tree", False, '')
|
|
1077
|
+
|
|
1078
|
+
def initStuff(app: Sphinx) -> None:
|
|
1079
|
+
Symbol.debug_lookup = app.config.cpp_debug_lookup
|
|
1080
|
+
Symbol.debug_show_tree = app.config.cpp_debug_show_tree
|
|
1081
|
+
app.config.cpp_index_common_prefix.sort(reverse=True)
|
|
1082
|
+
app.connect("builder-inited", initStuff)
|
|
1083
|
+
|
|
1084
|
+
return {
|
|
1085
|
+
'version': 'builtin',
|
|
1086
|
+
'env_version': 9,
|
|
1087
|
+
'parallel_read_safe': True,
|
|
1088
|
+
'parallel_write_safe': True,
|
|
1089
|
+
}
|