use clap::CommandFactory;
use clap_complete::{generator::generate, shells};
use std::path::PathBuf;
#[cfg(any(
feature = "audit",
feature = "clippy",
feature = "deny",
feature = "outdated",
feature = "typos",
feature = "udeps"
))]
#[derive(Debug, Clone, Copy, PartialEq, clap::ValueEnum, strum::EnumString)]
#[non_exhaustive]
pub enum Issue {
#[cfg(feature = "audit")]
#[strum(serialize = "audit")]
Audit,
#[cfg(feature = "clippy")]
#[strum(serialize = "clippy")]
Clippy,
#[cfg(feature = "deny")]
#[strum(serialize = "deny")]
Deny,
#[cfg(feature = "outdated")]
#[strum(serialize = "outdated")]
Outdated,
#[cfg(feature = "typos")]
#[strum(serialize = "typos")]
Typos,
#[cfg(feature = "udeps")]
#[strum(serialize = "udeps")]
Udeps,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, clap::ValueEnum)]
#[non_exhaustive]
#[allow(clippy::doc_markdown)]
pub enum Shell {
Bash,
Elvish,
Fish,
Nushell,
#[allow(clippy::enum_variant_names)]
PowerShell,
Zsh,
}
#[derive(Debug, Clone)]
pub enum InputPath {
Stdin,
File(PathBuf),
}
impl clap::builder::ValueParserFactory for InputPath {
type Parser = InputPathValueParser;
fn value_parser() -> Self::Parser {
InputPathValueParser
}
}
#[derive(Debug, Clone)]
pub struct InputPathValueParser;
impl clap::builder::TypedValueParser for InputPathValueParser {
type Value = InputPath;
fn parse_ref(
&self,
_cmd: &clap::Command,
_arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
if value.eq_ignore_ascii_case("-") {
Ok(InputPath::Stdin)
} else {
let os_string = value.to_owned();
let path_buf = PathBuf::from(os_string);
Ok(InputPath::File(path_buf))
}
}
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, clap::Parser)]
#[command(version, author)]
pub struct Command {
#[cfg(feature = "audit")]
#[arg(long)]
pub audit: bool,
#[cfg(feature = "audit")]
#[arg(long, default_value = "audit.json")]
pub audit_path: InputPath,
#[cfg(feature = "clippy")]
#[arg(long)]
pub clippy: bool,
#[cfg(feature = "clippy")]
#[arg(long, default_value = "clippy.json")]
pub clippy_path: InputPath,
#[cfg(feature = "deny")]
#[arg(long)]
pub deny: bool,
#[cfg(feature = "deny")]
#[arg(long, default_value = "deny.json")]
pub deny_path: InputPath,
#[cfg(feature = "outdated")]
#[arg(long)]
pub outdated: bool,
#[cfg(feature = "outdated")]
#[arg(long, default_value = "outdated.json")]
pub outdated_path: InputPath,
#[cfg(feature = "typos")]
#[arg(long)]
pub typos: bool,
#[cfg(feature = "typos")]
#[arg(long, default_value = "typos.json")]
pub typos_path: InputPath,
#[cfg(feature = "udeps")]
#[arg(long)]
pub udeps: bool,
#[cfg(feature = "udeps")]
#[arg(long, default_value = "udeps.json")]
pub udeps_path: InputPath,
#[arg(long, default_value = "sonar-issues.json")]
pub sonar_path: PathBuf,
#[arg(long, default_value = "codeclimate.json")]
pub codeclimate_path: PathBuf,
#[arg(long, value_enum)]
pub completion: Option<Shell>,
}
impl Command {
#[inline]
pub fn generate_completion(&self) {
if let Some(ref shell) = self.completion {
let mut app = Self::command();
let mut fd = std::io::stdout();
match *shell {
Shell::Bash => generate(shells::Bash, &mut app, "cargo-sonar", &mut fd),
Shell::Elvish => generate(shells::Elvish, &mut app, "cargo-sonar", &mut fd),
Shell::Fish => generate(shells::Fish, &mut app, "cargo-sonar", &mut fd),
Shell::Nushell => generate(
clap_complete_nushell::Nushell,
&mut app,
"cargo-sonar",
&mut fd,
),
Shell::PowerShell => generate(shells::PowerShell, &mut app, "cargo-sonar", &mut fd),
Shell::Zsh => generate(shells::Zsh, &mut app, "cargo-sonar", &mut fd),
}
std::process::exit(0);
}
}
}