svlint/opt/rustwide/workdir/src/syntaxrules/
re_forbidden_port_ref.rs1use crate::config::ConfigOption;
2use crate::linter::{check_regex, SyntaxRule, SyntaxRuleResult};
3use regex::Regex;
4use sv_parser::{unwrap_node, NodeEvent, RefNode, SyntaxTree, PortDirection};
5
6#[derive(Default)]
7pub struct ReForbiddenPortRef {
8 re: Option<Regex>,
9 under_ref_declaration: bool,
10 under_ansi_port_declaration: bool,
11 previous_port_direction_ref: bool,
12}
13
14impl SyntaxRule for ReForbiddenPortRef {
15 fn check(
16 &mut self,
17 syntax_tree: &SyntaxTree,
18 event: &NodeEvent,
19 option: &ConfigOption,
20 ) -> SyntaxRuleResult {
21 if self.re.is_none() {
22 self.re = Some(Regex::new(&option.re_forbidden_port_ref).unwrap());
23 }
24
25 let node = match event {
26 NodeEvent::Enter(x) => {
27 match x {
28 RefNode::RefDeclaration(_) => {
29 self.under_ref_declaration = true;
30 }
31 RefNode::AnsiPortDeclaration(_) => {
32 self.under_ansi_port_declaration = true;
33 }
34 RefNode::PortDirection(PortDirection::Ref(_)) => {
35 self.previous_port_direction_ref = true;
36 }
37 RefNode::ModuleAnsiHeader(_) |
38 RefNode::PortDirection(PortDirection::Inout(_)) |
39 RefNode::PortDirection(PortDirection::Input(_)) |
40 RefNode::PortDirection(PortDirection::Output(_)) => {
41 self.previous_port_direction_ref = false;
42 }
43 _ => ()
44 }
45 x
46 }
47 NodeEvent::Leave(x) => {
48 match x {
49 RefNode::RefDeclaration(_) => {
50 self.under_ref_declaration = false;
51 }
52 RefNode::AnsiPortDeclaration(_) => {
53 self.under_ansi_port_declaration = false;
54 }
55 _ => ()
56 }
57 return SyntaxRuleResult::Pass;
58 }
59 };
60
61 let c: bool = self.under_ref_declaration ||
62 (self.under_ansi_port_declaration && self.previous_port_direction_ref);
63
64 match (c, node) {
65 (true, RefNode::PortIdentifier(x)) => {
66 check_regex(false, unwrap_node!(*x, Identifier),
67 &syntax_tree, &self.re.as_ref().unwrap())
68 }
69 _ => SyntaxRuleResult::Pass
70 }
71 }
72
73 fn name(&self) -> String {
74 String::from("re_forbidden_port_ref")
75 }
76
77 fn hint(&self, option: &ConfigOption) -> String {
78 String::from(format!(
79 "Use a port identifier not matching regex `{}`.",
80 &option.re_forbidden_port_ref
81 ))
82 }
83
84 fn reason(&self) -> String {
85 String::from("Identifiers must conform to the naming scheme.")
86 }
87}