Add helper functions for `kModulePortDeclaration`s Also fix naming of port helper functions. Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
diff --git a/verilog/CST/port.cc b/verilog/CST/port.cc index a968523..eed3ea9 100644 --- a/verilog/CST/port.cc +++ b/verilog/CST/port.cc
@@ -32,7 +32,7 @@ using verible::Symbol; using verible::SyntaxTreeLeaf; -std::vector<verible::TreeSearchMatch> FindAllModulePortDeclarations( +std::vector<verible::TreeSearchMatch> FindAllPortDeclarations( const Symbol& root) { return SearchSyntaxTree(root, NodekPortDeclaration()); } @@ -52,16 +52,14 @@ return SearchSyntaxTree(root, NodekPortItem()); } -const SyntaxTreeLeaf* GetIdentifierFromModulePortDeclaration( - const Symbol& symbol) { +const SyntaxTreeLeaf* GetIdentifierFromPortDeclaration(const Symbol& symbol) { const auto* identifier_symbol = verible::GetSubtreeAsSymbol(symbol, NodeEnum::kPortDeclaration, 3); if (!identifier_symbol) return nullptr; return AutoUnwrapIdentifier(*identifier_symbol); } -const SyntaxTreeLeaf* GetDirectionFromModulePortDeclaration( - const Symbol& symbol) { +const SyntaxTreeLeaf* GetDirectionFromPortDeclaration(const Symbol& symbol) { if (const auto* dir_symbol = GetSubtreeAsSymbol(symbol, NodeEnum::kPortDeclaration, 0)) { return &SymbolCastToLeaf(*dir_symbol); @@ -69,6 +67,35 @@ return nullptr; } +std::vector<verible::TreeSearchMatch> FindAllModulePortDeclarations( + const verible::Symbol& root) { + return SearchSyntaxTree(root, NodekModulePortDeclaration()); +} + +const verible::SyntaxTreeLeaf* GetIdentifierFromModulePortDeclaration( + const verible::Symbol& symbol) { + auto& node = SymbolCastToNode(symbol); + if (!MatchNodeEnumOrNull(node, NodeEnum::kModulePortDeclaration)) + return nullptr; + auto id_unpacked_dims = FindAllIdentifierUnpackedDimensions(symbol); + if (id_unpacked_dims.empty()) return nullptr; + if (id_unpacked_dims.size() > 1) { + LOG(ERROR) << "Expected one identifier node in port declaration, but got " + << id_unpacked_dims.size(); + } + return GetSymbolIdentifierFromIdentifierUnpackedDimensions( + *id_unpacked_dims.front().match); +} + +const verible::SyntaxTreeLeaf* GetDirectionFromModulePortDeclaration( + const verible::Symbol& symbol) { + if (const auto* dir_symbol = + GetSubtreeAsSymbol(symbol, NodeEnum::kModulePortDeclaration, 0)) { + return &SymbolCastToLeaf(*dir_symbol); + } + return nullptr; +} + const verible::SyntaxTreeLeaf* GetIdentifierFromPortReference( const verible::Symbol& port_reference) { const auto* identifier_symbol =
diff --git a/verilog/CST/port.h b/verilog/CST/port.h index ef1e3be..7ff13af 100644 --- a/verilog/CST/port.h +++ b/verilog/CST/port.h
@@ -29,8 +29,8 @@ namespace verilog { -// Find all individual module port declarations. -std::vector<verible::TreeSearchMatch> FindAllModulePortDeclarations( +// Find all individual port declarations. +std::vector<verible::TreeSearchMatch> FindAllPortDeclarations( const verible::Symbol&); // Find all nodes tagged with kPort. @@ -41,12 +41,24 @@ std::vector<verible::TreeSearchMatch> FindAllActualNamedPort( const verible::Symbol&); -// Extract the name of the module port identifier from a port declaration. -const verible::SyntaxTreeLeaf* GetIdentifierFromModulePortDeclaration( +// Extract the name of the port identifier from a port declaration. +const verible::SyntaxTreeLeaf* GetIdentifierFromPortDeclaration( const verible::Symbol&); // Extract the direction from a port declaration. // Can return nullptr if the direction is not explicitly specified. +const verible::SyntaxTreeLeaf* GetDirectionFromPortDeclaration( + const verible::Symbol&); + +// Find all individual module port declarations. +std::vector<verible::TreeSearchMatch> FindAllModulePortDeclarations( + const verible::Symbol&); + +// Extract the name of the module port identifier from a port declaration. +const verible::SyntaxTreeLeaf* GetIdentifierFromModulePortDeclaration( + const verible::Symbol&); + +// Extract the direction from a module port declaration. const verible::SyntaxTreeLeaf* GetDirectionFromModulePortDeclaration( const verible::Symbol&);
diff --git a/verilog/CST/port_test.cc b/verilog/CST/port_test.cc index 9cb7ab6..b4c9617 100644 --- a/verilog/CST/port_test.cc +++ b/verilog/CST/port_test.cc
@@ -55,6 +55,135 @@ using verible::TreeSearchMatch; // Tests that no ports are found from an empty source. +TEST(FindAllPortDeclarationsTest, EmptySource) { + VerilogAnalyzer analyzer("", ""); + ASSERT_OK(analyzer.Analyze()); + const auto& root = analyzer.Data().SyntaxTree(); + const auto port_declarations = + FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); + EXPECT_TRUE(port_declarations.empty()); +} + +// Tests that no ports are found in port-less module. +TEST(FindAllPortDeclarationsTest, NonPort) { + VerilogAnalyzer analyzer("module foo; endmodule", ""); + ASSERT_OK(analyzer.Analyze()); + const auto& root = analyzer.Data().SyntaxTree(); + const auto port_declarations = + FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); + EXPECT_TRUE(port_declarations.empty()); +} + +// Tests that a package-item net declaration is not a port. +TEST(FindAllPortDeclarationsTest, OneWire) { + VerilogAnalyzer analyzer("wire w;", ""); + ASSERT_OK(analyzer.Analyze()); + const auto& root = analyzer.Data().SyntaxTree(); + const auto port_declarations = + FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); + EXPECT_TRUE(port_declarations.empty()); +} + +// Tests that a local wire inside a module is not a port. +TEST(FindAllPortDeclarationsTest, OneWireInModule) { + VerilogAnalyzer analyzer("module m; wire w; endmodule", ""); + ASSERT_OK(analyzer.Analyze()); + const auto& root = analyzer.Data().SyntaxTree(); + const auto port_declarations = + FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); + EXPECT_TRUE(port_declarations.empty()); +} + +// Tests that a port wire inside a module is found. +TEST(FindAllPortDeclarationsTest, OnePortInModule) { + const char* kTestCases[] = { + "logic l", + "wire w", + "input w", + "input [1:0] w", + "input w [0:1]", + "input w [6]", + "input [7:0] w [6]", + "input wire w", + "reg r", + "output r", + "output reg r", + "output reg [1:0] r", + "output reg r [0:3]", + "output reg [1:0] r [0:3]", + }; + for (auto test : kTestCases) { + VerilogAnalyzer analyzer(absl::StrCat("module m(", test, "); endmodule"), + ""); + ASSERT_OK(analyzer.Analyze()); + const auto& root = analyzer.Data().SyntaxTree(); + const auto port_declarations = + FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); + EXPECT_EQ(port_declarations.size(), 1); + const auto& decl = port_declarations.front(); + EXPECT_TRUE(decl.context.IsInside(NodeEnum::kModuleDeclaration)); + } +} + +TEST(GetIdentifierFromPortDeclarationTest, VariousPorts) { + constexpr int kTag = 1; // don't care + const SyntaxTreeSearchTestCase kTestCases[] = { + {"module foo(input ", {kTag, "bar"}, "); endmodule"}, + {"module foo(input logic ", {kTag, "b_a_r"}, "); endmodule"}, + {"module foo(input wire ", {kTag, "hello_world"}, " = 1); endmodule"}, + {"module foo(wire ", {kTag, "hello_world1"}, " = 1); endmodule"}, + {"module foo(input logic [3:0] ", {kTag, "bar2"}, "); endmodule"}, + {"module foo(input logic ", {kTag, "b_a_r"}, " [3:0]); endmodule"}, + {"module foo(input logic ", {kTag, "bar"}, " [4]); endmodule"}, + // multiple ports + {"module foo(input ", + {kTag, "bar"}, + ", output ", + {kTag, "bar2"}, + "); endmodule"}, + {"module foo(input logic ", + {kTag, "bar"}, + ", input wire ", + {kTag, "bar2"}, + "); endmodule"}, + {"module foo(input logic ", + {kTag, "bar"}, + ", output ", + {kTag, "bar2"}, + "); endmodule"}, + {"module foo(wire ", + {kTag, "bar"}, + ", wire ", + {kTag, "bar2"}, + " = 1); endmodule"}, + {"module foo(input logic [3:0] ", + {kTag, "bar"}, + ", input logic ", + {kTag, "bar2"}, + " [4]); endmodule"}, + {"module foo(input logic ", + {kTag, "bar"}, + " [3:0], input logic [3:0] ", + {kTag, "bar2"}, + "); endmodule"}, + }; + for (const auto& test : kTestCases) { + TestVerilogSyntaxRangeMatches( + __FUNCTION__, test, [](const TextStructureView& text_structure) { + const auto& root = text_structure.SyntaxTree(); + const auto port_declarations = FindAllPortDeclarations(*root); + std::vector<TreeSearchMatch> ids; + for (const auto& port : port_declarations) { + const auto* identifier_leaf = + GetIdentifierFromPortDeclaration(*port.match); + ids.push_back(TreeSearchMatch{identifier_leaf, /* no context */}); + } + return ids; + }); + } +} + +// Tests that no ports are found from an empty source. TEST(FindAllModulePortDeclarationsTest, EmptySource) { VerilogAnalyzer analyzer("", ""); ASSERT_OK(analyzer.Analyze()); @@ -97,23 +226,12 @@ // Tests that a port wire inside a module is found. TEST(FindAllModulePortDeclarationsTest, OnePortInModule) { const char* kTestCases[] = { - "logic l", - "wire w", - "input w", - "input [1:0] w", - "input w [0:1]", - "input w [6]", - "input [7:0] w [6]", - "input wire w", - "reg r", - "output r", - "output reg r", - "output reg [1:0] r", - "output reg r [0:3]", - "output reg [1:0] r [0:3]", + "input p", "input [1:0] p", "input p [0:1]", + "input p [6]", "input [7:0] p [6]", "input wire p", + "output p", "output reg p", "output reg [1:0] p", }; for (auto test : kTestCases) { - VerilogAnalyzer analyzer(absl::StrCat("module m(", test, "); endmodule"), + VerilogAnalyzer analyzer(absl::StrCat("module m(p); ", test, "; endmodule"), ""); ASSERT_OK(analyzer.Analyze()); const auto& root = analyzer.Data().SyntaxTree(); @@ -128,44 +246,37 @@ TEST(GetIdentifierFromModulePortDeclarationTest, VariousPorts) { constexpr int kTag = 1; // don't care const SyntaxTreeSearchTestCase kTestCases[] = { - {"module foo(input ", {kTag, "bar"}, "); endmodule"}, - {"module foo(input logic ", {kTag, "b_a_r"}, "); endmodule"}, - {"module foo(input wire ", {kTag, "hello_world"}, " = 1); endmodule"}, - {"module foo(wire ", {kTag, "hello_world1"}, " = 1); endmodule"}, - {"module foo(input logic [3:0] ", {kTag, "bar2"}, "); endmodule"}, - {"module foo(input logic ", {kTag, "b_a_r"}, " [3:0]); endmodule"}, - {"module foo(input logic ", {kTag, "bar"}, " [4]); endmodule"}, + {"module foo(bar); input ", {kTag, "bar"}, "; endmodule"}, + {"module foo(b_a_r); input logic ", {kTag, "b_a_r"}, "; endmodule"}, + {"module foo(bar2); input logic [3:0] ", {kTag, "bar2"}, "; endmodule"}, + {"module foo(b_a_r); input logic ", {kTag, "b_a_r"}, " [3:0]; endmodule"}, + {"module foo(bar); input logic ", {kTag, "bar"}, " [4]; endmodule"}, // multiple ports - {"module foo(input ", + {"module foo(bar, bar2); input ", {kTag, "bar"}, - ", output ", + "; output ", {kTag, "bar2"}, - "); endmodule"}, - {"module foo(input logic ", + "; endmodule"}, + {"module foo(bar, bar2); input logic ", {kTag, "bar"}, - ", input wire ", + "; input wire ", {kTag, "bar2"}, - "); endmodule"}, - {"module foo(input logic ", + "; endmodule"}, + {"module foo(bar, bar2); input logic ", {kTag, "bar"}, - ", output ", + "; output ", {kTag, "bar2"}, - "); endmodule"}, - {"module foo(wire ", + "; endmodule"}, + {"module foo(bar, bar2); input logic [3:0] ", {kTag, "bar"}, - ", wire ", + "; input logic ", {kTag, "bar2"}, - " = 1); endmodule"}, - {"module foo(input logic [3:0] ", + " [4]; endmodule"}, + {"module foo(bar, bar2); input logic ", {kTag, "bar"}, - ", input logic ", + " [3:0]; input logic [3:0] ", {kTag, "bar2"}, - " [4]); endmodule"}, - {"module foo(input logic ", - {kTag, "bar"}, - " [3:0], input logic [3:0] ", - {kTag, "bar2"}, - "); endmodule"}, + "; endmodule"}, }; for (const auto& test : kTestCases) { TestVerilogSyntaxRangeMatches( @@ -422,13 +533,12 @@ TestVerilogSyntaxRangeMatches( __FUNCTION__, test, [](const TextStructureView& text_structure) { const auto& root = text_structure.SyntaxTree(); - const auto& ports = - FindAllModulePortDeclarations(*ABSL_DIE_IF_NULL(root)); + const auto& ports = FindAllPortDeclarations(*ABSL_DIE_IF_NULL(root)); std::vector<TreeSearchMatch> directions; for (const auto& port : ports) { const auto* direction = - GetDirectionFromModulePortDeclaration(*port.match); + GetDirectionFromPortDeclaration(*port.match); directions.emplace_back( TreeSearchMatch{(const verible::Symbol*)direction, {}}); }
diff --git a/verilog/analysis/checkers/port_name_suffix_rule.cc b/verilog/analysis/checkers/port_name_suffix_rule.cc index 242c6e1..eb946e0 100644 --- a/verilog/analysis/checkers/port_name_suffix_rule.cc +++ b/verilog/analysis/checkers/port_name_suffix_rule.cc
@@ -103,9 +103,8 @@ constexpr absl::string_view implicit_direction = "input"; verible::matcher::BoundSymbolManager manager; if (PortMatcher().Matches(symbol, &manager)) { - const auto* identifier_leaf = - GetIdentifierFromModulePortDeclaration(symbol); - const auto* direction_leaf = GetDirectionFromModulePortDeclaration(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;
diff --git a/verilog/analysis/checkers/signal_name_style_rule.cc b/verilog/analysis/checkers/signal_name_style_rule.cc index 04e5b48..2bb57d5 100644 --- a/verilog/analysis/checkers/signal_name_style_rule.cc +++ b/verilog/analysis/checkers/signal_name_style_rule.cc
@@ -79,8 +79,7 @@ const SyntaxTreeContext& context) { verible::matcher::BoundSymbolManager manager; if (PortMatcher().Matches(symbol, &manager)) { - const auto* identifier_leaf = - GetIdentifierFromModulePortDeclaration(symbol); + const auto* identifier_leaf = GetIdentifierFromPortDeclaration(symbol); const auto name = ABSL_DIE_IF_NULL(identifier_leaf)->get().text(); if (!verible::IsLowerSnakeCaseWithDigits(name)) violations_.insert(
diff --git a/verilog/tools/kythe/indexing_facts_tree_extractor.cc b/verilog/tools/kythe/indexing_facts_tree_extractor.cc index d325fd7..9dfb647 100644 --- a/verilog/tools/kythe/indexing_facts_tree_extractor.cc +++ b/verilog/tools/kythe/indexing_facts_tree_extractor.cc
@@ -753,7 +753,7 @@ // module m(input a, input b); if (tag == NodeEnum::kPortDeclaration) { const SyntaxTreeLeaf* leaf = - GetIdentifierFromModulePortDeclaration(module_port_node); + GetIdentifierFromPortDeclaration(module_port_node); if (!leaf) return; facts_tree_context_.top().Children().emplace_back(