From b45c77c0e410654a1752019d63c440e8b44ea303 Mon Sep 17 00:00:00 2001 From: Thomas Heuschling Date: Mon, 8 Dec 2025 13:52:14 +0100 Subject: [PATCH] Implement turning off text rules with code comments --- MANUAL.md | 6 ++--- md/manual-introduction.md | 6 ++--- src/linter.rs | 57 ++++++++++++++++++++++++++++++++------- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 1993e494..0e8e6204 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -230,9 +230,8 @@ Where no configuration file can be found, all rules are implicitly enabled which will most likely result in errors from conflicting rules, e.g. **keyword_forbidden_generate** and **keyword_required_generate**. -If you need to turn off specific syntax rules for a section, then you can use -special comments within your SystemVerilog source code -(not currently available for text rules): +If you need to turn off specific rules for a section, then you can use +special comments within your SystemVerilog source code: ```systemverilog /* svlint off keyword_forbidden_always */ always @* foo = bar; // <-- This line is special. @@ -282,7 +281,6 @@ You are welcome to suggest a new rule through [Issues](https://github.com/dalance/svlint/issues) or [Pull Requests](https://github.com/dalance/svlint/pulls). - # Text Rules Text rules are applied before any parsing, i.e. the files to check are treated diff --git a/md/manual-introduction.md b/md/manual-introduction.md index e7f467ac..48b7c5e5 100644 --- a/md/manual-introduction.md +++ b/md/manual-introduction.md @@ -230,9 +230,8 @@ Where no configuration file can be found, all rules are implicitly enabled which will most likely result in errors from conflicting rules, e.g. **keyword_forbidden_generate** and **keyword_required_generate**. -If you need to turn off specific syntax rules for a section, then you can use -special comments within your SystemVerilog source code -(not currently available for text rules): +If you need to turn off specific rules for a section, then you can use +special comments within your SystemVerilog source code: ```systemverilog /* svlint off keyword_forbidden_always */ always @* foo = bar; // <-- This line is special. @@ -281,4 +280,3 @@ a short reason why it should be seen. You are welcome to suggest a new rule through [Issues](https://github.com/dalance/svlint/issues) or [Pull Requests](https://github.com/dalance/svlint/pulls). - diff --git a/src/linter.rs b/src/linter.rs index f1d3c1b1..d46bc19e 100644 --- a/src/linter.rs +++ b/src/linter.rs @@ -100,7 +100,8 @@ pub struct Linter { syntaxrules: Vec>, plugins: Vec, re_ctl: Regex, - pub ctl_enabled: HashMap, + pub ctl_enabled_syntax: HashMap, + pub ctl_enabled_text: HashMap, } #[derive(Debug)] @@ -120,9 +121,13 @@ impl Linter { // NOTE: Only syntaxrules are comment-controllable, not textrules. let re_ctl = Regex::new(r"/\*\s*svlint\s+(on|off)\s+([a-z0-9_]+)\s*\*/").unwrap(); - let mut ctl_enabled = HashMap::new(); + let mut ctl_enabled_syntax = HashMap::new(); for rule in &syntaxrules { - ctl_enabled.insert(rule.name(), true); + ctl_enabled_syntax.insert(rule.name(), true); + } + let mut ctl_enabled_text = HashMap::new(); + for rule in &textrules { + ctl_enabled_text.insert(rule.name(), true); } Linter { @@ -131,7 +136,8 @@ impl Linter { syntaxrules, plugins: Vec::new(), re_ctl, - ctl_enabled, + ctl_enabled_syntax, + ctl_enabled_text, } } @@ -149,11 +155,12 @@ impl Linter { match plugin { Rule::Text(p) => { let plugin = unsafe { Box::from_raw(p) }; + self.ctl_enabled_text.insert(plugin.name(), true); self.textrules.push(plugin); }, Rule::Syntax(p) => { let plugin = unsafe { Box::from_raw(p) }; - self.ctl_enabled.insert(plugin.name(), true); + self.ctl_enabled_syntax.insert(plugin.name(), true); self.syntaxrules.push(plugin); }, } @@ -163,10 +170,40 @@ impl Linter { Ok(()) } + fn update_ctl_enabled_text(&mut self, event: &TextRuleEvent) { + match event { + TextRuleEvent::StartOfFile => { + for (_, enable) in self.ctl_enabled_text.iter_mut() { + *enable = true; + } + } + TextRuleEvent::Line(x) => { + let res_caps = self.re_ctl.captures(*x); + if let Some(caps) = res_caps { + let ctl_name = caps.get(2).unwrap().as_str(); + if self.ctl_enabled_text.contains_key(ctl_name) { + let ctl_enable = match caps.get(1).unwrap().as_str() { + "off" => false, + _ => true, + }; + self.ctl_enabled_text.insert(ctl_name.to_string(), ctl_enable); + } + } + } + } + } + pub fn textrules_check(&mut self, event: TextRuleEvent, path: &Path, beg: &usize) -> Vec { + self.update_ctl_enabled_text(&event); let mut ret = Vec::new(); 'outer: for rule in &mut self.textrules { + match self.ctl_enabled_text[&rule.name()] { + true => {} + _ => { + continue 'outer; + } + } match rule.check(event, &self.option) { TextRuleResult::Fail {offset, len} => { match event { @@ -195,7 +232,7 @@ impl Linter { ret } - fn update_ctl_enabled(&mut self, syntax_tree: &SyntaxTree, event: &NodeEvent) { + fn update_ctl_enabled_syntax(&mut self, syntax_tree: &SyntaxTree, event: &NodeEvent) { match event { NodeEvent::Enter(RefNode::Comment(x)) => { let loc: Option<&Locate> = unwrap_locate!(*x); @@ -207,12 +244,12 @@ impl Linter { if caps.is_some() { let caps = caps.unwrap(); let ctl_name = caps.get(2).unwrap().as_str(); - if self.ctl_enabled.contains_key(ctl_name) { + if self.ctl_enabled_syntax.contains_key(ctl_name) { let ctl_enable = match caps.get(1).unwrap().as_str() { "off" => false, _ => true, }; - self.ctl_enabled.insert(ctl_name.to_string(), ctl_enable); + self.ctl_enabled_syntax.insert(ctl_name.to_string(), ctl_enable); } } } @@ -221,7 +258,7 @@ impl Linter { } pub fn syntaxrules_check(&mut self, syntax_tree: &SyntaxTree, event: &NodeEvent) -> Vec { - self.update_ctl_enabled(syntax_tree, event); + self.update_ctl_enabled_syntax(syntax_tree, event); let node = match event { NodeEvent::Enter(x) => x, @@ -235,7 +272,7 @@ impl Linter { let mut ret = Vec::new(); 'outer: for rule in &mut self.syntaxrules { - match self.ctl_enabled[&rule.name()] { + match self.ctl_enabled_syntax[&rule.name()] { true => {} _ => { continue 'outer;