summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/generator/pandoc.rs64
-rw-r--r--src/parser/clang/entities.rs61
-rw-r--r--src/types.rs4
3 files changed, 72 insertions, 57 deletions
diff --git a/src/generator/pandoc.rs b/src/generator/pandoc.rs
index 035acab..fe2e2f0 100644
--- a/src/generator/pandoc.rs
+++ b/src/generator/pandoc.rs
@@ -35,13 +35,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
35 35
36 let entity_kind = entity.kind; 36 let entity_kind = entity.kind;
37 for (children_kind, children) in entity.children { 37 for (children_kind, children) in entity.children {
38 if config 38 if is_inline(config, entity.language, &entity_kind, &children_kind) {
39 .inlines
40 .get(&entity.language)
41 .and_then(|lang_inlines| lang_inlines.get(&entity_kind))
42 .map(|children_inlines| children_inlines.contains(&children_kind))
43 == Some(true)
44 {
45 inline_children.insert(children_kind, children); 39 inline_children.insert(children_kind, children);
46 } else { 40 } else {
47 // By default, do not inline 41 // By default, do not inline
@@ -50,7 +44,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
50 } 44 }
51 45
52 for (section_name, children) in &separate_children { 46 for (section_name, children) in &separate_children {
53 if let Some(members_list) = member_list(children) { 47 if let Some(members_list) = member_list(children, LinkType::External) {
54 content.push(Block::Header( 48 content.push(Block::Header(
55 2, 49 2,
56 Attr::null(), 50 Attr::null(),
@@ -61,10 +55,10 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
61 } 55 }
62 } 56 }
63 57
64 let mut embedded_documentation = Vec::new(); 58 let mut inline_documentation = Vec::new();
65 59
66 for (section_name, children) in inline_children { 60 for (section_name, children) in inline_children {
67 if let Some(members_list) = member_list(&children) { 61 if let Some(members_list) = member_list(&children, LinkType::Anchor) {
68 content.push(Block::Header( 62 content.push(Block::Header(
69 2, 63 2,
70 Attr::null(), 64 Attr::null(),
@@ -73,20 +67,20 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
73 67
74 content.push(members_list); 68 content.push(members_list);
75 69
76 embedded_documentation.push(Block::Header( 70 inline_documentation.push(Block::Header(
77 2, 71 2,
78 Attr::null(), 72 Attr::null(),
79 vec![Inline::Str(section_name.0 + " Documentation")], 73 vec![Inline::Str(section_name.0 + " Documentation")],
80 )); 74 ));
81 75
82 for (_id, child) in children { 76 for (id, child) in children {
83 embedded_documentation.push(Block::Header( 77 inline_documentation.push(Block::Header(
84 3, 78 3,
85 Attr::null(), 79 Attr(id.0, vec![], vec![]),
86 vec![Inline::Code(Attr::null(), child.name)], 80 vec![Inline::Code(Attr::null(), child.name)],
87 )); 81 ));
88 82
89 embedded_documentation.push(Block::Div( 83 inline_documentation.push(Block::Div(
90 Attr(String::new(), vec![String::from("doc")], vec![]), 84 Attr(String::new(), vec![String::from("doc")], vec![]),
91 vec![raw_markdown(child.documentation)], 85 vec![raw_markdown(child.documentation)],
92 )); 86 ));
@@ -94,7 +88,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
94 } 88 }
95 } 89 }
96 90
97 content.append(&mut embedded_documentation); 91 content.append(&mut inline_documentation);
98 92
99 let leftovers = separate_children 93 let leftovers = separate_children
100 .into_iter() 94 .into_iter()
@@ -105,11 +99,25 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<
105 (Pandoc(meta, content), leftovers) 99 (Pandoc(meta, content), leftovers)
106} 100}
107 101
102fn is_inline(
103 config: &Config,
104 language: Language,
105 parent_kind: &EntityKind,
106 children_kind: &ChildrenKind,
107) -> bool {
108 config
109 .inlines
110 .get(&language)
111 .and_then(|lang_inlines| lang_inlines.get(parent_kind))
112 .map(|children_inlines| children_inlines.contains(children_kind))
113 == Some(true)
114}
115
108fn str_block(content: String) -> Block { 116fn str_block(content: String) -> Block {
109 Block::Plain(vec![Inline::Str(content)]) 117 Block::Plain(vec![Inline::Str(content)])
110} 118}
111 119
112fn entity_link(id: &EntityId, name: String) -> Inline { 120fn entity_link(id: &EntityId, name: String, link_type: LinkType) -> Inline {
113 use pandoc_types::definition::Target; 121 use pandoc_types::definition::Target;
114 use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; 122 use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
115 123
@@ -131,9 +139,12 @@ fn entity_link(id: &EntityId, name: String) -> Inline {
131 Attr::null(), 139 Attr::null(),
132 vec![Inline::Code(Attr::null(), name)], 140 vec![Inline::Code(Attr::null(), name)],
133 Target( 141 Target(
134 once("./") 142 once(match link_type {
135 .chain(utf8_percent_encode(&id.0, FRAGMENT)) 143 LinkType::External => "./",
136 .collect(), 144 LinkType::Anchor => "#",
145 })
146 .chain(utf8_percent_encode(&id.0, FRAGMENT))
147 .collect(),
137 String::new(), 148 String::new(),
138 ), 149 ),
139 ) 150 )
@@ -144,12 +155,21 @@ fn raw_markdown(text: String) -> Block {
144 Block::RawBlock(Format(String::from("markdown")), text) 155 Block::RawBlock(Format(String::from("markdown")), text)
145} 156}
146 157
147fn member_list<'a>(members: impl IntoIterator<Item = (&'a EntityId, &'a Entity)>) -> Option<Block> { 158#[derive(Debug, Clone, Copy)]
159enum LinkType {
160 Anchor,
161 External,
162}
163
164fn member_list<'a>(
165 members: impl IntoIterator<Item = (&'a EntityId, &'a Entity)>,
166 link_type: LinkType,
167) -> Option<Block> {
148 let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members 168 let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members
149 .into_iter() 169 .into_iter()
150 .map(|(id, entity)| { 170 .map(|(id, entity)| {
151 ( 171 (
152 vec![entity_link(id, entity.name.clone())], 172 vec![entity_link(id, entity.name.clone(), link_type)],
153 vec![vec![str_block(entity.brief_description.clone())]], 173 vec![vec![str_block(entity.brief_description.clone())]],
154 ) 174 )
155 }) 175 })
diff --git a/src/parser/clang/entities.rs b/src/parser/clang/entities.rs
index 41fe061..cbc17b7 100644
--- a/src/parser/clang/entities.rs
+++ b/src/parser/clang/entities.rs
@@ -1,4 +1,4 @@
1use crate::types::*; 1use crate::types::{self, *};
2 2
3use clang::{EntityKind, Usr}; 3use clang::{EntityKind, Usr};
4use thiserror::Error; 4use thiserror::Error;
@@ -169,55 +169,48 @@ where
169 } 169 }
170} 170}
171 171
172fn entity_id(usr: Usr) -> EntityId {
173 // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum
174 // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related.
175 //
176 // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581>
177 EntityId(usr.0.replace("@", "::").replace("#", ".").replace("$", "-"))
178}
179
180fn append_children<T: ClangEntity>(
181 acc: &mut types::Children,
182 to_insert: BTreeMap<Usr, Described<T>>,
183) {
184 for (usr, child) in to_insert {
185 acc.entry(ChildrenKind(String::from(
186 child.entity.kind().to_str_plural(),
187 )))
188 .or_default()
189 .insert(entity_id(usr), child.into());
190 }
191}
192
172impl<T: ClangEntity> From<Described<T>> for Entity { 193impl<T: ClangEntity> From<Described<T>> for Entity {
173 fn from(entity: Described<T>) -> Self { 194 fn from(entity: Described<T>) -> Self {
174 let mut children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>> = BTreeMap::new(); 195 let mut children: types::Children = BTreeMap::new();
175 196
176 let kind = EntityKind(String::from(entity.entity.kind().to_str_singular())); 197 let kind = EntityKind(String::from(entity.entity.kind().to_str_singular()));
177 let clang_children = entity.entity.into_children(); 198 let clang_children = entity.entity.into_children();
178 199
179 if let Some(namespaces) = clang_children.namespaces { 200 if let Some(namespaces) = clang_children.namespaces {
180 for (usr, namespace) in namespaces { 201 append_children(&mut children, namespaces);
181 children
182 .entry(ChildrenKind(String::from(
183 namespace.entity.kind().to_str_plural(),
184 )))
185 .or_default()
186 .insert(EntityId(usr.0), namespace.into());
187 }
188 } 202 }
189 203
190 if let Some(variables) = clang_children.variables { 204 if let Some(variables) = clang_children.variables {
191 for (usr, variable) in variables { 205 append_children(&mut children, variables);
192 children
193 .entry(ChildrenKind(String::from(
194 variable.entity.kind().to_str_plural(),
195 )))
196 .or_default()
197 .insert(EntityId(usr.0), variable.into());
198 }
199 } 206 }
200 207
201 if let Some(structs) = clang_children.structs { 208 if let Some(structs) = clang_children.structs {
202 for (usr, r#struct) in structs { 209 append_children(&mut children, structs);
203 children
204 .entry(ChildrenKind(String::from(
205 r#struct.entity.kind().to_str_plural(),
206 )))
207 .or_default()
208 .insert(EntityId(usr.0), r#struct.into());
209 }
210 } 210 }
211 211
212 if let Some(functions) = clang_children.functions { 212 if let Some(functions) = clang_children.functions {
213 for (usr, function) in functions { 213 append_children(&mut children, functions);
214 children
215 .entry(ChildrenKind(String::from(
216 function.entity.kind().to_str_plural(),
217 )))
218 .or_default()
219 .insert(EntityId(usr.0), function.into());
220 }
221 } 214 }
222 215
223 Entity { 216 Entity {
diff --git a/src/types.rs b/src/types.rs
index f378f8b..d192ab5 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -18,9 +18,11 @@ pub struct Entity {
18 pub kind: EntityKind, 18 pub kind: EntityKind,
19 pub brief_description: String, 19 pub brief_description: String,
20 pub documentation: String, 20 pub documentation: String,
21 pub children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>>, 21 pub children: Children,
22} 22}
23 23
24pub type Children = BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>>;
25
24// TODO: use newtype for entity kind, entity ID 26// TODO: use newtype for entity kind, entity ID
25 27
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]