1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#![deny(unsafe_code)]
#![warn(clippy::all)]
mod cli;
mod config;
mod generator;
mod parser;
mod types;
#[macro_use]
extern crate log;
use cli::{Command, ConfigCommand};
use generator::generate;
use anyhow::{Context, Result};
use codemap::CodeMap;
use codemap_diagnostic::{Diagnostic, Emitter, Level};
use structopt::StructOpt;
fn into_diagnostic(err: &anyhow::Error) -> Diagnostic {
if let Some(err) = err.downcast_ref::<config::ConfigLoadError>() {
err.into()
} else {
Diagnostic {
level: Level::Error,
message: err.to_string(),
code: None,
spans: vec![],
}
}
}
fn main() {
let mut codemap = CodeMap::new();
match start(&mut codemap) {
Ok(()) => {}
Err(err) => {
let mut emitter =
Emitter::stderr(codemap_diagnostic::ColorConfig::Auto, Some(&codemap));
let mut diagnostics = Vec::new();
diagnostics.push(into_diagnostic(&err));
if let Some(mut source) = err.source() {
diagnostics.push(Diagnostic {
level: Level::Note,
message: format!("Caused by: {}", source),
code: None,
spans: vec![],
});
while let Some(source2) = source.source() {
source = source2;
diagnostics.push(Diagnostic {
level: Level::Note,
message: format!("Caused by: {}", source),
code: None,
spans: vec![],
});
}
}
emitter.emit(&diagnostics);
}
}
}
fn start(codemap: &mut CodeMap) -> Result<()> {
let cli = cli::Cli::from_args();
pretty_env_logger::formatted_builder()
.filter(
None,
match cli.verbosity {
// Warnings and errors for internal warnings / errors
0 => log::LevelFilter::Warn,
1 => log::LevelFilter::Info,
2 => log::LevelFilter::Debug,
_ => log::LevelFilter::Trace,
},
)
.try_init()?;
std::env::set_current_dir(&cli.directory)
.with_context(|| format!("Cannot change current directory to: {:?}", cli.directory))?;
match &cli.command {
Command::Generate { file } => {
let file = file.clone();
let config = load_effective_config(cli, codemap)?;
let entities = if let Some(file) = file {
parser::clang::parse_file(file, &config.clang)?
} else {
parser::clang::parse_compile_commands(&config.clang)?
};
let base_output_dir = std::path::Path::new("doc");
generate(&base_output_dir, entities, &config.generator)?;
}
Command::Inspect { file } => {
let file = file.clone();
let config = load_effective_config(cli, codemap)?;
let entities = if let Some(file) = file {
parser::clang::parse_file(file, &config.clang)?
} else {
parser::clang::parse_compile_commands(&config.clang)?
};
serde_json::to_writer_pretty(std::io::stdout().lock(), &entities)?;
}
Command::Config {
command: ConfigCommand::Default,
} => {
print!("{}", toml::to_string_pretty(&config::Config::default())?);
}
Command::Config {
command: ConfigCommand::Show,
} => {
print!(
"{}",
toml::to_string_pretty(&load_effective_config(cli, codemap)?)?
);
}
}
Ok(())
}
fn load_effective_config(cli: cli::Cli, codemap: &mut CodeMap) -> Result<config::Config> {
let conf_file_conf = config::load_config(".", codemap)?;
Ok(config::Config::from_merge(cli, conf_file_conf)?)
}
|