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.

Files changed (388) hide show
  1. sphinx/__init__.py +8 -9
  2. sphinx/addnodes.py +31 -28
  3. sphinx/application.py +9 -15
  4. sphinx/builders/__init__.py +5 -6
  5. sphinx/builders/_epub_base.py +17 -9
  6. sphinx/builders/changes.py +10 -5
  7. sphinx/builders/dirhtml.py +4 -2
  8. sphinx/builders/dummy.py +3 -2
  9. sphinx/builders/epub3.py +5 -3
  10. sphinx/builders/gettext.py +24 -7
  11. sphinx/builders/html/__init__.py +88 -96
  12. sphinx/builders/html/_assets.py +16 -16
  13. sphinx/builders/html/transforms.py +4 -2
  14. sphinx/builders/latex/__init__.py +40 -33
  15. sphinx/builders/latex/nodes.py +6 -2
  16. sphinx/builders/latex/transforms.py +17 -8
  17. sphinx/builders/latex/util.py +1 -1
  18. sphinx/builders/linkcheck.py +86 -27
  19. sphinx/builders/manpage.py +8 -6
  20. sphinx/builders/singlehtml.py +5 -4
  21. sphinx/builders/texinfo.py +18 -14
  22. sphinx/builders/text.py +3 -2
  23. sphinx/builders/xml.py +5 -2
  24. sphinx/cmd/build.py +119 -76
  25. sphinx/cmd/make_mode.py +4 -9
  26. sphinx/cmd/quickstart.py +13 -16
  27. sphinx/config.py +432 -250
  28. sphinx/deprecation.py +23 -13
  29. sphinx/directives/__init__.py +8 -8
  30. sphinx/directives/code.py +7 -7
  31. sphinx/directives/other.py +23 -13
  32. sphinx/directives/patches.py +7 -6
  33. sphinx/domains/__init__.py +2 -2
  34. sphinx/domains/c/__init__.py +796 -0
  35. sphinx/domains/c/_ast.py +1421 -0
  36. sphinx/domains/c/_ids.py +65 -0
  37. sphinx/domains/c/_parser.py +1048 -0
  38. sphinx/domains/c/_symbol.py +700 -0
  39. sphinx/domains/changeset.py +11 -7
  40. sphinx/domains/citation.py +5 -2
  41. sphinx/domains/cpp/__init__.py +1089 -0
  42. sphinx/domains/cpp/_ast.py +3635 -0
  43. sphinx/domains/cpp/_ids.py +537 -0
  44. sphinx/domains/cpp/_parser.py +2117 -0
  45. sphinx/domains/cpp/_symbol.py +1092 -0
  46. sphinx/domains/index.py +6 -4
  47. sphinx/domains/javascript.py +16 -13
  48. sphinx/domains/math.py +9 -4
  49. sphinx/domains/python/__init__.py +890 -0
  50. sphinx/domains/python/_annotations.py +507 -0
  51. sphinx/domains/python/_object.py +426 -0
  52. sphinx/domains/rst.py +12 -7
  53. sphinx/domains/{std.py → std/__init__.py} +19 -16
  54. sphinx/environment/__init__.py +21 -19
  55. sphinx/environment/adapters/indexentries.py +2 -2
  56. sphinx/environment/adapters/toctree.py +10 -9
  57. sphinx/environment/collectors/__init__.py +6 -3
  58. sphinx/environment/collectors/asset.py +4 -3
  59. sphinx/environment/collectors/dependencies.py +3 -2
  60. sphinx/environment/collectors/metadata.py +6 -5
  61. sphinx/environment/collectors/title.py +3 -2
  62. sphinx/environment/collectors/toctree.py +5 -4
  63. sphinx/errors.py +13 -2
  64. sphinx/events.py +14 -9
  65. sphinx/ext/apidoc.py +9 -11
  66. sphinx/ext/autodoc/__init__.py +105 -71
  67. sphinx/ext/autodoc/directive.py +7 -6
  68. sphinx/ext/autodoc/importer.py +102 -36
  69. sphinx/ext/autodoc/mock.py +7 -5
  70. sphinx/ext/autodoc/preserve_defaults.py +4 -3
  71. sphinx/ext/autodoc/type_comment.py +2 -1
  72. sphinx/ext/autodoc/typehints.py +5 -4
  73. sphinx/ext/autosectionlabel.py +3 -2
  74. sphinx/ext/autosummary/__init__.py +21 -17
  75. sphinx/ext/autosummary/generate.py +9 -9
  76. sphinx/ext/coverage.py +26 -20
  77. sphinx/ext/doctest.py +38 -33
  78. sphinx/ext/duration.py +1 -0
  79. sphinx/ext/extlinks.py +4 -3
  80. sphinx/ext/githubpages.py +3 -2
  81. sphinx/ext/graphviz.py +10 -7
  82. sphinx/ext/ifconfig.py +5 -5
  83. sphinx/ext/imgconverter.py +6 -5
  84. sphinx/ext/imgmath.py +9 -8
  85. sphinx/ext/inheritance_diagram.py +31 -31
  86. sphinx/ext/intersphinx.py +140 -23
  87. sphinx/ext/linkcode.py +3 -2
  88. sphinx/ext/mathjax.py +2 -1
  89. sphinx/ext/napoleon/__init__.py +12 -7
  90. sphinx/ext/napoleon/docstring.py +34 -32
  91. sphinx/ext/todo.py +10 -7
  92. sphinx/ext/viewcode.py +12 -11
  93. sphinx/extension.py +18 -8
  94. sphinx/highlighting.py +39 -20
  95. sphinx/io.py +17 -8
  96. sphinx/jinja2glue.py +16 -15
  97. sphinx/locale/__init__.py +30 -23
  98. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
  100. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  101. sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
  102. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
  104. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
  106. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  107. sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
  108. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
  110. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
  112. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  113. sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
  114. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
  116. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
  118. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  119. sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
  120. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
  122. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
  124. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  125. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
  126. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
  128. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
  130. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  131. sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
  132. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
  134. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
  136. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  137. sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
  138. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  139. sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
  140. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  141. sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
  142. sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
  143. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/fr/LC_MESSAGES/sphinx.po +904 -847
  145. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
  147. sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
  148. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  149. sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
  150. sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
  151. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/he/LC_MESSAGES/sphinx.po +823 -766
  153. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
  155. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
  157. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
  159. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
  161. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
  163. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
  165. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
  167. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
  169. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
  171. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
  173. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
  175. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
  177. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
  179. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
  180. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  181. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
  182. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  183. sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
  184. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  185. sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
  186. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  187. sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
  188. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  189. sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
  190. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  191. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
  192. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  193. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
  194. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  195. sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
  196. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  197. sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
  198. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  199. sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
  200. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  201. sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
  202. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  203. sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
  204. sphinx/locale/sphinx.pot +813 -755
  205. sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
  206. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/sq/LC_MESSAGES/sphinx.po +865 -808
  208. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
  210. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  212. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
  214. sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
  215. sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
  217. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
  219. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
  221. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
  223. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  224. sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
  225. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  226. sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
  227. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  228. sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
  229. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
  230. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
  231. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  232. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
  233. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
  234. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +879 -822
  236. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
  238. sphinx/parsers.py +7 -5
  239. sphinx/project.py +18 -11
  240. sphinx/pycode/__init__.py +6 -5
  241. sphinx/pycode/ast.py +23 -8
  242. sphinx/pycode/parser.py +6 -5
  243. sphinx/registry.py +12 -6
  244. sphinx/roles.py +103 -57
  245. sphinx/search/__init__.py +17 -18
  246. sphinx/search/da.py +2 -2
  247. sphinx/search/de.py +2 -2
  248. sphinx/search/en.py +1 -1
  249. sphinx/search/es.py +2 -2
  250. sphinx/search/fi.py +2 -2
  251. sphinx/search/fr.py +2 -2
  252. sphinx/search/hu.py +2 -2
  253. sphinx/search/it.py +2 -2
  254. sphinx/search/ja.py +13 -22
  255. sphinx/search/nl.py +2 -2
  256. sphinx/search/no.py +2 -2
  257. sphinx/search/pt.py +2 -2
  258. sphinx/search/ro.py +1 -1
  259. sphinx/search/ru.py +2 -2
  260. sphinx/search/sv.py +2 -2
  261. sphinx/search/tr.py +1 -1
  262. sphinx/search/zh.py +2 -3
  263. sphinx/templates/graphviz/graphviz.css +1 -1
  264. sphinx/testing/fixtures.py +41 -24
  265. sphinx/testing/path.py +1 -1
  266. sphinx/testing/util.py +142 -53
  267. sphinx/texinputs/sphinx.xdy +1 -1
  268. sphinx/texinputs/sphinxlatextables.sty +1 -1
  269. sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
  270. sphinx/themes/agogo/layout.html +4 -4
  271. sphinx/themes/agogo/static/agogo.css_t +1 -1
  272. sphinx/themes/agogo/theme.toml +22 -0
  273. sphinx/themes/basic/defindex.html +1 -1
  274. sphinx/themes/basic/domainindex.html +1 -1
  275. sphinx/themes/basic/genindex-single.html +1 -1
  276. sphinx/themes/basic/genindex-split.html +1 -1
  277. sphinx/themes/basic/genindex.html +1 -1
  278. sphinx/themes/basic/globaltoc.html +1 -1
  279. sphinx/themes/basic/layout.html +1 -1
  280. sphinx/themes/basic/localtoc.html +1 -1
  281. sphinx/themes/basic/page.html +1 -1
  282. sphinx/themes/basic/relations.html +1 -1
  283. sphinx/themes/basic/search.html +5 -20
  284. sphinx/themes/basic/searchbox.html +3 -3
  285. sphinx/themes/basic/searchfield.html +3 -3
  286. sphinx/themes/basic/sourcelink.html +1 -1
  287. sphinx/themes/basic/static/basic.css_t +1 -1
  288. sphinx/themes/basic/static/doctools.js +1 -1
  289. sphinx/themes/basic/static/language_data.js_t +2 -2
  290. sphinx/themes/basic/static/searchtools.js +105 -60
  291. sphinx/themes/basic/theme.toml +23 -0
  292. sphinx/themes/bizstyle/layout.html +1 -6
  293. sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
  294. sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
  295. sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
  296. sphinx/themes/bizstyle/theme.toml +12 -0
  297. sphinx/themes/classic/layout.html +1 -1
  298. sphinx/themes/classic/static/classic.css_t +1 -1
  299. sphinx/themes/classic/static/sidebar.js_t +1 -1
  300. sphinx/themes/classic/theme.toml +34 -0
  301. sphinx/themes/default/theme.toml +2 -0
  302. sphinx/themes/epub/epub-cover.html +1 -1
  303. sphinx/themes/epub/layout.html +1 -1
  304. sphinx/themes/epub/static/epub.css_t +1 -1
  305. sphinx/themes/epub/theme.toml +10 -0
  306. sphinx/themes/haiku/layout.html +3 -3
  307. sphinx/themes/haiku/static/haiku.css_t +2 -2
  308. sphinx/themes/haiku/theme.toml +16 -0
  309. sphinx/themes/nature/static/nature.css_t +1 -1
  310. sphinx/themes/nature/theme.toml +6 -0
  311. sphinx/themes/nonav/layout.html +1 -1
  312. sphinx/themes/nonav/static/nonav.css_t +1 -1
  313. sphinx/themes/nonav/theme.toml +10 -0
  314. sphinx/themes/pyramid/static/epub.css_t +1 -1
  315. sphinx/themes/pyramid/static/pyramid.css_t +1 -1
  316. sphinx/themes/pyramid/theme.toml +6 -0
  317. sphinx/themes/scrolls/artwork/logo.svg +1 -1
  318. sphinx/themes/scrolls/layout.html +2 -2
  319. sphinx/themes/scrolls/static/scrolls.css_t +1 -1
  320. sphinx/themes/scrolls/theme.toml +15 -0
  321. sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
  322. sphinx/themes/sphinxdoc/theme.toml +6 -0
  323. sphinx/themes/traditional/static/traditional.css_t +1 -1
  324. sphinx/themes/traditional/theme.toml +9 -0
  325. sphinx/theming.py +427 -131
  326. sphinx/transforms/__init__.py +21 -24
  327. sphinx/transforms/compact_bullet_list.py +5 -5
  328. sphinx/transforms/i18n.py +30 -28
  329. sphinx/transforms/post_transforms/__init__.py +9 -7
  330. sphinx/transforms/post_transforms/code.py +4 -1
  331. sphinx/transforms/post_transforms/images.py +17 -13
  332. sphinx/transforms/references.py +3 -1
  333. sphinx/util/__init__.py +15 -11
  334. sphinx/util/_io.py +34 -0
  335. sphinx/util/_pathlib.py +23 -18
  336. sphinx/util/build_phase.py +1 -0
  337. sphinx/util/cfamily.py +19 -11
  338. sphinx/util/console.py +101 -21
  339. sphinx/util/display.py +3 -2
  340. sphinx/util/docfields.py +12 -8
  341. sphinx/util/docutils.py +21 -35
  342. sphinx/util/exceptions.py +3 -2
  343. sphinx/util/fileutil.py +5 -5
  344. sphinx/util/http_date.py +9 -2
  345. sphinx/util/i18n.py +40 -9
  346. sphinx/util/inspect.py +317 -245
  347. sphinx/util/inventory.py +22 -5
  348. sphinx/util/logging.py +81 -7
  349. sphinx/util/matching.py +2 -1
  350. sphinx/util/math.py +1 -2
  351. sphinx/util/nodes.py +39 -29
  352. sphinx/util/osutil.py +25 -6
  353. sphinx/util/parallel.py +6 -1
  354. sphinx/util/requests.py +8 -5
  355. sphinx/util/rst.py +8 -6
  356. sphinx/util/tags.py +3 -3
  357. sphinx/util/template.py +8 -3
  358. sphinx/util/typing.py +76 -42
  359. sphinx/versioning.py +6 -2
  360. sphinx/writers/html.py +1 -1
  361. sphinx/writers/html5.py +17 -13
  362. sphinx/writers/latex.py +12 -12
  363. sphinx/writers/manpage.py +13 -7
  364. sphinx/writers/texinfo.py +13 -10
  365. sphinx/writers/text.py +13 -23
  366. sphinx/writers/xml.py +1 -1
  367. sphinx-7.2.6.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
  368. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
  369. sphinx-7.3.0.dist-info/RECORD +581 -0
  370. sphinx/domains/c.py +0 -3906
  371. sphinx/domains/cpp.py +0 -8233
  372. sphinx/domains/python.py +0 -1769
  373. sphinx/themes/agogo/theme.conf +0 -20
  374. sphinx/themes/basic/theme.conf +0 -16
  375. sphinx/themes/bizstyle/theme.conf +0 -10
  376. sphinx/themes/classic/theme.conf +0 -32
  377. sphinx/themes/default/theme.conf +0 -2
  378. sphinx/themes/epub/theme.conf +0 -8
  379. sphinx/themes/haiku/theme.conf +0 -14
  380. sphinx/themes/nature/theme.conf +0 -4
  381. sphinx/themes/nonav/theme.conf +0 -8
  382. sphinx/themes/pyramid/theme.conf +0 -4
  383. sphinx/themes/scrolls/theme.conf +0 -13
  384. sphinx/themes/sphinxdoc/theme.conf +0 -4
  385. sphinx/themes/traditional/theme.conf +0 -7
  386. sphinx-7.2.6.dist-info/RECORD +0 -569
  387. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
  388. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,700 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Callable
