intent_render/
markdown.rs1use intent_parser::ast;
7
8use crate::format_type;
9
10pub fn render(file: &ast::File) -> String {
12 let mut out = String::new();
13 out.push_str(&format!("# {}\n\n", file.module.name));
14
15 if let Some(doc) = &file.doc {
16 for line in &doc.lines {
17 out.push_str(line);
18 out.push('\n');
19 }
20 out.push('\n');
21 }
22
23 if !file.imports.is_empty() {
24 out.push_str("**Imports:**\n\n");
25 for use_decl in &file.imports {
26 if let Some(item) = &use_decl.item {
27 out.push_str(&format!("- `{}.{}`\n", use_decl.module_name, item));
28 } else {
29 out.push_str(&format!("- `{}`\n", use_decl.module_name));
30 }
31 }
32 out.push('\n');
33 }
34
35 for item in &file.items {
36 match item {
37 ast::TopLevelItem::Entity(e) => render_entity(&mut out, e),
38 ast::TopLevelItem::Action(a) => render_action(&mut out, a),
39 ast::TopLevelItem::Invariant(i) => render_invariant(&mut out, i),
40 ast::TopLevelItem::EdgeCases(ec) => render_edge_cases(&mut out, ec),
41 ast::TopLevelItem::Test(_) => {} }
43 }
44
45 out
46}
47
48fn render_entity(out: &mut String, entity: &ast::EntityDecl) {
49 out.push_str(&format!("## Entity: {}\n\n", entity.name));
50 if let Some(doc) = &entity.doc {
51 for line in &doc.lines {
52 out.push_str(line);
53 out.push('\n');
54 }
55 out.push('\n');
56 }
57 out.push_str("| Field | Type |\n|-------|------|\n");
58 for field in &entity.fields {
59 out.push_str(&format!(
60 "| `{}` | `{}` |\n",
61 field.name,
62 format_type(&field.ty)
63 ));
64 }
65 out.push('\n');
66}
67
68fn render_action(out: &mut String, action: &ast::ActionDecl) {
69 out.push_str(&format!("## Action: {}\n\n", action.name));
70 if let Some(doc) = &action.doc {
71 for line in &doc.lines {
72 out.push_str(line);
73 out.push('\n');
74 }
75 out.push('\n');
76 }
77 if !action.params.is_empty() {
78 out.push_str("**Parameters:**\n\n");
79 for p in &action.params {
80 out.push_str(&format!("- `{}`: `{}`\n", p.name, format_type(&p.ty)));
81 }
82 out.push('\n');
83 }
84}
85
86fn render_invariant(out: &mut String, inv: &ast::InvariantDecl) {
87 out.push_str(&format!("## Invariant: {}\n\n", inv.name));
88 if let Some(doc) = &inv.doc {
89 for line in &doc.lines {
90 out.push_str(line);
91 out.push('\n');
92 }
93 out.push('\n');
94 }
95}
96
97fn render_edge_cases(out: &mut String, _ec: &ast::EdgeCasesDecl) {
98 out.push_str("## Edge Cases\n\n");
99}