sphinxcontrib-rust 0.1.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.
- sphinxcontrib_rust/__init__.py +97 -0
- sphinxcontrib_rust/directives.py +250 -0
- sphinxcontrib_rust/domain.py +209 -0
- sphinxcontrib_rust/index.py +172 -0
- sphinxcontrib_rust/items.py +116 -0
- sphinxcontrib_rust-0.1.0.dist-info/LICENSE +674 -0
- sphinxcontrib_rust-0.1.0.dist-info/METADATA +190 -0
- sphinxcontrib_rust-0.1.0.dist-info/RECORD +10 -0
- sphinxcontrib_rust-0.1.0.dist-info/WHEEL +5 -0
- sphinxcontrib_rust-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Init module for the extension with the ``setup`` function used by Sphinx"""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version
|
|
4
|
+
import subprocess
|
|
5
|
+
from shutil import which
|
|
6
|
+
from typing import Any, Mapping
|
|
7
|
+
|
|
8
|
+
import sphinx.config
|
|
9
|
+
from sphinx.application import Sphinx
|
|
10
|
+
from sphinx.util import logging
|
|
11
|
+
|
|
12
|
+
from sphinxcontrib_rust.domain import RustDomain
|
|
13
|
+
|
|
14
|
+
__PKG_NAME = "sphinxcontrib_rust"
|
|
15
|
+
__VERSION__ = version(__PKG_NAME)
|
|
16
|
+
__REQUIRED_EXTENSIONS = ["sphinx.ext.autodoc"]
|
|
17
|
+
__LOGGER = logging.getLogger(__PKG_NAME)
|
|
18
|
+
|
|
19
|
+
"""The configuration options added by the extension.
|
|
20
|
+
|
|
21
|
+
Each entry is tuple consisting of
|
|
22
|
+
* The option name.
|
|
23
|
+
* The default value.
|
|
24
|
+
* The rebuild condition .
|
|
25
|
+
* "html": Change needs a full rebuild of HTML.
|
|
26
|
+
* "env": Change needs a full rebuild of the build environment.
|
|
27
|
+
* "": No rebuild required.
|
|
28
|
+
* A list of types for the value.
|
|
29
|
+
"""
|
|
30
|
+
__CONFIG_OPTIONS = (
|
|
31
|
+
("rust_crates", None, "env", [dict]),
|
|
32
|
+
("rust_doc_dir", None, "env", [str]),
|
|
33
|
+
("rust_rustdoc_fmt", "rst", "env", [str]),
|
|
34
|
+
("rust_visibility", "pub", "html", [str]), # TODO: Define a type for this
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
See https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata
|
|
39
|
+
"""
|
|
40
|
+
__METADATA = {
|
|
41
|
+
"version": __VERSION__,
|
|
42
|
+
"parallel_read_safe": True,
|
|
43
|
+
"parallel_write_safe": True,
|
|
44
|
+
}
|
|
45
|
+
__RUSTDOCGEN = which("sphinx-rustdocgen")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def generate_docs(app: Sphinx, config: sphinx.config.Config):
|
|
49
|
+
"""Generate the Rust docs once the configuration has been read
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
:app: The Sphinx application.
|
|
53
|
+
:config: The parsed configuration.
|
|
54
|
+
"""
|
|
55
|
+
for crate, src_dir in config.rust_crates.items():
|
|
56
|
+
__LOGGER.info(
|
|
57
|
+
"[sphinxcontrib_rust] Processing contents of crate %s from directory %s",
|
|
58
|
+
crate,
|
|
59
|
+
src_dir,
|
|
60
|
+
)
|
|
61
|
+
__LOGGER.info(
|
|
62
|
+
"[sphinxcontrib_rust] Generated files will be saved in %s/%s",
|
|
63
|
+
config.rust_doc_dir,
|
|
64
|
+
crate,
|
|
65
|
+
)
|
|
66
|
+
subprocess.run(
|
|
67
|
+
[
|
|
68
|
+
__RUSTDOCGEN,
|
|
69
|
+
crate,
|
|
70
|
+
src_dir,
|
|
71
|
+
config.rust_doc_dir,
|
|
72
|
+
config.rust_rustdoc_fmt,
|
|
73
|
+
],
|
|
74
|
+
check=True,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def setup(app: Sphinx) -> Mapping[str, Any]:
|
|
79
|
+
"""Set up the extension"""
|
|
80
|
+
if __RUSTDOCGEN is None:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"Could not find the sphinx-rustdocgen executable. "
|
|
83
|
+
"Make sure it is installed and available on the default PATH."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
app.require_sphinx("7.0")
|
|
87
|
+
|
|
88
|
+
for extension in __REQUIRED_EXTENSIONS:
|
|
89
|
+
app.setup_extension(extension)
|
|
90
|
+
|
|
91
|
+
for option in __CONFIG_OPTIONS:
|
|
92
|
+
app.add_config_value(*option)
|
|
93
|
+
|
|
94
|
+
app.add_domain(RustDomain)
|
|
95
|
+
app.connect("config-inited", generate_docs)
|
|
96
|
+
|
|
97
|
+
return __METADATA
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The module provides all the directive classes for the Rust object types.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import Sequence, Type
|
|
7
|
+
|
|
8
|
+
from docutils.parsers.rst import directives
|
|
9
|
+
from sphinx import addnodes
|
|
10
|
+
from sphinx.addnodes import desc_signature
|
|
11
|
+
from sphinx.directives import (
|
|
12
|
+
ObjDescT,
|
|
13
|
+
ObjectDescription,
|
|
14
|
+
nl_escape_re,
|
|
15
|
+
strip_backslash_re,
|
|
16
|
+
)
|
|
17
|
+
from sphinx.util.nodes import make_id
|
|
18
|
+
|
|
19
|
+
from sphinxcontrib_rust.items import RustItem, RustItemType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RustDirective(ABC, ObjectDescription[Sequence[str]]):
|
|
23
|
+
"""Base class for Rust directives"""
|
|
24
|
+
|
|
25
|
+
option_spec = {
|
|
26
|
+
"no-index": directives.flag,
|
|
27
|
+
"vis": directives.unchanged_required,
|
|
28
|
+
"sig": directives.unchanged,
|
|
29
|
+
"toc": directives.unchanged,
|
|
30
|
+
"type": directives.unchanged,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def rust_item_type(self) -> RustItemType:
|
|
36
|
+
"""The Rust object type for the directive"""
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def get_directives(cls) -> dict[RustItemType, Type["RustDirective"]]:
|
|
41
|
+
"""Get all the directives for the object types"""
|
|
42
|
+
return {
|
|
43
|
+
RustItemType.CRATE: RustCrateDirective,
|
|
44
|
+
RustItemType.ENUM: RustEnumDirective,
|
|
45
|
+
RustItemType.FUNCTION: RustFunctionDirective,
|
|
46
|
+
RustItemType.IMPL: RustImplDirective,
|
|
47
|
+
RustItemType.MACRO: RustMacroDirective,
|
|
48
|
+
RustItemType.MODULE: RustModuleDirective,
|
|
49
|
+
RustItemType.STRUCT: RustStructDirective,
|
|
50
|
+
RustItemType.TRAIT: RustTraitDirective,
|
|
51
|
+
RustItemType.TYPE: RustTypeDirective,
|
|
52
|
+
RustItemType.VARIABLE: RustVariableDirective,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def add_target_and_index(
|
|
56
|
+
self, name: Sequence[str], sig: str, signode: desc_signature
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Adds the item to the domain and generates the index for it.
|
|
59
|
+
|
|
60
|
+
This is called after :py:func:`handle_signature` has executed.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
:name: The name of the item, which is the return value from
|
|
64
|
+
:py:func:`handle_signature`.
|
|
65
|
+
:sig: The argument to the directive, which is the Rust path
|
|
66
|
+
of the item set by the Rust doc generator.
|
|
67
|
+
:signode: The docutils node of the for item.
|
|
68
|
+
"""
|
|
69
|
+
fullname = "::".join(name) # XXX: Can we just use sig here?
|
|
70
|
+
node_id = make_id(self.env, self.state.document, "", fullname)
|
|
71
|
+
signode["ids"].append(node_id)
|
|
72
|
+
|
|
73
|
+
rust_obj = RustItem(
|
|
74
|
+
name=fullname,
|
|
75
|
+
dispname=self.options.get("sig", name[-1]),
|
|
76
|
+
type_=self.rust_item_type,
|
|
77
|
+
docname=self.env.docname,
|
|
78
|
+
anchor="-".join(name), # Need to join with - for HTML anchors
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Add to the domain
|
|
82
|
+
self.env.domains["rust"].data[self.rust_item_type].append(rust_obj)
|
|
83
|
+
|
|
84
|
+
if "no-index" not in self.options:
|
|
85
|
+
self.indexnode["entries"].append(("single", fullname, node_id, "", None))
|
|
86
|
+
|
|
87
|
+
def get_signatures(self) -> list[str]:
|
|
88
|
+
"""Override the default get_signatures method, which splits the signatures by line.
|
|
89
|
+
|
|
90
|
+
Currently, only one signature is allowed for each Rust object, and due to the use
|
|
91
|
+
of where on new lines, it is all part of one signature. Only the final newline is
|
|
92
|
+
removed.
|
|
93
|
+
|
|
94
|
+
See Also:
|
|
95
|
+
* `Docs for the method`_
|
|
96
|
+
* `Source code for super`_
|
|
97
|
+
|
|
98
|
+
.. _`Docs for the method`:
|
|
99
|
+
https://www.sphinx-doc.org/en/master/_modules/sphinx/directives.html#ObjectDescription.get_signatures
|
|
100
|
+
.. _`Source code for super`:
|
|
101
|
+
https://www.sphinx-doc.org/en/master/_modules/sphinx/directives.html#ObjectDescription.get_signatures
|
|
102
|
+
"""
|
|
103
|
+
sig = nl_escape_re.sub("", self.arguments[0]).strip()
|
|
104
|
+
return (
|
|
105
|
+
[strip_backslash_re.sub(r"\1", sig)]
|
|
106
|
+
if self.config.strip_signature_backslash
|
|
107
|
+
else [sig]
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def handle_signature(self, sig: str, signode: addnodes.desc_signature) -> ObjDescT:
|
|
111
|
+
"""Handle the directive and generate its display signature.
|
|
112
|
+
|
|
113
|
+
The display signature is what is displayed instead of the directive name and
|
|
114
|
+
options in the generated output. The ``:sig:`` option of the directive is used
|
|
115
|
+
to override the provided ``sig`` value. If the option is not set, the item type
|
|
116
|
+
and the final component of the path are used.
|
|
117
|
+
|
|
118
|
+
Raising ``ValueError`` will put the ``sig`` value into a single node, which
|
|
119
|
+
is what the super implementation does.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
:sig: The argument of the directive as set during doc generation, not the
|
|
123
|
+
``:sig:`` option. The Rust side of the code will put the full Rust path
|
|
124
|
+
of the item as the argument.
|
|
125
|
+
:signode: The docutils node for the item, to which the display signature nodes
|
|
126
|
+
should be appended.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
The path for the object, which is a tuple of the Rust path components and
|
|
130
|
+
defines the hierarchy of the object for indexing.
|
|
131
|
+
"""
|
|
132
|
+
path = tuple(sig.split("::"))
|
|
133
|
+
# TODO: Parse the signature as RST content and handle multi-line
|
|
134
|
+
signode += addnodes.desc_name(
|
|
135
|
+
sig,
|
|
136
|
+
self.options.get("sig", f"{self.rust_item_type.display_name} {path[-1]}"),
|
|
137
|
+
)
|
|
138
|
+
signode.path = path
|
|
139
|
+
return path
|
|
140
|
+
|
|
141
|
+
def _object_hierarchy_parts(
|
|
142
|
+
self, sig_node: addnodes.desc_signature
|
|
143
|
+
) -> tuple[str, ...]:
|
|
144
|
+
"""Returns the hierarchy of the object for indexing and de-duplication.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
:sig_node: The docutils node of the for item.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
A tuple of the Rust path for the item, as set during the
|
|
151
|
+
doc generation.
|
|
152
|
+
"""
|
|
153
|
+
return sig_node.path
|
|
154
|
+
|
|
155
|
+
def _toc_entry_name(self, sig_node: addnodes.desc_signature) -> str:
|
|
156
|
+
"""Generate the TOC entry for the item.
|
|
157
|
+
|
|
158
|
+
For most directives, this is just the item type and identifier of the
|
|
159
|
+
item. The ``:toc:`` option is set during doc generation where that is
|
|
160
|
+
not sufficient (``impl`` blocks) or not desired (enum variants).
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
sig_node: The docutils node for the item.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The text to display for the item in the TOC and sidebar.
|
|
167
|
+
"""
|
|
168
|
+
return self.options.get(
|
|
169
|
+
"toc", f"{self.rust_item_type.display_name} {sig_node.path[-1]}"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class RustCrateDirective(RustDirective):
|
|
174
|
+
"""Directive for handling crate documentation"""
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def rust_item_type(self) -> RustItemType:
|
|
178
|
+
return RustItemType.CRATE
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class RustEnumDirective(RustDirective):
|
|
182
|
+
"""Directive for handling enum documentation"""
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def rust_item_type(self) -> RustItemType:
|
|
186
|
+
return RustItemType.ENUM
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class RustFunctionDirective(RustDirective):
|
|
190
|
+
"""Directive for handling function documentation"""
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def rust_item_type(self) -> RustItemType:
|
|
194
|
+
return RustItemType.FUNCTION
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class RustImplDirective(RustDirective):
|
|
198
|
+
"""Directive for handling function documentation"""
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def rust_item_type(self) -> RustItemType:
|
|
202
|
+
return RustItemType.IMPL
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class RustMacroDirective(RustDirective):
|
|
206
|
+
"""Directive for handling function documentation"""
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def rust_item_type(self) -> RustItemType:
|
|
210
|
+
return RustItemType.MACRO
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class RustModuleDirective(RustDirective):
|
|
214
|
+
"""Directive for handling module documentation"""
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def rust_item_type(self) -> RustItemType:
|
|
218
|
+
return RustItemType.MODULE
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class RustStructDirective(RustDirective):
|
|
222
|
+
"""Directive for handling struct documentation"""
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def rust_item_type(self) -> RustItemType:
|
|
226
|
+
return RustItemType.STRUCT
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class RustTraitDirective(RustDirective):
|
|
230
|
+
"""Directive for handling trait documentation"""
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def rust_item_type(self) -> RustItemType:
|
|
234
|
+
return RustItemType.TRAIT
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class RustTypeDirective(RustDirective):
|
|
238
|
+
"""Directive for handling type documentation"""
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def rust_item_type(self) -> RustItemType:
|
|
242
|
+
return RustItemType.TYPE
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class RustVariableDirective(RustDirective):
|
|
246
|
+
"""Directive for handling type documentation"""
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def rust_item_type(self) -> RustItemType:
|
|
250
|
+
return RustItemType.VARIABLE
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The module defines the :py:class:`RustDomain` class, which is a Sphinx domain
|
|
3
|
+
for the various concepts used within the Rust programming language.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional, Type, Union, Iterable
|
|
7
|
+
|
|
8
|
+
from docutils.nodes import Element
|
|
9
|
+
from docutils.parsers.rst import Directive
|
|
10
|
+
from sphinx.addnodes import pending_xref
|
|
11
|
+
from sphinx.builders import Builder
|
|
12
|
+
from sphinx.domains import Domain, Index, ObjType
|
|
13
|
+
from sphinx.environment import BuildEnvironment
|
|
14
|
+
from sphinx.roles import XRefRole
|
|
15
|
+
from sphinx.util import logging
|
|
16
|
+
from sphinx.util.nodes import make_refnode
|
|
17
|
+
from sphinx.util.typing import RoleFunction
|
|
18
|
+
|
|
19
|
+
from sphinxcontrib_rust.directives import RustDirective
|
|
20
|
+
from sphinxcontrib_rust.index import (
|
|
21
|
+
CrateIndex,
|
|
22
|
+
EnumIndex,
|
|
23
|
+
FunctionIndex,
|
|
24
|
+
ModuleIndex,
|
|
25
|
+
StructIndex,
|
|
26
|
+
TraitIndex,
|
|
27
|
+
TypeIndex,
|
|
28
|
+
VariableIndex,
|
|
29
|
+
)
|
|
30
|
+
from sphinxcontrib_rust.items import RustItem, RustItemType
|
|
31
|
+
|
|
32
|
+
LOGGER = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class RustXRefRole(XRefRole):
|
|
36
|
+
"""An :py:class:`XRefRole` extension for Rust roles"""
|
|
37
|
+
|
|
38
|
+
def process_link(
|
|
39
|
+
self,
|
|
40
|
+
env: BuildEnvironment,
|
|
41
|
+
refnode: Element,
|
|
42
|
+
has_explicit_title: bool,
|
|
43
|
+
title: str,
|
|
44
|
+
target: str,
|
|
45
|
+
) -> tuple[str, str]:
|
|
46
|
+
"""Process the link by parsing the tile and the target"""
|
|
47
|
+
# pylint: disable=too-many-arguments
|
|
48
|
+
if not has_explicit_title:
|
|
49
|
+
# This is the most common case where
|
|
50
|
+
# only the target is specified as the title like
|
|
51
|
+
# `` :rust:struct:`~crate::module::Struct` ``
|
|
52
|
+
# title == target in this case
|
|
53
|
+
|
|
54
|
+
# Remove any leading or trailing ::s.
|
|
55
|
+
# Only meaningful for targets, once support
|
|
56
|
+
# for relative references is added.
|
|
57
|
+
title = title.strip("::")
|
|
58
|
+
|
|
59
|
+
# Remove the ~ from the target, only meaningful for titles.
|
|
60
|
+
target = target.lstrip("~")
|
|
61
|
+
|
|
62
|
+
# ~ will use only the final part of the name as the title
|
|
63
|
+
# instead of the full path.
|
|
64
|
+
if title[0:1] == "~":
|
|
65
|
+
title = title[1:]
|
|
66
|
+
sep = title.rfind("::")
|
|
67
|
+
if sep != -1:
|
|
68
|
+
title = title[sep + 2 :]
|
|
69
|
+
|
|
70
|
+
return title, target
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class RustDomain(Domain):
|
|
74
|
+
"""The Sphinx domain for the Rust programming language.
|
|
75
|
+
|
|
76
|
+
The domain provides the various roles and directives that can be used in the Sphinx
|
|
77
|
+
documentation for linking with Rust code.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
name = "rust"
|
|
81
|
+
label = "Rust"
|
|
82
|
+
|
|
83
|
+
# The various object types provided by the domain
|
|
84
|
+
object_types: dict[str, ObjType] = {
|
|
85
|
+
t.value: t.get_sphinx_obj_type() for t in RustItemType
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# The various directives add to Sphinx for documenting the Rust object types
|
|
89
|
+
directives: dict[str, Type[Directive]] = {
|
|
90
|
+
t.value: d for t, d in RustDirective.get_directives().items()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# The various roles added to Sphinx for referencing the Rust object types
|
|
94
|
+
roles: dict[str, Union[RoleFunction, XRefRole]] = {
|
|
95
|
+
# TODO: Customize this role
|
|
96
|
+
r: RustXRefRole()
|
|
97
|
+
for _, r in RustItemType.iter_roles()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# The indices for all the object types
|
|
101
|
+
indices: list[Type[Index]] = [
|
|
102
|
+
CrateIndex,
|
|
103
|
+
ModuleIndex,
|
|
104
|
+
StructIndex,
|
|
105
|
+
TraitIndex,
|
|
106
|
+
EnumIndex,
|
|
107
|
+
FunctionIndex,
|
|
108
|
+
VariableIndex,
|
|
109
|
+
TypeIndex,
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
# The domain data created by Sphinx. This is here just for type annotation.
|
|
113
|
+
data: dict[RustItemType, list[RustItem]]
|
|
114
|
+
|
|
115
|
+
# Initial data for the domain, gets copied as self.data by Sphinx
|
|
116
|
+
initial_data: dict[RustItemType, list[RustItem]] = {
|
|
117
|
+
t: [] for t in RustItemType
|
|
118
|
+
} # XXX: Perhaps better to create dict instead of list and key by name.
|
|
119
|
+
|
|
120
|
+
# Bump this when the data format changes.
|
|
121
|
+
data_version = 0
|
|
122
|
+
|
|
123
|
+
def get_objects(self) -> Iterable[tuple[str, str, str, str, str, int]]:
|
|
124
|
+
for typ, objs in self.data.items():
|
|
125
|
+
if not isinstance(typ, RustItemType):
|
|
126
|
+
continue
|
|
127
|
+
for obj in objs:
|
|
128
|
+
yield (
|
|
129
|
+
obj.name,
|
|
130
|
+
obj.dispname,
|
|
131
|
+
obj.type_.value,
|
|
132
|
+
obj.docname,
|
|
133
|
+
obj.anchor,
|
|
134
|
+
obj.priority,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def clear_doc(self, docname: str) -> None:
|
|
138
|
+
for typ, objs in self.data.items():
|
|
139
|
+
if isinstance(typ, RustItemType):
|
|
140
|
+
self.data[typ][:] = [o for o in objs if o.docname != docname]
|
|
141
|
+
|
|
142
|
+
def _find_match(self, target: str, typ: str | None = None) -> Optional[RustItem]:
|
|
143
|
+
search_types = [RustItemType.from_str(typ)] if typ else self.data.keys()
|
|
144
|
+
matches = set()
|
|
145
|
+
for search_type in search_types:
|
|
146
|
+
matches.update(o for o in self.data[search_type] if o.name == target)
|
|
147
|
+
return list(matches)[0] if matches else None
|
|
148
|
+
|
|
149
|
+
def resolve_xref(
|
|
150
|
+
self,
|
|
151
|
+
env: BuildEnvironment,
|
|
152
|
+
fromdocname: str,
|
|
153
|
+
builder: Builder,
|
|
154
|
+
typ: str,
|
|
155
|
+
target: str,
|
|
156
|
+
node: pending_xref,
|
|
157
|
+
contnode: Element,
|
|
158
|
+
) -> Element | None:
|
|
159
|
+
# pylint:disable=too-many-arguments
|
|
160
|
+
match = self._find_match(target, typ)
|
|
161
|
+
return (
|
|
162
|
+
make_refnode(
|
|
163
|
+
builder,
|
|
164
|
+
fromdocname,
|
|
165
|
+
match.docname,
|
|
166
|
+
(
|
|
167
|
+
match.name.replace("::", "-")
|
|
168
|
+
if match.type_ not in (RustItemType.MODULE, RustItemType.CRATE)
|
|
169
|
+
else None
|
|
170
|
+
),
|
|
171
|
+
[contnode],
|
|
172
|
+
match.name,
|
|
173
|
+
)
|
|
174
|
+
if match
|
|
175
|
+
else None
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def resolve_any_xref(
|
|
179
|
+
self,
|
|
180
|
+
env: BuildEnvironment,
|
|
181
|
+
fromdocname: str,
|
|
182
|
+
builder: Builder,
|
|
183
|
+
target: str,
|
|
184
|
+
node: pending_xref,
|
|
185
|
+
contnode: Element,
|
|
186
|
+
) -> list[tuple[str, Element]]:
|
|
187
|
+
# pylint:disable=too-many-arguments
|
|
188
|
+
match = self._find_match(target)
|
|
189
|
+
return (
|
|
190
|
+
make_refnode(
|
|
191
|
+
builder,
|
|
192
|
+
fromdocname,
|
|
193
|
+
match.docname,
|
|
194
|
+
(
|
|
195
|
+
match.name.replace("::", "-")
|
|
196
|
+
if match.type_ not in (RustItemType.MODULE, RustItemType.CRATE)
|
|
197
|
+
else None
|
|
198
|
+
),
|
|
199
|
+
[contnode],
|
|
200
|
+
match.name,
|
|
201
|
+
)
|
|
202
|
+
if match
|
|
203
|
+
else None
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def merge_domaindata(self, docnames: list[str], otherdata: dict) -> None:
|
|
207
|
+
otherdata: dict[RustItemType, list[RustItem]]
|
|
208
|
+
for typ, objs in otherdata.items():
|
|
209
|
+
self.data[typ].extend(o for o in objs if o.docname in docnames)
|