use anyhow::Result; use serde_derive::{Deserialize, Serialize}; use structopt::StructOpt; use std::path::PathBuf; #[derive(Debug, Clone, StructOpt, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub(crate) struct Config { pub(super) compile_commands_location: PathBuf, pub(super) extra_args: Vec, } #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub(crate) struct ProvidedConfig { #[structopt(long = "clang-compile-commands-location")] pub(super) compile_commands_location: Option, #[structopt(long = "clang-extra-args", number_of_values = 1)] pub(super) extra_args: Option>, } impl Default for Config { fn default() -> Self { Config::from_merge(ProvidedConfig::default(), ProvidedConfig::default()) // Currently errors out only on CLI parse fail with clang's extra args .unwrap() } } fn default_extra_args() -> Vec { vec![ // We don't parse function bodies so libclang report every arguments/functions/etc. as unused. String::from("-Wno-unused-const-variable"), String::from("-Wno-unused-function"), String::from("-Wno-unused-parameter"), String::from("-Wno-unused-private-field"), String::from("-Wno-unused-variable"), // We don't "link" so every linker arguments from the compile_commands.json gets reported String::from("-Qunused-arguments"), ] } impl Config { pub(crate) fn from_merge(cli: ProvidedConfig, config: ProvidedConfig) -> Result { let mut extra_args = Vec::new(); if let Some(cli_extra_args) = cli.extra_args { for args in cli_extra_args { extra_args.append(&mut ::shell_words::split(&args)?); } } extra_args.append(&mut config.extra_args.unwrap_or_else(default_extra_args)); Ok(Self { compile_commands_location: cli .compile_commands_location .or(config.compile_commands_location) .unwrap_or_else(|| PathBuf::from(r".")), extra_args, }) } }