Skip to content

Commit 3caae4e

Browse files
committed
Add signatures and references
1 parent cb5d603 commit 3caae4e

File tree

14 files changed

+272
-59
lines changed

14 files changed

+272
-59
lines changed

crates/analyzer/src/analyze/crate_.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub fn analyze_crate(path: &str) -> Result<AnalysisResult> {
138138
}
139139

140140
#[derive(Debug, Clone, Serialize, Deserialize)]
141+
/// Result from a crate analysis
141142
pub struct AnalysisResult {
142143
pub crate_: Crate,
143144
pub modules: Vec<Module>,
@@ -146,6 +147,7 @@ pub struct AnalysisResult {
146147
}
147148

148149
#[derive(Debug, Clone, Serialize, Deserialize)]
150+
/// Representation of a crate
149151
pub struct Crate {
150152
pub name: String,
151153
pub version: String,

crates/analyzer/src/analyze/enum_.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Analyze enums
12
use quote::quote;
23
use serde::{Deserialize, Serialize};
34
use syn::ItemEnum;

crates/analyzer/src/analyze/module.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Analyze modules
12
use anyhow::Result;
23
use serde::{Deserialize, Serialize};
34
use syn::parse_file;

crates/analyzer/src/analyze/struct_.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Analyze structs
12
use serde::{Deserialize, Serialize};
23
use syn::{ItemStruct, Visibility};
34

crates/analyzer/src/analyze/type_.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
//! Analyze types
12
use quote::quote;
23
use serde::{Deserialize, Serialize};
34

45
#[derive(Debug, Clone, Serialize, Deserialize)]
6+
/// A segment of a type signature
7+
///
8+
/// Types are split into segments to allow for identification of referenceable elements
59
pub enum TypeSegment {
610
String(String),
711
Path(String),

crates/py_binding/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ pub struct Variant {
488488
pub name: String,
489489
#[pyo3(get)]
490490
pub docstring: String,
491+
// TODO discriminant
492+
#[pyo3(get)]
493+
pub fields: Vec<Field>,
491494
}
492495

493496
#[pymethods]
@@ -502,6 +505,7 @@ impl From<analyze::Variant> for Variant {
502505
Variant {
503506
name: var.name,
504507
docstring: var.docstring,
508+
fields: var.fields.into_iter().map(Field::from).collect(),
505509
}
506510
}
507511
}

python/sphinx_rust/directives/_core.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from typing import TYPE_CHECKING
22

33
from docutils import nodes, utils
4+
from sphinx import addnodes
45
from sphinx.util.docutils import LoggingReporter, SphinxDirective
56
from sphinx.util.logging import getLogger
67

78
if TYPE_CHECKING:
89
from sphinx.environment import BuildEnvironment
910

11+
from sphinx_rust.domain import ObjType, RustDomain
12+
1013

1114
LOGGER = getLogger(__name__)
1215

@@ -24,6 +27,13 @@ class RustAutoDirective(SphinxDirective):
2427
def doc(self) -> nodes.document:
2528
return self.state.document # type: ignore[no-any-return]
2629

30+
@property
31+
def rust_domain(self) -> "RustDomain":
32+
# avoid circular import
33+
from sphinx_rust.domain import RustDomain # noqa: PLC0415
34+
35+
return self.env.domains[RustDomain.name] # type: ignore[return-value]
36+
2737
@property
2838
def cache_path(self) -> str:
2939
return str(self.env.rust_cache_path) # type: ignore[attr-defined]
@@ -92,3 +102,22 @@ def parse_docstring(
92102
# TODO merge document metadata with parent document, e.g. targets etc?
93103
# or docutils.Include actually runs the transforms on the included document, before returning its children
94104
return document.children
105+
106+
107+
def create_xref(
108+
docname: str, ident: str, objtype: "ObjType", *, warn_dangling: bool = False
109+
) -> addnodes.pending_xref:
110+
"""Create a cross-reference node."""
111+
options = {
112+
"refdoc": docname,
113+
"refdomain": "rust",
114+
"reftype": objtype,
115+
"refexplicit": True,
116+
"refwarn": warn_dangling,
117+
"reftarget": ident,
118+
}
119+
ref = addnodes.pending_xref(ident, **options)
120+
name = ident.split("::")[-1]
121+
ref += nodes.literal(name, name)
122+
123+
return ref

python/sphinx_rust/directives/crate.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
RustAutoDirective,
1010
create_field_list,
1111
create_summary_table,
12+
create_xref,
1213
parse_docstring,
1314
)
1415

1516
if TYPE_CHECKING:
17+
from sphinx_rust.domain import ObjType
1618
from sphinx_rust.sphinx_rust import Enum, Module, Struct
1719

1820
LOGGER = getLogger(__name__)
@@ -61,23 +63,29 @@ def run(self) -> list[nodes.Node]:
6163
root += parse_docstring(self.env, self.doc, crate.docstring)
6264

6365
items: list[Module | Struct | Enum]
64-
for name, items in [ # type: ignore[assignment]
65-
("Modules", load_modules(self.cache_path, qualifier + "::")),
66-
("Structs", load_structs(self.cache_path, qualifier + "::")),
67-
("Enums", load_enums(self.cache_path, qualifier + "::")),
66+
objtype: ObjType
67+
for name, objtype, items in [ # type: ignore[assignment]
68+
("Modules", "module", load_modules(self.cache_path, qualifier + "::")),
69+
("Structs", "struct", load_structs(self.cache_path, qualifier + "::")),
70+
("Enums", "enum", load_enums(self.cache_path, qualifier + "::")),
6871
]:
6972
if items:
7073
section = self.create_section(name)
7174
root += section
7275
rows = [
7376
(
74-
# TODO should be references not just text
75-
[nodes.Text(item.name)],
77+
[
78+
nodes.paragraph(
79+
"",
80+
"",
81+
create_xref(self.env.docname, item.name, objtype),
82+
)
83+
],
7684
parse_docstring(
7785
self.env,
7886
self.doc,
7987
# TODO the first line should only be a paragraph
80-
item.docstring.splitlines()[0] if item.docstring else "\-",
88+
item.docstring.splitlines()[0] if item.docstring else r"\-",
8189
),
8290
)
8391
for item in sorted(items, key=lambda m: m.name)

python/sphinx_rust/directives/enum.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from typing import TYPE_CHECKING
22

33
from docutils import nodes
4+
from sphinx import addnodes
45
from sphinx.util.logging import getLogger
6+
from sphinx.util.nodes import make_id
57

68
from sphinx_rust.sphinx_rust import load_enum
79

@@ -54,14 +56,26 @@ def run(self) -> list[nodes.Node]:
5456

5557
root = nodes.Element()
5658

57-
# TODO signature block
59+
desc = addnodes.desc()
60+
root += desc
61+
signature = addnodes.desc_signature(
62+
enum.name, f'pub enum {enum.name.split("::")[-1]} {{}}'
63+
)
64+
desc += signature
65+
# TODO add variants to signature
66+
# desc += addnodes.desc_content("", nodes.paragraph("", ))
67+
node_id = make_id(self.env, self.doc, "", enum.name)
68+
signature["ids"].append(node_id)
69+
self.doc.note_explicit_target(signature)
70+
self.rust_domain.note_object(enum.name, "enum", node_id, signature)
5871

5972
if enum.docstring:
6073
root += parse_docstring(self.env, self.doc, enum.docstring)
6174

6275
if enum.variants:
6376
section = self.create_section("Variants")
6477
root += section
78+
# TODO document variant fields
6579
section += create_field_list(
6680
[
6781
(

python/sphinx_rust/directives/module.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
from typing import TYPE_CHECKING
22

33
from docutils import nodes
4+
from sphinx import addnodes
45
from sphinx.util.logging import getLogger
6+
from sphinx.util.nodes import make_id
57

68
from sphinx_rust.sphinx_rust import load_enums, load_module, load_modules, load_structs
79

810
from ._core import (
911
RustAutoDirective,
1012
create_summary_table,
13+
create_xref,
1114
parse_docstring,
1215
)
1316

1417
if TYPE_CHECKING:
18+
from sphinx_rust.domain import ObjType
1519
from sphinx_rust.sphinx_rust import Enum, Module, Struct
1620

1721
LOGGER = getLogger(__name__)
@@ -54,27 +58,45 @@ def run(self) -> list[nodes.Node]:
5458

5559
root = nodes.Element()
5660

61+
desc = addnodes.desc()
62+
root += desc
63+
signature = addnodes.desc_signature(
64+
module.name, f'pub mod {module.name.split("::")[-1]};'
65+
)
66+
desc += signature
67+
# desc += addnodes.desc_content("", nodes.paragraph("", ))
68+
node_id = make_id(self.env, self.doc, "", module.name)
69+
signature["ids"].append(node_id)
70+
self.doc.note_explicit_target(signature)
71+
self.rust_domain.note_object(module.name, "module", node_id, signature)
72+
5773
if module.docstring:
5874
root += parse_docstring(self.env, self.doc, module.docstring)
5975

6076
items: list[Module | Struct | Enum]
61-
for name, items in [ # type: ignore[assignment]
62-
("Modules", load_modules(self.cache_path, qualifier + "::")),
63-
("Structs", load_structs(self.cache_path, qualifier + "::")),
64-
("Enums", load_enums(self.cache_path, qualifier + "::")),
77+
objtype: ObjType
78+
for name, objtype, items in [ # type: ignore[assignment]
79+
("Modules", "module", load_modules(self.cache_path, qualifier + "::")),
80+
("Structs", "struct", load_structs(self.cache_path, qualifier + "::")),
81+
("Enums", "enum", load_enums(self.cache_path, qualifier + "::")),
6582
]:
6683
if items:
6784
section = self.create_section(name)
6885
root += section
6986
rows = [
7087
(
71-
# TODO should be references not just text
72-
[nodes.Text(item.name)],
88+
[
89+
nodes.paragraph(
90+
"",
91+
"",
92+
create_xref(self.env.docname, item.name, objtype),
93+
)
94+
],
7395
parse_docstring(
7496
self.env,
7597
self.doc,
7698
# TODO the first line should only be a paragraph
77-
item.docstring.splitlines()[0] if item.docstring else "\-",
99+
item.docstring.splitlines()[0] if item.docstring else r"\-",
78100
),
79101
)
80102
for item in sorted(items, key=lambda m: m.name)

0 commit comments

Comments
 (0)