Merge pull request #2534 from EylonKrause/fix/port-name-suffix-ref-underscore
port-name-suffix: handle `ref` direction and all-underscore names
diff --git a/verible/verilog/analysis/checkers/BUILD b/verible/verilog/analysis/checkers/BUILD
index 2151eaa..4681607 100644
--- a/verible/verilog/analysis/checkers/BUILD
+++ b/verible/verilog/analysis/checkers/BUILD
@@ -1824,6 +1824,7 @@
"//verible/common/text:symbol",
"//verible/common/text:syntax-tree-context",
"//verible/common/text:token-info",
+ "//verible/common/util:container-util",
"//verible/verilog/CST:port",
"//verible/verilog/CST:verilog-matchers",
"//verible/verilog/analysis:descriptions",
diff --git a/verible/verilog/analysis/checkers/port-name-suffix-rule.cc b/verible/verilog/analysis/checkers/port-name-suffix-rule.cc
index 85a0db3..ffecef3 100644
--- a/verible/verilog/analysis/checkers/port-name-suffix-rule.cc
+++ b/verible/verilog/analysis/checkers/port-name-suffix-rule.cc
@@ -28,6 +28,7 @@
#include "verible/common/text/symbol.h"
#include "verible/common/text/syntax-tree-context.h"
#include "verible/common/text/token-info.h"
+#include "verible/common/util/container-util.h"
#include "verible/verilog/CST/port.h"
#include "verible/verilog/CST/verilog-matchers.h"
#include "verible/verilog/analysis/descriptions.h"
@@ -90,10 +91,16 @@
{"output", {"o", "no", "po"}},
{"inout", {"io", "nio", "pio"}}};
- // At this point it is guaranteed that the direction will be set to
- // one of the expected values (used as keys in the map above).
- // Therefore checking the suffix like this is safe
- return suffixes.at(direction).count(suffix) == 1;
+ // `direction` is usually one of the map keys, but the grammar also permits a
+ // `ref` port direction, which has no suffix convention. FindWithDefault looks
+ // the direction up with an empty-set fallback, so an unknown direction (e.g.
+ // `ref`) has no required suffixes and is treated as "correct" (no violation),
+ // consistent with Violation() which also ignores non-input/output/inout
+ // directions.
+ static const std::set<std::string_view> kNoConvention;
+ const std::set<std::string_view> &valid =
+ verible::container::FindWithDefault(suffixes, direction, kNoConvention);
+ return valid.empty() || valid.count(suffix) == 1;
}
void PortNameSuffixRule::HandleSymbol(const Symbol &symbol,
@@ -113,8 +120,11 @@
absl::StrSplit(name, '_', absl::SkipEmpty());
if (name_parts.size() < 2) {
- // No suffix at all
+ // No suffix at all. This also covers an all-underscore name (e.g. "_"),
+ // for which SkipEmpty leaves name_parts empty; return here so the
+ // name_parts.back() access below is not reached on an empty vector.
Violation(direction, token, context);
+ return;
}
if (!IsSuffixCorrect(name_parts.back(), direction)) {
diff --git a/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc b/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc
index 69f18f4..db69d71 100644
--- a/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc
+++ b/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc
@@ -57,6 +57,9 @@
{"module t (input bit name_i); endmodule;"},
{"module t (output bit abc_o); endmodule;"},
{"module t (inout bit xyz_io); endmodule;"},
+ // A `ref` port has no suffix convention and must not be flagged (and must
+ // not crash the rule via std::map::at).
+ {"module t (ref logic data_x); endmodule;"},
{"module t (input logic name_i,\n"
"output logic abc_o,\n"
"inout logic xyz_io,\n"
@@ -90,6 +93,10 @@
{"module t (output logic ", {kToken, "_o"}, "); endmodule;"},
{"module t (inout logic ", {kToken, "_io"}, "); endmodule;"},
+ // An all-underscore name splits (SkipEmpty) to an empty parts list; it
+ // must report a suffix violation, not dereference an empty vector.
+ {"module t (input logic ", {kToken, "_"}, "); endmodule;"},
+
{"module t (input logic ", {kToken, "namei"}, "); endmodule;"},
{"module t (input logic ", {kToken, "nam_ei"}, "); endmodule;"},
{"module t (input logic ", {kToken, "name_o"}, "); endmodule;"},