Skip to content

Commit bc7a671

Browse files
committed
Generate doc comments for struct fields
Closes #3
1 parent 29a99ec commit bc7a671

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

codegen/main.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,9 @@ impl PythonBindType {
8686

8787
let mut docs = Vec::new();
8888

89-
let binding = contents[..struct_def_pos].to_string();
90-
for line in binding.lines().rev() {
89+
for line in contents[..struct_def_pos].lines().rev() {
9190
if line.starts_with("///") {
92-
docs.push(line.trim().trim_start_matches("///").trim());
91+
docs.push(line.trim_start_matches("///").trim());
9392
} else {
9493
break;
9594
}

codegen/pyi.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> {
125125
if variable_type == rust_type {
126126
python_types.push(python_type.to_string());
127127
write_fmt!(file, " {variable_name}: {python_type}");
128+
129+
if let Some(docs) = variable_info.doc_str.as_ref() {
130+
write_str!(file, " \"\"\"");
131+
132+
for line in docs {
133+
write_fmt!(file, " {line}");
134+
}
135+
136+
write_str!(file, " \"\"\"");
137+
}
138+
128139
continue 'outer;
129140
}
130141
}
@@ -227,6 +238,16 @@ pub fn generator(type_data: &[PythonBindType]) -> io::Result<()> {
227238
write_fmt!(file, " {variable_name}: {type_name}");
228239
}
229240
}
241+
242+
if let Some(docs) = variable_info.doc_str.as_ref() {
243+
write_str!(file, " \"\"\"");
244+
245+
for line in docs {
246+
write_fmt!(file, " {line}");
247+
}
248+
249+
write_str!(file, " \"\"\"");
250+
}
230251
}
231252

232253
if !gen.types.is_empty() {

codegen/structs.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub struct CustomType {
4242
pub frozen_needs_py: bool,
4343
pub is_special_base: Option<SpecialBase>,
4444
pub snake_case_name: String,
45+
pub doc_str: Option<Vec<String>>,
4546
}
4647

4748
pub struct StructBindGenerator {
@@ -153,10 +154,38 @@ impl StructBindGenerator {
153154
let raw_types: Vec<_> = struct_definition
154155
.split('\n')
155156
.filter_map(|s| {
156-
s.trim_start_matches(' ')
157+
let (name, raw_type) = s
158+
.trim_start_matches(' ')
157159
.trim_start_matches("pub ")
158160
.trim_end_matches(',')
159-
.split_once(": ")
161+
.split_once(": ")?;
162+
163+
let var_def = format!("pub fn {name}(");
164+
let var_def_pos = contents.find(&var_def).unwrap();
165+
166+
let mut docs = Vec::new();
167+
168+
for line in contents[..var_def_pos].lines().rev().skip(2) {
169+
let line = line.trim();
170+
if line.starts_with("///") {
171+
docs.push(line.trim_start_matches("///").trim());
172+
} else {
173+
break;
174+
}
175+
}
176+
177+
let struct_doc_str = if docs.is_empty() {
178+
None
179+
} else {
180+
Some(
181+
docs.into_iter()
182+
.map(|s| s.to_string())
183+
.rev()
184+
.collect::<Vec<_>>(),
185+
)
186+
};
187+
188+
Some((name, raw_type, struct_doc_str))
160189
})
161190
.collect();
162191

@@ -165,10 +194,10 @@ impl StructBindGenerator {
165194
Some(custom_types)
166195
}
167196

168-
fn raw_types_to_custom(raw_types: Vec<(&str, &str)>) -> Vec<CustomType> {
197+
fn raw_types_to_custom(raw_types: Vec<(&str, &str, Option<Vec<String>>)>) -> Vec<CustomType> {
169198
raw_types
170199
.into_iter()
171-
.map(|(name, raw_type)| {
200+
.map(|(name, raw_type, doc_str)| {
172201
let (rust_type, inner_type) = if raw_type.starts_with("Vec<") {
173202
if raw_type == "Vec<u8>" {
174203
(RustType::Vec(InnerVecType::U8), None)
@@ -266,6 +295,7 @@ impl StructBindGenerator {
266295
frozen_needs_py,
267296
is_special_base,
268297
snake_case_name: String::new(),
298+
doc_str,
269299
}
270300
})
271301
.collect()

0 commit comments

Comments
 (0)