Sphinx 7.2.5__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 +21 -20
  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 +132 -52
  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.5.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
  368. {sphinx-7.2.5.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.5.dist-info/RECORD +0 -569
  387. {sphinx-7.2.5.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
  388. {sphinx-7.2.5.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,796 @@
1
+ """The C language domain."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any, ClassVar
6
+
7
+ from docutils import nodes
8
+ from docutils.parsers.rst import directives
9
+
10
+ from sphinx import addnodes
11
+ from sphinx.directives import ObjectDescription
12
+ from sphinx.domains import Domain, ObjType
13
+ from sphinx.domains.c._ast import (
14
+ ASTDeclaration,
15
+ ASTIdentifier,
16
+ ASTNestedName,
17
+ )
18
+ from sphinx.domains.c._ids import _macroKeywords, _max_id
19
+ from sphinx.domains.c._parser import DefinitionParser
20
+ from sphinx.domains.c._symbol import Symbol, _DuplicateSymbolError
21
+ from sphinx.locale import _, __
22
+ from sphinx.roles import SphinxRole, XRefRole
23
+ from sphinx.transforms import SphinxTransform
24
+ from sphinx.transforms.post_transforms import ReferencesResolver
25
+ from sphinx.util import logging
26
+ from sphinx.util.cfamily import (
27
+ DefinitionError,
28
+ NoOldIdError,
29
+ anon_identifier_re,
30
+ )
31
+ from sphinx.util.docfields import Field, GroupedField, TypedField
32
+ from sphinx.util.docutils import SphinxDirective
33
+ from sphinx.util.nodes import make_refnode
34
+
35
+ if TYPE_CHECKING:
36
+ from collections.abc import Iterator
37
+
38
+ from docutils.nodes import Element, Node, TextElement, system_message
39
+
40
+ from sphinx.addnodes import pending_xref
41
+ from sphinx.application import Sphinx
42
+ from sphinx.builders import Builder
43
+ from sphinx.domains.c._symbol import LookupKey
44
+ from sphinx.environment import BuildEnvironment
45
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec
46
+
47
+ logger = logging.getLogger(__name__)
48
+
49
+
50
+ def _make_phony_error_name() -> ASTNestedName:
51
+ return ASTNestedName([ASTIdentifier("PhonyNameDueToError")], rooted=False)
52
+
53
+
54
+ class CObject(ObjectDescription[ASTDeclaration]):
55
+ """
56
+ Description of a C language object.
57
+ """
58
+
59
+ option_spec: ClassVar[OptionSpec] = {
60
+ 'no-index-entry': directives.flag,
61
+ 'no-contents-entry': directives.flag,
62
+ 'no-typesetting': directives.flag,
63
+ 'noindexentry': directives.flag,
64
+ 'nocontentsentry': directives.flag,
65
+ 'single-line-parameter-list': directives.flag,
66
+ }
67
+
68
+ def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None:
69
+ assert ast.objectType == 'enumerator'
70
+ # find the parent, if it exists && is an enum
71
+ # then add the name to the parent scope
72
+ symbol = ast.symbol
73
+ assert symbol
74
+ assert symbol.ident is not None
75
+ parentSymbol = symbol.parent
76
+ assert parentSymbol
77
+ if parentSymbol.parent is None:
78
+ # TODO: we could warn, but it is somewhat equivalent to
79
+ # enumeratorss, without the enum
80
+ return # no parent
81
+ parentDecl = parentSymbol.declaration
82
+ if parentDecl is None:
83
+ # the parent is not explicitly declared
84
+ # TODO: we could warn, but?
85
+ return
86
+ if parentDecl.objectType != 'enum':
87
+ # TODO: maybe issue a warning, enumerators in non-enums is weird,
88
+ # but it is somewhat equivalent to enumeratorss, without the enum
89
+ return
90
+ if parentDecl.directiveType != 'enum':
91
+ return
92
+
93
+ targetSymbol = parentSymbol.parent
94
+ s = targetSymbol.find_identifier(symbol.ident, matchSelf=False, recurseInAnon=True,
95
+ searchInSiblings=False)
96
+ if s is not None:
97
+ # something is already declared with that name
98
+ return
99
+ declClone = symbol.declaration.clone()
100
+ declClone.enumeratorScopedSymbol = symbol
101
+ Symbol(parent=targetSymbol, ident=symbol.ident,
102
+ declaration=declClone,
103
+ docname=self.env.docname, line=self.get_source_info()[1])
104
+
105
+ def add_target_and_index(self, ast: ASTDeclaration, sig: str,
106
+ signode: TextElement) -> None:
107
+ ids = []
108
+ for i in range(1, _max_id + 1):
109
+ try:
110
+ id = ast.get_id(version=i)
111
+ ids.append(id)
112
+ except NoOldIdError:
113
+ assert i < _max_id
114
+ # let's keep the newest first
115
+ ids.reverse()
116
+ newestId = ids[0]
117
+ assert newestId # shouldn't be None
118
+
119
+ name = ast.symbol.get_full_nested_name().get_display_string().lstrip('.')
120
+ if newestId not in self.state.document.ids:
121
+ # always add the newest id
122
+ assert newestId
123
+ signode['ids'].append(newestId)
124
+ # only add compatibility ids when there are no conflicts
125
+ for id in ids[1:]:
126
+ if not id: # is None when the element didn't exist in that version
127
+ continue
128
+ if id not in self.state.document.ids:
129
+ signode['ids'].append(id)
130
+
131
+ self.state.document.note_explicit_target(signode)
132
+
133
+ if 'no-index-entry' not in self.options:
134
+ indexText = self.get_index_text(name)
135
+ self.indexnode['entries'].append(('single', indexText, newestId, '', None))
136
+
137
+ @property
138
+ def object_type(self) -> str:
139
+ raise NotImplementedError
140
+
141
+ @property
142
+ def display_object_type(self) -> str:
143
+ return self.object_type
144
+
145
+ def get_index_text(self, name: str) -> str:
146
+ return _('%s (C %s)') % (name, self.display_object_type)
147
+
148
+ def parse_definition(self, parser: DefinitionParser) -> ASTDeclaration:
149
+ return parser.parse_declaration(self.object_type, self.objtype)
150
+
151
+ def describe_signature(self, signode: TextElement, ast: ASTDeclaration,
152
+ options: dict) -> None:
153
+ ast.describe_signature(signode, 'lastIsName', self.env, options)
154
+
155
+ def run(self) -> list[Node]:
156
+ env = self.state.document.settings.env # from ObjectDescription.run
157
+ if 'c:parent_symbol' not in env.temp_data:
158
+ root = env.domaindata['c']['root_symbol']
159
+ env.temp_data['c:parent_symbol'] = root
160
+ env.ref_context['c:parent_key'] = root.get_lookup_key()
161
+
162
+ # When multiple declarations are made in the same directive
163
+ # they need to know about each other to provide symbol lookup for function parameters.
164
+ # We use last_symbol to store the latest added declaration in a directive.
165
+ env.temp_data['c:last_symbol'] = None
166
+ return super().run()
167
+
168
+ def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration:
169
+ parentSymbol: Symbol = self.env.temp_data['c:parent_symbol']
170
+
171
+ max_len = (self.env.config.c_maximum_signature_line_length
172
+ or self.env.config.maximum_signature_line_length
173
+ or 0)
174
+ signode['multi_line_parameter_list'] = (
175
+ 'single-line-parameter-list' not in self.options
176
+ and (len(sig) > max_len > 0)
177
+ )
178
+
179
+ parser = DefinitionParser(sig, location=signode, config=self.env.config)
180
+ try:
181
+ ast = self.parse_definition(parser)
182
+ parser.assert_end()
183
+ except DefinitionError as e:
184
+ logger.warning(e, location=signode)
185
+ # It is easier to assume some phony name than handling the error in
186
+ # the possibly inner declarations.
187
+ name = _make_phony_error_name()
188
+ symbol = parentSymbol.add_name(name)
189
+ self.env.temp_data['c:last_symbol'] = symbol
190
+ raise ValueError from e
191
+
192
+ try:
193
+ symbol = parentSymbol.add_declaration(
194
+ ast, docname=self.env.docname, line=self.get_source_info()[1])
195
+ # append the new declaration to the sibling list
196
+ assert symbol.siblingAbove is None
197
+ assert symbol.siblingBelow is None
198
+ symbol.siblingAbove = self.env.temp_data['c:last_symbol']
199
+ if symbol.siblingAbove is not None:
200
+ assert symbol.siblingAbove.siblingBelow is None
201
+ symbol.siblingAbove.siblingBelow = symbol
202
+ self.env.temp_data['c:last_symbol'] = symbol
203
+ except _DuplicateSymbolError as e:
204
+ # Assume we are actually in the old symbol,
205
+ # instead of the newly created duplicate.
206
+ self.env.temp_data['c:last_symbol'] = e.symbol
207
+ msg = __("Duplicate C declaration, also defined at %s:%s.\n"
208
+ "Declaration is '.. c:%s:: %s'.")
209
+ msg = msg % (e.symbol.docname, e.symbol.line, self.display_object_type, sig)
210
+ logger.warning(msg, location=signode)
211
+
212
+ if ast.objectType == 'enumerator':
213
+ self._add_enumerator_to_parent(ast)
214
+
215
+ # note: handle_signature may be called multiple time per directive,
216
+ # if it has multiple signatures, so don't mess with the original options.
217
+ options = dict(self.options)
218
+ self.describe_signature(signode, ast, options)
219
+ return ast
220
+
221
+ def before_content(self) -> None:
222
+ lastSymbol: Symbol = self.env.temp_data['c:last_symbol']
223
+ assert lastSymbol
224
+ self.oldParentSymbol = self.env.temp_data['c:parent_symbol']
225
+ self.oldParentKey: LookupKey = self.env.ref_context['c:parent_key']
226
+ self.env.temp_data['c:parent_symbol'] = lastSymbol
227
+ self.env.ref_context['c:parent_key'] = lastSymbol.get_lookup_key()
228
+
229
+ def after_content(self) -> None:
230
+ self.env.temp_data['c:parent_symbol'] = self.oldParentSymbol
231
+ self.env.ref_context['c:parent_key'] = self.oldParentKey
232
+
233
+
234
+ class CMemberObject(CObject):
235
+ object_type = 'member'
236
+
237
+ @property
238
+ def display_object_type(self) -> str:
239
+ # the distinction between var and member is only cosmetic
240
+ assert self.objtype in ('member', 'var')
241
+ return self.objtype
242
+
243
+
244
+ _function_doc_field_types = [
245
+ TypedField('parameter', label=_('Parameters'),
246
+ names=('param', 'parameter', 'arg', 'argument'),
247
+ typerolename='expr', typenames=('type',)),
248
+ GroupedField('retval', label=_('Return values'),
249
+ names=('retvals', 'retval'),
250
+ can_collapse=True),
251
+ Field('returnvalue', label=_('Returns'), has_arg=False,
252
+ names=('returns', 'return')),
253
+ Field('returntype', label=_('Return type'), has_arg=False,
254
+ names=('rtype',)),
255
+ ]
256
+
257
+
258
+ class CFunctionObject(CObject):
259
+ object_type = 'function'
260
+
261
+ doc_field_types = _function_doc_field_types.copy()
262
+
263
+
264
+ class CMacroObject(CObject):
265
+ object_type = 'macro'
266
+
267
+ doc_field_types = _function_doc_field_types.copy()
268
+
269
+
270
+ class CStructObject(CObject):
271
+ object_type = 'struct'
272
+
273
+
274
+ class CUnionObject(CObject):
275
+ object_type = 'union'
276
+
277
+
278
+ class CEnumObject(CObject):
279
+ object_type = 'enum'
280
+
281
+
282
+ class CEnumeratorObject(CObject):
283
+ object_type = 'enumerator'
284
+
285
+
286
+ class CTypeObject(CObject):
287
+ object_type = 'type'
288
+
289
+
290
+ class CNamespaceObject(SphinxDirective):
291
+ """
292
+ This directive is just to tell Sphinx that we're documenting stuff in
293
+ namespace foo.
294
+ """
295
+
296
+ has_content = False
297
+ required_arguments = 1
298
+ optional_arguments = 0
299
+ final_argument_whitespace = True
300
+ option_spec: ClassVar[OptionSpec] = {}
301
+
302
+ def run(self) -> list[Node]:
303
+ rootSymbol = self.env.domaindata['c']['root_symbol']
304
+ if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
305
+ symbol = rootSymbol
306
+ stack: list[Symbol] = []
307
+ else:
308
+ parser = DefinitionParser(self.arguments[0],
309
+ location=self.get_location(),
310
+ config=self.env.config)
311
+ try:
312
+ name = parser.parse_namespace_object()
313
+ parser.assert_end()
314
+ except DefinitionError as e:
315
+ logger.warning(e, location=self.get_location())
316
+ name = _make_phony_error_name()
317
+ symbol = rootSymbol.add_name(name)
318
+ stack = [symbol]
319
+ self.env.temp_data['c:parent_symbol'] = symbol
320
+ self.env.temp_data['c:namespace_stack'] = stack
321
+ self.env.ref_context['c:parent_key'] = symbol.get_lookup_key()
322
+ return []
323
+
324
+
325
+ class CNamespacePushObject(SphinxDirective):
326
+ has_content = False
327
+ required_arguments = 1
328
+ optional_arguments = 0
329
+ final_argument_whitespace = True
330
+ option_spec: ClassVar[OptionSpec] = {}
331
+
332
+ def run(self) -> list[Node]:
333
+ if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
334
+ return []
335
+ parser = DefinitionParser(self.arguments[0],
336
+ location=self.get_location(),
337
+ config=self.env.config)
338
+ try:
339
+ name = parser.parse_namespace_object()
340
+ parser.assert_end()
341
+ except DefinitionError as e:
342
+ logger.warning(e, location=self.get_location())
343
+ name = _make_phony_error_name()
344
+ oldParent = self.env.temp_data.get('c:parent_symbol', None)
345
+ if not oldParent:
346
+ oldParent = self.env.domaindata['c']['root_symbol']
347
+ symbol = oldParent.add_name(name)
348
+ stack = self.env.temp_data.get('c:namespace_stack', [])
349
+ stack.append(symbol)
350
+ self.env.temp_data['c:parent_symbol'] = symbol
351
+ self.env.temp_data['c:namespace_stack'] = stack
352
+ self.env.ref_context['c:parent_key'] = symbol.get_lookup_key()
353
+ return []
354
+
355
+
356
+ class CNamespacePopObject(SphinxDirective):
357
+ has_content = False
358
+ required_arguments = 0
359
+ optional_arguments = 0
360
+ final_argument_whitespace = True
361
+ option_spec: ClassVar[OptionSpec] = {}
362
+
363
+ def run(self) -> list[Node]:
364
+ stack = self.env.temp_data.get('c:namespace_stack', None)
365
+ if not stack or len(stack) == 0:
366
+ logger.warning("C namespace pop on empty stack. Defaulting to global scope.",
367
+ location=self.get_location())
368
+ stack = []
369
+ else:
370
+ stack.pop()
371
+ if len(stack) > 0:
372
+ symbol = stack[-1]
373
+ else:
374
+ symbol = self.env.domaindata['c']['root_symbol']
375
+ self.env.temp_data['c:parent_symbol'] = symbol
376
+ self.env.temp_data['c:namespace_stack'] = stack
377
+ self.env.ref_context['c:parent_key'] = symbol.get_lookup_key()
378
+ return []
379
+
380
+
381
+ class AliasNode(nodes.Element):
382
+ def __init__(
383
+ self,
384
+ sig: str,
385
+ aliasOptions: dict,
386
+ document: Any,
387
+ env: BuildEnvironment | None = None,
388
+ parentKey: LookupKey | None = None,
389
+ ) -> None:
390
+ super().__init__()
391
+ self.sig = sig
392
+ self.aliasOptions = aliasOptions
393
+ self.document = document
394
+ if env is not None:
395
+ if 'c:parent_symbol' not in env.temp_data:
396
+ root = env.domaindata['c']['root_symbol']
397
+ env.temp_data['c:parent_symbol'] = root
398
+ env.ref_context['c:parent_key'] = root.get_lookup_key()
399
+ self.parentKey = env.ref_context['c:parent_key']
400
+ else:
401
+ assert parentKey is not None
402
+ self.parentKey = parentKey
403
+
404
+ def copy(self) -> AliasNode:
405
+ return self.__class__(self.sig, self.aliasOptions, self.document,
406
+ env=None, parentKey=self.parentKey)
407
+
408
+
409
+ class AliasTransform(SphinxTransform):
410
+ default_priority = ReferencesResolver.default_priority - 1
411
+
412
+ def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool,
413
+ aliasOptions: dict, renderOptions: dict,
414
+ document: Any) -> list[Node]:
415
+ if maxdepth == 0:
416
+ recurse = True
417
+ elif maxdepth == 1:
418
+ recurse = False
419
+ else:
420
+ maxdepth -= 1
421
+ recurse = True
422
+
423
+ nodes: list[Node] = []
424
+ if not skipThis:
425
+ signode = addnodes.desc_signature('', '')
426
+ nodes.append(signode)
427
+ s.declaration.describe_signature(signode, 'markName', self.env, renderOptions)
428
+
429
+ if recurse:
430
+ if skipThis:
431
+ childContainer: list[Node] | addnodes.desc = nodes
432
+ else:
433
+ content = addnodes.desc_content()
434
+ desc = addnodes.desc()
435
+ content.append(desc)
436
+ desc.document = document
437
+ desc['domain'] = 'c'
438
+ # 'desctype' is a backwards compatible attribute
439
+ desc['objtype'] = desc['desctype'] = 'alias'
440
+ desc['no-index'] = True
441
+ childContainer = desc
442
+
443
+ for sChild in s.children:
444
+ if sChild.declaration is None:
445
+ continue
446
+ childNodes = self._render_symbol(
447
+ sChild, maxdepth=maxdepth, skipThis=False,
448
+ aliasOptions=aliasOptions, renderOptions=renderOptions,
449
+ document=document)
450
+ childContainer.extend(childNodes)
451
+
452
+ if not skipThis and len(desc.children) != 0:
453
+ nodes.append(content)
454
+ return nodes
455
+
456
+ def apply(self, **kwargs: Any) -> None:
457
+ for node in self.document.findall(AliasNode):
458
+ sig = node.sig
459
+ parentKey = node.parentKey
460
+ try:
461
+ parser = DefinitionParser(sig, location=node,
462
+ config=self.env.config)
463
+ name = parser.parse_xref_object()
464
+ except DefinitionError as e:
465
+ logger.warning(e, location=node)
466
+ name = None
467
+
468
+ if name is None:
469
+ # could not be parsed, so stop here
470
+ signode = addnodes.desc_signature(sig, '')
471
+ signode.clear()
472
+ signode += addnodes.desc_name(sig, sig)
473
+ node.replace_self(signode)
474
+ continue
475
+
476
+ rootSymbol: Symbol = self.env.domains['c'].data['root_symbol']
477
+ parentSymbol: Symbol | None = rootSymbol.direct_lookup(parentKey)
478
+ if not parentSymbol:
479
+ logger.debug("Target: %s", sig)
480
+ logger.debug("ParentKey: %s", parentKey)
481
+ logger.debug(rootSymbol.dump(1))
482
+ assert parentSymbol # should be there
483
+
484
+ s = parentSymbol.find_declaration(
485
+ name, 'any',
486
+ matchSelf=True, recurseInAnon=True)
487
+ if s is None:
488
+ signode = addnodes.desc_signature(sig, '')
489
+ node.append(signode)
490
+ signode.clear()
491
+ signode += addnodes.desc_name(sig, sig)
492
+
493
+ logger.warning("Could not find C declaration for alias '%s'." % name,
494
+ location=node)
495
+ node.replace_self(signode)
496
+ continue
497
+ # Declarations like .. var:: int Missing::var
498
+ # may introduce symbols without declarations.
499
+ # But if we skip the root then it is ok to start recursion from it.
500
+ if not node.aliasOptions['noroot'] and s.declaration is None:
501
+ signode = addnodes.desc_signature(sig, '')
502
+ node.append(signode)
503
+ signode.clear()
504
+ signode += addnodes.desc_name(sig, sig)
505
+
506
+ logger.warning(
507
+ "Can not render C declaration for alias '%s'. No such declaration." % name,
508
+ location=node)
509
+ node.replace_self(signode)
510
+ continue
511
+
512
+ nodes = self._render_symbol(s, maxdepth=node.aliasOptions['maxdepth'],
513
+ skipThis=node.aliasOptions['noroot'],
514
+ aliasOptions=node.aliasOptions,
515
+ renderOptions={}, document=node.document)
516
+ node.replace_self(nodes)
517
+
518
+
519
+ class CAliasObject(ObjectDescription):
520
+ option_spec: ClassVar[OptionSpec] = {
521
+ 'maxdepth': directives.nonnegative_int,
522
+ 'noroot': directives.flag,
523
+ }
524
+
525
+ def run(self) -> list[Node]:
526
+ """
527
+ On purpose this doesn't call the ObjectDescription version, but is based on it.
528
+ Each alias signature may expand into multiple real signatures if 'noroot'.
529
+ The code is therefore based on the ObjectDescription version.
530
+ """
531
+ if ':' in self.name:
532
+ self.domain, self.objtype = self.name.split(':', 1)
533
+ else:
534
+ self.domain, self.objtype = '', self.name
535
+
536
+ node = addnodes.desc()
537
+ node.document = self.state.document
538
+ node['domain'] = self.domain
539
+ # 'desctype' is a backwards compatible attribute
540
+ node['objtype'] = node['desctype'] = self.objtype
541
+ node['no-index'] = True
542
+
543
+ self.names: list[str] = []
544
+ aliasOptions = {
545
+ 'maxdepth': self.options.get('maxdepth', 1),
546
+ 'noroot': 'noroot' in self.options,
547
+ }
548
+ if aliasOptions['noroot'] and aliasOptions['maxdepth'] == 1:
549
+ logger.warning("Error in C alias declaration."
550
+ " Requested 'noroot' but 'maxdepth' 1."
551
+ " When skipping the root declaration,"
552
+ " need 'maxdepth' 0 for infinite or at least 2.",
553
+ location=self.get_location())
554
+ for sig in self.get_signatures():
555
+ node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env))
556
+ return [node]
557
+
558
+
559
+ class CXRefRole(XRefRole):
560
+ def process_link(self, env: BuildEnvironment, refnode: Element,
561
+ has_explicit_title: bool, title: str, target: str) -> tuple[str, str]:
562
+ refnode.attributes.update(env.ref_context)
563
+
564
+ if not has_explicit_title:
565
+ # major hax: replace anon names via simple string manipulation.
566
+ # Can this actually fail?
567
+ title = anon_identifier_re.sub("[anonymous]", str(title))
568
+
569
+ if not has_explicit_title:
570
+ target = target.lstrip('~') # only has a meaning for the title
571
+ # if the first character is a tilde, don't display the module/class
572
+ # parts of the contents
573
+ if title[0:1] == '~':
574
+ title = title[1:]
575
+ dot = title.rfind('.')
576
+ if dot != -1:
577
+ title = title[dot + 1:]
578
+ return title, target
579
+
580
+
581
+ class CExprRole(SphinxRole):
582
+ def __init__(self, asCode: bool) -> None:
583
+ super().__init__()
584
+ if asCode:
585
+ # render the expression as inline code
586
+ self.class_type = 'c-expr'
587
+ else:
588
+ # render the expression as inline text
589
+ self.class_type = 'c-texpr'
590
+
591
+ def run(self) -> tuple[list[Node], list[system_message]]:
592
+ text = self.text.replace('\n', ' ')
593
+ parser = DefinitionParser(text, location=self.get_location(),
594
+ config=self.env.config)
595
+ # attempt to mimic XRefRole classes, except that...
596
+ try:
597
+ ast = parser.parse_expression()
598
+ except DefinitionError as ex:
599
+ logger.warning('Unparseable C expression: %r\n%s', text, ex,
600
+ location=self.get_location())
601
+ # see below
602
+ return [addnodes.desc_inline('c', text, text, classes=[self.class_type])], []
603
+ parentSymbol = self.env.temp_data.get('c:parent_symbol', None)
604
+ if parentSymbol is None:
605
+ parentSymbol = self.env.domaindata['c']['root_symbol']
606
+ # ...most if not all of these classes should really apply to the individual references,
607
+ # not the container node
608
+ signode = addnodes.desc_inline('c', classes=[self.class_type])
609
+ ast.describe_signature(signode, 'markType', self.env, parentSymbol)
610
+ return [signode], []
611
+
612
+
613
+ class CDomain(Domain):
614
+ """C language domain."""
615
+
616
+ name = 'c'
617
+ label = 'C'
618
+ object_types = {
619
+ # 'identifier' is the one used for xrefs generated in signatures, not in roles
620
+ 'member': ObjType(_('member'), 'var', 'member', 'data', 'identifier'),
621
+ 'var': ObjType(_('variable'), 'var', 'member', 'data', 'identifier'),
622
+ 'function': ObjType(_('function'), 'func', 'identifier', 'type'),
623
+ 'macro': ObjType(_('macro'), 'macro', 'identifier'),
624
+ 'struct': ObjType(_('struct'), 'struct', 'identifier', 'type'),
625
+ 'union': ObjType(_('union'), 'union', 'identifier', 'type'),
626
+ 'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
627
+ 'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
628
+ 'type': ObjType(_('type'), 'identifier', 'type'),
629
+ # generated object types
630
+ 'functionParam': ObjType(_('function parameter'), 'identifier', 'var', 'member', 'data'), # NoQA: E501
631
+ }
632
+
633
+ directives = {
634
+ 'member': CMemberObject,
635
+ 'var': CMemberObject,
636
+ 'function': CFunctionObject,
637
+ 'macro': CMacroObject,
638
+ 'struct': CStructObject,
639
+ 'union': CUnionObject,
640
+ 'enum': CEnumObject,
641
+ 'enumerator': CEnumeratorObject,
642
+ 'type': CTypeObject,
643
+ # scope control
644
+ 'namespace': CNamespaceObject,
645
+ 'namespace-push': CNamespacePushObject,
646
+ 'namespace-pop': CNamespacePopObject,
647
+ # other
648
+ 'alias': CAliasObject,
649
+ }
650
+ roles = {
651
+ 'member': CXRefRole(),
652
+ 'data': CXRefRole(),
653
+ 'var': CXRefRole(),
654
+ 'func': CXRefRole(fix_parens=True),
655
+ 'macro': CXRefRole(),
656
+ 'struct': CXRefRole(),
657
+ 'union': CXRefRole(),
658
+ 'enum': CXRefRole(),
659
+ 'enumerator': CXRefRole(),
660
+ 'type': CXRefRole(),
661
+ 'expr': CExprRole(asCode=True),
662
+ 'texpr': CExprRole(asCode=False),
663
+ }
664
+ initial_data: dict[str, Symbol | dict[str, tuple[str, str, str]]] = {
665
+ 'root_symbol': Symbol(None, None, None, None, None),
666
+ 'objects': {}, # fullname -> docname, node_id, objtype
667
+ }
668
+
669
+ def clear_doc(self, docname: str) -> None:
670
+ if Symbol.debug_show_tree:
671
+ logger.debug("clear_doc: %s", docname)
672
+ logger.debug("\tbefore:")
673
+ logger.debug(self.data['root_symbol'].dump(1))
674
+ logger.debug("\tbefore end")
675
+
676
+ rootSymbol = self.data['root_symbol']
677
+ rootSymbol.clear_doc(docname)
678
+
679
+ if Symbol.debug_show_tree:
680
+ logger.debug("\tafter:")
681
+ logger.debug(self.data['root_symbol'].dump(1))
682
+ logger.debug("\tafter end")
683
+ logger.debug("clear_doc end: %s", docname)
684
+
685
+ def process_doc(self, env: BuildEnvironment, docname: str,
686
+ document: nodes.document) -> None:
687
+ if Symbol.debug_show_tree:
688
+ logger.debug("process_doc: %s", docname)
689
+ logger.debug(self.data['root_symbol'].dump(0))
690
+ logger.debug("process_doc end: %s", docname)
691
+
692
+ def process_field_xref(self, pnode: pending_xref) -> None:
693
+ pnode.attributes.update(self.env.ref_context)
694
+
695
+ def merge_domaindata(self, docnames: list[str], otherdata: dict[str, Any]) -> None:
696
+ if Symbol.debug_show_tree:
697
+ logger.debug("merge_domaindata:")
698
+ logger.debug("\tself:")
699
+ logger.debug(self.data['root_symbol'].dump(1))
700
+ logger.debug("\tself end")
701
+ logger.debug("\tother:")
702
+ logger.debug(otherdata['root_symbol'].dump(1))
703
+ logger.debug("\tother end")
704
+ logger.debug("merge_domaindata end")
705
+
706
+ self.data['root_symbol'].merge_with(otherdata['root_symbol'],
707
+ docnames, self.env)
708
+ ourObjects = self.data['objects']
709
+ for fullname, (fn, id_, objtype) in otherdata['objects'].items():
710
+ if fn in docnames:
711
+ if fullname not in ourObjects:
712
+ ourObjects[fullname] = (fn, id_, objtype)
713
+ # no need to warn on duplicates, the symbol merge already does that
714
+
715
+ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
716
+ typ: str, target: str, node: pending_xref,
717
+ contnode: Element) -> tuple[Element | None, str | None]:
718
+ parser = DefinitionParser(target, location=node, config=env.config)
719
+ try:
720
+ name = parser.parse_xref_object()
721
+ except DefinitionError as e:
722
+ logger.warning('Unparseable C cross-reference: %r\n%s', target, e,
723
+ location=node)
724
+ return None, None
725
+ parentKey: LookupKey = node.get("c:parent_key", None)
726
+ rootSymbol = self.data['root_symbol']
727
+ if parentKey:
728
+ parentSymbol: Symbol = rootSymbol.direct_lookup(parentKey)
729
+ if not parentSymbol:
730
+ logger.debug("Target: %s", target)
731
+ logger.debug("ParentKey: %s", parentKey)
732
+ logger.debug(rootSymbol.dump(1))
733
+ assert parentSymbol # should be there
734
+ else:
735
+ parentSymbol = rootSymbol
736
+ s = parentSymbol.find_declaration(name, typ,
737
+ matchSelf=True, recurseInAnon=True)
738
+ if s is None or s.declaration is None:
739
+ return None, None
740
+
741
+ # TODO: check role type vs. object type
742
+
743
+ declaration = s.declaration
744
+ displayName = name.get_display_string()
745
+ docname = s.docname
746
+ assert docname
747
+
748
+ return make_refnode(builder, fromdocname, docname,
749
+ declaration.get_newest_id(), contnode, displayName,
750
+ ), declaration.objectType
751
+
752
+ def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
753
+ typ: str, target: str, node: pending_xref,
754
+ contnode: Element) -> Element | None:
755
+ return self._resolve_xref_inner(env, fromdocname, builder, typ,
756
+ target, node, contnode)[0]
757
+
758
+ def resolve_any_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
759
+ target: str, node: pending_xref, contnode: Element,
760
+ ) -> list[tuple[str, Element]]:
761
+ with logging.suppress_logging():
762
+ retnode, objtype = self._resolve_xref_inner(env, fromdocname, builder,
763
+ 'any', target, node, contnode)
764
+ if retnode:
765
+ return [('c:' + self.role_for_objtype(objtype), retnode)]
766
+ return []
767
+
768
+ def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
769
+ rootSymbol = self.data['root_symbol']
770
+ for symbol in rootSymbol.get_all_symbols():
771
+ if symbol.declaration is None:
772
+ continue
773
+ assert symbol.docname
774
+ fullNestedName = symbol.get_full_nested_name()
775
+ name = str(fullNestedName).lstrip('.')
776
+ dispname = fullNestedName.get_display_string().lstrip('.')
777
+ objectType = symbol.declaration.objectType
778
+ docname = symbol.docname
779
+ newestId = symbol.declaration.get_newest_id()
780
+ yield (name, dispname, objectType, docname, newestId, 1)
781
+
782
+
783
+ def setup(app: Sphinx) -> ExtensionMetadata:
784
+ app.add_domain(CDomain)
785
+ app.add_config_value("c_id_attributes", [], 'env')
786
+ app.add_config_value("c_paren_attributes", [], 'env')
787
+ app.add_config_value("c_extra_keywords", _macroKeywords, 'env')
788
+ app.add_config_value("c_maximum_signature_line_length", None, 'env', types={int, None})
789
+ app.add_post_transform(AliasTransform)
790
+
791
+ return {
792
+ 'version': 'builtin',
793
+ 'env_version': 3,
794
+ 'parallel_read_safe': True,
795
+ 'parallel_write_safe': True,
796
+ }