Skip to content

Commit f821ae6

Browse files
committed
Add MyST parsing
1 parent c0a3a2f commit f821ae6

File tree

18 files changed

+685
-387
lines changed

18 files changed

+685
-387
lines changed

crates/analyzer/src/analyze/crate_.rs

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn analyze_crate(path: &str) -> Result<AnalysisResult> {
7373

7474
// read the top-level module
7575
let content = std::fs::read_to_string(&root_file)?;
76-
let (module, structs, enums) = Module::parse(&crate_.name, &content).context(format!(
76+
let (module, structs, enums) = Module::parse(&[&crate_.name], &content).context(format!(
7777
"Error parsing module {}",
7878
root_file.to_string_lossy()
7979
))?;
@@ -85,7 +85,7 @@ pub fn analyze_crate(path: &str) -> Result<AnalysisResult> {
8585
(
8686
root_file.parent().unwrap().to_path_buf(),
8787
s.to_string(),
88-
crate_.name.clone(),
88+
vec![crate_.name.clone()],
8989
)
9090
})
9191
.collect::<Vec<_>>();
@@ -94,7 +94,7 @@ pub fn analyze_crate(path: &str) -> Result<AnalysisResult> {
9494

9595
// recursively find/read the public sub-modules
9696
let mut read_modules = vec![];
97-
while let Some((parent_dir, module_name, parent_ident)) = modules_to_read.pop() {
97+
while let Some((parent_dir, module_name, parent)) = modules_to_read.pop() {
9898
let (module_path, submodule_dir) =
9999
if parent_dir.join(&module_name).with_extension("rs").exists() {
100100
(
@@ -117,16 +117,20 @@ pub fn analyze_crate(path: &str) -> Result<AnalysisResult> {
117117
read_modules.push(module_path.clone());
118118

119119
let content = std::fs::read_to_string(&module_path)?;
120-
let path_name = format!("{}::{}", parent_ident, module_name);
121-
let (module, structs, enums) = Module::parse(&path_name, &content).context(format!(
120+
let path: Vec<String> = [&parent[..], &[module_name]].concat();
121+
let (module, structs, enums) = Module::parse(
122+
&path.iter().map(|s| s.as_str()).collect::<Vec<&str>>(),
123+
&content,
124+
)
125+
.context(format!(
122126
"Error parsing module {}",
123127
module_path.to_string_lossy()
124128
))?;
125129
modules_to_read.extend(
126130
module
127131
.declarations
128132
.iter()
129-
.map(|s| (submodule_dir.clone(), s.to_string(), path_name.clone()))
133+
.map(|s| (submodule_dir.clone(), s.to_string(), path.clone()))
130134
.collect::<Vec<_>>(),
131135
);
132136
result_.modules.push(module);
@@ -256,30 +260,49 @@ mod tests {
256260

257261
assert_yaml_snapshot!(crate_, @r###"
258262
---
259-
crates:
260-
- name: my_crate
261-
version: 0.1.0
262-
docstring: The crate docstring
263+
crate_:
264+
name: my_crate
265+
version: 0.1.0
266+
docstring: The crate docstring
263267
modules:
264-
- name: "my_crate::my_module"
268+
- path:
269+
- my_crate
270+
- my_module
265271
docstring: The module docstring
266272
declarations:
267273
- my_submodule
268-
- name: "my_crate::my_module::my_submodule"
274+
- path:
275+
- my_crate
276+
- my_module
277+
- my_submodule
269278
docstring: The sub-module docstring
270279
declarations: []
271280
structs:
272-
- name: "my_crate::my_module::DummyStruct1"
281+
- path:
282+
- my_crate
283+
- my_module
284+
- DummyStruct1
273285
docstring: The struct1 docstring
274286
fields: []
275-
- name: "my_crate::my_module::my_submodule::DummyStruct2"
287+
- path:
288+
- my_crate
289+
- my_module
290+
- my_submodule
291+
- DummyStruct2
276292
docstring: The struct2 docstring
277293
fields: []
278294
enums:
279-
- name: "my_crate::my_module::DummyEnum1"
295+
- path:
296+
- my_crate
297+
- my_module
298+
- DummyEnum1
280299
docstring: The enum1 docstring
281300
variants: []
282-
- name: "my_crate::my_module::my_submodule::DummyEnum2"
301+
- path:
302+
- my_crate
303+
- my_module
304+
- my_submodule
305+
- DummyEnum2
283306
docstring: The enum2 docstring
284307
variants: []
285308
"###);

crates/analyzer/src/analyze/enum_.rs

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,30 @@ use super::{docstring_from_attrs, struct_::Field};
1313
/// :tags: rust
1414
/// :status: in-progress
1515
pub struct Enum {
16-
/// The name of the enum
17-
pub name: String,
16+
/// The fully qualified name of the enum
17+
pub path: Vec<String>,
1818
/// The docstring of the enum
1919
pub docstring: String,
2020
pub variants: Vec<Variant>,
2121
}
2222

2323
impl Enum {
24+
/// Fully qualified name of the variant
25+
pub fn path_str(&self) -> String {
26+
self.path.join("::")
27+
}
2428
/// Extract the relevant information from the AST
25-
pub fn parse(parent: &str, ast: &ItemEnum) -> Self {
26-
let name = format!("{}::{}", parent, ast.ident);
29+
pub fn parse(parent: &[&str], ast: &ItemEnum) -> Self {
30+
let name = ast.ident.to_string();
31+
let path: Vec<&str> = parent.iter().copied().chain(Some(name.as_str())).collect();
2732
let docstring = docstring_from_attrs(&ast.attrs);
28-
let variants = ast.variants.iter().map(Variant::parse).collect::<Vec<_>>();
33+
let variants = ast
34+
.variants
35+
.iter()
36+
.map(|v| Variant::parse(&path, v))
37+
.collect::<Vec<_>>();
2938
Self {
30-
name,
39+
path: path.iter().map(|s| s.to_string()).collect(),
3140
docstring,
3241
variants,
3342
}
@@ -37,26 +46,40 @@ impl Enum {
3746
#[derive(Debug, Clone, Serialize, Deserialize)]
3847
/// Representation of a Enum variant
3948
pub struct Variant {
40-
/// The name of the variant
41-
pub name: String,
49+
/// The fully qualified name of the variant
50+
pub path: Vec<String>,
4251
/// The docstring of the variant
4352
pub docstring: String,
4453
pub discriminant: Option<String>, // TODO shouldn't just be a string
4554
pub fields: Vec<Field>,
4655
}
4756

4857
impl Variant {
58+
/// Fully qualified name of the variant
59+
pub fn name(&self) -> String {
60+
self.path.join("::")
61+
}
4962
/// Extract the relevant information from the AST
50-
pub fn parse(ast: &syn::Variant) -> Self {
63+
pub fn parse(parent: &[&str], ast: &syn::Variant) -> Self {
5164
let name = ast.ident.to_string();
65+
let path = parent
66+
.iter()
67+
.copied()
68+
.chain(Some(name.as_str()))
69+
.collect::<Vec<&str>>();
5270
let docstring = docstring_from_attrs(&ast.attrs);
5371
let discriminant = ast
5472
.discriminant
5573
.as_ref()
5674
.map(|(_, e)| quote! {#e}.to_string());
57-
let fields = ast.fields.iter().map(Field::parse).collect::<Vec<_>>();
75+
let fields = ast
76+
.fields
77+
.iter()
78+
.enumerate()
79+
.map(|(i, f)| Field::parse(&path, i, f))
80+
.collect::<Vec<_>>();
5881
Self {
59-
name,
82+
path: path.iter().map(|s| s.to_string()).collect(),
6083
docstring,
6184
discriminant,
6285
fields,
@@ -89,33 +112,55 @@ mod tests {
89112
},
90113
}
91114
};
92-
let enum_ = Enum::parse("crate", &ast);
115+
let enum_ = Enum::parse(&["crate"], &ast);
93116
assert_yaml_snapshot!(enum_, @r###"
94117
---
95-
name: "crate::MyEnum"
118+
path:
119+
- crate
120+
- MyEnum
96121
docstring: "Multi-line\ndocstring"
97122
variants:
98-
- name: MyVariant1
123+
- path:
124+
- crate
125+
- MyEnum
126+
- MyVariant1
99127
docstring: variant without fields
100128
discriminant: ~
101129
fields: []
102-
- name: MyVariant2
130+
- path:
131+
- crate
132+
- MyEnum
133+
- MyVariant2
103134
docstring: variant with discriminant
104135
discriminant: "1"
105136
fields: []
106-
- name: MyVariant3
137+
- path:
138+
- crate
139+
- MyEnum
140+
- MyVariant3
107141
docstring: variant with unnamed fields
108142
discriminant: ~
109143
fields:
110-
- name: ~
144+
- path:
145+
- crate
146+
- MyEnum
147+
- MyVariant3
148+
- "0"
111149
docstring: ""
112150
type_:
113151
- Path: u8
114-
- name: MyVariant3
152+
- path:
153+
- crate
154+
- MyEnum
155+
- MyVariant3
115156
docstring: variant with named fields
116157
discriminant: ~
117158
fields:
118-
- name: field
159+
- path:
160+
- crate
161+
- MyEnum
162+
- MyVariant3
163+
- field
119164
docstring: field docstring
120165
type_:
121166
- Path: u8

crates/analyzer/src/analyze/module.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,23 @@ use super::{docstring_from_attrs, enum_::Enum, struct_::Struct};
1313
/// :tags: rust
1414
/// :status: in-progress
1515
pub struct Module {
16-
pub name: String,
16+
/// The fully qualified name of the module
17+
pub path: Vec<String>,
1718
pub docstring: String,
1819
/// The public declarations in the module
1920
pub declarations: Vec<String>,
2021
}
2122

2223
impl Module {
24+
/// Fully qualified name of the variant
25+
pub fn path_str(&self) -> String {
26+
self.path.join("::")
27+
}
2328
/// Extract the relevant information from the AST
24-
pub fn parse(name: &str, content: &str) -> Result<(Self, Vec<Struct>, Vec<Enum>)> {
29+
pub fn parse(path: &[&str], content: &str) -> Result<(Self, Vec<Struct>, Vec<Enum>)> {
2530
let syntax = parse_file(content)?;
26-
2731
let mut mod_ = Self {
28-
name: name.to_string(),
32+
path: path.iter().map(|s| s.to_string()).collect(),
2933
docstring: docstring_from_attrs(&syntax.attrs),
3034
declarations: vec![],
3135
};
@@ -44,13 +48,13 @@ impl Module {
4448
}
4549
syn::Item::Struct(struct_item) => {
4650
if let syn::Visibility::Public(_) = struct_item.vis {
47-
let struct_ = Struct::parse(name, struct_item);
51+
let struct_ = Struct::parse(path, struct_item);
4852
structs.push(struct_);
4953
}
5054
}
5155
syn::Item::Enum(enum_item) => {
5256
if let syn::Visibility::Public(_) = enum_item.vis {
53-
let enum_ = Enum::parse(name, enum_item);
57+
let enum_ = Enum::parse(path, enum_item);
5458
enums.push(enum_);
5559
}
5660
}
@@ -81,17 +85,23 @@ pub enum MyEnum {
8185
MyVariant1,
8286
}
8387
"###;
84-
let mod_ = Module::parse("test", content).unwrap();
88+
let mod_ = Module::parse(&["test"], content).unwrap();
8589
assert_yaml_snapshot!(mod_, @r###"
8690
---
87-
- name: test
91+
- path:
92+
- test
8893
docstring: "Multi-line\ndocstring"
8994
declarations: []
9095
- []
91-
- - name: "test::MyEnum"
96+
- - path:
97+
- test
98+
- MyEnum
9299
docstring: ""
93100
variants:
94-
- name: MyVariant1
101+
- path:
102+
- test
103+
- MyEnum
104+
- MyVariant1
95105
docstring: ""
96106
discriminant: ~
97107
fields: []

0 commit comments

Comments
 (0)