diff options
author | Minijackson <minijackson@riseup.net> | 2019-11-15 18:14:07 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2019-11-15 18:14:07 +0100 |
commit | 304d9f220cc208dd78fce11b703354ecd8d2168c (patch) | |
tree | 22c0bc3b13a21c8696d0e20be217c71d8555eabd /src/config.rs | |
parent | 3301430c676e4af6b95d96b6408a66f9d2768653 (diff) | |
download | poseidoc-304d9f220cc208dd78fce11b703354ecd8d2168c.tar.gz poseidoc-304d9f220cc208dd78fce11b703354ecd8d2168c.zip |
add basic config file, use codemap_diagnostic for main errors
Diffstat (limited to 'src/config.rs')
-rw-r--r-- | src/config.rs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..4463479 --- /dev/null +++ b/src/config.rs | |||
@@ -0,0 +1,107 @@ | |||
1 | use anyhow::{anyhow, Context, Result}; | ||
2 | use codemap::CodeMap; | ||
3 | use codemap_diagnostic::Diagnostic; | ||
4 | use serde_derive::{Deserialize, Serialize}; | ||
5 | use structopt::StructOpt; | ||
6 | use thiserror::Error; | ||
7 | |||
8 | use std::path::{Path, PathBuf}; | ||
9 | use std::sync::Arc; | ||
10 | |||
11 | pub(super) const DEFAULT_PROJECT_CONFIGURATION_FILE_NAME: &str = "poseidoc.toml"; | ||
12 | |||
13 | #[derive(Debug, Clone, StructOpt, Deserialize, Serialize)] | ||
14 | #[structopt(rename_all = "kebab-case")] | ||
15 | #[serde(rename_all = "kebab-case", default)] | ||
16 | pub(crate) struct Config { | ||
17 | #[structopt(skip)] | ||
18 | pub(crate) name: String, | ||
19 | #[structopt(long, default_value = ".")] | ||
20 | pub(crate) compile_commands_location: PathBuf, | ||
21 | #[structopt(skip = vec![])] | ||
22 | pub(crate) extra_clang_args: Vec<String>, | ||
23 | } | ||
24 | |||
25 | impl Default for Config { | ||
26 | fn default() -> Self { | ||
27 | Config { | ||
28 | name: "My Project".into(), | ||
29 | compile_commands_location: PathBuf::from(r"."), | ||
30 | extra_clang_args: Vec::new(), | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | |||
35 | pub(super) fn load_config(location: impl AsRef<Path>, codemap: &mut CodeMap) -> Result<Config> { | ||
36 | let location = location.as_ref(); | ||
37 | |||
38 | let final_path = if location.is_dir() { | ||
39 | location.join(DEFAULT_PROJECT_CONFIGURATION_FILE_NAME) | ||
40 | } else if !location.exists() { | ||
41 | return Err(anyhow!("File {:?} does not exists", location)) | ||
42 | .with_context(|| format!("Failed to open project configuration: {:?}", location)); | ||
43 | } else { | ||
44 | location.to_owned() | ||
45 | }; | ||
46 | |||
47 | let config_str = | ||
48 | std::fs::read_to_string(&final_path).map_err(|err| ConfigLoadError::IoError { | ||
49 | file_name: final_path.clone(), | ||
50 | source: err, | ||
51 | })?; | ||
52 | Ok( | ||
53 | toml::from_str(&config_str).map_err(|err| ConfigLoadError::TomlDeserialzation { | ||
54 | file: codemap.add_file(final_path.to_string_lossy().into(), config_str), | ||
55 | source: err, | ||
56 | })?, | ||
57 | ) | ||
58 | } | ||
59 | |||
60 | #[derive(Debug, Error)] | ||
61 | #[error("Error loading project configuration")] | ||
62 | pub(crate) enum ConfigLoadError { | ||
63 | #[error("Failed to read project configuration: {:?}", file_name)] | ||
64 | IoError { | ||
65 | file_name: PathBuf, | ||
66 | source: std::io::Error, | ||
67 | }, | ||
68 | #[error("Failed to parse project configuration: {:?}", file.name())] | ||
69 | TomlDeserialzation { | ||
70 | file: Arc<codemap::File>, | ||
71 | source: toml::de::Error, | ||
72 | }, | ||
73 | } | ||
74 | |||
75 | impl From<&ConfigLoadError> for Diagnostic { | ||
76 | fn from(err: &ConfigLoadError) -> Diagnostic { | ||
77 | use codemap_diagnostic::{Level, SpanLabel, SpanStyle}; | ||
78 | use std::convert::TryInto; | ||
79 | |||
80 | let message = err.to_string(); | ||
81 | |||
82 | let spans = match err { | ||
83 | ConfigLoadError::IoError { .. } => vec![], | ||
84 | ConfigLoadError::TomlDeserialzation { file, source, .. } => { | ||
85 | if let Some((line, col)) = source.line_col() { | ||
86 | let line_span = file.line_span(line); | ||
87 | let col = col.try_into().unwrap(); | ||
88 | let span = line_span.subspan(col, col); | ||
89 | vec![SpanLabel { | ||
90 | span, | ||
91 | label: None, | ||
92 | style: SpanStyle::Primary, | ||
93 | }] | ||
94 | } else { | ||
95 | vec![] | ||
96 | } | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | Diagnostic { | ||
101 | level: Level::Error, | ||
102 | message, | ||
103 | code: None, | ||
104 | spans, | ||
105 | } | ||
106 | } | ||
107 | } | ||