Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Toggle code by use Arc for avoid clone rules. #228

Merged
merged 1 commit into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions autocorrect/src/code/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@ fn format_pair<R: RuleType, O: Results>(results: &mut O, pair: Pair<R>) {
// If they has CJK chars, disable `halfwidth-punctuation` rule temporary.
let mut last_toggle = None;
if rule_name == "block" && CJK_RE.is_match(pair_str) {
last_toggle = Some(results.get_toggle());
results.toggle_merge(toggle::Toggle::Disable(vec![
"halfwidth-punctuation".to_owned()
]));
last_toggle = Some(results.get_toggle().clone());
results.toggle_merge_for_codeblock();
}

for child in sub_pairs {
Expand All @@ -74,7 +72,7 @@ fn format_pair<R: RuleType, O: Results>(results: &mut O, pair: Pair<R>) {
}

// Restore toggle if last_toggle is some
if let Some(t) = last_toggle {
if let Some(t) = &last_toggle {
results.toggle(t);
}

Expand All @@ -93,7 +91,7 @@ pub fn format_or_lint<R: RuleType, O: Results>(results: &mut O, rule_name: &str,
// Check AutoCorrect enable/disable toggle marker
// If disable results.is_enabled() will be false
if rule_name == "comment" || rule_name == "COMMENT" {
results.toggle(toggle::parse(part));
results.toggle(&toggle::parse(part));
}

let disabled_rules = results.get_toggle().disable_rules();
Expand Down
2 changes: 0 additions & 2 deletions autocorrect/src/code/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,6 @@ mod tests {

#[test]
fn test_disable_context_codeblock() {
use std::collections::HashMap;

let last_mode = *crate::config::Config::current()
.context
.get("codeblock")
Expand Down
195 changes: 106 additions & 89 deletions autocorrect/src/config/toggle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, sync::Arc};

use pest::Parser;
use pest_derive::Parser;
Expand All @@ -11,48 +11,69 @@ pub struct ToggleParser;
pub enum Toggle {
None,
// Empty to disable all
Disable(Vec<String>),
Disable(Arc<HashMap<String, bool>>),
// Empty to enable all
Enable(Vec<String>),
Enable(Arc<HashMap<String, bool>>),
}

impl Default for Toggle {
fn default() -> Self {
Toggle::Enable(vec![])
Toggle::enable(vec![])
}
}

impl Toggle {
pub fn none() -> Self {
Toggle::None
}

pub fn enable(rules: Vec<&str>) -> Self {
let rules = rules
.into_iter()
.map(|r| (r.to_lowercase().to_string(), true))
.collect();
Toggle::Enable(Arc::new(rules))
}

pub fn disable(rules: Vec<&str>) -> Self {
let rules = rules
.into_iter()
.map(|r| (r.to_lowercase().to_string(), true))
.collect();
Toggle::Disable(Arc::new(rules))
}

pub fn is_none(&self) -> bool {
match self {
Toggle::None => true,
_ => false,
}
}

pub fn match_rule(&self, rule_name: &str) -> Option<bool> {
match self {
Toggle::None => None,
Toggle::Disable(rules) => {
if rules.is_empty() {
Some(false)
} else {
Some(!rules.contains(&rule_name.to_string()))
Some(!rules.contains_key(rule_name))
}
}
Toggle::Enable(rules) => {
if rules.is_empty() {
Some(true)
} else {
Some(rules.contains(&rule_name.to_string()))
Some(rules.contains_key(rule_name))
}
}
}
}

pub fn disable_rules(&self) -> HashMap<String, bool> {
pub fn disable_rules(&self) -> Arc<HashMap<String, bool>> {
match self {
Toggle::Disable(rules) => {
let mut map = HashMap::new();
for rule in rules {
map.insert(rule.to_string(), true);
}
map
}
_ => HashMap::new(),
Toggle::Disable(rules) => rules.clone(),
_ => Arc::new(HashMap::new()),
}
}

Expand All @@ -61,26 +82,41 @@ impl Toggle {
match new_toggle {
Toggle::Disable(rules) => {
if let Toggle::Disable(old_rules) = self {
let mut old_rules = old_rules
.iter()
.map(|(k, v)| (k.clone(), *v))
.collect::<HashMap<String, bool>>();
if !old_rules.is_empty() {
old_rules.extend(rules.clone());
for (k, v) in rules.iter() {
old_rules.insert(k.clone(), *v);
}
}

if rules.is_empty() {
old_rules.clear();
}
*self = Toggle::Disable(Arc::new(old_rules));
} else {
*self = Toggle::Disable(rules);
}
}
Toggle::Enable(rules) => {
if let Toggle::Enable(old_rules) = self {
let mut old_rules = old_rules
.iter()
.map(|(k, v)| (k.clone(), *v))
.collect::<HashMap<String, bool>>();

if !old_rules.is_empty() {
old_rules.extend(rules.clone());
for (k, v) in rules.iter() {
old_rules.insert(k.clone(), *v);
}
}

if rules.is_empty() {
old_rules.clear();
}
*self = Toggle::Enable(Arc::new(old_rules));
} else {
*self = Toggle::Enable(rules);
}
Expand All @@ -98,20 +134,20 @@ pub fn parse(input: &str) -> Toggle {
let mut rules = vec![];
for pair in pair.into_inner() {
if pair.as_rule() == Rule::rule_name {
rules.push(pair.as_str().to_lowercase().to_owned());
rules.push(pair.as_str());
}
}

return Toggle::Disable(rules);
return Toggle::disable(rules);
}
Rule::enable => {
let mut rules = vec![];
for pair in pair.into_inner() {
if pair.as_rule() == Rule::rule_name {
rules.push(pair.as_str().to_lowercase().to_owned());
rules.push(pair.as_str());
}
}
return Toggle::Enable(rules);
return Toggle::enable(rules);
}
_ => {}
}
Expand All @@ -128,80 +164,67 @@ mod tests {

#[test]
fn it_match_rule() {
assert_eq!(Toggle::Enable(vec![]).match_rule("rule"), Some(true));
assert_eq!(Toggle::Enable(vec![]).match_rule("foo"), Some(true));
assert_eq!(Toggle::Enable(vec![]).match_rule(""), Some(true));
assert_eq!(Toggle::enable(vec![]).match_rule("rule"), Some(true));
assert_eq!(Toggle::enable(vec![]).match_rule("foo"), Some(true));
assert_eq!(Toggle::enable(vec![]).match_rule(""), Some(true));

assert_eq!(Toggle::enable(vec!["foo"]).match_rule("foo"), Some(true));
assert_eq!(Toggle::enable(vec!["bar"]).match_rule("foo"), Some(false));
assert_eq!(
Toggle::Enable(vec!["foo".to_owned()]).match_rule("foo"),
Some(true)
);
assert_eq!(
Toggle::Enable(vec!["bar".to_owned()]).match_rule("foo"),
Some(false)
);
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]).match_rule("foo"),
Toggle::enable(vec!["foo", "bar"]).match_rule("foo"),
Some(true)
);
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]).match_rule("bar"),
Toggle::enable(vec!["foo", "bar"]).match_rule("bar"),
Some(true)
);
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]).match_rule("dar"),
Toggle::enable(vec!["foo", "bar"]).match_rule("dar"),
Some(false)
);
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]).match_rule(""),
Toggle::enable(vec!["foo", "bar"]).match_rule(""),
Some(false)
);
}

