use std::collections::BTreeSet;
use super::cli::FixCli;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum FixKind {
ShortenImport,
PreferModuleImport,
InlinePathQualifiedType,
NarrowToPubCrate,
FixPubUse,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct FixSelection {
kinds: BTreeSet<FixKind>,
}
impl FixSelection {
pub(crate) fn from_cli(fix_cli: &FixCli) -> Self {
let mut kinds = BTreeSet::new();
if fix_cli.fix() || fix_cli.fix_all() {
kinds.insert(FixKind::ShortenImport);
kinds.insert(FixKind::PreferModuleImport);
kinds.insert(FixKind::InlinePathQualifiedType);
kinds.insert(FixKind::NarrowToPubCrate);
}
if fix_cli.fix_pub_use() || fix_cli.fix_all() {
kinds.insert(FixKind::FixPubUse);
}
Self { kinds }
}
fn all_fix_kinds() -> Self {
let mut kinds = BTreeSet::new();
kinds.insert(FixKind::ShortenImport);
kinds.insert(FixKind::PreferModuleImport);
kinds.insert(FixKind::InlinePathQualifiedType);
kinds.insert(FixKind::NarrowToPubCrate);
kinds.insert(FixKind::FixPubUse);
Self { kinds }
}
pub(crate) fn contains(&self, kind: FixKind) -> bool { self.kinds.contains(&kind) }
pub(crate) fn is_empty(&self) -> bool { self.kinds.is_empty() }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum OperationIntent {
ReadOnly,
DryRun,
Apply,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct OperationMode {
pub intent: OperationIntent,
pub fixes: FixSelection,
}
impl OperationMode {
pub(crate) fn from_cli(fix_cli: &FixCli) -> Self {
let fixes = FixSelection::from_cli(fix_cli);
if fix_cli.dry_run() {
let effective_fixes = if fixes.is_empty() {
FixSelection::all_fix_kinds()
} else {
fixes
};
return Self {
intent: OperationIntent::DryRun,
fixes: effective_fixes,
};
}
if fixes.is_empty() {
Self {
intent: OperationIntent::ReadOnly,
fixes,
}
} else {
Self {
intent: OperationIntent::Apply,
fixes,
}
}
}
}
#[cfg(test)]
mod tests {
use super::FixKind;
use super::OperationIntent;
use super::OperationMode;
use crate::cli::AutoFixCli;
use crate::cli::FixCli;
use crate::cli::FixExecutionCli;
#[test]
fn operation_mode_is_read_only_without_fix_flags() {
let cli = FixCli {
auto_fix: AutoFixCli::default(),
execution: FixExecutionCli::default(),
};
let mode = OperationMode::from_cli(&cli);
assert_eq!(mode.intent, OperationIntent::ReadOnly);
}
#[test]
fn operation_mode_dry_run_alone_implies_all_fix_kinds() {
let cli = FixCli {
auto_fix: AutoFixCli::default(),
execution: FixExecutionCli {
dry_run: true,
..Default::default()
},
};
let mode = OperationMode::from_cli(&cli);
assert_eq!(mode.intent, OperationIntent::DryRun);
assert!(mode.fixes.contains(FixKind::ShortenImport));
assert!(mode.fixes.contains(FixKind::PreferModuleImport));
assert!(mode.fixes.contains(FixKind::InlinePathQualifiedType));
assert!(mode.fixes.contains(FixKind::NarrowToPubCrate));
assert!(mode.fixes.contains(FixKind::FixPubUse));
}
#[test]
fn operation_mode_allows_previewing_multiple_fix_kinds() {
let cli = FixCli {
auto_fix: AutoFixCli {
fix: true,
fix_pub_use: true,
..Default::default()
},
execution: FixExecutionCli {
dry_run: true,
..Default::default()
},
};
let mode = OperationMode::from_cli(&cli);
assert_eq!(mode.intent, OperationIntent::DryRun);
assert!(mode.fixes.contains(FixKind::ShortenImport));
assert!(mode.fixes.contains(FixKind::NarrowToPubCrate));
assert!(mode.fixes.contains(FixKind::FixPubUse));
}
#[test]
fn operation_mode_allows_applying_multiple_fix_kinds() {
let cli = FixCli {
auto_fix: AutoFixCli {
fix: true,
fix_pub_use: true,
..Default::default()
},
execution: FixExecutionCli::default(),
};
let mode = OperationMode::from_cli(&cli);
assert_eq!(mode.intent, OperationIntent::Apply);
assert!(mode.fixes.contains(FixKind::ShortenImport));
assert!(mode.fixes.contains(FixKind::NarrowToPubCrate));
assert!(mode.fixes.contains(FixKind::FixPubUse));
}
}