Sphinx 8.1.3__py3-none-any.whl → 8.2.0rc1__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 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +48 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +114 -57
- sphinx/domains/python/_object.py +151 -67
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +21 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +66 -0
- sphinx/ext/autodoc/__init__.py +829 -480
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +271 -143
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +61 -50
- sphinx/writers/latex.py +80 -65
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +44 -45
- sphinx/writers/text.py +48 -30
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/METADATA +23 -15
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/RECORD +190 -186
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/entry_points.txt +0 -0
sphinx/domains/cpp/__init__.py
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
|
-
from
|
|
6
|
+
from types import NoneType
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
8
9
|
from docutils import nodes
|
|
9
10
|
from docutils.parsers.rst import directives
|
|
@@ -38,6 +39,7 @@ from sphinx.util.nodes import make_refnode
|
|
|
38
39
|
|
|
39
40
|
if TYPE_CHECKING:
|
|
40
41
|
from collections.abc import Iterator, Set
|
|
42
|
+
from typing import Any, ClassVar
|
|
41
43
|
|
|
42
44
|
from docutils.nodes import Element, Node, TextElement, system_message
|
|
43
45
|
|
|
@@ -49,7 +51,7 @@ if TYPE_CHECKING:
|
|
|
49
51
|
from sphinx.util.typing import ExtensionMetadata, OptionSpec
|
|
50
52
|
|
|
51
53
|
# re-export objects for backwards compatibility
|
|
52
|
-
#
|
|
54
|
+
# See: https://github.com/sphinx-doc/sphinx/issues/12295
|
|
53
55
|
from sphinx.domains.cpp._ast import ( # NoQA: F401
|
|
54
56
|
ASTAlignofExpr,
|
|
55
57
|
ASTArray,
|
|
@@ -144,7 +146,7 @@ logger = logging.getLogger(__name__)
|
|
|
144
146
|
|
|
145
147
|
|
|
146
148
|
def _make_phony_error_name() -> ASTNestedName:
|
|
147
|
-
nne = ASTNestedNameElement(ASTIdentifier(
|
|
149
|
+
nne = ASTNestedNameElement(ASTIdentifier('PhonyNameDueToError'), None)
|
|
148
150
|
return ASTNestedName([nne], [False], rooted=False)
|
|
149
151
|
|
|
150
152
|
|
|
@@ -152,9 +154,12 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
152
154
|
"""Description of a C++ language object."""
|
|
153
155
|
|
|
154
156
|
doc_field_types: list[Field] = [
|
|
155
|
-
GroupedField(
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
GroupedField(
|
|
158
|
+
'template parameter',
|
|
159
|
+
label=_('Template Parameters'),
|
|
160
|
+
names=('tparam', 'template parameter'),
|
|
161
|
+
can_collapse=True,
|
|
162
|
+
),
|
|
158
163
|
]
|
|
159
164
|
|
|
160
165
|
option_spec: ClassVar[OptionSpec] = {
|
|
@@ -177,40 +182,50 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
177
182
|
assert symbol.identOrOp is not None
|
|
178
183
|
assert symbol.templateParams is None
|
|
179
184
|
assert symbol.templateArgs is None
|
|
180
|
-
|
|
181
|
-
assert
|
|
182
|
-
if
|
|
185
|
+
parent_symbol = symbol.parent
|
|
186
|
+
assert parent_symbol
|
|
187
|
+
if parent_symbol.parent is None:
|
|
183
188
|
# TODO: we could warn, but it is somewhat equivalent to unscoped
|
|
184
189
|
# enums, without the enum
|
|
185
190
|
return # no parent
|
|
186
|
-
|
|
187
|
-
if
|
|
191
|
+
parent_decl = parent_symbol.declaration
|
|
192
|
+
if parent_decl is None:
|
|
188
193
|
# the parent is not explicitly declared
|
|
189
194
|
# TODO: we could warn, but it could be a style to just assume
|
|
190
195
|
# enumerator parents to be scoped
|
|
191
196
|
return
|
|
192
|
-
if
|
|
197
|
+
if parent_decl.objectType != 'enum':
|
|
193
198
|
# TODO: maybe issue a warning, enumerators in non-enums is weird,
|
|
194
199
|
# but it is somewhat equivalent to unscoped enums, without the enum
|
|
195
200
|
return
|
|
196
|
-
if
|
|
201
|
+
if parent_decl.directiveType != 'enum':
|
|
197
202
|
return
|
|
198
203
|
|
|
199
|
-
|
|
200
|
-
s =
|
|
201
|
-
|
|
204
|
+
target_symbol = parent_symbol.parent
|
|
205
|
+
s = target_symbol.find_identifier(
|
|
206
|
+
symbol.identOrOp,
|
|
207
|
+
matchSelf=False,
|
|
208
|
+
recurseInAnon=True,
|
|
209
|
+
searchInSiblings=False,
|
|
210
|
+
)
|
|
202
211
|
if s is not None:
|
|
203
212
|
# something is already declared with that name
|
|
204
213
|
return
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Symbol(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
+
decl_clone = symbol.declaration.clone()
|
|
215
|
+
decl_clone.enumeratorScopedSymbol = symbol
|
|
216
|
+
Symbol(
|
|
217
|
+
parent=target_symbol,
|
|
218
|
+
identOrOp=symbol.identOrOp,
|
|
219
|
+
templateParams=None,
|
|
220
|
+
templateArgs=None,
|
|
221
|
+
declaration=decl_clone,
|
|
222
|
+
docname=self.env.docname,
|
|
223
|
+
line=self.get_source_info()[1],
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def add_target_and_index(
|
|
227
|
+
self, ast: ASTDeclaration, sig: str, signode: TextElement
|
|
228
|
+
) -> None:
|
|
214
229
|
# general note: name must be lstrip(':')'ed, to remove "::"
|
|
215
230
|
ids = []
|
|
216
231
|
for i in range(1, _max_id + 1):
|
|
@@ -221,16 +236,20 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
221
236
|
assert i < _max_id
|
|
222
237
|
# let's keep the newest first
|
|
223
238
|
ids.reverse()
|
|
224
|
-
|
|
225
|
-
assert
|
|
226
|
-
if not re.compile(r'^[a-zA-Z0-9_]*$').match(
|
|
227
|
-
logger.warning(
|
|
228
|
-
|
|
229
|
-
|
|
239
|
+
newest_id = ids[0]
|
|
240
|
+
assert newest_id # shouldn't be None
|
|
241
|
+
if not re.compile(r'^[a-zA-Z0-9_]*$').match(newest_id):
|
|
242
|
+
logger.warning(
|
|
243
|
+
'Index id generation for C++ object "%s" failed, please '
|
|
244
|
+
'report as bug (id=%s).',
|
|
245
|
+
ast,
|
|
246
|
+
newest_id,
|
|
247
|
+
location=self.get_location(),
|
|
248
|
+
)
|
|
230
249
|
|
|
231
250
|
name = ast.symbol.get_full_nested_name().get_display_string().lstrip(':')
|
|
232
251
|
# Add index entry, but not if it's a declaration inside a concept
|
|
233
|
-
|
|
252
|
+
is_in_concept = False
|
|
234
253
|
s = ast.symbol.parent
|
|
235
254
|
while s is not None:
|
|
236
255
|
decl = s.declaration
|
|
@@ -238,25 +257,31 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
238
257
|
if decl is None:
|
|
239
258
|
continue
|
|
240
259
|
if decl.objectType == 'concept':
|
|
241
|
-
|
|
260
|
+
is_in_concept = True
|
|
242
261
|
break
|
|
243
|
-
if not
|
|
244
|
-
|
|
245
|
-
for prefix in self.
|
|
262
|
+
if not is_in_concept and 'no-index-entry' not in self.options:
|
|
263
|
+
stripped_name = name
|
|
264
|
+
for prefix in self.config.cpp_index_common_prefix:
|
|
246
265
|
if name.startswith(prefix):
|
|
247
|
-
|
|
266
|
+
stripped_name = stripped_name[len(prefix) :]
|
|
248
267
|
break
|
|
249
|
-
|
|
250
|
-
self.indexnode['entries'].append((
|
|
251
|
-
|
|
252
|
-
|
|
268
|
+
index_text = self.get_index_text(stripped_name)
|
|
269
|
+
self.indexnode['entries'].append((
|
|
270
|
+
'single',
|
|
271
|
+
index_text,
|
|
272
|
+
newest_id,
|
|
273
|
+
'',
|
|
274
|
+
None,
|
|
275
|
+
))
|
|
276
|
+
|
|
277
|
+
if newest_id not in self.state.document.ids:
|
|
253
278
|
# if the name is not unique, the first one will win
|
|
254
279
|
names = self.env.domaindata['cpp']['names']
|
|
255
280
|
if name not in names:
|
|
256
281
|
names[name] = ast.symbol.docname
|
|
257
282
|
# always add the newest id
|
|
258
|
-
assert
|
|
259
|
-
signode['ids'].append(
|
|
283
|
+
assert newest_id
|
|
284
|
+
signode['ids'].append(newest_id)
|
|
260
285
|
# only add compatibility ids when there are no conflicts
|
|
261
286
|
for id in ids[1:]:
|
|
262
287
|
if not id: # is None when the element didn't exist in that version
|
|
@@ -279,19 +304,20 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
279
304
|
def parse_definition(self, parser: DefinitionParser) -> ASTDeclaration:
|
|
280
305
|
return parser.parse_declaration(self.object_type, self.objtype)
|
|
281
306
|
|
|
282
|
-
def describe_signature(
|
|
283
|
-
|
|
307
|
+
def describe_signature(
|
|
308
|
+
self, signode: desc_signature, ast: ASTDeclaration, options: dict[str, Any]
|
|
309
|
+
) -> None:
|
|
284
310
|
ast.describe_signature(signode, 'lastIsName', self.env, options)
|
|
285
311
|
|
|
286
312
|
def run(self) -> list[Node]:
|
|
287
|
-
env = self.
|
|
288
|
-
if
|
|
313
|
+
env = self.env
|
|
314
|
+
if env.current_document.cpp_parent_symbol is None:
|
|
289
315
|
root = env.domaindata['cpp']['root_symbol']
|
|
290
|
-
env.
|
|
316
|
+
env.current_document.cpp_parent_symbol = root
|
|
291
317
|
env.ref_context['cpp:parent_key'] = root.get_lookup_key()
|
|
292
318
|
|
|
293
319
|
# The lookup keys assume that no nested scopes exists inside overloaded functions.
|
|
294
|
-
#
|
|
320
|
+
# See: https://github.com/sphinx-doc/sphinx/issues/5191
|
|
295
321
|
# Example:
|
|
296
322
|
# .. cpp:function:: void f(int)
|
|
297
323
|
# .. cpp:function:: void f(double)
|
|
@@ -301,35 +327,39 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
301
327
|
# :cpp:any:`boom`
|
|
302
328
|
#
|
|
303
329
|
# So we disallow any signatures inside functions.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if
|
|
307
|
-
msg = (
|
|
308
|
-
|
|
309
|
-
|
|
330
|
+
parent_symbol = env.current_document.cpp_parent_symbol
|
|
331
|
+
parent_decl = parent_symbol.declaration
|
|
332
|
+
if parent_decl is not None and parent_decl.objectType == 'function':
|
|
333
|
+
msg = (
|
|
334
|
+
'C++ declarations inside functions are not supported. '
|
|
335
|
+
f'Parent function: {parent_symbol.get_full_nested_name()}\n'
|
|
336
|
+
f'Directive name: {self.name}\nDirective arg: {self.arguments[0]}'
|
|
337
|
+
)
|
|
310
338
|
logger.warning(msg, location=self.get_location())
|
|
311
339
|
name = _make_phony_error_name()
|
|
312
|
-
symbol =
|
|
313
|
-
env.
|
|
340
|
+
symbol = parent_symbol.add_name(name)
|
|
341
|
+
env.current_document.cpp_last_symbol = symbol
|
|
314
342
|
return []
|
|
315
343
|
# When multiple declarations are made in the same directive
|
|
316
344
|
# they need to know about each other to provide symbol lookup for function parameters.
|
|
317
345
|
# We use last_symbol to store the latest added declaration in a directive.
|
|
318
|
-
env.
|
|
346
|
+
env.current_document.cpp_last_symbol = None
|
|
319
347
|
return super().run()
|
|
320
348
|
|
|
321
349
|
def handle_signature(self, sig: str, signode: desc_signature) -> ASTDeclaration:
|
|
322
|
-
|
|
350
|
+
parent_symbol: Symbol = self.env.current_document.cpp_parent_symbol
|
|
323
351
|
|
|
324
|
-
max_len = (
|
|
325
|
-
|
|
326
|
-
|
|
352
|
+
max_len = (
|
|
353
|
+
self.config.cpp_maximum_signature_line_length
|
|
354
|
+
or self.config.maximum_signature_line_length
|
|
355
|
+
or 0
|
|
356
|
+
)
|
|
327
357
|
signode['multi_line_parameter_list'] = (
|
|
328
358
|
'single-line-parameter-list' not in self.options
|
|
329
359
|
and (len(sig) > max_len > 0)
|
|
330
360
|
)
|
|
331
361
|
|
|
332
|
-
parser = DefinitionParser(sig, location=signode, config=self.
|
|
362
|
+
parser = DefinitionParser(sig, location=signode, config=self.config)
|
|
333
363
|
try:
|
|
334
364
|
ast = self.parse_definition(parser)
|
|
335
365
|
parser.assert_end()
|
|
@@ -338,30 +368,40 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
338
368
|
# It is easier to assume some phony name than handling the error in
|
|
339
369
|
# the possibly inner declarations.
|
|
340
370
|
name = _make_phony_error_name()
|
|
341
|
-
symbol =
|
|
342
|
-
self.env.
|
|
371
|
+
symbol = parent_symbol.add_name(name)
|
|
372
|
+
self.env.current_document.cpp_last_symbol = symbol
|
|
343
373
|
raise ValueError from e
|
|
344
374
|
|
|
345
375
|
try:
|
|
346
|
-
symbol =
|
|
347
|
-
ast, docname=self.env.docname, line=self.get_source_info()[1]
|
|
376
|
+
symbol = parent_symbol.add_declaration(
|
|
377
|
+
ast, docname=self.env.docname, line=self.get_source_info()[1]
|
|
378
|
+
)
|
|
348
379
|
# append the new declaration to the sibling list
|
|
349
380
|
assert symbol.siblingAbove is None
|
|
350
381
|
assert symbol.siblingBelow is None
|
|
351
|
-
symbol.siblingAbove = self.env.
|
|
382
|
+
symbol.siblingAbove = self.env.current_document.cpp_last_symbol
|
|
352
383
|
if symbol.siblingAbove is not None:
|
|
353
384
|
assert symbol.siblingAbove.siblingBelow is None
|
|
354
385
|
symbol.siblingAbove.siblingBelow = symbol
|
|
355
|
-
self.env.
|
|
386
|
+
self.env.current_document.cpp_last_symbol = symbol
|
|
356
387
|
except _DuplicateSymbolError as e:
|
|
357
388
|
# Assume we are actually in the old symbol,
|
|
358
389
|
# instead of the newly created duplicate.
|
|
359
|
-
self.env.
|
|
360
|
-
msg = __(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
logger.warning(
|
|
390
|
+
self.env.current_document.cpp_last_symbol = e.symbol
|
|
391
|
+
msg = __(
|
|
392
|
+
'Duplicate C++ declaration, also defined at %s:%s.\n'
|
|
393
|
+
"Declaration is '.. cpp:%s:: %s'."
|
|
394
|
+
)
|
|
395
|
+
logger.warning(
|
|
396
|
+
msg,
|
|
397
|
+
e.symbol.docname,
|
|
398
|
+
e.symbol.line,
|
|
399
|
+
self.display_object_type,
|
|
400
|
+
sig,
|
|
401
|
+
location=signode,
|
|
402
|
+
type='duplicate_declaration',
|
|
403
|
+
subtype='cpp',
|
|
404
|
+
)
|
|
365
405
|
|
|
366
406
|
if ast.objectType == 'enumerator':
|
|
367
407
|
self._add_enumerator_to_parent(ast)
|
|
@@ -374,31 +414,35 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
374
414
|
return ast
|
|
375
415
|
|
|
376
416
|
def before_content(self) -> None:
|
|
377
|
-
|
|
378
|
-
assert
|
|
379
|
-
self.oldParentSymbol = self.env.
|
|
417
|
+
last_symbol: Symbol = self.env.current_document.cpp_last_symbol
|
|
418
|
+
assert last_symbol
|
|
419
|
+
self.oldParentSymbol = self.env.current_document.cpp_parent_symbol
|
|
380
420
|
self.oldParentKey: LookupKey = self.env.ref_context['cpp:parent_key']
|
|
381
|
-
self.env.
|
|
382
|
-
self.env.ref_context['cpp:parent_key'] =
|
|
383
|
-
self.env.
|
|
384
|
-
*self.env.
|
|
385
|
-
|
|
421
|
+
self.env.current_document.cpp_parent_symbol = last_symbol
|
|
422
|
+
self.env.ref_context['cpp:parent_key'] = last_symbol.get_lookup_key()
|
|
423
|
+
self.env.current_document.cpp_domain_name = (
|
|
424
|
+
*self.env.current_document.cpp_domain_name,
|
|
425
|
+
last_symbol.identOrOp._stringify(str),
|
|
386
426
|
)
|
|
387
427
|
|
|
388
428
|
def after_content(self) -> None:
|
|
389
|
-
self.env.
|
|
429
|
+
self.env.current_document.cpp_parent_symbol = self.oldParentSymbol
|
|
390
430
|
self.env.ref_context['cpp:parent_key'] = self.oldParentKey
|
|
391
|
-
|
|
431
|
+
cpp_domain_name = self.env.current_document.cpp_domain_name
|
|
432
|
+
self.env.current_document.cpp_domain_name = cpp_domain_name[:-1]
|
|
392
433
|
|
|
393
434
|
def _object_hierarchy_parts(self, sig_node: desc_signature) -> tuple[str, ...]:
|
|
394
|
-
|
|
395
|
-
|
|
435
|
+
last_symbol: Symbol = self.env.current_document.cpp_last_symbol
|
|
436
|
+
return tuple(
|
|
437
|
+
s.identOrOp._stringify(str)
|
|
438
|
+
for s in last_symbol.get_full_nested_name().names
|
|
439
|
+
)
|
|
396
440
|
|
|
397
441
|
def _toc_entry_name(self, sig_node: desc_signature) -> str:
|
|
398
442
|
if not sig_node.get('_toc_parts'):
|
|
399
443
|
return ''
|
|
400
444
|
|
|
401
|
-
config = self.
|
|
445
|
+
config = self.config
|
|
402
446
|
objtype = sig_node.parent.get('objtype')
|
|
403
447
|
if config.add_function_parentheses and objtype in {'function', 'method'}:
|
|
404
448
|
parens = '()'
|
|
@@ -406,7 +450,10 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
|
|
406
450
|
parens = ''
|
|
407
451
|
*parents, name = sig_node['_toc_parts']
|
|
408
452
|
if config.toc_object_entries_show_parents == 'domain':
|
|
409
|
-
return '::'.join((
|
|
453
|
+
return '::'.join((
|
|
454
|
+
*self.env.current_document.cpp_domain_name,
|
|
455
|
+
name + parens,
|
|
456
|
+
))
|
|
410
457
|
if config.toc_object_entries_show_parents == 'hide':
|
|
411
458
|
return name + parens
|
|
412
459
|
if config.toc_object_entries_show_parents == 'all':
|
|
@@ -432,25 +479,30 @@ class CPPFunctionObject(CPPObject):
|
|
|
432
479
|
doc_field_types = [
|
|
433
480
|
*CPPObject.doc_field_types,
|
|
434
481
|
GroupedField(
|
|
435
|
-
|
|
436
|
-
label=_(
|
|
437
|
-
names=(
|
|
482
|
+
'parameter',
|
|
483
|
+
label=_('Parameters'),
|
|
484
|
+
names=('param', 'parameter', 'arg', 'argument'),
|
|
438
485
|
can_collapse=True,
|
|
439
486
|
),
|
|
440
487
|
GroupedField(
|
|
441
|
-
|
|
442
|
-
label=_(
|
|
443
|
-
rolename=
|
|
444
|
-
names=(
|
|
488
|
+
'exceptions',
|
|
489
|
+
label=_('Throws'),
|
|
490
|
+
rolename='expr',
|
|
491
|
+
names=('throws', 'throw', 'exception'),
|
|
445
492
|
can_collapse=True,
|
|
446
493
|
),
|
|
447
494
|
GroupedField(
|
|
448
|
-
|
|
449
|
-
label=_(
|
|
450
|
-
names=(
|
|
495
|
+
'retval',
|
|
496
|
+
label=_('Return values'),
|
|
497
|
+
names=('retvals', 'retval'),
|
|
451
498
|
can_collapse=True,
|
|
452
499
|
),
|
|
453
|
-
Field(
|
|
500
|
+
Field(
|
|
501
|
+
'returnvalue',
|
|
502
|
+
label=_('Returns'),
|
|
503
|
+
has_arg=False,
|
|
504
|
+
names=('returns', 'return'),
|
|
505
|
+
),
|
|
454
506
|
]
|
|
455
507
|
|
|
456
508
|
|
|
@@ -460,7 +512,7 @@ class CPPClassObject(CPPObject):
|
|
|
460
512
|
@property
|
|
461
513
|
def display_object_type(self) -> str:
|
|
462
514
|
# the distinction between class and struct is only cosmetic
|
|
463
|
-
assert self.objtype in
|
|
515
|
+
assert self.objtype in {'class', 'struct'}
|
|
464
516
|
return self.objtype
|
|
465
517
|
|
|
466
518
|
|
|
@@ -477,8 +529,7 @@ class CPPEnumeratorObject(CPPObject):
|
|
|
477
529
|
|
|
478
530
|
|
|
479
531
|
class CPPNamespaceObject(SphinxDirective):
|
|
480
|
-
"""
|
|
481
|
-
This directive is just to tell Sphinx that we're documenting stuff in
|
|
532
|
+
"""This directive is just to tell Sphinx that we're documenting stuff in
|
|
482
533
|
namespace foo.
|
|
483
534
|
"""
|
|
484
535
|
|
|
@@ -489,14 +540,14 @@ class CPPNamespaceObject(SphinxDirective):
|
|
|
489
540
|
option_spec: ClassVar[OptionSpec] = {}
|
|
490
541
|
|
|
491
542
|
def run(self) -> list[Node]:
|
|
492
|
-
|
|
493
|
-
if self.arguments[0].strip() in
|
|
494
|
-
symbol =
|
|
543
|
+
root_symbol = self.env.domaindata['cpp']['root_symbol']
|
|
544
|
+
if self.arguments[0].strip() in {'NULL', '0', 'nullptr'}:
|
|
545
|
+
symbol = root_symbol
|
|
495
546
|
stack: list[Symbol] = []
|
|
496
547
|
else:
|
|
497
|
-
parser = DefinitionParser(
|
|
498
|
-
|
|
499
|
-
|
|
548
|
+
parser = DefinitionParser(
|
|
549
|
+
self.arguments[0], location=self.get_location(), config=self.config
|
|
550
|
+
)
|
|
500
551
|
try:
|
|
501
552
|
ast = parser.parse_namespace_object()
|
|
502
553
|
parser.assert_end()
|
|
@@ -504,10 +555,10 @@ class CPPNamespaceObject(SphinxDirective):
|
|
|
504
555
|
logger.warning(e, location=self.get_location())
|
|
505
556
|
name = _make_phony_error_name()
|
|
506
557
|
ast = ASTNamespace(name, None)
|
|
507
|
-
symbol =
|
|
558
|
+
symbol = root_symbol.add_name(ast.nestedName, ast.templatePrefix)
|
|
508
559
|
stack = [symbol]
|
|
509
|
-
self.env.
|
|
510
|
-
self.env.
|
|
560
|
+
self.env.current_document.cpp_parent_symbol = symbol
|
|
561
|
+
self.env.current_document.cpp_namespace_stack = stack
|
|
511
562
|
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
512
563
|
return []
|
|
513
564
|
|
|
@@ -520,11 +571,11 @@ class CPPNamespacePushObject(SphinxDirective):
|
|
|
520
571
|
option_spec: ClassVar[OptionSpec] = {}
|
|
521
572
|
|
|
522
573
|
def run(self) -> list[Node]:
|
|
523
|
-
if self.arguments[0].strip() in
|
|
574
|
+
if self.arguments[0].strip() in {'NULL', '0', 'nullptr'}:
|
|
524
575
|
return []
|
|
525
|
-
parser = DefinitionParser(
|
|
526
|
-
|
|
527
|
-
|
|
576
|
+
parser = DefinitionParser(
|
|
577
|
+
self.arguments[0], location=self.get_location(), config=self.config
|
|
578
|
+
)
|
|
528
579
|
try:
|
|
529
580
|
ast = parser.parse_namespace_object()
|
|
530
581
|
parser.assert_end()
|
|
@@ -532,14 +583,12 @@ class CPPNamespacePushObject(SphinxDirective):
|
|
|
532
583
|
logger.warning(e, location=self.get_location())
|
|
533
584
|
name = _make_phony_error_name()
|
|
534
585
|
ast = ASTNamespace(name, None)
|
|
535
|
-
|
|
536
|
-
if not
|
|
537
|
-
|
|
538
|
-
symbol =
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
self.env.temp_data['cpp:parent_symbol'] = symbol
|
|
542
|
-
self.env.temp_data['cpp:namespace_stack'] = stack
|
|
586
|
+
old_parent = self.env.current_document.cpp_parent_symbol
|
|
587
|
+
if not old_parent:
|
|
588
|
+
old_parent = self.env.domaindata['cpp']['root_symbol']
|
|
589
|
+
symbol = old_parent.add_name(ast.nestedName, ast.templatePrefix)
|
|
590
|
+
self.env.current_document.cpp_namespace_stack.append(symbol)
|
|
591
|
+
self.env.current_document.cpp_parent_symbol = symbol
|
|
543
592
|
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
544
593
|
return []
|
|
545
594
|
|
|
@@ -552,34 +601,39 @@ class CPPNamespacePopObject(SphinxDirective):
|
|
|
552
601
|
option_spec: ClassVar[OptionSpec] = {}
|
|
553
602
|
|
|
554
603
|
def run(self) -> list[Node]:
|
|
555
|
-
stack = self.env.
|
|
556
|
-
if
|
|
557
|
-
logger.warning(
|
|
558
|
-
|
|
559
|
-
|
|
604
|
+
stack = self.env.current_document.cpp_namespace_stack
|
|
605
|
+
if len(stack) == 0:
|
|
606
|
+
logger.warning(
|
|
607
|
+
'C++ namespace pop on empty stack. Defaulting to global scope.',
|
|
608
|
+
location=self.get_location(),
|
|
609
|
+
)
|
|
560
610
|
else:
|
|
561
611
|
stack.pop()
|
|
562
612
|
if len(stack) > 0:
|
|
563
613
|
symbol = stack[-1]
|
|
564
614
|
else:
|
|
565
615
|
symbol = self.env.domaindata['cpp']['root_symbol']
|
|
566
|
-
self.env.
|
|
567
|
-
self.env.temp_data['cpp:namespace_stack'] = stack
|
|
616
|
+
self.env.current_document.cpp_parent_symbol = symbol
|
|
568
617
|
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
|
|
569
618
|
return []
|
|
570
619
|
|
|
571
620
|
|
|
572
621
|
class AliasNode(nodes.Element):
|
|
573
|
-
def __init__(
|
|
574
|
-
|
|
575
|
-
|
|
622
|
+
def __init__(
|
|
623
|
+
self,
|
|
624
|
+
sig: str,
|
|
625
|
+
aliasOptions: dict[str, bool],
|
|
626
|
+
env: BuildEnvironment | None = None,
|
|
627
|
+
parentKey: LookupKey | None = None,
|
|
628
|
+
) -> None:
|
|
576
629
|
super().__init__()
|
|
577
630
|
self.sig = sig
|
|
578
631
|
self.aliasOptions = aliasOptions
|
|
632
|
+
self.parentKey: LookupKey
|
|
579
633
|
if env is not None:
|
|
580
|
-
if
|
|
634
|
+
if env.current_document.cpp_parent_symbol is None:
|
|
581
635
|
root = env.domaindata['cpp']['root_symbol']
|
|
582
|
-
env.
|
|
636
|
+
env.current_document.cpp_parent_symbol = root
|
|
583
637
|
env.ref_context['cpp:parent_key'] = root.get_lookup_key()
|
|
584
638
|
self.parentKey = env.ref_context['cpp:parent_key']
|
|
585
639
|
else:
|
|
@@ -587,16 +641,23 @@ class AliasNode(nodes.Element):
|
|
|
587
641
|
self.parentKey = parentKey
|
|
588
642
|
|
|
589
643
|
def copy(self) -> AliasNode:
|
|
590
|
-
return self.__class__(
|
|
591
|
-
|
|
644
|
+
return self.__class__(
|
|
645
|
+
self.sig, self.aliasOptions, env=None, parentKey=self.parentKey
|
|
646
|
+
)
|
|
592
647
|
|
|
593
648
|
|
|
594
649
|
class AliasTransform(SphinxTransform):
|
|
595
650
|
default_priority = ReferencesResolver.default_priority - 1
|
|
596
651
|
|
|
597
|
-
def _render_symbol(
|
|
598
|
-
|
|
599
|
-
|
|
652
|
+
def _render_symbol(
|
|
653
|
+
self,
|
|
654
|
+
s: Symbol,
|
|
655
|
+
maxdepth: int,
|
|
656
|
+
skip_this: bool,
|
|
657
|
+
alias_options: dict[str, bool],
|
|
658
|
+
render_options: dict[str, bool],
|
|
659
|
+
document: Any,
|
|
660
|
+
) -> list[Node]:
|
|
600
661
|
if maxdepth == 0:
|
|
601
662
|
recurse = True
|
|
602
663
|
elif maxdepth == 1:
|
|
@@ -606,14 +667,16 @@ class AliasTransform(SphinxTransform):
|
|
|
606
667
|
recurse = True
|
|
607
668
|
|
|
608
669
|
nodes: list[Node] = []
|
|
609
|
-
if not
|
|
670
|
+
if not skip_this:
|
|
610
671
|
signode = addnodes.desc_signature('', '')
|
|
611
672
|
nodes.append(signode)
|
|
612
|
-
s.declaration.describe_signature(
|
|
673
|
+
s.declaration.describe_signature(
|
|
674
|
+
signode, 'markName', self.env, render_options
|
|
675
|
+
)
|
|
613
676
|
|
|
614
677
|
if recurse:
|
|
615
|
-
if
|
|
616
|
-
|
|
678
|
+
if skip_this:
|
|
679
|
+
child_container: list[Node] | addnodes.desc = nodes
|
|
617
680
|
else:
|
|
618
681
|
content = addnodes.desc_content()
|
|
619
682
|
desc = addnodes.desc()
|
|
@@ -623,35 +686,38 @@ class AliasTransform(SphinxTransform):
|
|
|
623
686
|
# 'desctype' is a backwards compatible attribute
|
|
624
687
|
desc['objtype'] = desc['desctype'] = 'alias'
|
|
625
688
|
desc['no-index'] = True
|
|
626
|
-
|
|
689
|
+
child_container = desc
|
|
627
690
|
|
|
628
|
-
for
|
|
629
|
-
if
|
|
691
|
+
for s_child in s._children:
|
|
692
|
+
if s_child.declaration is None:
|
|
630
693
|
continue
|
|
631
|
-
if
|
|
694
|
+
if s_child.declaration.objectType in {'templateParam', 'functionParam'}:
|
|
632
695
|
continue
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
696
|
+
child_nodes = self._render_symbol(
|
|
697
|
+
s_child,
|
|
698
|
+
maxdepth=maxdepth,
|
|
699
|
+
skip_this=False,
|
|
700
|
+
alias_options=alias_options,
|
|
701
|
+
render_options=render_options,
|
|
702
|
+
document=document,
|
|
703
|
+
)
|
|
704
|
+
child_container.extend(child_nodes)
|
|
705
|
+
|
|
706
|
+
if not skip_this and len(desc.children) != 0:
|
|
640
707
|
nodes.append(content)
|
|
641
708
|
return nodes
|
|
642
709
|
|
|
643
710
|
def apply(self, **kwargs: Any) -> None:
|
|
644
711
|
for node in self.document.findall(AliasNode):
|
|
645
712
|
sig = node.sig
|
|
646
|
-
|
|
713
|
+
parent_key = node.parentKey
|
|
647
714
|
try:
|
|
648
|
-
parser = DefinitionParser(sig, location=node,
|
|
649
|
-
|
|
650
|
-
ast, isShorthand = parser.parse_xref_object()
|
|
715
|
+
parser = DefinitionParser(sig, location=node, config=self.config)
|
|
716
|
+
ast, is_shorthand = parser.parse_xref_object()
|
|
651
717
|
parser.assert_end()
|
|
652
718
|
except DefinitionError as e:
|
|
653
719
|
logger.warning(e, location=node)
|
|
654
|
-
ast,
|
|
720
|
+
ast, is_shorthand = None, None
|
|
655
721
|
|
|
656
722
|
if ast is None:
|
|
657
723
|
# could not be parsed, so stop here
|
|
@@ -661,39 +727,45 @@ class AliasTransform(SphinxTransform):
|
|
|
661
727
|
node.replace_self(signode)
|
|
662
728
|
continue
|
|
663
729
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if not
|
|
667
|
-
logger.debug(
|
|
668
|
-
logger.debug(
|
|
669
|
-
logger.debug(
|
|
670
|
-
assert
|
|
730
|
+
root_symbol: Symbol = self.env.domains.cpp_domain.data['root_symbol']
|
|
731
|
+
parent_symbol: Symbol = root_symbol.direct_lookup(parent_key)
|
|
732
|
+
if not parent_symbol:
|
|
733
|
+
logger.debug('Target: %s', sig)
|
|
734
|
+
logger.debug('ParentKey: %s', parent_key)
|
|
735
|
+
logger.debug(root_symbol.dump(1))
|
|
736
|
+
assert parent_symbol # should be there
|
|
671
737
|
|
|
672
738
|
symbols: list[Symbol] = []
|
|
673
|
-
if
|
|
739
|
+
if is_shorthand:
|
|
674
740
|
assert isinstance(ast, ASTNamespace)
|
|
675
741
|
ns = ast
|
|
676
742
|
name = ns.nestedName
|
|
677
743
|
if ns.templatePrefix:
|
|
678
|
-
|
|
744
|
+
template_decls = ns.templatePrefix.templates
|
|
679
745
|
else:
|
|
680
|
-
|
|
681
|
-
symbols,
|
|
746
|
+
template_decls = []
|
|
747
|
+
symbols, fail_reason = parent_symbol.find_name(
|
|
682
748
|
nestedName=name,
|
|
683
|
-
templateDecls=
|
|
749
|
+
templateDecls=template_decls,
|
|
684
750
|
typ='any',
|
|
685
751
|
templateShorthand=True,
|
|
686
|
-
matchSelf=True,
|
|
687
|
-
|
|
752
|
+
matchSelf=True,
|
|
753
|
+
recurseInAnon=True,
|
|
754
|
+
searchInSiblings=False,
|
|
755
|
+
)
|
|
688
756
|
if symbols is None:
|
|
689
757
|
symbols = []
|
|
690
758
|
else:
|
|
691
759
|
assert isinstance(ast, ASTDeclaration)
|
|
692
760
|
decl = ast
|
|
693
761
|
name = decl.name
|
|
694
|
-
s =
|
|
695
|
-
|
|
696
|
-
|
|
762
|
+
s = parent_symbol.find_declaration(
|
|
763
|
+
decl,
|
|
764
|
+
'any',
|
|
765
|
+
templateShorthand=True,
|
|
766
|
+
matchSelf=True,
|
|
767
|
+
recurseInAnon=True,
|
|
768
|
+
)
|
|
697
769
|
if s is not None:
|
|
698
770
|
symbols.append(s)
|
|
699
771
|
|
|
@@ -705,35 +777,37 @@ class AliasTransform(SphinxTransform):
|
|
|
705
777
|
signode.clear()
|
|
706
778
|
signode += addnodes.desc_name(sig, sig)
|
|
707
779
|
|
|
708
|
-
logger.warning(
|
|
709
|
-
|
|
780
|
+
logger.warning(
|
|
781
|
+
"Can not find C++ declaration for alias '%s'.", ast, location=node
|
|
782
|
+
)
|
|
710
783
|
node.replace_self(signode)
|
|
711
784
|
else:
|
|
712
785
|
nodes = []
|
|
713
|
-
|
|
786
|
+
render_options = {
|
|
714
787
|
'tparam-line-spec': False,
|
|
715
788
|
}
|
|
716
789
|
for s in symbols:
|
|
717
790
|
assert s.declaration is not None
|
|
718
791
|
res = self._render_symbol(
|
|
719
|
-
s,
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
792
|
+
s,
|
|
793
|
+
maxdepth=node.aliasOptions['maxdepth'],
|
|
794
|
+
skip_this=node.aliasOptions['noroot'],
|
|
795
|
+
alias_options=node.aliasOptions,
|
|
796
|
+
render_options=render_options,
|
|
797
|
+
document=node.document,
|
|
798
|
+
)
|
|
724
799
|
nodes.extend(res)
|
|
725
800
|
node.replace_self(nodes)
|
|
726
801
|
|
|
727
802
|
|
|
728
|
-
class CPPAliasObject(ObjectDescription):
|
|
803
|
+
class CPPAliasObject(ObjectDescription[str]):
|
|
729
804
|
option_spec: ClassVar[OptionSpec] = {
|
|
730
805
|
'maxdepth': directives.nonnegative_int,
|
|
731
806
|
'noroot': directives.flag,
|
|
732
807
|
}
|
|
733
808
|
|
|
734
809
|
def run(self) -> list[Node]:
|
|
735
|
-
"""
|
|
736
|
-
On purpose this doesn't call the ObjectDescription version, but is based on it.
|
|
810
|
+
"""On purpose this doesn't call the ObjectDescription version, but is based on it.
|
|
737
811
|
Each alias signature may expand into multiple real signatures (an overload set).
|
|
738
812
|
The code is therefore based on the ObjectDescription version.
|
|
739
813
|
"""
|
|
@@ -749,37 +823,45 @@ class CPPAliasObject(ObjectDescription):
|
|
|
749
823
|
node['objtype'] = node['desctype'] = self.objtype
|
|
750
824
|
|
|
751
825
|
self.names: list[str] = []
|
|
752
|
-
|
|
826
|
+
alias_options = {
|
|
753
827
|
'maxdepth': self.options.get('maxdepth', 1),
|
|
754
828
|
'noroot': 'noroot' in self.options,
|
|
755
829
|
}
|
|
756
|
-
if
|
|
757
|
-
logger.warning(
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
830
|
+
if alias_options['noroot'] and alias_options['maxdepth'] == 1:
|
|
831
|
+
logger.warning(
|
|
832
|
+
'Error in C++ alias declaration.'
|
|
833
|
+
" Requested 'noroot' but 'maxdepth' 1."
|
|
834
|
+
' When skipping the root declaration,'
|
|
835
|
+
" need 'maxdepth' 0 for infinite or at least 2.",
|
|
836
|
+
location=self.get_location(),
|
|
837
|
+
)
|
|
762
838
|
signatures = self.get_signatures()
|
|
763
839
|
for sig in signatures:
|
|
764
|
-
node.append(AliasNode(sig,
|
|
840
|
+
node.append(AliasNode(sig, alias_options, env=self.env))
|
|
765
841
|
|
|
766
842
|
self.before_content()
|
|
767
843
|
content_node = addnodes.desc_content('', *self.parse_content_to_nodes())
|
|
768
844
|
node.append(content_node)
|
|
769
|
-
self.env.
|
|
845
|
+
self.env.current_document.obj_desc_name = ''
|
|
770
846
|
self.after_content()
|
|
771
847
|
return [node]
|
|
772
848
|
|
|
773
849
|
|
|
774
850
|
class CPPXRefRole(XRefRole):
|
|
775
|
-
def process_link(
|
|
776
|
-
|
|
851
|
+
def process_link(
|
|
852
|
+
self,
|
|
853
|
+
env: BuildEnvironment,
|
|
854
|
+
refnode: Element,
|
|
855
|
+
has_explicit_title: bool,
|
|
856
|
+
title: str,
|
|
857
|
+
target: str,
|
|
858
|
+
) -> tuple[str, str]:
|
|
777
859
|
refnode.attributes.update(env.ref_context)
|
|
778
860
|
|
|
779
861
|
if not has_explicit_title:
|
|
780
862
|
# major hax: replace anon names via simple string manipulation.
|
|
781
863
|
# Can this actually fail?
|
|
782
|
-
title = anon_identifier_re.sub(
|
|
864
|
+
title = anon_identifier_re.sub('[anonymous]', str(title))
|
|
783
865
|
|
|
784
866
|
if refnode['reftype'] == 'any':
|
|
785
867
|
# Assume the removal part of fix_parens for :any: refs.
|
|
@@ -796,7 +878,7 @@ class CPPXRefRole(XRefRole):
|
|
|
796
878
|
title = title[1:]
|
|
797
879
|
dcolon = title.rfind('::')
|
|
798
880
|
if dcolon != -1:
|
|
799
|
-
title = title[dcolon + 2:]
|
|
881
|
+
title = title[dcolon + 2 :]
|
|
800
882
|
return title, target
|
|
801
883
|
|
|
802
884
|
|
|
@@ -812,24 +894,29 @@ class CPPExprRole(SphinxRole):
|
|
|
812
894
|
|
|
813
895
|
def run(self) -> tuple[list[Node], list[system_message]]:
|
|
814
896
|
text = self.text.replace('\n', ' ')
|
|
815
|
-
parser = DefinitionParser(
|
|
816
|
-
|
|
817
|
-
|
|
897
|
+
parser = DefinitionParser(
|
|
898
|
+
text, location=self.get_location(), config=self.config
|
|
899
|
+
)
|
|
818
900
|
# attempt to mimic XRefRole classes, except that...
|
|
819
901
|
try:
|
|
820
902
|
ast = parser.parse_expression()
|
|
821
903
|
except DefinitionError as ex:
|
|
822
|
-
logger.warning(
|
|
823
|
-
|
|
904
|
+
logger.warning(
|
|
905
|
+
'Unparseable C++ expression: %r\n%s',
|
|
906
|
+
text,
|
|
907
|
+
ex,
|
|
908
|
+
location=self.get_location(),
|
|
909
|
+
)
|
|
824
910
|
# see below
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
911
|
+
node = addnodes.desc_inline('cpp', text, text, classes=[self.class_type])
|
|
912
|
+
return [node], []
|
|
913
|
+
parent_symbol = self.env.current_document.cpp_parent_symbol
|
|
914
|
+
if parent_symbol is None:
|
|
915
|
+
parent_symbol = self.env.domaindata['cpp']['root_symbol']
|
|
829
916
|
# ...most if not all of these classes should really apply to the individual references,
|
|
830
917
|
# not the container node
|
|
831
918
|
signode = addnodes.desc_inline('cpp', classes=[self.class_type])
|
|
832
|
-
ast.describe_signature(signode, 'markType', self.env,
|
|
919
|
+
ast.describe_signature(signode, 'markType', self.env, parent_symbol)
|
|
833
920
|
return [signode], []
|
|
834
921
|
|
|
835
922
|
|
|
@@ -849,18 +936,28 @@ class CPPDomain(Domain):
|
|
|
849
936
|
name = 'cpp'
|
|
850
937
|
label = 'C++'
|
|
851
938
|
object_types = {
|
|
852
|
-
'class':
|
|
853
|
-
'union':
|
|
854
|
-
'function':
|
|
855
|
-
'member':
|
|
856
|
-
'type':
|
|
857
|
-
'concept':
|
|
858
|
-
'enum':
|
|
859
|
-
'enumerator': ObjType(_('enumerator'), 'enumerator',
|
|
939
|
+
'class': ObjType(_('class'), 'class', 'struct', 'identifier', 'type'),
|
|
940
|
+
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
|
|
941
|
+
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
|
|
942
|
+
'member': ObjType(_('member'), 'member', 'var', 'identifier'),
|
|
943
|
+
'type': ObjType(_('type'), 'identifier', 'type'),
|
|
944
|
+
'concept': ObjType(_('concept'), 'concept', 'identifier'),
|
|
945
|
+
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
|
|
946
|
+
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
|
|
860
947
|
# generated object types
|
|
861
|
-
'functionParam': ObjType(
|
|
862
|
-
|
|
863
|
-
|
|
948
|
+
'functionParam': ObjType(
|
|
949
|
+
_('function parameter'), 'identifier', 'member', 'var'
|
|
950
|
+
),
|
|
951
|
+
'templateParam': ObjType(
|
|
952
|
+
_('template parameter'),
|
|
953
|
+
'identifier',
|
|
954
|
+
'class',
|
|
955
|
+
'struct',
|
|
956
|
+
'union',
|
|
957
|
+
'member',
|
|
958
|
+
'var',
|
|
959
|
+
'type',
|
|
960
|
+
),
|
|
864
961
|
}
|
|
865
962
|
|
|
866
963
|
directives = {
|
|
@@ -906,115 +1003,130 @@ class CPPDomain(Domain):
|
|
|
906
1003
|
|
|
907
1004
|
def clear_doc(self, docname: str) -> None:
|
|
908
1005
|
if Symbol.debug_show_tree:
|
|
909
|
-
logger.debug(
|
|
910
|
-
logger.debug(
|
|
1006
|
+
logger.debug('clear_doc: %s', docname)
|
|
1007
|
+
logger.debug('\tbefore:')
|
|
911
1008
|
logger.debug(self.data['root_symbol'].dump(1))
|
|
912
|
-
logger.debug(
|
|
1009
|
+
logger.debug('\tbefore end')
|
|
913
1010
|
|
|
914
|
-
|
|
915
|
-
|
|
1011
|
+
root_symbol = self.data['root_symbol']
|
|
1012
|
+
root_symbol.clear_doc(docname)
|
|
916
1013
|
|
|
917
1014
|
if Symbol.debug_show_tree:
|
|
918
|
-
logger.debug(
|
|
1015
|
+
logger.debug('\tafter:')
|
|
919
1016
|
logger.debug(self.data['root_symbol'].dump(1))
|
|
920
|
-
logger.debug(
|
|
921
|
-
logger.debug(
|
|
922
|
-
for name,
|
|
923
|
-
if
|
|
1017
|
+
logger.debug('\tafter end')
|
|
1018
|
+
logger.debug('clear_doc end: %s', docname)
|
|
1019
|
+
for name, n_docname in list(self.data['names'].items()):
|
|
1020
|
+
if n_docname == docname:
|
|
924
1021
|
del self.data['names'][name]
|
|
925
1022
|
|
|
926
|
-
def process_doc(
|
|
927
|
-
|
|
1023
|
+
def process_doc(
|
|
1024
|
+
self, env: BuildEnvironment, docname: str, document: nodes.document
|
|
1025
|
+
) -> None:
|
|
928
1026
|
if Symbol.debug_show_tree:
|
|
929
|
-
logger.debug(
|
|
1027
|
+
logger.debug('process_doc: %s', docname)
|
|
930
1028
|
logger.debug(self.data['root_symbol'].dump(0))
|
|
931
|
-
logger.debug(
|
|
1029
|
+
logger.debug('process_doc end: %s', docname)
|
|
932
1030
|
|
|
933
1031
|
def process_field_xref(self, pnode: pending_xref) -> None:
|
|
934
1032
|
pnode.attributes.update(self.env.ref_context)
|
|
935
1033
|
|
|
936
1034
|
def merge_domaindata(self, docnames: Set[str], otherdata: dict[str, Any]) -> None:
|
|
937
1035
|
if Symbol.debug_show_tree:
|
|
938
|
-
logger.debug(
|
|
939
|
-
logger.debug(
|
|
1036
|
+
logger.debug('merge_domaindata:')
|
|
1037
|
+
logger.debug('\tself:')
|
|
940
1038
|
logger.debug(self.data['root_symbol'].dump(1))
|
|
941
|
-
logger.debug(
|
|
942
|
-
logger.debug(
|
|
1039
|
+
logger.debug('\tself end')
|
|
1040
|
+
logger.debug('\tother:')
|
|
943
1041
|
logger.debug(otherdata['root_symbol'].dump(1))
|
|
944
|
-
logger.debug(
|
|
1042
|
+
logger.debug('\tother end')
|
|
945
1043
|
|
|
946
|
-
self.data['root_symbol'].merge_with(
|
|
947
|
-
|
|
948
|
-
|
|
1044
|
+
self.data['root_symbol'].merge_with(
|
|
1045
|
+
otherdata['root_symbol'], docnames, self.env
|
|
1046
|
+
)
|
|
1047
|
+
our_names = self.data['names']
|
|
949
1048
|
for name, docname in otherdata['names'].items():
|
|
950
1049
|
if docname in docnames:
|
|
951
|
-
if name not in
|
|
952
|
-
|
|
1050
|
+
if name not in our_names:
|
|
1051
|
+
our_names[name] = docname
|
|
953
1052
|
# no need to warn on duplicates, the symbol merge already does that
|
|
954
1053
|
if Symbol.debug_show_tree:
|
|
955
|
-
logger.debug(
|
|
1054
|
+
logger.debug('\tresult:')
|
|
956
1055
|
logger.debug(self.data['root_symbol'].dump(1))
|
|
957
|
-
logger.debug(
|
|
958
|
-
logger.debug(
|
|
959
|
-
|
|
960
|
-
def _resolve_xref_inner(
|
|
961
|
-
|
|
962
|
-
|
|
1056
|
+
logger.debug('\tresult end')
|
|
1057
|
+
logger.debug('merge_domaindata end')
|
|
1058
|
+
|
|
1059
|
+
def _resolve_xref_inner(
|
|
1060
|
+
self,
|
|
1061
|
+
env: BuildEnvironment,
|
|
1062
|
+
fromdocname: str,
|
|
1063
|
+
builder: Builder,
|
|
1064
|
+
typ: str,
|
|
1065
|
+
target: str,
|
|
1066
|
+
node: pending_xref,
|
|
1067
|
+
contnode: Element,
|
|
1068
|
+
) -> tuple[nodes.reference, str] | tuple[None, None]:
|
|
963
1069
|
# add parens again for those that could be functions
|
|
964
|
-
if typ in
|
|
1070
|
+
if typ in {'any', 'func'}:
|
|
965
1071
|
target += '()'
|
|
966
1072
|
parser = DefinitionParser(target, location=node, config=env.config)
|
|
967
1073
|
try:
|
|
968
|
-
ast,
|
|
1074
|
+
ast, is_shorthand = parser.parse_xref_object()
|
|
969
1075
|
except DefinitionError as e:
|
|
970
|
-
|
|
971
|
-
def findWarning(e: Exception) -> tuple[str, Exception]:
|
|
972
|
-
if typ != 'any' and typ != 'func':
|
|
973
|
-
return target, e
|
|
1076
|
+
if typ in {'any', 'func'}:
|
|
974
1077
|
# hax on top of the paren hax to try to get correct errors
|
|
975
|
-
parser2 = DefinitionParser(
|
|
976
|
-
|
|
977
|
-
|
|
1078
|
+
parser2 = DefinitionParser(
|
|
1079
|
+
target[:-2], location=node, config=env.config
|
|
1080
|
+
)
|
|
978
1081
|
try:
|
|
979
1082
|
parser2.parse_xref_object()
|
|
980
1083
|
except DefinitionError as e2:
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1084
|
+
target = target[:-2]
|
|
1085
|
+
ex = e2
|
|
1086
|
+
else:
|
|
1087
|
+
# strange, that we don't get the error now, use the original
|
|
1088
|
+
ex = e
|
|
1089
|
+
else:
|
|
1090
|
+
ex = e
|
|
1091
|
+
|
|
1092
|
+
logger.warning(
|
|
1093
|
+
'Unparseable C++ cross-reference: %r\n%s', target, ex, location=node
|
|
1094
|
+
)
|
|
987
1095
|
return None, None
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
if
|
|
991
|
-
|
|
992
|
-
if not
|
|
993
|
-
logger.debug(
|
|
994
|
-
logger.debug(
|
|
995
|
-
logger.debug(
|
|
996
|
-
assert
|
|
1096
|
+
parent_key: LookupKey | None = node.get('cpp:parent_key', None)
|
|
1097
|
+
root_symbol = self.data['root_symbol']
|
|
1098
|
+
if parent_key:
|
|
1099
|
+
parent_symbol: Symbol = root_symbol.direct_lookup(parent_key)
|
|
1100
|
+
if not parent_symbol:
|
|
1101
|
+
logger.debug('Target: %s', target)
|
|
1102
|
+
logger.debug('ParentKey: %s', parent_key.data)
|
|
1103
|
+
logger.debug(root_symbol.dump(1))
|
|
1104
|
+
assert parent_symbol # should be there
|
|
997
1105
|
else:
|
|
998
|
-
|
|
1106
|
+
parent_symbol = root_symbol
|
|
999
1107
|
|
|
1000
|
-
if
|
|
1108
|
+
if is_shorthand:
|
|
1001
1109
|
assert isinstance(ast, ASTNamespace)
|
|
1002
1110
|
ns = ast
|
|
1003
1111
|
name = ns.nestedName
|
|
1004
1112
|
if ns.templatePrefix:
|
|
1005
|
-
|
|
1113
|
+
template_decls = ns.templatePrefix.templates
|
|
1006
1114
|
else:
|
|
1007
|
-
|
|
1115
|
+
template_decls = []
|
|
1008
1116
|
# let's be conservative with the sibling lookup for now
|
|
1009
|
-
|
|
1010
|
-
symbols,
|
|
1011
|
-
name,
|
|
1117
|
+
search_in_siblings = (not name.rooted) and len(name.names) == 1
|
|
1118
|
+
symbols, fail_reason = parent_symbol.find_name(
|
|
1119
|
+
name,
|
|
1120
|
+
template_decls,
|
|
1121
|
+
typ,
|
|
1012
1122
|
templateShorthand=True,
|
|
1013
|
-
matchSelf=True,
|
|
1014
|
-
|
|
1123
|
+
matchSelf=True,
|
|
1124
|
+
recurseInAnon=True,
|
|
1125
|
+
searchInSiblings=search_in_siblings,
|
|
1126
|
+
)
|
|
1015
1127
|
if symbols is None:
|
|
1016
1128
|
if typ == 'identifier':
|
|
1017
|
-
if
|
|
1129
|
+
if fail_reason == 'templateParamInQualified':
|
|
1018
1130
|
# this is an xref we created as part of a signature,
|
|
1019
1131
|
# so don't warn for names nested in template parameters
|
|
1020
1132
|
raise NoUri(str(name), typ)
|
|
@@ -1026,44 +1138,48 @@ class CPPDomain(Domain):
|
|
|
1026
1138
|
assert isinstance(ast, ASTDeclaration)
|
|
1027
1139
|
decl = ast
|
|
1028
1140
|
name = decl.name
|
|
1029
|
-
s =
|
|
1030
|
-
|
|
1031
|
-
|
|
1141
|
+
s = parent_symbol.find_declaration(
|
|
1142
|
+
decl, typ, templateShorthand=True, matchSelf=True, recurseInAnon=True
|
|
1143
|
+
)
|
|
1032
1144
|
if s is None or s.declaration is None:
|
|
1033
|
-
|
|
1034
|
-
if
|
|
1035
|
-
raise NoUri(
|
|
1145
|
+
txt_name = str(name)
|
|
1146
|
+
if txt_name.startswith('std::') or txt_name == 'std':
|
|
1147
|
+
raise NoUri(txt_name, typ)
|
|
1036
1148
|
return None, None
|
|
1037
1149
|
|
|
1038
1150
|
typ = typ.removeprefix('cpp:')
|
|
1039
|
-
|
|
1151
|
+
decl_typ = s.declaration.objectType
|
|
1040
1152
|
|
|
1041
|
-
def
|
|
1153
|
+
def check_type() -> bool:
|
|
1042
1154
|
if typ == 'any':
|
|
1043
1155
|
return True
|
|
1044
1156
|
objtypes = self.objtypes_for_role(typ)
|
|
1045
1157
|
if objtypes:
|
|
1046
|
-
return
|
|
1047
|
-
logger.debug(f
|
|
1158
|
+
return decl_typ in objtypes
|
|
1159
|
+
logger.debug(f'Type is {typ}, declaration type is {decl_typ}') # NoQA: G004
|
|
1048
1160
|
raise AssertionError
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1161
|
+
|
|
1162
|
+
if not check_type():
|
|
1163
|
+
logger.warning(
|
|
1164
|
+
'cpp:%s targets a %s (%s).',
|
|
1165
|
+
typ,
|
|
1166
|
+
s.declaration.objectType,
|
|
1167
|
+
s.get_full_nested_name(),
|
|
1168
|
+
location=node,
|
|
1169
|
+
)
|
|
1054
1170
|
|
|
1055
1171
|
declaration = s.declaration
|
|
1056
|
-
if
|
|
1057
|
-
|
|
1058
|
-
|
|
1172
|
+
if is_shorthand:
|
|
1173
|
+
full_nested_name = s.get_full_nested_name()
|
|
1174
|
+
display_name = full_nested_name.get_display_string().lstrip(':')
|
|
1059
1175
|
else:
|
|
1060
|
-
|
|
1176
|
+
display_name = decl.get_display_string()
|
|
1061
1177
|
docname = s.docname
|
|
1062
1178
|
assert docname
|
|
1063
1179
|
|
|
1064
1180
|
# the non-identifier refs are cross-references, which should be processed:
|
|
1065
1181
|
# - fix parenthesis due to operator() and add_function_parentheses
|
|
1066
|
-
if typ !=
|
|
1182
|
+
if typ != 'identifier':
|
|
1067
1183
|
title = contnode.pop(0).astext()
|
|
1068
1184
|
# If it's operator(), we need to add '()' if explicit function parens
|
|
1069
1185
|
# are requested. Then the Sphinx machinery will add another pair.
|
|
@@ -1071,52 +1187,83 @@ class CPPDomain(Domain):
|
|
|
1071
1187
|
# parens as well.
|
|
1072
1188
|
# However, if it's a non-shorthand function ref, for a function that
|
|
1073
1189
|
# takes no arguments, then we may need to add parens again as well.
|
|
1074
|
-
|
|
1075
|
-
if
|
|
1076
|
-
|
|
1190
|
+
add_paren = 0
|
|
1191
|
+
if (
|
|
1192
|
+
not node.get('refexplicit', False)
|
|
1193
|
+
and declaration.objectType == 'function'
|
|
1194
|
+
):
|
|
1195
|
+
if is_shorthand:
|
|
1077
1196
|
# this is just the normal haxing for 'any' roles
|
|
1078
1197
|
if env.config.add_function_parentheses and typ == 'any':
|
|
1079
|
-
|
|
1198
|
+
add_paren += 1
|
|
1080
1199
|
# and now this stuff for operator()
|
|
1081
|
-
if (
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1200
|
+
if (
|
|
1201
|
+
env.config.add_function_parentheses
|
|
1202
|
+
and typ == 'func'
|
|
1203
|
+
and title.endswith('operator()')
|
|
1204
|
+
):
|
|
1205
|
+
add_paren += 1
|
|
1206
|
+
if (
|
|
1207
|
+
typ in {'any', 'func'}
|
|
1208
|
+
and title.endswith('operator')
|
|
1209
|
+
and display_name.endswith('operator()')
|
|
1210
|
+
):
|
|
1211
|
+
add_paren += 1
|
|
1088
1212
|
else:
|
|
1089
1213
|
# our job here is to essentially nullify add_function_parentheses
|
|
1090
1214
|
if env.config.add_function_parentheses:
|
|
1091
|
-
if typ == 'any' and
|
|
1092
|
-
|
|
1215
|
+
if typ == 'any' and display_name.endswith('()'):
|
|
1216
|
+
add_paren += 1
|
|
1093
1217
|
elif typ == 'func':
|
|
1094
|
-
if not
|
|
1218
|
+
if not display_name.endswith('()'):
|
|
1095
1219
|
title = title.removesuffix('()')
|
|
1096
1220
|
else:
|
|
1097
|
-
if
|
|
1098
|
-
|
|
1099
|
-
if
|
|
1100
|
-
title += '()' *
|
|
1221
|
+
if display_name.endswith('()'):
|
|
1222
|
+
add_paren += 1
|
|
1223
|
+
if add_paren > 0:
|
|
1224
|
+
title += '()' * add_paren
|
|
1101
1225
|
# and reconstruct the title again
|
|
1102
1226
|
contnode += nodes.Text(title)
|
|
1103
|
-
res =
|
|
1104
|
-
|
|
1105
|
-
|
|
1227
|
+
res = (
|
|
1228
|
+
make_refnode(
|
|
1229
|
+
builder,
|
|
1230
|
+
fromdocname,
|
|
1231
|
+
docname,
|
|
1232
|
+
declaration.get_newest_id(),
|
|
1233
|
+
contnode,
|
|
1234
|
+
display_name,
|
|
1235
|
+
),
|
|
1236
|
+
declaration.objectType,
|
|
1237
|
+
)
|
|
1106
1238
|
return res
|
|
1107
1239
|
|
|
1108
|
-
def resolve_xref(
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1240
|
+
def resolve_xref(
|
|
1241
|
+
self,
|
|
1242
|
+
env: BuildEnvironment,
|
|
1243
|
+
fromdocname: str,
|
|
1244
|
+
builder: Builder,
|
|
1245
|
+
typ: str,
|
|
1246
|
+
target: str,
|
|
1247
|
+
node: pending_xref,
|
|
1248
|
+
contnode: Element,
|
|
1249
|
+
) -> nodes.reference | None:
|
|
1250
|
+
return self._resolve_xref_inner(
|
|
1251
|
+
env, fromdocname, builder, typ, target, node, contnode
|
|
1252
|
+
)[0]
|
|
1253
|
+
|
|
1254
|
+
def resolve_any_xref(
|
|
1255
|
+
self,
|
|
1256
|
+
env: BuildEnvironment,
|
|
1257
|
+
fromdocname: str,
|
|
1258
|
+
builder: Builder,
|
|
1259
|
+
target: str,
|
|
1260
|
+
node: pending_xref,
|
|
1261
|
+
contnode: Element,
|
|
1262
|
+
) -> list[tuple[str, nodes.reference]]:
|
|
1117
1263
|
with logging.suppress_logging():
|
|
1118
|
-
retnode, objtype = self._resolve_xref_inner(
|
|
1119
|
-
|
|
1264
|
+
retnode, objtype = self._resolve_xref_inner(
|
|
1265
|
+
env, fromdocname, builder, 'any', target, node, contnode
|
|
1266
|
+
)
|
|
1120
1267
|
if retnode:
|
|
1121
1268
|
if objtype == 'templateParam':
|
|
1122
1269
|
return [('cpp:templateParam', retnode)]
|
|
@@ -1125,50 +1272,58 @@ class CPPDomain(Domain):
|
|
|
1125
1272
|
return []
|
|
1126
1273
|
|
|
1127
1274
|
def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
|
|
1128
|
-
|
|
1129
|
-
for symbol in
|
|
1275
|
+
root_symbol = self.data['root_symbol']
|
|
1276
|
+
for symbol in root_symbol.get_all_symbols():
|
|
1130
1277
|
if symbol.declaration is None:
|
|
1131
1278
|
continue
|
|
1132
1279
|
assert symbol.docname
|
|
1133
|
-
|
|
1134
|
-
name = str(
|
|
1135
|
-
dispname =
|
|
1136
|
-
|
|
1280
|
+
full_nested_name = symbol.get_full_nested_name()
|
|
1281
|
+
name = str(full_nested_name).lstrip(':')
|
|
1282
|
+
dispname = full_nested_name.get_display_string().lstrip(':')
|
|
1283
|
+
object_type = symbol.declaration.objectType
|
|
1137
1284
|
docname = symbol.docname
|
|
1138
|
-
|
|
1139
|
-
yield
|
|
1285
|
+
newest_id = symbol.declaration.get_newest_id()
|
|
1286
|
+
yield name, dispname, object_type, docname, newest_id, 1
|
|
1140
1287
|
|
|
1141
1288
|
def get_full_qualified_name(self, node: Element) -> str | None:
|
|
1142
1289
|
target = node.get('reftarget', None)
|
|
1143
1290
|
if target is None:
|
|
1144
1291
|
return None
|
|
1145
|
-
|
|
1146
|
-
if
|
|
1292
|
+
parent_key: LookupKey | None = node.get('cpp:parent_key', None)
|
|
1293
|
+
if parent_key is None or len(parent_key.data) <= 0:
|
|
1147
1294
|
return None
|
|
1148
1295
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
return f'{
|
|
1296
|
+
root_symbol = self.data['root_symbol']
|
|
1297
|
+
parent_symbol = root_symbol.direct_lookup(parent_key)
|
|
1298
|
+
parent_name = parent_symbol.get_full_nested_name()
|
|
1299
|
+
return f'{parent_name}::{target}'
|
|
1153
1300
|
|
|
1154
1301
|
|
|
1155
1302
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
1156
1303
|
app.add_domain(CPPDomain)
|
|
1157
|
-
app.add_config_value(
|
|
1158
|
-
app.add_config_value(
|
|
1159
|
-
app.add_config_value(
|
|
1160
|
-
|
|
1304
|
+
app.add_config_value('cpp_index_common_prefix', [], 'env', types=frozenset({list}))
|
|
1305
|
+
app.add_config_value('cpp_id_attributes', [], 'env', types=frozenset({list, tuple}))
|
|
1306
|
+
app.add_config_value(
|
|
1307
|
+
'cpp_paren_attributes', [], 'env', types=frozenset({list, tuple})
|
|
1308
|
+
)
|
|
1309
|
+
app.add_config_value(
|
|
1310
|
+
'cpp_maximum_signature_line_length',
|
|
1311
|
+
None,
|
|
1312
|
+
'env',
|
|
1313
|
+
types=frozenset({int, NoneType}),
|
|
1314
|
+
)
|
|
1161
1315
|
app.add_post_transform(AliasTransform)
|
|
1162
1316
|
|
|
1163
1317
|
# debug stuff
|
|
1164
|
-
app.add_config_value(
|
|
1165
|
-
app.add_config_value(
|
|
1318
|
+
app.add_config_value('cpp_debug_lookup', False, '', types=frozenset({bool}))
|
|
1319
|
+
app.add_config_value('cpp_debug_show_tree', False, '', types=frozenset({bool}))
|
|
1166
1320
|
|
|
1167
|
-
def
|
|
1321
|
+
def init_stuff(app: Sphinx) -> None:
|
|
1168
1322
|
Symbol.debug_lookup = app.config.cpp_debug_lookup
|
|
1169
1323
|
Symbol.debug_show_tree = app.config.cpp_debug_show_tree
|
|
1170
1324
|
app.config.cpp_index_common_prefix.sort(reverse=True)
|
|
1171
|
-
|
|
1325
|
+
|
|
1326
|
+
app.connect('builder-inited', init_stuff)
|
|
1172
1327
|
|
|
1173
1328
|
return {
|
|
1174
1329
|
'version': 'builtin',
|