From 78330ba9c1a6a4953d331ffba32b7feeaec7a373 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 31 Mar 2021 21:23:30 -0500 Subject: [PATCH] refactor(cli): Drop the traits from layering --- src/args.rs | 49 ++++++--- src/config.rs | 290 ++++++++------------------------------------------ src/main.rs | 4 +- 3 files changed, 82 insertions(+), 261 deletions(-) diff --git a/src/args.rs b/src/args.rs index 16e2db7..45c8ab1 100644 --- a/src/args.rs +++ b/src/args.rs @@ -129,7 +129,21 @@ pub(crate) struct FileArgs { pub(crate) locale: Option, } -impl config::EngineSource for FileArgs { +impl FileArgs { + pub fn to_config(&self) -> config::EngineConfig { + config::EngineConfig { + binary: self.binary(), + check_filename: self.check_filename(), + check_file: self.check_file(), + tokenizer: None, + dict: Some(config::DictConfig { + locale: self.locale, + ..Default::default() + }), + ..Default::default() + } + } + fn binary(&self) -> Option { match (self.binary, self.no_binary) { (true, false) => Some(true), @@ -156,16 +170,6 @@ impl config::EngineSource for FileArgs { (_, _) => unreachable!("StructOpt should make this impossible"), } } - - fn dict(&self) -> Option<&dyn config::DictSource> { - Some(self) - } -} - -impl config::DictSource for FileArgs { - fn locale(&self) -> Option { - self.locale - } } #[derive(Debug, StructOpt)] @@ -175,9 +179,12 @@ pub(crate) struct ConfigArgs { walk: WalkArgs, } -impl config::ConfigSource for ConfigArgs { - fn walk(&self) -> Option<&dyn config::WalkSource> { - Some(&self.walk) +impl ConfigArgs { + pub fn to_config(&self) -> config::Config { + config::Config { + files: self.walk.to_config(), + ..Default::default() + } } } @@ -221,7 +228,19 @@ pub(crate) struct WalkArgs { ignore_vcs: bool, } -impl config::WalkSource for WalkArgs { +impl WalkArgs { + pub fn to_config(&self) -> config::Walk { + config::Walk { + ignore_hidden: self.ignore_hidden(), + ignore_files: self.ignore_files(), + ignore_dot: self.ignore_dot(), + ignore_vcs: self.ignore_vcs(), + ignore_global: self.ignore_global(), + ignore_parent: self.ignore_parent(), + ..Default::default() + } + } + fn ignore_hidden(&self) -> Option { match (self.hidden, self.no_hidden) { (true, false) => Some(false), diff --git a/src/config.rs b/src/config.rs index 97cb9d5..a8e7323 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,113 +1,5 @@ use std::collections::HashMap; -pub trait ConfigSource { - fn walk(&self) -> Option<&dyn WalkSource> { - None - } - - fn default(&self) -> Option<&dyn EngineSource> { - None - } -} - -pub trait WalkSource { - /// Skip hidden files and directories. - fn ignore_hidden(&self) -> Option { - None - } - - /// Respect ignore files. - fn ignore_files(&self) -> Option { - None - } - - /// Respect .ignore files. - fn ignore_dot(&self) -> Option { - None - } - - /// Respect ignore files in vcs directories. - fn ignore_vcs(&self) -> Option { - None - } - - /// Respect global ignore files. - fn ignore_global(&self) -> Option { - None - } - - /// Respect ignore files in parent directories. - fn ignore_parent(&self) -> Option { - None - } -} - -pub trait EngineSource { - /// Check binary files. - fn binary(&self) -> Option { - None - } - - /// Verifying spelling in file names. - fn check_filename(&self) -> Option { - None - } - - /// Verifying spelling in files. - fn check_file(&self) -> Option { - None - } - - fn tokenizer(&self) -> Option<&dyn TokenizerSource> { - None - } - - fn dict(&self) -> Option<&dyn DictSource> { - None - } -} - -pub trait TokenizerSource { - /// Do not check identifiers that appear to be hexadecimal values. - fn ignore_hex(&self) -> Option { - None - } - - /// Allow identifiers to start with digits, in addition to letters. - fn identifier_leading_digits(&self) -> Option { - None - } - - /// Allow identifiers to start with one of these characters. - fn identifier_leading_chars(&self) -> Option<&str> { - None - } - - /// Allow identifiers to include digits, in addition to letters. - fn identifier_include_digits(&self) -> Option { - None - } - - /// Allow identifiers to include these characters. - fn identifier_include_chars(&self) -> Option<&str> { - None - } -} - -pub trait DictSource { - fn locale(&self) -> Option { - None - } - - fn extend_identifiers(&self) -> Box + '_> { - Box::new(None.into_iter()) - } - - fn extend_words(&self) -> Box + '_> { - Box::new(None.into_iter()) - } -} - #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields, default)] #[serde(rename_all = "kebab-case")] @@ -145,23 +37,9 @@ impl Config { } } - pub fn update(&mut self, source: &dyn ConfigSource) { - if let Some(walk) = source.walk() { - self.files.update(walk); - } - if let Some(default) = source.default() { - self.default.update(default); - } - } -} - -impl ConfigSource for Config { - fn walk(&self) -> Option<&dyn WalkSource> { - Some(&self.files) - } - - fn default(&self) -> Option<&dyn EngineSource> { - Some(&self.default) + pub fn update(&mut self, source: &Config) { + self.files.update(&source.files); + self.default.update(&source.default); } } @@ -169,11 +47,17 @@ impl ConfigSource for Config { #[serde(deny_unknown_fields, default)] #[serde(rename_all = "kebab-case")] pub struct Walk { + /// Skip hidden files and directories. pub ignore_hidden: Option, + /// Respect ignore files. pub ignore_files: Option, + /// Respect .ignore files. pub ignore_dot: Option, + /// Respect ignore files in vcs directories. pub ignore_vcs: Option, + /// Respect global ignore files. pub ignore_global: Option, + /// Respect ignore files in parent directories. pub ignore_parent: Option, } @@ -190,28 +74,28 @@ impl Walk { } } - pub fn update(&mut self, source: &dyn WalkSource) { - if let Some(source) = source.ignore_hidden() { + pub fn update(&mut self, source: &Walk) { + if let Some(source) = source.ignore_hidden { self.ignore_hidden = Some(source); } - if let Some(source) = source.ignore_files() { + if let Some(source) = source.ignore_files { self.ignore_files = Some(source); self.ignore_dot = None; self.ignore_vcs = None; self.ignore_global = None; self.ignore_parent = None; } - if let Some(source) = source.ignore_dot() { + if let Some(source) = source.ignore_dot { self.ignore_dot = Some(source); } - if let Some(source) = source.ignore_vcs() { + if let Some(source) = source.ignore_vcs { self.ignore_vcs = Some(source); self.ignore_global = None; } - if let Some(source) = source.ignore_global() { + if let Some(source) = source.ignore_global { self.ignore_global = Some(source); } - if let Some(source) = source.ignore_parent() { + if let Some(source) = source.ignore_parent { self.ignore_parent = Some(source); } } @@ -240,38 +124,15 @@ impl Walk { } } -impl WalkSource for Walk { - fn ignore_hidden(&self) -> Option { - self.ignore_hidden - } - - fn ignore_files(&self) -> Option { - self.ignore_files - } - - fn ignore_dot(&self) -> Option { - self.ignore_dot - } - - fn ignore_vcs(&self) -> Option { - self.ignore_vcs - } - - fn ignore_global(&self) -> Option { - self.ignore_global - } - - fn ignore_parent(&self) -> Option { - self.ignore_parent - } -} - #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields, default)] #[serde(rename_all = "kebab-case")] pub struct EngineConfig { + /// Check binary files. pub binary: Option, + /// Verifying spelling in file names. pub check_filename: Option, + /// Verifying spelling in files. pub check_file: Option, #[serde(flatten)] pub tokenizer: Option, @@ -295,17 +156,17 @@ impl EngineConfig { } } - pub fn update(&mut self, source: &dyn EngineSource) { - if let Some(source) = source.binary() { + pub fn update(&mut self, source: &EngineConfig) { + if let Some(source) = source.binary { self.binary = Some(source); } - if let Some(source) = source.check_filename() { + if let Some(source) = source.check_filename { self.check_filename = Some(source); } - if let Some(source) = source.check_file() { + if let Some(source) = source.check_file { self.check_file = Some(source); } - if let Some(source) = source.tokenizer() { + if let Some(source) = source.tokenizer.as_ref() { let mut tokenizer = None; std::mem::swap(&mut tokenizer, &mut self.tokenizer); let mut tokenizer = tokenizer.unwrap_or_default(); @@ -313,7 +174,7 @@ impl EngineConfig { let mut tokenizer = Some(tokenizer); std::mem::swap(&mut tokenizer, &mut self.tokenizer); } - if let Some(source) = source.dict() { + if let Some(source) = source.dict.as_ref() { let mut dict = None; std::mem::swap(&mut dict, &mut self.dict); let mut dict = dict.unwrap_or_default(); @@ -336,36 +197,19 @@ impl EngineConfig { } } -impl EngineSource for EngineConfig { - fn binary(&self) -> Option { - self.binary - } - - fn check_filename(&self) -> Option { - self.check_filename - } - - fn check_file(&self) -> Option { - self.check_file - } - - fn tokenizer(&self) -> Option<&dyn TokenizerSource> { - self.tokenizer.as_ref().map(|t| t as &dyn TokenizerSource) - } - - fn dict(&self) -> Option<&dyn DictSource> { - self.dict.as_ref().map(|d| d as &dyn DictSource) - } -} - #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields, default)] #[serde(rename_all = "kebab-case")] pub struct TokenizerConfig { + /// Do not check identifiers that appear to be hexadecimal values. pub ignore_hex: Option, + /// Allow identifiers to start with digits, in addition to letters. pub identifier_leading_digits: Option, + /// Allow identifiers to start with one of these characters. pub identifier_leading_chars: Option, + /// Allow identifiers to include digits, in addition to letters. pub identifier_include_digits: Option, + /// Allow identifiers to include these characters. pub identifier_include_chars: Option, } @@ -385,21 +229,21 @@ impl TokenizerConfig { } } - pub fn update(&mut self, source: &dyn TokenizerSource) { - if let Some(source) = source.ignore_hex() { + pub fn update(&mut self, source: &TokenizerConfig) { + if let Some(source) = source.ignore_hex { self.ignore_hex = Some(source); } - if let Some(source) = source.identifier_leading_digits() { + if let Some(source) = source.identifier_leading_digits { self.identifier_leading_digits = Some(source); } - if let Some(source) = source.identifier_leading_chars() { - self.identifier_leading_chars = Some(kstring::KString::from_ref(source)); + if let Some(source) = source.identifier_leading_chars.as_ref() { + self.identifier_leading_chars = Some(source.clone()); } - if let Some(source) = source.identifier_include_digits() { + if let Some(source) = source.identifier_include_digits { self.identifier_include_digits = Some(source); } - if let Some(source) = source.identifier_include_chars() { - self.identifier_include_chars = Some(kstring::KString::from_ref(source)); + if let Some(source) = source.identifier_include_chars.as_ref() { + self.identifier_include_chars = Some(source.clone()); } } @@ -424,28 +268,6 @@ impl TokenizerConfig { } } -impl TokenizerSource for TokenizerConfig { - fn ignore_hex(&self) -> Option { - self.ignore_hex - } - - fn identifier_leading_digits(&self) -> Option { - self.identifier_leading_digits - } - - fn identifier_leading_chars(&self) -> Option<&str> { - self.identifier_leading_chars.as_deref() - } - - fn identifier_include_digits(&self) -> Option { - self.identifier_include_digits - } - - fn identifier_include_chars(&self) -> Option<&str> { - self.identifier_include_chars.as_deref() - } -} - #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields, default)] #[serde(rename_all = "kebab-case")] @@ -465,19 +287,21 @@ impl DictConfig { } } - pub fn update(&mut self, source: &dyn DictSource) { - if let Some(source) = source.locale() { + pub fn update(&mut self, source: &DictConfig) { + if let Some(source) = source.locale { self.locale = Some(source); } self.extend_identifiers.extend( source - .extend_identifiers() - .map(|(k, v)| (kstring::KString::from_ref(k), kstring::KString::from_ref(v))), + .extend_identifiers + .iter() + .map(|(key, value)| (key.clone(), value.clone())), ); self.extend_words.extend( source - .extend_words() - .map(|(k, v)| (kstring::KString::from_ref(k), kstring::KString::from_ref(v))), + .extend_words + .iter() + .map(|(key, value)| (key.clone(), value.clone())), ); } @@ -502,28 +326,6 @@ impl DictConfig { } } -impl DictSource for DictConfig { - fn locale(&self) -> Option { - self.locale - } - - fn extend_identifiers(&self) -> Box + '_> { - Box::new( - self.extend_identifiers - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())), - ) - } - - fn extend_words(&self) -> Box + '_> { - Box::new( - self.extend_words - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())), - ) - } -} - fn find_project_file(dir: &std::path::Path, names: &[&str]) -> Option { let mut file_path = dir.join("placeholder"); for name in names { diff --git a/src/main.rs b/src/main.rs index 886337a..c0202f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ fn run_dump_config(args: &args::Args, output_path: &std::path::Path) -> proc_exi let storage = typos_cli::policy::ConfigStorage::new(); let mut overrides = config::EngineConfig::default(); - overrides.update(&args.overrides); + overrides.update(&args.overrides.to_config()); let mut engine = typos_cli::policy::ConfigEngine::new(&storage); engine.set_isolated(args.isolated).set_overrides(overrides); if let Some(path) = args.custom_config.as_ref() { @@ -87,7 +87,7 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult { let storage = typos_cli::policy::ConfigStorage::new(); let mut overrides = config::EngineConfig::default(); - overrides.update(&args.overrides); + overrides.update(&args.overrides.to_config()); let mut engine = typos_cli::policy::ConfigEngine::new(&storage); engine.set_isolated(args.isolated).set_overrides(overrides); if let Some(path) = args.custom_config.as_ref() {