#[test]
fn it_parse() {
assert_eq!(Toggle::Enable(vec![]), parse("autocorrect-enable"));
assert_eq!(Toggle::Enable(vec![]), parse("// autocorrect-enable"));
assert_eq!(Toggle::Enable(vec![]), parse("# autocorrect-enable"));
assert_eq!(Toggle::Enable(vec![]), parse("# autocorrect: true"));
assert_eq!(Toggle::Enable(vec![]), parse("# autocorrect:true"));
assert_eq!(Toggle::Disable(vec![]), parse("# autocorrect: false"));
assert_eq!(Toggle::Disable(vec![]), parse("# autocorrect:false"));
assert_eq!(Toggle::Disable(vec![]), parse("# autocorrect-disable"));
assert_eq!(Toggle::Disable(vec![]), parse("// autocorrect-disable"));
assert_eq!(Toggle::None, parse("// hello world"));
assert_eq!(Toggle::enable(vec![]), parse("autocorrect-enable"));
assert_eq!(Toggle::enable(vec![]), parse("// autocorrect-enable"));
assert_eq!(Toggle::enable(vec![]), parse("# autocorrect-enable"));
assert_eq!(Toggle::enable(vec![]), parse("# autocorrect: true"));
assert_eq!(Toggle::enable(vec![]), parse("# autocorrect:true"));
assert_eq!(Toggle::disable(vec![]), parse("# autocorrect: false"));
assert_eq!(Toggle::disable(vec![]), parse("# autocorrect:false"));
assert_eq!(Toggle::disable(vec![]), parse("# autocorrect-disable"));
assert_eq!(Toggle::disable(vec![]), parse("// autocorrect-disable"));
assert_eq!(Toggle::none(), parse("// hello world"));
}

#[test]
fn it_parse_with_rules() {
assert_eq!(
Toggle::Enable(vec!["foo".to_owned()]),
parse("autocorrect-enable foo")
);
assert_eq!(Toggle::enable(vec!["foo"]), parse("autocorrect-enable foo"));

assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]),
Toggle::enable(vec!["foo", "bar"]),
parse("// autocorrect-enable foo, bar")
);
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]),
Toggle::enable(vec!["foo", "bar"]),
parse("// autocorrect-enable foo,bar")
);

