svlint/opt/rustwide/workdir/src/syntaxrules/
style_operator_integer.rs1use crate::config::ConfigOption;
2use crate::linter::{SyntaxRule, SyntaxRuleResult};
3use regex::Regex;
4use sv_parser::{NodeEvent, RefNode, SyntaxTree};
5
6#[derive(Default)]
7pub struct StyleOperatorInteger {
8 re_split: Option<Regex>,
9 re_op: Option<Regex>,
10 re_succ: Option<Regex>,
11}
12
13impl SyntaxRule for StyleOperatorInteger {
14 fn check(
15 &mut self,
16 syntax_tree: &SyntaxTree,
17 event: &NodeEvent,
18 _option: &ConfigOption,
19 ) -> SyntaxRuleResult {
20 if self.re_split.is_none() {
29 self.re_split = Some(Regex::new(r"(?P<op>\S+)(?P<succ>(?s:.)*)").unwrap());
30 }
31 if self.re_op.is_none() {
32 let operators =
33 [ "&" , "\\|"
35 , "\\^"
36 , "\\^~"
37 , "~\\^"
38 , ">>"
39 , "<<"
40 , ">>>"
41 , "<<<"
42 ].join("|"); self.re_op = Some(Regex::new(format!("^({})$", operators).as_str()).unwrap());
45 }
46 if self.re_succ.is_none() {
47 self.re_succ = Some(Regex::new(r"^([\n\v\f\r]| /| $)").unwrap());
48 }
49
50 let node = match event {
51 NodeEvent::Enter(x) => x,
52 NodeEvent::Leave(_) => {
53 return SyntaxRuleResult::Pass;
54 }
55 };
56
57 let s: Option<&str> = match node {
58 RefNode::BinaryOperator(x) => {
59 Some(syntax_tree.get_str(*x).unwrap())
60 }
61 RefNode::BinaryModulePathOperator(x) => {
62 Some(syntax_tree.get_str(*x).unwrap())
63 }
64 _ => None,
65 };
66
67 if let Some(t) = s {
68 let re_split = self.re_split.as_ref().unwrap();
69 let re_op = self.re_op.as_ref().unwrap();
70 let caps = re_split.captures(&t).unwrap();
71
72 if re_op.is_match(&caps[1]) {
73 let re_succ = self.re_succ.as_ref().unwrap();
74
75 if re_succ.is_match(&caps[2]) {
76 SyntaxRuleResult::Pass
77 } else {
78 SyntaxRuleResult::Fail
79 }
80 } else {
81 SyntaxRuleResult::Pass
82 }
83 } else {
84 SyntaxRuleResult::Pass
85 }
86 }
87
88 fn name(&self) -> String {
89 String::from("style_operator_integer")
90 }
91
92 fn hint(&self, _option: &ConfigOption) -> String {
93 String::from("Follow operator with a newline or exactly 1 space.")
94 }
95
96 fn reason(&self) -> String {
97 String::from("Consistent use of whitespace enhances readability by reducing visual noise.")
98 }
99}