summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 5c613e0252a6092a494fd19506fcfd0bf2d3cd47 (plain)
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
#![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 = parser::clang::parse_compile_commands(&config.clang, codemap)?;
            //let manager = parse_file(file, &config.extra_clang_args);

            let base_output_dir = std::path::Path::new("doc");
            generate(&base_output_dir, entities, &config.generator)?;
        }
        Command::Inspect => {
            let config = load_effective_config(cli, codemap)?;
            let entities = parser::clang::parse_compile_commands(&config.clang, codemap)?;
            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)?)
}