assert_eq!(
Toggle::Disable(vec!["foo".to_owned()]),
Toggle::disable(vec!["foo"]),
parse("# autocorrect-disable foo")
);
assert_eq!(
Toggle::Disable(vec!["foo".to_owned(), "bar".to_owned()]),
Toggle::disable(vec!["foo", "bar"]),
parse("// autocorrect-disable foo,bar")
);
assert_eq!(
Toggle::Disable(vec![
"foo".to_owned(),
"bar".to_owned(),
"foo-bar_dar".to_owned()
]),
Toggle::disable(vec!["foo", "bar", "foo-bar_dar"]),
parse("// autocorrect-disable foo,Bar, Foo-bAr_dar")
);
}
Expand Down Expand Up @@ -237,39 +260,33 @@ mod tests {

#[test]
fn test_merge() {
let mut toggle = Toggle::Enable(vec!["foo".to_owned()]);
toggle.merge(Toggle::Enable(vec!["bar".to_owned()]));
assert_eq!(
Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]),
toggle
);
toggle.merge(Toggle::Enable(vec![]));
assert_eq!(Toggle::Enable(vec![]), toggle);
toggle.merge(Toggle::Enable(vec!["foo".to_owned()]));
assert_eq!(Toggle::Enable(vec![]), toggle);
let mut toggle = Toggle::enable(vec!["foo"]);
toggle.merge(Toggle::enable(vec!["bar"]));
assert_eq!(Toggle::enable(vec!["foo", "bar"]), toggle);
toggle.merge(Toggle::enable(vec![]));
assert_eq!(Toggle::enable(vec![]), toggle);
toggle.merge(Toggle::enable(vec!["foo"]));
assert_eq!(Toggle::enable(vec![]), toggle);

let mut toggle = Toggle::Disable(vec!["foo".to_owned(), "bar".to_owned()]);
toggle.merge(Toggle::Disable(vec!["dar".to_owned()]));
assert_eq!(
Toggle::Disable(vec!["foo".to_owned(), "bar".to_owned(), "dar".to_owned()]),
toggle
);
toggle.merge(Toggle::Disable(vec![]));
assert_eq!(Toggle::Disable(vec![]), toggle);
toggle.merge(Toggle::Disable(vec!["foo".to_owned()]));
assert_eq!(Toggle::Disable(vec![]), toggle);
let mut toggle = Toggle::disable(vec!["foo", "bar"]);
toggle.merge(Toggle::disable(vec!["dar"]));
assert_eq!(Toggle::disable(vec!["foo", "bar", "dar"]), toggle);
toggle.merge(Toggle::disable(vec![]));
assert_eq!(Toggle::disable(vec![]), toggle);
toggle.merge(Toggle::disable(vec!["foo"]));
assert_eq!(Toggle::disable(vec![]), toggle);

// Merge with disable enum value, override
let mut toggle = Toggle::Enable(vec!["foo".to_owned(), "bar".to_owned()]);
toggle.merge(Toggle::Disable(vec!["dar".to_owned()]));
assert_eq!(Toggle::Disable(vec!["dar".to_owned()]), toggle);
toggle.merge(Toggle::None);
assert_eq!(Toggle::None, toggle);
let mut toggle = Toggle::enable(vec!["foo", "bar"]);
toggle.merge(Toggle::disable(vec!["dar"]));
assert_eq!(Toggle::disable(vec!["dar"]), toggle);
toggle.merge(Toggle::none());
assert_eq!(Toggle::none(), toggle);

let mut toggle = Toggle::Disable(vec!["foo".to_owned(), "bar".to_owned()]);
toggle.merge(Toggle::Enable(vec!["dar".to_owned()]));
assert_eq!(Toggle::Enable(vec!["dar".to_owned()]), toggle);
toggle.merge(Toggle::None);
assert_eq!(Toggle::None, toggle);
let mut toggle = Toggle::disable(vec!["foo", "bar"]);
toggle.merge(Toggle::enable(vec!["dar"]));
assert_eq!(Toggle::enable(vec!["dar"]), toggle);
toggle.merge(Toggle::none());
assert_eq!(Toggle::none(), toggle);
}
}
2 changes: 1 addition & 1 deletion autocorrect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ macro_rules! regexp {
#[allow(unused)]
macro_rules! map {
{$($key:expr => $value:expr),+ $(,)?} => {{
let mut m = HashMap::new();
let mut m = std::collections::HashMap::new();
$(
m.insert($key, $value);
)+
Expand Down
Loading
Loading