diff --git a/verible/verilog/analysis/checkers/port-name-suffix-rule.cc b/verible/verilog/analysis/checkers/port-name-suffix-rule.cc index 1d4235fb4..6923d019e 100644 --- a/verible/verilog/analysis/checkers/port-name-suffix-rule.cc +++ b/verible/verilog/analysis/checkers/port-name-suffix-rule.cc @@ -104,8 +104,33 @@ void PortNameSuffixRule::HandleSymbol(const Symbol &symbol, const auto *identifier_leaf = GetIdentifierFromPortDeclaration(symbol); const auto *direction_leaf = GetDirectionFromPortDeclaration(symbol); const auto token = identifier_leaf->get(); - const auto direction = - direction_leaf ? direction_leaf->get().text() : implicit_direction; + std::string direction; + if (direction_leaf) { + direction = std::string(direction_leaf->get().text()); + } else { + // Non-ANSI style: try to find direction inside module body + // Search parent for matching port declaration with direction + const SyntaxTreeContext *parent_ctx = &context; + while (parent_ctx && !direction_leaf) { + // Iterate symbols in parent context to find matching identifier + for (const auto &sym : *parent_ctx) { + if (sym->Kind() == SymbolKind::kNode) { + const auto *decl_dir = GetDirectionFromPortDeclaration(*sym); + const auto *decl_id = GetIdentifierFromPortDeclaration(*sym); + if (decl_id && + decl_id->get().text() == identifier_leaf->get().text()) { + if (decl_dir) { + direction = std::string(decl_dir->get().text()); + break; + } + } + } + } + parent_ctx = parent_ctx->parent(); + } + if (direction.empty()) direction = std::string(implicit_direction); + } + const auto name = ABSL_DIE_IF_NULL(identifier_leaf)->get().text(); // Check if there is any suffix 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 69f18f41b..420f9dae4 100644 --- a/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc +++ b/verible/verilog/analysis/checkers/port-name-suffix-rule_test.cc @@ -67,6 +67,25 @@ TEST(PortNameSuffixRuleTest, AcceptTests) { "output bit abcb_o,\n" "inout bit xyzb_io);\n" "endmodule;"}, + {"module t (name_i,\n" + "abc_o,\n" + "xyz_io,\n" + "namea_i,\n" + "abca_o,\n" + "xyza_io,\n" + "nameb_i,\n" + "abcb_o,\n" + "xyzb_io);\n" + "input logic name_i;\n" + "output logic abc_o;\n" + "inout logic xyz_io;\n" + "input logic [7:0] namea_i;\n" + "output logic [2:0] abca_o;\n" + "inout logic [3:0] xyza_io;\n" + "input bit nameb_i;\n" + "output bit abcb_o;\n" + "inout bit xyzb_io;\n" + "endmodule;"}, }; RunLintTestCases(kTestCases); } @@ -108,6 +127,10 @@ TEST(PortNameSuffixRuleTest, RejectTests) { {"module t (output logic ", {kToken, "name_pi"}, "); endmodule;"}, {"module t (output logic ", {kToken, "name_pio"}, "); endmodule;"}, + {"module t (", {kToken, "name"}, "); input logic name; endmodule;"}, + {"module t (", {kToken, "abc"}, "); output logic abc; endmodule;"}, + {"module t (", {kToken, "xyz"}, "); inout logic [3:0] xyz; endmodule;"}, + {"module t (input logic ", {kToken, "name"}, ",\n"