diff options
author | Minijackson <minijackson@riseup.net> | 2019-12-21 12:13:21 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2019-12-21 12:13:21 +0100 |
commit | e773caea8010b87726ea524d31798fb2e43e12f4 (patch) | |
tree | 9034295831afb25f4bfea5a05d9f83d03e69e86c | |
parent | de896baff7e97fac4dde79078c9a2fa1c652576b (diff) | |
download | poseidoc-e773caea8010b87726ea524d31798fb2e43e12f4.tar.gz poseidoc-e773caea8010b87726ea524d31798fb2e43e12f4.zip |
newtype in types, more generator config, parsing -> parser
-rw-r--r-- | src/cli.rs | 7 | ||||
-rw-r--r-- | src/config.rs | 6 | ||||
-rw-r--r-- | src/generator/config.rs | 52 | ||||
-rw-r--r-- | src/generator/mod.rs | 42 | ||||
-rw-r--r-- | src/generator/pandoc.rs | 19 | ||||
-rw-r--r-- | src/main.rs | 9 | ||||
-rw-r--r-- | src/parser/clang/config.rs (renamed from src/parsing/clang/config.rs) | 8 | ||||
-rw-r--r-- | src/parser/clang/entities.rs (renamed from src/parsing/clang/entities.rs) | 129 | ||||
-rw-r--r-- | src/parser/clang/mod.rs (renamed from src/parsing/clang/mod.rs) | 0 | ||||
-rw-r--r-- | src/parser/clang/parsing.rs (renamed from src/parsing/clang/parsing.rs) | 34 | ||||
-rw-r--r-- | src/parser/mod.rs (renamed from src/parsing/mod.rs) | 0 | ||||
-rw-r--r-- | src/types.rs | 70 |
12 files changed, 256 insertions, 120 deletions
@@ -21,11 +21,14 @@ pub(crate) struct Cli { | |||
21 | 21 | ||
22 | #[derive(Debug, Clone, StructOpt)] | 22 | #[derive(Debug, Clone, StructOpt)] |
23 | pub(crate) enum Command { | 23 | pub(crate) enum Command { |
24 | Generate { file: String }, | 24 | Generate { |
25 | file: String, | ||
26 | }, | ||
27 | Inspect, | ||
25 | Config { | 28 | Config { |
26 | #[structopt(subcommand)] | 29 | #[structopt(subcommand)] |
27 | command: ConfigCommand, | 30 | command: ConfigCommand, |
28 | } | 31 | }, |
29 | } | 32 | } |
30 | 33 | ||
31 | #[derive(Debug, Clone, StructOpt)] | 34 | #[derive(Debug, Clone, StructOpt)] |
diff --git a/src/config.rs b/src/config.rs index 72a9ff6..942dfcf 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -2,7 +2,7 @@ use crate::cli::Cli; | |||
2 | use crate::generator::config::{ | 2 | use crate::generator::config::{ |
3 | Config as GeneratorConfig, ProvidedConfig as ProvidedGeneratorConfig, | 3 | Config as GeneratorConfig, ProvidedConfig as ProvidedGeneratorConfig, |
4 | }; | 4 | }; |
5 | use crate::parsing::clang::config::{Config as ClangConfig, ProvidedConfig as ProvidedClangConfig}; | 5 | use crate::parser::clang::config::{Config as ClangConfig, ProvidedConfig as ProvidedClangConfig}; |
6 | 6 | ||
7 | use anyhow::{anyhow, Context, Result}; | 7 | use anyhow::{anyhow, Context, Result}; |
8 | use codemap::CodeMap; | 8 | use codemap::CodeMap; |
@@ -19,8 +19,8 @@ pub(super) const DEFAULT_PROJECT_CONFIGURATION_FILE_NAME: &str = "poseidoc.toml" | |||
19 | #[derive(Debug, Clone, Serialize)] | 19 | #[derive(Debug, Clone, Serialize)] |
20 | pub(crate) struct Config { | 20 | pub(crate) struct Config { |
21 | pub(crate) name: String, | 21 | pub(crate) name: String, |
22 | pub(crate) clang: ClangConfig, | ||
23 | pub(crate) generator: GeneratorConfig, | 22 | pub(crate) generator: GeneratorConfig, |
23 | pub(crate) clang: ClangConfig, | ||
24 | } | 24 | } |
25 | 25 | ||
26 | impl Default for Config { | 26 | impl Default for Config { |
@@ -57,7 +57,7 @@ pub(crate) struct ProvidedConfig { | |||
57 | #[structopt(flatten)] | 57 | #[structopt(flatten)] |
58 | #[serde(default)] | 58 | #[serde(default)] |
59 | pub(crate) clang: ProvidedClangConfig, | 59 | pub(crate) clang: ProvidedClangConfig, |
60 | #[structopt(skip)] | 60 | #[structopt(flatten)] |
61 | #[serde(default)] | 61 | #[serde(default)] |
62 | pub(crate) generator: ProvidedGeneratorConfig, | 62 | pub(crate) generator: ProvidedGeneratorConfig, |
63 | } | 63 | } |
diff --git a/src/generator/config.rs b/src/generator/config.rs index 43fee60..3057fee 100644 --- a/src/generator/config.rs +++ b/src/generator/config.rs | |||
@@ -1,40 +1,58 @@ | |||
1 | use crate::types::*; | ||
2 | |||
1 | use serde_derive::{Deserialize, Serialize}; | 3 | use serde_derive::{Deserialize, Serialize}; |
2 | use structopt::StructOpt; | 4 | use structopt::StructOpt; |
3 | 5 | ||
4 | use std::collections::{HashMap, HashSet}; | 6 | use std::collections::{HashMap, HashSet}; |
5 | 7 | ||
8 | pub(crate) type Inlines = HashMap<Language, HashMap<EntityKind, HashSet<ChildrenKind>>>; | ||
9 | |||
6 | #[derive(Debug, Clone, Serialize)] | 10 | #[derive(Debug, Clone, Serialize)] |
7 | pub(crate) struct Config { | 11 | pub(crate) struct Config { |
12 | pub(super) from: String, | ||
13 | pub(super) to: String, | ||
14 | pub(super) pandoc_filters: Vec<String>, | ||
8 | /// Tells us in which language, which entity types should inline which children entity type in | 15 | /// Tells us in which language, which entity types should inline which children entity type in |
9 | /// their documentation. | 16 | /// their documentation. |
10 | /// | 17 | /// |
11 | /// e.g. in C++, classes should inline their children methods documentation. | 18 | /// e.g. in C++, classes should inline their children methods documentation. |
12 | pub(crate) inlines: HashMap<String, HashMap<String, HashSet<String>>>, | 19 | pub(super) inlines: Inlines, |
13 | } | 20 | } |
14 | 21 | ||
15 | impl Config { | 22 | impl Config { |
16 | pub(crate) fn from_merge(_cli: ProvidedConfig, conf: ProvidedConfig) -> Self { | 23 | pub(crate) fn from_merge(mut cli: ProvidedConfig, mut conf: ProvidedConfig) -> Self { |
24 | conf.pandoc_filters.append(&mut cli.pandoc_filters); | ||
17 | Self { | 25 | Self { |
26 | from: cli | ||
27 | .from | ||
28 | .or(conf.from) | ||
29 | .unwrap_or_else(|| String::from("markdown-raw_tex")), | ||
30 | to: cli.to.or(conf.to).unwrap_or_else(|| String::from("html")), | ||
31 | pandoc_filters: conf.pandoc_filters, | ||
18 | inlines: conf.inlines.unwrap_or_else(default_inlines), | 32 | inlines: conf.inlines.unwrap_or_else(default_inlines), |
19 | } | 33 | } |
20 | } | 34 | } |
21 | } | 35 | } |
22 | 36 | ||
23 | fn default_inlines() -> HashMap<String, HashMap<String, HashSet<String>>> { | 37 | fn default_inlines() -> Inlines { |
24 | let mut clang = HashMap::new(); | 38 | let mut clang = HashMap::new(); |
25 | let mut clang_inline_children = HashSet::new(); | 39 | let mut clang_inline_children = HashSet::new(); |
26 | // TODO: this is not great: no differences between variable/field for children, but differences | 40 | clang_inline_children.insert(ChildrenKind(String::from("variables"))); |
27 | // as a parent... | 41 | clang_inline_children.insert(ChildrenKind(String::from("fields"))); |
28 | clang_inline_children.insert(String::from("variable")); | 42 | clang_inline_children.insert(ChildrenKind(String::from("functions"))); |
29 | //classes.insert(String::from("field")); | 43 | clang_inline_children.insert(ChildrenKind(String::from("methods"))); |
30 | clang_inline_children.insert(String::from("function")); | 44 | clang.insert( |
31 | //classes.insert(String::from("method")); | 45 | EntityKind(String::from("struct")), |
32 | clang.insert(String::from("struct"), clang_inline_children.clone()); | 46 | clang_inline_children.clone(), |
33 | clang.insert(String::from("class"), clang_inline_children.clone()); | 47 | ); |
34 | clang.insert(String::from("namespace"), clang_inline_children); | 48 | clang.insert( |
49 | EntityKind(String::from("class")), | ||
50 | clang_inline_children.clone(), | ||
51 | ); | ||
52 | clang.insert(EntityKind(String::from("namespace")), clang_inline_children); | ||
35 | 53 | ||
36 | let mut inlines = HashMap::new(); | 54 | let mut inlines = HashMap::new(); |
37 | inlines.insert(String::from("clang"), clang); | 55 | inlines.insert(Language::Clang, clang); |
38 | 56 | ||
39 | inlines | 57 | inlines |
40 | } | 58 | } |
@@ -48,6 +66,12 @@ impl Default for Config { | |||
48 | #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] | 66 | #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] |
49 | #[serde(rename_all = "kebab-case")] | 67 | #[serde(rename_all = "kebab-case")] |
50 | pub(crate) struct ProvidedConfig { | 68 | pub(crate) struct ProvidedConfig { |
69 | #[structopt(long = "generator-from")] | ||
70 | pub(super) from: Option<String>, | ||
71 | #[structopt(long = "generator-to")] | ||
72 | pub(super) to: Option<String>, | ||
73 | #[structopt(long = "generator-pandoc-filters", number_of_values = 1)] | ||
74 | pub(super) pandoc_filters: Vec<String>, | ||
51 | #[structopt(skip)] | 75 | #[structopt(skip)] |
52 | pub(crate) inlines: Option<HashMap<String, HashMap<String, HashSet<String>>>>, | 76 | pub(super) inlines: Option<Inlines>, |
53 | } | 77 | } |
diff --git a/src/generator/mod.rs b/src/generator/mod.rs index b4e1c94..3f62779 100644 --- a/src/generator/mod.rs +++ b/src/generator/mod.rs | |||
@@ -2,11 +2,8 @@ pub(crate) mod config; | |||
2 | mod pandoc; | 2 | mod pandoc; |
3 | 3 | ||
4 | use self::config::Config; | 4 | use self::config::Config; |
5 | //use crate::entities::{ | ||
6 | // Description, DynEntity, EntitiesManager, EntitiesManagerComponents, Usr, | ||
7 | //}; | ||
8 | use self::pandoc::into_pandoc; | 5 | use self::pandoc::into_pandoc; |
9 | use crate::types::Entity; | 6 | use crate::types::*; |
10 | 7 | ||
11 | use anyhow::{ensure, Context, Result}; | 8 | use anyhow::{ensure, Context, Result}; |
12 | use rayon::Scope; | 9 | use rayon::Scope; |
@@ -18,7 +15,11 @@ use std::path::Path; | |||
18 | 15 | ||
19 | const DEFAULT_CSS: &[u8] = include_bytes!("../../res/style.css"); | 16 | const DEFAULT_CSS: &[u8] = include_bytes!("../../res/style.css"); |
20 | 17 | ||
21 | pub(crate) fn generate(base_dir: &Path, entities: BTreeMap<String, Entity>, config: &Config) -> Result<()> { | 18 | pub(crate) fn generate( |
19 | base_dir: &Path, | ||
20 | entities: BTreeMap<EntityId, Entity>, | ||
21 | config: &Config, | ||
22 | ) -> Result<()> { | ||
22 | let md_output_dir = base_dir.join("markdown"); | 23 | let md_output_dir = base_dir.join("markdown"); |
23 | let html_output_dir = base_dir.join("html"); | 24 | let html_output_dir = base_dir.join("html"); |
24 | 25 | ||
@@ -54,7 +55,7 @@ pub(crate) fn generate(base_dir: &Path, entities: BTreeMap<String, Entity>, conf | |||
54 | } | 55 | } |
55 | 56 | ||
56 | fn generate_recursively<'a>( | 57 | fn generate_recursively<'a>( |
57 | id: String, | 58 | id: EntityId, |
58 | entity: Entity, | 59 | entity: Entity, |
59 | pool: &Scope<'a>, | 60 | pool: &Scope<'a>, |
60 | md_output_dir: &'a Path, | 61 | md_output_dir: &'a Path, |
@@ -63,7 +64,7 @@ fn generate_recursively<'a>( | |||
63 | config: &'a Config, | 64 | config: &'a Config, |
64 | ) { | 65 | ) { |
65 | pool.spawn(move |pool| { | 66 | pool.spawn(move |pool| { |
66 | trace!("Trying to generate {}", id); | 67 | trace!("Trying to generate {}", id.0); |
67 | 68 | ||
68 | let leftovers = generate_single( | 69 | let leftovers = generate_single( |
69 | &id, | 70 | &id, |
@@ -90,18 +91,18 @@ fn generate_recursively<'a>( | |||
90 | } | 91 | } |
91 | 92 | ||
92 | fn generate_single( | 93 | fn generate_single( |
93 | id: &str, | 94 | id: &EntityId, |
94 | entity: Entity, | 95 | entity: Entity, |
95 | md_output_dir: impl AsRef<Path>, | 96 | md_output_dir: impl AsRef<Path>, |
96 | html_output_dir: impl AsRef<Path>, | 97 | html_output_dir: impl AsRef<Path>, |
97 | css_path: impl AsRef<Path>, | 98 | css_path: impl AsRef<Path>, |
98 | config: &Config | 99 | config: &Config, |
99 | ) -> Result<BTreeMap<String, Entity>> { | 100 | ) -> Result<BTreeMap<EntityId, Entity>> { |
100 | use std::io::prelude::*; | 101 | use std::io::prelude::*; |
101 | use std::process::{Command, Stdio}; | 102 | use std::process::{Command, Stdio}; |
102 | 103 | ||
103 | let md_output_file = md_output_dir.as_ref().join(id); | 104 | let md_output_file = md_output_dir.as_ref().join(&id.0); |
104 | let html_output_file = html_output_dir.as_ref().join(id); | 105 | let html_output_file = html_output_dir.as_ref().join(&id.0); |
105 | 106 | ||
106 | let mut command = Command::new("pandoc"); | 107 | let mut command = Command::new("pandoc"); |
107 | 108 | ||
@@ -111,7 +112,10 @@ fn generate_single( | |||
111 | .stderr(Stdio::piped()) | 112 | .stderr(Stdio::piped()) |
112 | .args(&[ | 113 | .args(&[ |
113 | "--from=json", | 114 | "--from=json", |
114 | "--to=markdown", | 115 | // standalone keeps the sent metadat |
116 | "--standalone", | ||
117 | "--to", | ||
118 | &config.from, | ||
115 | "--output", | 119 | "--output", |
116 | md_output_file | 120 | md_output_file |
117 | .to_str() | 121 | .to_str() |
@@ -165,8 +169,10 @@ fn generate_single( | |||
165 | .stdout(Stdio::piped()) | 169 | .stdout(Stdio::piped()) |
166 | .stderr(Stdio::piped()) | 170 | .stderr(Stdio::piped()) |
167 | .args(&[ | 171 | .args(&[ |
168 | "--from=markdown-raw_tex", | 172 | "--from", |
169 | "--to=html", | 173 | &config.from, |
174 | "--to", | ||
175 | &config.to, | ||
170 | "--css", | 176 | "--css", |
171 | css_path | 177 | css_path |
172 | .as_ref() | 178 | .as_ref() |
@@ -183,6 +189,10 @@ fn generate_single( | |||
183 | .context("Entity name is not valid UTF-8")?, | 189 | .context("Entity name is not valid UTF-8")?, |
184 | ]); | 190 | ]); |
185 | 191 | ||
192 | for filter in &config.pandoc_filters { | ||
193 | command.args(&["--filter", filter]); | ||
194 | } | ||
195 | |||
186 | let command_str = format!("{:?}", command); | 196 | let command_str = format!("{:?}", command); |
187 | debug!("Launching command: {}", command_str); | 197 | debug!("Launching command: {}", command_str); |
188 | 198 | ||
@@ -190,6 +200,8 @@ fn generate_single( | |||
190 | .output() | 200 | .output() |
191 | .context("Failed to execute Pandoc command")?; | 201 | .context("Failed to execute Pandoc command")?; |
192 | 202 | ||
203 | std::io::stderr().lock().write_all(&output.stderr)?; | ||
204 | |||
193 | ensure!( | 205 | ensure!( |
194 | output.status.success(), | 206 | output.status.success(), |
195 | CommandError { | 207 | CommandError { |
diff --git a/src/generator/pandoc.rs b/src/generator/pandoc.rs index 1753d34..035acab 100644 --- a/src/generator/pandoc.rs +++ b/src/generator/pandoc.rs | |||
@@ -1,14 +1,11 @@ | |||
1 | use super::config::Config; | 1 | use super::config::Config; |
2 | use crate::types::Entity; | 2 | use crate::types::*; |
3 | 3 | ||
4 | use pandoc_types::definition::{Attr, Block, Inline, Meta, MetaValue, Pandoc}; | 4 | use pandoc_types::definition::{Attr, Block, Inline, Meta, MetaValue, Pandoc}; |
5 | 5 | ||
6 | use std::collections::BTreeMap; | 6 | use std::collections::BTreeMap; |
7 | 7 | ||
8 | pub(crate) fn into_pandoc( | 8 | pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap<EntityId, Entity>) { |
9 | entity: Entity, | ||
10 | config: &Config, | ||
11 | ) -> (Pandoc, BTreeMap<String, Entity>) { | ||
12 | let mut meta = Meta::null(); | 9 | let mut meta = Meta::null(); |
13 | 10 | ||
14 | let title = vec![Inline::Code(Attr::null(), entity.name.clone())]; | 11 | let title = vec![Inline::Code(Attr::null(), entity.name.clone())]; |
@@ -57,7 +54,7 @@ pub(crate) fn into_pandoc( | |||
57 | content.push(Block::Header( | 54 | content.push(Block::Header( |
58 | 2, | 55 | 2, |
59 | Attr::null(), | 56 | Attr::null(), |
60 | vec![Inline::Str(String::from(section_name))], | 57 | vec![Inline::Str(section_name.0.clone())], |
61 | )); | 58 | )); |
62 | 59 | ||
63 | content.push(members_list); | 60 | content.push(members_list); |
@@ -71,7 +68,7 @@ pub(crate) fn into_pandoc( | |||
71 | content.push(Block::Header( | 68 | content.push(Block::Header( |
72 | 2, | 69 | 2, |
73 | Attr::null(), | 70 | Attr::null(), |
74 | vec![Inline::Str(section_name.clone())], | 71 | vec![Inline::Str(section_name.0.clone())], |
75 | )); | 72 | )); |
76 | 73 | ||
77 | content.push(members_list); | 74 | content.push(members_list); |
@@ -79,7 +76,7 @@ pub(crate) fn into_pandoc( | |||
79 | embedded_documentation.push(Block::Header( | 76 | embedded_documentation.push(Block::Header( |
80 | 2, | 77 | 2, |
81 | Attr::null(), | 78 | Attr::null(), |
82 | vec![Inline::Str(section_name + " Documentation")], | 79 | vec![Inline::Str(section_name.0 + " Documentation")], |
83 | )); | 80 | )); |
84 | 81 | ||
85 | for (_id, child) in children { | 82 | for (_id, child) in children { |
@@ -112,7 +109,7 @@ fn str_block(content: String) -> Block { | |||
112 | Block::Plain(vec![Inline::Str(content)]) | 109 | Block::Plain(vec![Inline::Str(content)]) |
113 | } | 110 | } |
114 | 111 | ||
115 | fn entity_link(id: &str, name: String) -> Inline { | 112 | fn entity_link(id: &EntityId, name: String) -> Inline { |
116 | use pandoc_types::definition::Target; | 113 | use pandoc_types::definition::Target; |
117 | use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; | 114 | use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; |
118 | 115 | ||
@@ -135,7 +132,7 @@ fn entity_link(id: &str, name: String) -> Inline { | |||
135 | vec![Inline::Code(Attr::null(), name)], | 132 | vec![Inline::Code(Attr::null(), name)], |
136 | Target( | 133 | Target( |
137 | once("./") | 134 | once("./") |
138 | .chain(utf8_percent_encode(id, FRAGMENT)) | 135 | .chain(utf8_percent_encode(&id.0, FRAGMENT)) |
139 | .collect(), | 136 | .collect(), |
140 | String::new(), | 137 | String::new(), |
141 | ), | 138 | ), |
@@ -147,7 +144,7 @@ fn raw_markdown(text: String) -> Block { | |||
147 | Block::RawBlock(Format(String::from("markdown")), text) | 144 | Block::RawBlock(Format(String::from("markdown")), text) |
148 | } | 145 | } |
149 | 146 | ||
150 | fn member_list<'a>(members: impl IntoIterator<Item = (&'a String, &'a Entity)>) -> Option<Block> { | 147 | fn member_list<'a>(members: impl IntoIterator<Item = (&'a EntityId, &'a Entity)>) -> Option<Block> { |
151 | let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members | 148 | let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members |
152 | .into_iter() | 149 | .into_iter() |
153 | .map(|(id, entity)| { | 150 | .map(|(id, entity)| { |
diff --git a/src/main.rs b/src/main.rs index b42d73c..5c613e0 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | mod cli; | 3 | mod cli; |
4 | mod config; | 4 | mod config; |
5 | mod generator; | 5 | mod generator; |
6 | mod parsing; | 6 | mod parser; |
7 | mod types; | 7 | mod types; |
8 | 8 | ||
9 | #[macro_use] | 9 | #[macro_use] |
@@ -87,12 +87,17 @@ fn start(codemap: &mut CodeMap) -> Result<()> { | |||
87 | //let file = file.clone(); | 87 | //let file = file.clone(); |
88 | let config = load_effective_config(cli, codemap)?; | 88 | let config = load_effective_config(cli, codemap)?; |
89 | 89 | ||
90 | let entities = parsing::clang::parse_compile_commands(&config.clang, codemap)?; | 90 | let entities = parser::clang::parse_compile_commands(&config.clang, codemap)?; |
91 | //let manager = parse_file(file, &config.extra_clang_args); | 91 | //let manager = parse_file(file, &config.extra_clang_args); |
92 | 92 | ||
93 | let base_output_dir = std::path::Path::new("doc"); | 93 | let base_output_dir = std::path::Path::new("doc"); |
94 | generate(&base_output_dir, entities, &config.generator)?; | 94 | generate(&base_output_dir, entities, &config.generator)?; |
95 | } | 95 | } |
96 | Command::Inspect => { | ||
97 | let config = load_effective_config(cli, codemap)?; | ||
98 | let entities = parser::clang::parse_compile_commands(&config.clang, codemap)?; | ||
99 | serde_json::to_writer_pretty(std::io::stdout().lock(), &entities)?; | ||
100 | } | ||
96 | Command::Config { | 101 | Command::Config { |
97 | command: ConfigCommand::Default, | 102 | command: ConfigCommand::Default, |
98 | } => { | 103 | } => { |
diff --git a/src/parsing/clang/config.rs b/src/parser/clang/config.rs index cb05876..05fe3ab 100644 --- a/src/parsing/clang/config.rs +++ b/src/parser/clang/config.rs | |||
@@ -7,18 +7,18 @@ use std::path::PathBuf; | |||
7 | #[derive(Debug, Clone, StructOpt, Deserialize, Serialize)] | 7 | #[derive(Debug, Clone, StructOpt, Deserialize, Serialize)] |
8 | #[serde(rename_all = "kebab-case")] | 8 | #[serde(rename_all = "kebab-case")] |
9 | pub(crate) struct Config { | 9 | pub(crate) struct Config { |
10 | pub(crate) compile_commands_location: PathBuf, | 10 | pub(super) compile_commands_location: PathBuf, |
11 | pub(crate) extra_args: Vec<String>, | 11 | pub(super) extra_args: Vec<String>, |
12 | } | 12 | } |
13 | 13 | ||
14 | #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] | 14 | #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] |
15 | #[serde(rename_all = "kebab-case")] | 15 | #[serde(rename_all = "kebab-case")] |
16 | pub(crate) struct ProvidedConfig { | 16 | pub(crate) struct ProvidedConfig { |
17 | #[structopt(long = "clang-compile-commands-location")] | 17 | #[structopt(long = "clang-compile-commands-location")] |
18 | pub(crate) compile_commands_location: Option<PathBuf>, | 18 | pub(super) compile_commands_location: Option<PathBuf>, |
19 | #[structopt(long = "clang-extra-args", number_of_values = 1)] | 19 | #[structopt(long = "clang-extra-args", number_of_values = 1)] |
20 | #[serde(default)] | 20 | #[serde(default)] |
21 | pub(crate) extra_args: Vec<String>, | 21 | pub(super) extra_args: Vec<String>, |
22 | } | 22 | } |
23 | 23 | ||
24 | impl Default for Config { | 24 | impl Default for Config { |
diff --git a/src/parsing/clang/entities.rs b/src/parser/clang/entities.rs index a8062bb..41fe061 100644 --- a/src/parsing/clang/entities.rs +++ b/src/parser/clang/entities.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::types::Entity; | 1 | use crate::types::*; |
2 | 2 | ||
3 | use clang::{EntityKind, Usr}; | 3 | use clang::{EntityKind, Usr}; |
4 | use thiserror::Error; | 4 | use thiserror::Error; |
@@ -16,7 +16,7 @@ pub(super) struct Children { | |||
16 | functions: Option<BTreeMap<Usr, Described<Function>>>, | 16 | functions: Option<BTreeMap<Usr, Described<Function>>>, |
17 | } | 17 | } |
18 | 18 | ||
19 | #[derive(Debug, Clone, PartialEq, Eq)] | 19 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
20 | pub(super) enum ClangEntityKind { | 20 | pub(super) enum ClangEntityKind { |
21 | Namespace, | 21 | Namespace, |
22 | Variable(VariableKind), | 22 | Variable(VariableKind), |
@@ -24,24 +24,50 @@ pub(super) enum ClangEntityKind { | |||
24 | Function(FunctionKind), | 24 | Function(FunctionKind), |
25 | } | 25 | } |
26 | 26 | ||
27 | #[derive(Debug, Clone, PartialEq, Eq)] | 27 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
28 | pub(super) enum VariableKind { | 28 | pub(super) enum VariableKind { |
29 | Variable, | 29 | Variable, |
30 | Field, | 30 | Field, |
31 | } | 31 | } |
32 | 32 | ||
33 | #[derive(Debug, Clone, PartialEq, Eq)] | 33 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
34 | pub(super) enum StructKind { | 34 | pub(super) enum StructKind { |
35 | Struct, | 35 | Struct, |
36 | Class, | 36 | Class, |
37 | } | 37 | } |
38 | 38 | ||
39 | #[derive(Debug, Clone, PartialEq, Eq)] | 39 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
40 | pub(super) enum FunctionKind { | 40 | pub(super) enum FunctionKind { |
41 | Function, | 41 | Function, |
42 | Method, | 42 | Method, |
43 | } | 43 | } |
44 | 44 | ||
45 | impl ClangEntityKind { | ||
46 | fn to_str_singular(self) -> &'static str { | ||
47 | match self { | ||
48 | ClangEntityKind::Namespace => "namespace", | ||
49 | ClangEntityKind::Variable(VariableKind::Variable) => "variable", | ||
50 | ClangEntityKind::Variable(VariableKind::Field) => "field", | ||
51 | ClangEntityKind::Struct(StructKind::Struct) => "struct", | ||
52 | ClangEntityKind::Struct(StructKind::Class) => "class", | ||
53 | ClangEntityKind::Function(FunctionKind::Function) => "function", | ||
54 | ClangEntityKind::Function(FunctionKind::Method) => "method", | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn to_str_plural(self) -> &'static str { | ||
59 | match self { | ||
60 | ClangEntityKind::Namespace => "namespaces", | ||
61 | ClangEntityKind::Variable(VariableKind::Variable) => "variables", | ||
62 | ClangEntityKind::Variable(VariableKind::Field) => "fields", | ||
63 | ClangEntityKind::Struct(StructKind::Struct) => "structs", | ||
64 | ClangEntityKind::Struct(StructKind::Class) => "classes", | ||
65 | ClangEntityKind::Function(FunctionKind::Function) => "functions", | ||
66 | ClangEntityKind::Function(FunctionKind::Method) => "methods", | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
45 | #[derive(Debug, Error)] | 71 | #[derive(Debug, Error)] |
46 | #[error("Unsupported Clang entity kind: {:?}", _0)] | 72 | #[error("Unsupported Clang entity kind: {:?}", _0)] |
47 | pub(super) struct TryFromEntityKindError(String); | 73 | pub(super) struct TryFromEntityKindError(String); |
@@ -66,7 +92,7 @@ impl TryFrom<EntityKind> for ClangEntityKind { | |||
66 | } | 92 | } |
67 | 93 | ||
68 | pub(super) trait ClangEntity { | 94 | pub(super) trait ClangEntity { |
69 | fn kind(&self) -> &'static str; | 95 | fn kind(&self) -> ClangEntityKind; |
70 | 96 | ||
71 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { | 97 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { |
72 | None | 98 | None |
@@ -145,54 +171,58 @@ where | |||
145 | 171 | ||
146 | impl<T: ClangEntity> From<Described<T>> for Entity { | 172 | impl<T: ClangEntity> From<Described<T>> for Entity { |
147 | fn from(entity: Described<T>) -> Self { | 173 | fn from(entity: Described<T>) -> Self { |
148 | let mut children = BTreeMap::new(); | 174 | let mut children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>> = BTreeMap::new(); |
149 | 175 | ||
150 | let kind = String::from(entity.entity.kind()); | 176 | let kind = EntityKind(String::from(entity.entity.kind().to_str_singular())); |
151 | let clang_children = entity.entity.into_children(); | 177 | let clang_children = entity.entity.into_children(); |
152 | 178 | ||
153 | if let Some(namespaces) = clang_children.namespaces { | 179 | if let Some(namespaces) = clang_children.namespaces { |
154 | children.insert( | 180 | for (usr, namespace) in namespaces { |
155 | String::from("namespace"), | 181 | children |
156 | namespaces | 182 | .entry(ChildrenKind(String::from( |
157 | .into_iter() | 183 | namespace.entity.kind().to_str_plural(), |
158 | .map(|(usr, namespace)| (usr.0, namespace.into())) | 184 | ))) |
159 | .collect(), | 185 | .or_default() |
160 | ); | 186 | .insert(EntityId(usr.0), namespace.into()); |
187 | } | ||
161 | } | 188 | } |
162 | 189 | ||
163 | if let Some(variables) = clang_children.variables { | 190 | if let Some(variables) = clang_children.variables { |
164 | children.insert( | 191 | for (usr, variable) in variables { |
165 | String::from("variable"), | 192 | children |
166 | variables | 193 | .entry(ChildrenKind(String::from( |
167 | .into_iter() | 194 | variable.entity.kind().to_str_plural(), |
168 | .map(|(usr, variable)| (usr.0, variable.into())) | 195 | ))) |
169 | .collect(), | 196 | .or_default() |
170 | ); | 197 | .insert(EntityId(usr.0), variable.into()); |
198 | } | ||
171 | } | 199 | } |
172 | 200 | ||
173 | if let Some(structs) = clang_children.structs { | 201 | if let Some(structs) = clang_children.structs { |
174 | children.insert( | 202 | for (usr, r#struct) in structs { |
175 | String::from("struct"), | 203 | children |
176 | structs | 204 | .entry(ChildrenKind(String::from( |
177 | .into_iter() | 205 | r#struct.entity.kind().to_str_plural(), |
178 | .map(|(usr, the_struct)| (usr.0, the_struct.into())) | 206 | ))) |
179 | .collect(), | 207 | .or_default() |
180 | ); | 208 | .insert(EntityId(usr.0), r#struct.into()); |
209 | } | ||
181 | } | 210 | } |
182 | 211 | ||
183 | if let Some(functions) = clang_children.functions { | 212 | if let Some(functions) = clang_children.functions { |
184 | children.insert( | 213 | for (usr, function) in functions { |
185 | String::from("function"), | 214 | children |
186 | functions | 215 | .entry(ChildrenKind(String::from( |
187 | .into_iter() | 216 | function.entity.kind().to_str_plural(), |
188 | .map(|(usr, function)| (usr.0, function.into())) | 217 | ))) |
189 | .collect(), | 218 | .or_default() |
190 | ); | 219 | .insert(EntityId(usr.0), function.into()); |
220 | } | ||
191 | } | 221 | } |
192 | 222 | ||
193 | Entity { | 223 | Entity { |
194 | name: entity.description.name, | 224 | name: entity.description.name, |
195 | language: String::from("clang"), | 225 | language: Language::Clang, |
196 | kind, | 226 | kind, |
197 | brief_description: entity.description.brief, | 227 | brief_description: entity.description.brief, |
198 | documentation: entity.description.detailed, | 228 | documentation: entity.description.detailed, |
@@ -223,8 +253,8 @@ pub(super) struct Namespace { | |||
223 | } | 253 | } |
224 | 254 | ||
225 | impl ClangEntity for Namespace { | 255 | impl ClangEntity for Namespace { |
226 | fn kind(&self) -> &'static str { | 256 | fn kind(&self) -> ClangEntityKind { |
227 | "namespace" | 257 | ClangEntityKind::Namespace |
228 | } | 258 | } |
229 | 259 | ||
230 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { | 260 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { |
@@ -268,11 +298,8 @@ pub(super) struct Variable { | |||
268 | } | 298 | } |
269 | 299 | ||
270 | impl ClangEntity for Variable { | 300 | impl ClangEntity for Variable { |
271 | fn kind(&self) -> &'static str { | 301 | fn kind(&self) -> ClangEntityKind { |
272 | match self.kind { | 302 | ClangEntityKind::Variable(self.kind) |
273 | VariableKind::Variable => "variable", | ||
274 | VariableKind::Field => "field", | ||
275 | } | ||
276 | } | 303 | } |
277 | } | 304 | } |
278 | 305 | ||
@@ -297,11 +324,8 @@ pub(super) struct Struct { | |||
297 | } | 324 | } |
298 | 325 | ||
299 | impl ClangEntity for Struct { | 326 | impl ClangEntity for Struct { |
300 | fn kind(&self) -> &'static str { | 327 | fn kind(&self) -> ClangEntityKind { |
301 | match self.kind { | 328 | ClangEntityKind::Struct(self.kind) |
302 | StructKind::Struct => "struct", | ||
303 | StructKind::Class => "class", | ||
304 | } | ||
305 | } | 329 | } |
306 | 330 | ||
307 | fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { | 331 | fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { |
@@ -343,11 +367,8 @@ pub(super) struct Function { | |||
343 | } | 367 | } |
344 | 368 | ||
345 | impl ClangEntity for Function { | 369 | impl ClangEntity for Function { |
346 | fn kind(&self) -> &'static str { | 370 | fn kind(&self) -> ClangEntityKind { |
347 | match self.kind { | 371 | ClangEntityKind::Function(self.kind) |
348 | FunctionKind::Function => "function", | ||
349 | FunctionKind::Method => "method", | ||
350 | } | ||
351 | } | 372 | } |
352 | } | 373 | } |
353 | 374 | ||
diff --git a/src/parsing/clang/mod.rs b/src/parser/clang/mod.rs index 047c49e..047c49e 100644 --- a/src/parsing/clang/mod.rs +++ b/src/parser/clang/mod.rs | |||
diff --git a/src/parsing/clang/parsing.rs b/src/parser/clang/parsing.rs index 5359253..a654681 100644 --- a/src/parsing/clang/parsing.rs +++ b/src/parser/clang/parsing.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use super::config::Config; | 1 | use super::config::Config; |
2 | use super::entities::*; | 2 | use super::entities::*; |
3 | use crate::types::Entity; | 3 | use crate::types::*; |
4 | 4 | ||
5 | use anyhow::{anyhow, Context, Error, Result}; | 5 | use anyhow::{anyhow, Context, Error, Result}; |
6 | use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr}; | 6 | use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr}; |
@@ -208,7 +208,7 @@ impl FromTopLevel for Struct { | |||
208 | pub(crate) fn parse_compile_commands( | 208 | pub(crate) fn parse_compile_commands( |
209 | config: &Config, | 209 | config: &Config, |
210 | codemap: &mut CodeMap, | 210 | codemap: &mut CodeMap, |
211 | ) -> Result<BTreeMap<String, Entity>> { | 211 | ) -> Result<BTreeMap<EntityId, Entity>> { |
212 | let clang = Clang::new().unwrap(); | 212 | let clang = Clang::new().unwrap(); |
213 | let index = Index::new( | 213 | let index = Index::new( |
214 | &clang, /* exclude from pch = */ false, /* print diagnostics = */ false, | 214 | &clang, /* exclude from pch = */ false, /* print diagnostics = */ false, |
@@ -280,10 +280,25 @@ pub(crate) fn parse_compile_commands( | |||
280 | let normalized_entities = entities | 280 | let normalized_entities = entities |
281 | .namespaces | 281 | .namespaces |
282 | .into_iter() | 282 | .into_iter() |
283 | .map(|(usr, entity)| (usr.0, entity.into())) | 283 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())) |
284 | .chain(entities.variables.into_iter().map(|(usr, entity)| (usr.0, entity.into()))) | 284 | .chain( |
285 | .chain(entities.structs.into_iter().map(|(usr, entity)| (usr.0, entity.into()))) | 285 | entities |
286 | .chain(entities.functions.into_iter().map(|(usr, entity)| (usr.0, entity.into()))) | 286 | .variables |
287 | .into_iter() | ||
288 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
289 | ) | ||
290 | .chain( | ||
291 | entities | ||
292 | .structs | ||
293 | .into_iter() | ||
294 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
295 | ) | ||
296 | .chain( | ||
297 | entities | ||
298 | .functions | ||
299 | .into_iter() | ||
300 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
301 | ) | ||
287 | .collect(); | 302 | .collect(); |
288 | 303 | ||
289 | Ok(normalized_entities) | 304 | Ok(normalized_entities) |
@@ -463,11 +478,12 @@ fn add_entity( | |||
463 | }; | 478 | }; |
464 | 479 | ||
465 | if let Some(in_tree_entity) = toplevel.get_entity_mut(libclang_entity) { | 480 | if let Some(in_tree_entity) = toplevel.get_entity_mut(libclang_entity) { |
466 | // if current.has_documentation && !tree.has_documentation { | 481 | // if current.has_documentation && !tree.has_documentation { |
467 | // append_documentation | 482 | // append_documentation |
468 | // } | 483 | // } |
469 | } else if libclang_entity.is_definition() { | 484 | } else if libclang_entity.is_definition() { |
470 | // TODO: This probably means that you can't put documentation in forward declarations. | 485 | // TODO: This probably means that you can't put documentation in forward declarations. |
486 | // TODO: Ad-hoc toplevel functions are not documented | ||
471 | // | 487 | // |
472 | // This seems restrictive, but since there can be multiple declarations but only one definition, | 488 | // This seems restrictive, but since there can be multiple declarations but only one definition, |
473 | // you should probably put your documentation on the definition anyway? | 489 | // you should probably put your documentation on the definition anyway? |
diff --git a/src/parsing/mod.rs b/src/parser/mod.rs index 0736eee..0736eee 100644 --- a/src/parsing/mod.rs +++ b/src/parser/mod.rs | |||
diff --git a/src/types.rs b/src/types.rs index 82f9c65..f378f8b 100644 --- a/src/types.rs +++ b/src/types.rs | |||
@@ -1,22 +1,80 @@ | |||
1 | use serde_derive::{Serialize, Deserialize}; | 1 | use serde_derive::{Serialize, Deserialize}; |
2 | use thiserror::Error; | ||
2 | 3 | ||
3 | use std::collections::BTreeMap; | 4 | use std::collections::BTreeMap; |
5 | use std::str::FromStr; | ||
4 | 6 | ||
5 | #[derive(Debug, Clone, Serialize, Deserialize)] | 7 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] |
6 | pub struct Poseidoc { | 8 | pub struct Poseidoc { |
7 | pub config: toml::Value, | 9 | pub config: toml::Value, |
8 | pub entities: BTreeMap<String, Entity>, | 10 | pub entities: BTreeMap<String, Entity>, |
9 | } | 11 | } |
10 | 12 | ||
11 | #[derive(Debug, Clone, Serialize, Deserialize)] | 13 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] |
12 | pub struct Entity { | 14 | pub struct Entity { |
13 | pub name: String, | 15 | pub name: String, |
14 | //location: SourceLocation | 16 | //location: SourceLocation |
15 | pub language: String, | 17 | pub language: Language, |
16 | pub kind: String, | 18 | pub kind: EntityKind, |
17 | pub brief_description: String, | 19 | pub brief_description: String, |
18 | pub documentation: String, | 20 | pub documentation: String, |
19 | pub children: BTreeMap<String, BTreeMap<String, Entity>>, | 21 | pub children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>>, |
20 | } | 22 | } |
21 | 23 | ||
22 | // TODO: use newtype for language, entity kind, entity ID | 24 | // TODO: use newtype for entity kind, entity ID |
25 | |||
26 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
27 | #[serde(try_from = "&str", into = "&'static str")] | ||
28 | pub enum Language { | ||
29 | Clang, | ||
30 | } | ||
31 | |||
32 | impl std::fmt::Display for Language { | ||
33 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
34 | write!(f, "{}", <&'static str>::from(*self)) | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl FromStr for Language { | ||
39 | type Err = LanguageParseError; | ||
40 | |||
41 | fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
42 | match s { | ||
43 | "clang" => Ok(Language::Clang), | ||
44 | _ => Err(LanguageParseError(())), | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | impl std::convert::TryFrom<&str> for Language { | ||
50 | type Error = LanguageParseError; | ||
51 | fn try_from(s: &str) -> Result<Language, Self::Error> { | ||
52 | Language::from_str(s) | ||
53 | } | ||
54 | } | ||
55 | |||
56 | impl From<Language> for &'static str { | ||
57 | fn from(lang: Language) -> &'static str { | ||
58 | match lang { | ||
59 | Language::Clang => "clang", | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Error)] | ||
65 | #[error("invalid language")] | ||
66 | pub struct LanguageParseError(()); | ||
67 | |||
68 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] | ||
69 | #[serde(transparent)] | ||
70 | pub struct EntityKind(pub String); | ||
71 | |||
72 | // Plural version of EntityKind | ||
73 | |||
74 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] | ||
75 | #[serde(transparent)] | ||
76 | pub struct ChildrenKind(pub String); | ||
77 | |||
78 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] | ||
79 | #[serde(transparent)] | ||
80 | pub struct EntityId(pub String); | ||