4
+
5
+ from sphinx.domains.c._ast import (
6
+ ASTDeclaration,
7
+ ASTIdentifier,
8
+ ASTNestedName,
9
+ )
10
+ from sphinx.locale import __
11
+ from sphinx.util import logging
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Iterator
15
+
16
+ from typing_extensions import Self
17
+
18
+ from sphinx.environment import BuildEnvironment
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class _DuplicateSymbolError(Exception):
24
+ def __init__(self, symbol: Symbol, declaration: ASTDeclaration) -> None:
25
+ assert symbol
26
+ assert declaration
27
+ self.symbol = symbol
28
+ self.declaration = declaration
29
+
30
+ def __str__(self) -> str:
31
+ return "Internal C duplicate symbol error:\n%s" % self.symbol.dump(0)
32
+
33
+
34
+ class SymbolLookupResult:
35
+ def __init__(self, symbols: Iterator[Symbol], parentSymbol: Symbol,
36
+ ident: ASTIdentifier) -> None:
37
+ self.symbols = symbols
38
+ self.parentSymbol = parentSymbol
39
+ self.ident = ident
40
+
41
+
42
+ class LookupKey:
43
+ def __init__(self, data: list[tuple[ASTIdentifier, str]]) -> None:
44
+ self.data = data
45
+
46
+ def __str__(self) -> str:
47
+ inner = ', '.join(f"({ident}, {id_})" for ident, id_ in self.data)
48
+ return f'[{inner}]'
49
+
50
+
51
+ class Symbol:
52
+ debug_indent = 0
53
+ debug_indent_string = " "
54
+ debug_lookup = False
55
+ debug_show_tree = False
56
+
57
+ def __copy__(self) -> Self:
58
+ raise AssertionError # shouldn't happen
59
+
60
+ def __deepcopy__(self, memo: Any) -> Symbol:
61
+ if self.parent:
62
+ raise AssertionError # shouldn't happen
63
+ # the domain base class makes a copy of the initial data, which is fine
64
+ return Symbol(None, None, None, None, None)
65
+
66
+ @staticmethod
67
+ def debug_print(*args: Any) -> None:
68
+ msg = Symbol.debug_indent_string * Symbol.debug_indent
69
+ msg += "".join(str(e) for e in args)
70
+ logger.debug(msg)
71
+
72
+ def _assert_invariants(self) -> None:
73
+ if not self.parent:
74
+ # parent == None means global scope, so declaration means a parent
75
+ assert not self.declaration
76
+ assert not self.docname
77
+ else:
78
+ if self.declaration:
79
+ assert self.docname
80
+
81
+ def __setattr__(self, key: str, value: Any) -> None:
82
+ if key == "children":
83
+ raise AssertionError
84
+ return super().__setattr__(key, value)
85
+
86
+ def __init__(
87
+ self,
88
+ parent: Symbol | None,
89
+ ident: ASTIdentifier | None,
90
+ declaration: ASTDeclaration | None,
91
+ docname: str | None,
92
+ line: int | None,
93
+ ) -> None:
94
+ self.parent = parent
95
+ # declarations in a single directive are linked together
96
+ self.siblingAbove: Symbol | None = None
97
+ self.siblingBelow: Symbol | None = None
98
+ self.ident = ident
99
+ self.declaration = declaration
100
+ self.docname = docname
101
+ self.line = line
102
+ self.isRedeclaration = False
103
+ self._assert_invariants()
104
+
105
+ # Remember to modify Symbol.remove if modifications to the parent change.
106
+ self._children: list[Symbol] = []
107
+ self._anonChildren: list[Symbol] = []
108
+ # note: _children includes _anonChildren
109
+ if self.parent:
110
+ self.parent._children.append(self)
111
+ if self.declaration:
112
+ self.declaration.symbol = self
113
+
114
+ # Do symbol addition after self._children has been initialised.
115
+ self._add_function_params()
116
+
117
+ def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> None:
118
+ self._assert_invariants()
119
+ assert self.declaration is None
120
+ assert self.docname is None
121
+ assert self.line is None
122
+ assert declaration is not None
123
+ assert docname is not None
124
+ assert line is not None
125
+ self.declaration = declaration
126
+ self.declaration.symbol = self
127
+ self.docname = docname
128
+ self.line = line
129
+ self._assert_invariants()
130
+ # and symbol addition should be done as well
131
+ self._add_function_params()
132
+
133
+ def _add_function_params(self) -> None:
134
+ if Symbol.debug_lookup:
135
+ Symbol.debug_indent += 1
136
+ Symbol.debug_print("_add_function_params:")
137
+ # Note: we may be called from _fill_empty, so the symbols we want
138
+ # to add may actually already be present (as empty symbols).
139
+
140
+ # add symbols for function parameters, if any
141
+ if self.declaration is not None and self.declaration.function_params is not None:
142
+ for p in self.declaration.function_params:
143
+ if p.arg is None:
144
+ continue
145
+ nn = p.arg.name
146
+ if nn is None:
147
+ continue
148
+ # (comparing to the template params: we have checked that we are a declaration)
149
+ decl = ASTDeclaration('functionParam', None, p)
150
+ assert not nn.rooted
151
+ assert len(nn.names) == 1
152
+ self._add_symbols(nn, decl, self.docname, self.line)
153
+ if Symbol.debug_lookup:
154
+ Symbol.debug_indent -= 1
155
+
156
+ def remove(self) -> None:
157
+ if self.parent is None:
158
+ return
159
+ assert self in self.parent._children
160
+ self.parent._children.remove(self)
161
+ self.parent = None
162
+
163
+ def clear_doc(self, docname: str) -> None:
164
+ for sChild in self._children:
165
+ sChild.clear_doc(docname)
166
+ if sChild.declaration and sChild.docname == docname:
167
+ sChild.declaration = None
168
+ sChild.docname = None
169
+ sChild.line = None
170
+ if sChild.siblingAbove is not None:
171
+ sChild.siblingAbove.siblingBelow = sChild.siblingBelow
172
+ if sChild.siblingBelow is not None:
173
+ sChild.siblingBelow.siblingAbove = sChild.siblingAbove
174
+ sChild.siblingAbove = None
175
+ sChild.siblingBelow = None
176
+
177
+ def get_all_symbols(self) -> Iterator[Symbol]:
178
+ yield self
179
+ for sChild in self._children:
180
+ yield from sChild.get_all_symbols()
181
+
182
+ @property
183
+ def children(self) -> Iterator[Symbol]:
184
+ yield from self._children
185
+
186
+ @property
187
+ def children_recurse_anon(self) -> Iterator[Symbol]:
188
+ for c in self._children:
189
+ yield c
190
+ if not c.ident.is_anon():
191
+ continue
192
+ yield from c.children_recurse_anon
193
+
194
+ def get_lookup_key(self) -> LookupKey:
195
+ # The pickle files for the environment and for each document are distinct.
196
+ # The environment has all the symbols, but the documents has xrefs that
197
+ # must know their scope. A lookup key is essentially a specification of
198
+ # how to find a specific symbol.
199
+ symbols = []
200
+ s = self
201
+ while s.parent:
202
+ symbols.append(s)
203
+ s = s.parent
204
+ symbols.reverse()
205
+ key = []
206
+ for s in symbols:
207
+ if s.declaration is not None:
208
+ # TODO: do we need the ID?
209
+ key.append((s.ident, s.declaration.get_newest_id()))
210
+ else:
211
+ key.append((s.ident, None))
212
+ return LookupKey(key)
213
+
214
+ def get_full_nested_name(self) -> ASTNestedName:
215
+ symbols = []
216
+ s = self
217
+ while s.parent:
218
+ symbols.append(s)
219
+ s = s.parent
220
+ symbols.reverse()
221
+ names = [s.ident for s in symbols]
222
+ return ASTNestedName(names, rooted=False)
223
+
224
+ def _find_first_named_symbol(self, ident: ASTIdentifier,
225
+ matchSelf: bool, recurseInAnon: bool) -> Symbol | None:
226
+ # TODO: further simplification from C++ to C
227
+ if Symbol.debug_lookup:
228
+ Symbol.debug_print("_find_first_named_symbol ->")
229
+ res = self._find_named_symbols(ident, matchSelf, recurseInAnon,
230
+ searchInSiblings=False)
231
+ try:
232
+ return next(res)
233
+ except StopIteration:
234
+ return None
235
+
236
+ def _find_named_symbols(self, ident: ASTIdentifier,
237
+ matchSelf: bool, recurseInAnon: bool,
238
+ searchInSiblings: bool) -> Iterator[Symbol]:
239
+ # TODO: further simplification from C++ to C
240
+ if Symbol.debug_lookup:
241
+ Symbol.debug_indent += 1
242
+ Symbol.debug_print("_find_named_symbols:")
243
+ Symbol.debug_indent += 1
244
+ Symbol.debug_print("self:")
245
+ logger.debug(self.to_string(Symbol.debug_indent + 1, addEndNewline=False))
246
+ Symbol.debug_print("ident: ", ident)
247
+ Symbol.debug_print("matchSelf: ", matchSelf)
248
+ Symbol.debug_print("recurseInAnon: ", recurseInAnon)
249
+ Symbol.debug_print("searchInSiblings: ", searchInSiblings)
250
+
251
+ def candidates() -> Iterator[Symbol]:
252
+ s = self
253
+ if Symbol.debug_lookup:
254
+ Symbol.debug_print("searching in self:")
255
+ logger.debug(s.to_string(Symbol.debug_indent + 1, addEndNewline=False))
256
+ while True:
257
+ if matchSelf:
258
+ yield s
259
+ if recurseInAnon:
260
+ yield from s.children_recurse_anon
261
+ else:
262
+ yield from s._children
263
+
264
+ if s.siblingAbove is None:
265
+ break
266
+ s = s.siblingAbove
267
+ if Symbol.debug_lookup:
268
+ Symbol.debug_print("searching in sibling:")
269
+ logger.debug(s.to_string(Symbol.debug_indent + 1, addEndNewline=False))
270
+
271
+ for s in candidates():
272
+ if Symbol.debug_lookup:
273
+ Symbol.debug_print("candidate:")
274
+ logger.debug(s.to_string(Symbol.debug_indent + 1, addEndNewline=False))
275
+ if s.ident == ident:
276
+ if Symbol.debug_lookup:
277
+ Symbol.debug_indent += 1
278
+ Symbol.debug_print("matches")
279
+ Symbol.debug_indent -= 3
280
+ yield s
281
+ if Symbol.debug_lookup:
282
+ Symbol.debug_indent += 2
283
+ if Symbol.debug_lookup:
284
+ Symbol.debug_indent -= 2
285
+
286
+ def _symbol_lookup(
287
+ self,
288
+ nestedName: ASTNestedName,
289
+ onMissingQualifiedSymbol: Callable[[Symbol, ASTIdentifier], Symbol | None],
290
+ ancestorLookupType: str | None,
291
+ matchSelf: bool,
292
+ recurseInAnon: bool,
293
+ searchInSiblings: bool,
294
+ ) -> SymbolLookupResult | None:
295
+ # TODO: further simplification from C++ to C
296
+ # ancestorLookupType: if not None, specifies the target type of the lookup
297
+ if Symbol.debug_lookup:
298
+ Symbol.debug_indent += 1
299
+ Symbol.debug_print("_symbol_lookup:")
300
+ Symbol.debug_indent += 1
301
+ Symbol.debug_print("self:")
302
+ logger.debug(self.to_string(Symbol.debug_indent + 1, addEndNewline=False))
303
+ Symbol.debug_print("nestedName: ", nestedName)
304
+ Symbol.debug_print("ancestorLookupType:", ancestorLookupType)
305
+ Symbol.debug_print("matchSelf: ", matchSelf)
306
+ Symbol.debug_print("recurseInAnon: ", recurseInAnon)
307
+ Symbol.debug_print("searchInSiblings: ", searchInSiblings)
308
+
309
+ names = nestedName.names
310
+
311
+ # find the right starting point for lookup
312
+ parentSymbol = self
313
+ if nestedName.rooted:
314
+ while parentSymbol.parent:
315
+ parentSymbol = parentSymbol.parent
316
+ if ancestorLookupType is not None:
317
+ # walk up until we find the first identifier
318
+ firstName = names[0]
319
+ while parentSymbol.parent:
320
+ if parentSymbol.find_identifier(firstName,
321
+ matchSelf=matchSelf,
322
+ recurseInAnon=recurseInAnon,
323
+ searchInSiblings=searchInSiblings):
324
+ break
325
+ parentSymbol = parentSymbol.parent
326
+
327
+ if Symbol.debug_lookup:
328
+ Symbol.debug_print("starting point:")
329
+ logger.debug(parentSymbol.to_string(Symbol.debug_indent + 1, addEndNewline=False))
330
+
331
+ # and now the actual lookup
332
+ for ident in names[:-1]:
333
+ symbol = parentSymbol._find_first_named_symbol(
334
+ ident, matchSelf=matchSelf, recurseInAnon=recurseInAnon)
335
+ if symbol is None:
336
+ symbol = onMissingQualifiedSymbol(parentSymbol, ident)
337
+ if symbol is None:
338
+ if Symbol.debug_lookup:
339
+ Symbol.debug_indent -= 2
340
+ return None
341
+ # We have now matched part of a nested name, and need to match more
342
+ # so even if we should matchSelf before, we definitely shouldn't
343
+ # even more. (see also issue #2666)
344
+ matchSelf = False
345
+ parentSymbol = symbol
346
+
347
+ if Symbol.debug_lookup:
348
+ Symbol.debug_print("handle last name from:")
349
+ logger.debug(parentSymbol.to_string(Symbol.debug_indent + 1, addEndNewline=False))
350
+
351
+ # handle the last name
352
+ ident = names[-1]
353
+
354
+ symbols = parentSymbol._find_named_symbols(
355
+ ident, matchSelf=matchSelf,
356
+ recurseInAnon=recurseInAnon,
357
+ searchInSiblings=searchInSiblings)
358
+ if Symbol.debug_lookup:
359
+ symbols = list(symbols) # type: ignore[assignment]
360
+ Symbol.debug_indent -= 2
361
+ return SymbolLookupResult(symbols, parentSymbol, ident)
362
+
363
+ def _add_symbols(
364
+ self,
365
+ nestedName: ASTNestedName,
366
+ declaration: ASTDeclaration | None,
367
+ docname: str | None,
368
+ line: int | None,
369
+ ) -> Symbol:
370
+ # TODO: further simplification from C++ to C
371
+ # Used for adding a whole path of symbols, where the last may or may not
372
+ # be an actual declaration.
373
+
374
+ if Symbol.debug_lookup:
375
+ Symbol.debug_indent += 1
376
+ Symbol.debug_print("_add_symbols:")
377
+ Symbol.debug_indent += 1
378
+ Symbol.debug_print("nn: ", nestedName)
379
+ Symbol.debug_print("decl: ", declaration)
380
+ Symbol.debug_print(f"location: {docname}:{line}")
381
+
382
+ def onMissingQualifiedSymbol(parentSymbol: Symbol, ident: ASTIdentifier) -> Symbol:
383
+ if Symbol.debug_lookup:
384
+ Symbol.debug_indent += 1
385
+ Symbol.debug_print("_add_symbols, onMissingQualifiedSymbol:")
386
+ Symbol.debug_indent += 1
387
+ Symbol.debug_print("ident: ", ident)
388
+ Symbol.debug_indent -= 2
389
+ return Symbol(parent=parentSymbol, ident=ident,
390
+ declaration=None, docname=None, line=None)
391
+
392
+ lookupResult = self._symbol_lookup(nestedName,
393
+ onMissingQualifiedSymbol,
394
+ ancestorLookupType=None,
395
+ matchSelf=False,
396
+ recurseInAnon=False,
397
+ searchInSiblings=False)
398
+ assert lookupResult is not None # we create symbols all the way, so that can't happen
399
+ symbols = list(lookupResult.symbols)
400
+ if len(symbols) == 0:
401
+ if Symbol.debug_lookup:
402
+ Symbol.debug_print("_add_symbols, result, no symbol:")
403
+ Symbol.debug_indent += 1
404
+ Symbol.debug_print("ident: ", lookupResult.ident)
405
+ Symbol.debug_print("declaration: ", declaration)
406
+ Symbol.debug_print(f"location: {docname}:{line}")
407
+ Symbol.debug_indent -= 1
408
+ symbol = Symbol(parent=lookupResult.parentSymbol,
409
+ ident=lookupResult.ident,
410
+ declaration=declaration,
411
+ docname=docname, line=line)
412
+ if Symbol.debug_lookup:
413
+ Symbol.debug_indent -= 2
414
+ return symbol
415
+
416
+ if Symbol.debug_lookup:
417
+ Symbol.debug_print("_add_symbols, result, symbols:")
418
+ Symbol.debug_indent += 1
419
+ Symbol.debug_print("number symbols:", len(symbols))
420
+ Symbol.debug_indent -= 1
421
+
422
+ if not declaration:
423
+ if Symbol.debug_lookup:
424
+ Symbol.debug_print("no declaration")
425
+ Symbol.debug_indent -= 2
426
+ # good, just a scope creation
427
+ # TODO: what if we have more than one symbol?
428
+ return symbols[0]
429
+
430
+ noDecl = []
431
+ withDecl = []
432
+ dupDecl = []
433
+ for s in symbols:
434
+ if s.declaration is None:
435
+ noDecl.append(s)
436
+ elif s.isRedeclaration:
437
+ dupDecl.append(s)
438
+ else:
439
+ withDecl.append(s)
440
+ if Symbol.debug_lookup:
441
+ Symbol.debug_print("#noDecl: ", len(noDecl))
442
+ Symbol.debug_print("#withDecl:", len(withDecl))
443
+ Symbol.debug_print("#dupDecl: ", len(dupDecl))
444
+
445
+ # With partial builds we may start with a large symbol tree stripped of declarations.
446
+ # Essentially any combination of noDecl, withDecl, and dupDecls seems possible.
447
+ # TODO: make partial builds fully work. What should happen when the primary symbol gets
448
+ # deleted, and other duplicates exist? The full document should probably be rebuild.
449
+
450
+ # First check if one of those with a declaration matches.
451
+ # If it's a function, we need to compare IDs,
452
+ # otherwise there should be only one symbol with a declaration.
453
+ def makeCandSymbol() -> Symbol:
454
+ if Symbol.debug_lookup:
455
+ Symbol.debug_print("begin: creating candidate symbol")
456
+ symbol = Symbol(parent=lookupResult.parentSymbol,
457
+ ident=lookupResult.ident,
458
+ declaration=declaration,
459
+ docname=docname, line=line)
460
+ if Symbol.debug_lookup:
461
+ Symbol.debug_print("end: creating candidate symbol")
462
+ return symbol
463
+
464
+ if len(withDecl) == 0:
465
+ candSymbol = None
466
+ else:
467
+ candSymbol = makeCandSymbol()
468
+
469
+ def handleDuplicateDeclaration(symbol: Symbol, candSymbol: Symbol) -> None:
470
+ if Symbol.debug_lookup:
471
+ Symbol.debug_indent += 1
472
+ Symbol.debug_print("redeclaration")
473
+ Symbol.debug_indent -= 1
474
+ Symbol.debug_indent -= 2
475
+ # Redeclaration of the same symbol.
476
+ # Let the new one be there, but raise an error to the client
477
+ # so it can use the real symbol as subscope.
478
+ # This will probably result in a duplicate id warning.
479
+ candSymbol.isRedeclaration = True
480
+ raise _DuplicateSymbolError(symbol, declaration)
481
+
482
+ if declaration.objectType != "function":
483
+ assert len(withDecl) <= 1
484
+ handleDuplicateDeclaration(withDecl[0], candSymbol)
485
+ # (not reachable)
486
+
487
+ # a function, so compare IDs
488
+ candId = declaration.get_newest_id()
489
+ if Symbol.debug_lookup:
490
+ Symbol.debug_print("candId:", candId)
491
+ for symbol in withDecl:
492
+ oldId = symbol.declaration.get_newest_id()
493
+ if Symbol.debug_lookup:
494
+ Symbol.debug_print("oldId: ", oldId)
495
+ if candId == oldId:
496
+ handleDuplicateDeclaration(symbol, candSymbol)
497
+ # (not reachable)
498
+ # no candidate symbol found with matching ID
499
+ # if there is an empty symbol, fill that one
500
+ if len(noDecl) == 0:
501
+ if Symbol.debug_lookup:
502
+ Symbol.debug_print(
503
+ "no match, no empty, candSybmol is not None?:", candSymbol is not None,
504
+ )
505
+ Symbol.debug_indent -= 2
506
+ if candSymbol is not None:
507
+ return candSymbol
508
+ else:
509
+ return makeCandSymbol()
510
+ else:
511
+ if Symbol.debug_lookup:
512
+ Symbol.debug_print(
513
+ "no match, but fill an empty declaration, candSybmol is not None?:",
514
+ candSymbol is not None)
515
+ Symbol.debug_indent -= 2
516
+ if candSymbol is not None:
517
+ candSymbol.remove()
518
+ # assert len(noDecl) == 1
519
+ # TODO: enable assertion when we at some point find out how to do cleanup
520
+ # for now, just take the first one, it should work fine ... right?
521
+ symbol = noDecl[0]
522
+ # If someone first opened the scope, and then later
523
+ # declares it, e.g,
524
+ # .. namespace:: Test
525
+ # .. namespace:: nullptr
526
+ # .. class:: Test
527
+ symbol._fill_empty(declaration, docname, line)
528
+ return symbol
529
+
530
+ def merge_with(self, other: Symbol, docnames: list[str],
531
+ env: BuildEnvironment) -> None:
532
+ if Symbol.debug_lookup:
533
+ Symbol.debug_indent += 1
534
+ Symbol.debug_print("merge_with:")
535
+ assert other is not None
536
+ for otherChild in other._children:
537
+ ourChild = self._find_first_named_symbol(
538
+ ident=otherChild.ident, matchSelf=False,
539
+ recurseInAnon=False)
540
+ if ourChild is None:
541
+ # TODO: hmm, should we prune by docnames?
542
+ self._children.append(otherChild)
543
+ otherChild.parent = self
544
+ otherChild._assert_invariants()
545
+ continue
546
+ if otherChild.declaration and otherChild.docname in docnames:
547
+ if not ourChild.declaration:
548
+ ourChild._fill_empty(otherChild.declaration,
549
+ otherChild.docname, otherChild.line)
550
+ elif ourChild.docname != otherChild.docname:
551
+ name = str(ourChild.declaration)
552
+ msg = __("Duplicate C declaration, also defined at %s:%s.\n"
553
+ "Declaration is '.. c:%s:: %s'.")
554
+ msg = msg % (ourChild.docname, ourChild.line,
555
+ ourChild.declaration.directiveType, name)
556
+ logger.warning(msg, location=(otherChild.docname, otherChild.line))
557
+ else:
558
+ # Both have declarations, and in the same docname.
559
+ # This can apparently happen, it should be safe to
560
+ # just ignore it, right?
561
+ pass
562
+ ourChild.merge_with(otherChild, docnames, env)
563
+ if Symbol.debug_lookup:
564
+ Symbol.debug_indent -= 1
565
+
566
+ def add_name(self, nestedName: ASTNestedName) -> Symbol:
567
+ if Symbol.debug_lookup:
568
+ Symbol.debug_indent += 1
569
+ Symbol.debug_print("add_name:")
570
+ res = self._add_symbols(nestedName, declaration=None, docname=None, line=None)
571
+ if Symbol.debug_lookup:
572
+ Symbol.debug_indent -= 1
573
+ return res
574
+
575
+ def add_declaration(self, declaration: ASTDeclaration,
576
+ docname: str, line: int) -> Symbol:
577
+ if Symbol.debug_lookup:
578
+ Symbol.debug_indent += 1
579
+ Symbol.debug_print("add_declaration:")
580
+ assert declaration is not None
581
+ assert docname is not None
582
+ assert line is not None
583
+ nestedName = declaration.name
584
+ res = self._add_symbols(nestedName, declaration, docname, line)
585
+ if Symbol.debug_lookup:
586
+ Symbol.debug_indent -= 1
587
+ return res
588
+
589
+ def find_identifier(self, ident: ASTIdentifier,
590
+ matchSelf: bool, recurseInAnon: bool, searchInSiblings: bool,
591
+ ) -> Symbol | None:
592
+ if Symbol.debug_lookup:
593
+ Symbol.debug_indent += 1
594
+ Symbol.debug_print("find_identifier:")
595
+ Symbol.debug_indent += 1
596
+ Symbol.debug_print("ident: ", ident)
597
+ Symbol.debug_print("matchSelf: ", matchSelf)
598
+ Symbol.debug_print("recurseInAnon: ", recurseInAnon)
599
+ Symbol.debug_print("searchInSiblings:", searchInSiblings)
600
+ logger.debug(self.to_string(Symbol.debug_indent + 1, addEndNewline=False))
601
+ Symbol.debug_indent -= 2
602
+ current = self
603
+ while current is not None:
604
+ if Symbol.debug_lookup:
605
+ Symbol.debug_indent += 2
606
+ Symbol.debug_print("trying:")
607
+ logger.debug(current.to_string(Symbol.debug_indent + 1, addEndNewline=False))
608
+ Symbol.debug_indent -= 2
609
+ if matchSelf and current.ident == ident:
610
+ return current
611
+ children = current.children_recurse_anon if recurseInAnon else current._children
612
+ for s in children:
613
+ if s.ident == ident:
614
+ return s
615
+ if not searchInSiblings:
616
+ break
617
+ current = current.siblingAbove
618
+ return None
619
+
620
+ def direct_lookup(self, key: LookupKey) -> Symbol | None:
621
+ if Symbol.debug_lookup:
622
+ Symbol.debug_indent += 1
623
+ Symbol.debug_print("direct_lookup:")
624
+ Symbol.debug_indent += 1
625
+ s = self
626
+ for name, id_ in key.data:
627
+ res = None
628
+ for cand in s._children:
629
+ if cand.ident == name:
630
+ res = cand
631
+ break
632
+ s = res
633
+ if Symbol.debug_lookup:
634
+ Symbol.debug_print("name: ", name)
635
+ Symbol.debug_print("id: ", id_)
636
+ if s is not None:
637
+ logger.debug(s.to_string(Symbol.debug_indent + 1, addEndNewline=False))
638
+ else:
639
+ Symbol.debug_print("not found")
640
+ if s is None:
641
+ if Symbol.debug_lookup:
642
+ Symbol.debug_indent -= 2
643
+ return None
644
+ if Symbol.debug_lookup:
645
+ Symbol.debug_indent -= 2
646
+ return s
647
+
648
+ def find_declaration(self, nestedName: ASTNestedName, typ: str,
649
+ matchSelf: bool, recurseInAnon: bool) -> Symbol | None:
650
+ # templateShorthand: missing template parameter lists for templates is ok
651
+ if Symbol.debug_lookup:
652
+ Symbol.debug_indent += 1
653
+ Symbol.debug_print("find_declaration:")
654
+
655
+ def onMissingQualifiedSymbol(
656
+ parentSymbol: Symbol,
657
+ ident: ASTIdentifier,
658
+ ) -> Symbol | None:
659
+ return None
660
+
661
+ lookupResult = self._symbol_lookup(nestedName,
662
+ onMissingQualifiedSymbol,
663
+ ancestorLookupType=typ,
664
+ matchSelf=matchSelf,
665
+ recurseInAnon=recurseInAnon,
666
+ searchInSiblings=False)
667
+ if Symbol.debug_lookup:
668
+ Symbol.debug_indent -= 1
669
+ if lookupResult is None:
670
+ return None
671
+
672
+ symbols = list(lookupResult.symbols)
673
+ if len(symbols) == 0:
674
+ return None
675
+ return symbols[0]
676
+
677
+ def to_string(self, indent: int, *, addEndNewline: bool = True) -> str:
678
+ res = [Symbol.debug_indent_string * indent]
679
+ if not self.parent:
680
+ res.append('::')
681
+ else:
682
+ if self.ident:
683
+ res.append(str(self.ident))
684
+ else:
685
+ res.append(str(self.declaration))
686
+ if self.declaration:
687
+ res.append(": ")
688
+ if self.isRedeclaration:
689
+ res.append('!!duplicate!! ')
690
+ res.append(str(self.declaration))
691
+ if self.docname:
692
+ res.append('\t(')
693
+ res.append(self.docname)
694
+ res.append(')')
695
+ if addEndNewline:
696
+ res.append('\n')
697
+ return ''.join(res)
698
+
699
+ def dump(self, indent: int) -> str:
700
+ return ''.join([self.to_string(indent), *(c.dump(indent + 1) for c in self._children)])