| // Copyright 2017-2020 The Verible Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "verilog/CST/parameters.h" | |
| #include <memory> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include "absl/strings/string_view.h" | |
| #include "common/analysis/syntax_tree_search.h" | |
| #include "common/analysis/syntax_tree_search_test_utils.h" | |
| #include "common/text/concrete_syntax_leaf.h" | |
| #include "common/text/concrete_syntax_tree.h" | |
| #include "common/text/symbol.h" | |
| #include "common/text/text_structure.h" | |
| #include "common/text/token_info.h" | |
| #include "common/util/casts.h" | |
| #include "common/util/logging.h" | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "verilog/CST/match_test_utils.h" | |
| #include "verilog/CST/verilog_nonterminals.h" | |
| #include "verilog/analysis/verilog_analyzer.h" | |
| #include "verilog/parser/verilog_token_enum.h" | |
| #undef ASSERT_OK | |
| #define ASSERT_OK(value) ASSERT_TRUE((value).ok()) | |
| namespace verilog { | |
| namespace { | |
| using verible::down_cast; | |
| using verible::SyntaxTreeSearchTestCase; | |
| using verible::TextStructureView; | |
| using verible::TreeSearchMatch; | |
| // Tests that the correct amount of kParameterDeclarations are found. | |
| TEST(FindAllParamDeclarationsTest, BasicParams) { | |
| constexpr int kTag = 1; // don't care | |
| const SyntaxTreeSearchTestCase kTestCases[] = { | |
| {""}, | |
| {"module foo; endmodule"}, | |
| {"module foo (input bar); endmodule"}, | |
| {"module foo; ", {kTag, "localparam Bar = 1;"}, " endmodule"}, | |
| {"module foo; ", {kTag, "localparam int Bar = 1;"}, " endmodule"}, | |
| {"module foo; ", {kTag, "parameter int Bar = 1;"}, " endmodule"}, | |
| {"module foo #(", {kTag, "parameter int Bar = 1"}, "); endmodule"}, | |
| {"module foo; ", | |
| {kTag, "localparam int Bar = 1;"}, | |
| " ", | |
| {kTag, "localparam int BarSecond = 2;"}, | |
| " endmodule"}, | |
| {"class foo; ", {kTag, "localparam int Bar = 1;"}, " endclass"}, | |
| {"class foo #(", {kTag, "parameter int Bar = 1"}, "); endclass"}, | |
| {"package foo; ", {kTag, "parameter Bar = 1;"}, " endpackage"}, | |
| {"package foo; ", {kTag, "parameter int Bar = 1;"}, " endpackage"}, | |
| {{kTag, "parameter int Bar = 1;"}}, | |
| {{kTag, "parameter Bar = 1;"}}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| TestVerilogSyntaxRangeMatches( | |
| __FUNCTION__, test, [](const TextStructureView& text_structure) { | |
| const auto& root = text_structure.SyntaxTree(); | |
| return FindAllParamDeclarations(*ABSL_DIE_IF_NULL(root)); | |
| }); | |
| } | |
| } | |
| // Tests that GetParamKeyword correctly returns that the parameter type is | |
| // localparam. | |
| TEST(GetParamKeywordTest, LocalParamDeclared) { | |
| constexpr std::pair<absl::string_view, int> kTestCases[] = { | |
| {"module foo; localparam int Bar = 1; endmodule", 1}, | |
| {"class foo; localparam int Bar = 1; endclass", 1}, | |
| {"module foo; localparam Bar = 1; endmodule", 1}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| ASSERT_EQ(param_declarations.size(), test.second); | |
| const auto& param_node = down_cast<const verible::SyntaxTreeNode&>( | |
| *param_declarations.front().match); | |
| const auto param_keyword = GetParamKeyword(param_node); | |
| EXPECT_EQ(param_keyword, TK_localparam); | |
| } | |
| } | |
| // Tests that GetParamKeyword correctly returns that the parameter type is | |
| // parameter. | |
| TEST(GetParamKeywordTest, ParameterDeclared) { | |
| constexpr std::pair<absl::string_view, int> kTestCases[] = { | |
| {"module foo; parameter int Bar = 1; endmodule", 1}, | |
| {"module foo #(parameter int Bar = 1); endmodule", 1}, | |
| {"module foo #(int Bar = 1); endmodule", 1}, | |
| {"class foo; parameter int Bar = 1; endclass", 1}, | |
| {"class foo #(parameter int Bar = 1); endclass", 1}, | |
| {"class foo #(int Bar = 1); endclass", 1}, | |
| {"package foo; parameter int Bar = 1; endpackage", 1}, | |
| {"package foo; parameter Bar = 1; endpackage", 1}, | |
| {"parameter int Bar = 1;", 1}, | |
| {"parameter Bar = 1;", 1}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| ASSERT_EQ(param_declarations.size(), test.second); | |
| const auto& param_node = down_cast<const verible::SyntaxTreeNode&>( | |
| *param_declarations.front().match); | |
| const auto param_keyword = GetParamKeyword(param_node); | |
| EXPECT_EQ(param_keyword, TK_parameter); | |
| } | |
| } | |
| // Tests that GetParamKeyword correctly returns the parameter type when multiple | |
| // parameters are defined. | |
| TEST(GetParamKeywordTest, MultipleParamsDeclared) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; parameter int Bar = 1; localparam int Bar_2 = 2; " | |
| "endmodule"}, | |
| {"class foo; parameter int Bar = 1; localparam int Bar_2 = 2; endclass"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| // Make sure the first one is TK_parameter. | |
| const auto& param_node = | |
| down_cast<const verible::SyntaxTreeNode&>(*param_declarations[0].match); | |
| const auto param_keyword = GetParamKeyword(param_node); | |
| EXPECT_EQ(param_keyword, TK_parameter); | |
| // Make sure the second one is TK_localparam. | |
| const auto& localparam_node = | |
| down_cast<const verible::SyntaxTreeNode&>(*param_declarations[1].match); | |
| const auto localparam_keyword = GetParamKeyword(localparam_node); | |
| EXPECT_EQ(localparam_keyword, TK_localparam); | |
| } | |
| } | |
| // Tests that GetParamTypeSymbol correctly returns the kParamType node. | |
| TEST(GetParamTypeSymbolTest, BasicTests) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule"}, | |
| {"module foo; parameter int Bar = 1; endmodule"}, | |
| {"module foo #(parameter int Bar = 1); endmodule"}, | |
| {"module foo; localparam int Bar = 1; endmodule"}, | |
| {"class foo; parameter int Bar = 1; endclass"}, | |
| {"class foo; localparam int Bar = 1; endclass"}, | |
| {"package foo; parameter int Bar = 1; endpackage"}, | |
| {"parameter int Bar = 1;"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto* param_type_symbol = | |
| GetParamTypeSymbol(*param_declarations.front().match); | |
| const auto t = param_type_symbol->Tag(); | |
| EXPECT_EQ(t.kind, verible::SymbolKind::kNode); | |
| EXPECT_EQ(NodeEnum(t.tag), NodeEnum::kParamType); | |
| } | |
| } | |
| // Tests that GetParameterNameToken correctly returns the token of the | |
| // parameter. | |
| TEST(GetParameterNameTokenTest, BasicTests) { | |
| constexpr std::pair<absl::string_view, absl::string_view> kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule", "Bar"}, | |
| {"module foo; localparam Bar_1 = 1; endmodule", "Bar_1"}, | |
| {"module foo; localparam int HelloWorld = 1; endmodule", "HelloWorld"}, | |
| {"module foo #(parameter int HelloWorld1 = 1); endmodule", "HelloWorld1"}, | |
| {"class foo; parameter HelloWorld_1 = 1; endclass", "HelloWorld_1"}, | |
| {"class foo; localparam FooBar = 1; endclass", "FooBar"}, | |
| {"class foo; localparam int Bar_1_1 = 1; endclass", "Bar_1_1"}, | |
| {"package foo; parameter BAR = 1; endpackage", "BAR"}, | |
| {"package foo; parameter int HELLO_WORLD = 1; endpackage", "HELLO_WORLD"}, | |
| {"parameter int Bar = 1;", "Bar"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto name_token = | |
| GetParameterNameToken(*param_declarations.front().match); | |
| EXPECT_EQ(name_token->text(), test.second); | |
| } | |
| } | |
| // Test that GetAllParameterNameTokens correctly returns all tokens | |
| TEST(GetAllParameterNameTokensTest, BasicTests) { | |
| constexpr std::pair<absl::string_view, int> kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule", 1}, | |
| {"module foo; localparam Bar_1 = 1; endmodule", 1}, | |
| {"module foo; localparam int HelloWorld = 1; endmodule", 1}, | |
| {"module foo #(parameter int HelloWorld1 = 1); endmodule", 1}, | |
| {"class foo; parameter HelloWorld_1 = 1; endclass", 1}, | |
| {"class foo; localparam FooBar = 1; endclass", 1}, | |
| {"class foo; localparam int Bar_1_1 = 1; endclass", 1}, | |
| {"package foo; parameter BAR = 1; endpackage", 1}, | |
| {"package foo; parameter int HELLO_WORLD = 1; endpackage", 1}, | |
| {"parameter int Bar = 1;", 1}, | |
| {"parameter int Bar = 1, Foo = 1;", 2}, | |
| {"parameter int Bar = 1, Foo = 1, Baz = 1;", 3}, | |
| {"module foo; parameter int Bar = 1; endmodule;", 1}, | |
| {"module foo; parameter int Bar = 1, Foo = 1; endmodule;", 2}, | |
| {"module foo; parameter int Bar = 1, Foo = 1, Baz = 1; endmodule;", 3}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto name_tokens = | |
| GetAllParameterNameTokens(*param_declarations.front().match); | |
| EXPECT_EQ(name_tokens.size(), test.second); | |
| } | |
| } | |
| // Tests that GetAllAssignedParameterSymbols correctly returns all the | |
| // symbols for each kParameterAssign node | |
| TEST(GetAllAssignedParameterSymbolsTest, BasicTests) { | |
| constexpr std::pair<absl::string_view, int> kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule", 0}, | |
| {"module foo; localparam Bar_1 = 1; endmodule", 0}, | |
| {"module foo; localparam int HelloWorld = 1; endmodule", 0}, | |
| {"module foo #(parameter int HelloWorld1 = 1); endmodule", 0}, | |
| {"class foo; parameter HelloWorld_1 = 1; endclass", 0}, | |
| {"class foo; localparam FooBar = 1; endclass", 0}, | |
| {"class foo; localparam int Bar_1_1 = 1; endclass", 0}, | |
| {"package foo; parameter BAR = 1; endpackage", 0}, | |
| {"package foo; parameter int HELLO_WORLD = 1; endpackage", 0}, | |
| {"parameter int Bar = 1;", 0}, | |
| {"parameter int Bar = 1, Foo = 1;", 1}, | |
| {"parameter int Bar = 1, Foo = 1, Baz = 1;", 2}, | |
| {"module foo; parameter int Bar = 1; endmodule;", 0}, | |
| {"module foo; parameter int Bar = 1, Foo = 1; endmodule;", 1}, | |
| {"module foo; parameter int Bar = 1, Foo = 1, Baz = 1; endmodule;", 2}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto assigned_parameters = | |
| GetAllAssignedParameterSymbols(*param_declarations.front().match); | |
| EXPECT_EQ(assigned_parameters.size(), test.second); | |
| } | |
| } | |
| TEST(GetAssignedParameterNameToken, BasicTests) { | |
| constexpr std::pair<absl::string_view, absl::string_view> kTestCases[] = { | |
| {"parameter int Bar = 1, Foo = 1;", "Foo"}, | |
| {"module foo; parameter int Bar = 1, Fox = 1; endmodule;", "Fox"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto assigned_parameters = | |
| GetAllAssignedParameterSymbols(*param_declarations.front().match); | |
| EXPECT_EQ(assigned_parameters.size(), 1); | |
| const auto name_token = | |
| GetAssignedParameterNameToken(*assigned_parameters.front()); | |
| EXPECT_EQ(name_token->text(), test.second); | |
| } | |
| } | |
| // Tests that GetSymbolIdentifierFromParamDeclaration correctly returns the | |
| // token of the symbol identifier. | |
| TEST(GetSymbolIdentifierFromParamDeclarationTest, BasicTests) { | |
| constexpr std::pair<absl::string_view, absl::string_view> kTestCases[] = { | |
| {"module foo; parameter type Bar; endmodule", "Bar"}, | |
| {"module foo; localparam type Bar_1; endmodule", "Bar_1"}, | |
| {"module foo #(parameter type HelloWorld1); endmodule", "HelloWorld1"}, | |
| {"class foo #(parameter type Bar); endclass", "Bar"}, | |
| {"class foo; parameter type HelloWorld_1; endclass", "HelloWorld_1"}, | |
| {"class foo; localparam type Bar_1_1; endclass", "Bar_1_1"}, | |
| {"package foo; parameter type HELLO_WORLD; endpackage", "HELLO_WORLD"}, | |
| {"parameter type Bar;", "Bar"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto name_token = GetSymbolIdentifierFromParamDeclaration( | |
| *param_declarations.front().match); | |
| EXPECT_EQ(name_token->text(), test.second); | |
| } | |
| } | |
| // Tests that IsParamTypeDeclaration correctly returns true if the parameter is | |
| // a parameter type declaration. | |
| TEST(IsParamTypeDeclarationTest, BasicTests) { | |
| constexpr std::pair<absl::string_view, bool> kTestCases[] = { | |
| {"module foo; parameter type Bar; endmodule", true}, | |
| {"module foo; localparam type Bar_1; endmodule", true}, | |
| {"module foo #(parameter type HelloWorld1); endmodule", true}, | |
| {"class foo #(parameter type Bar); endclass", true}, | |
| {"class foo; parameter type HelloWorld_1; endclass", true}, | |
| {"class foo; localparam type Bar_1_1; endclass", true}, | |
| {"package foo; parameter type HELLO_WORLD; endpackage", true}, | |
| {"parameter type Bar;", true}, | |
| {"module foo; parameter Bar = 1; endmodule", false}, | |
| {"module foo; localparam int HelloWorld = 1; endmodule", false}, | |
| {"module foo #(parameter int HelloWorld1 = 1); endmodule", false}, | |
| {"class foo; parameter HelloWorld_1 = 1; endclass", false}, | |
| {"class foo; localparam FooBar = 1; endclass", false}, | |
| {"package foo; parameter int HELLO_WORLD = 1; endpackage", false}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test.first, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto is_param_type = | |
| IsParamTypeDeclaration(*param_declarations.front().match); | |
| EXPECT_EQ(is_param_type, test.second); | |
| } | |
| } | |
| // Tests that GetTypeAssignmentFromParamDeclaration correctly returns the | |
| // kTypeAssignment node. | |
| TEST(GetTypeAssignmentFromParamDeclarationTests, BasicTests) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; parameter type Bar = 1; endmodule"}, | |
| {"module foo #(parameter type Bar = 1); endmodule"}, | |
| {"module foo; localparam type Bar = 1; endmodule"}, | |
| {"class foo; parameter type Bar = 1; endclass"}, | |
| {"class foo; localparam type Bar = 1; endclass"}, | |
| {"package foo; parameter type Bar = 1; endpackage"}, | |
| {"parameter type Bar = 1;"}, | |
| {"module m#(parameter type Bar)();\nendmodule"}, | |
| {"module m#(parameter Bar)();\nendmodule"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto* type_assignment_symbol = GetTypeAssignmentFromParamDeclaration( | |
| *param_declarations.front().match); | |
| if (type_assignment_symbol == nullptr) { | |
| continue; | |
| } | |
| const auto t = type_assignment_symbol->Tag(); | |
| EXPECT_EQ(t.kind, verible::SymbolKind::kNode); | |
| EXPECT_EQ(NodeEnum(t.tag), NodeEnum::kTypeAssignment); | |
| } | |
| } | |
| // Tests that GetIdentifierLeafFromTypeAssignment correctly returns the | |
| // SyntaxTreeLeaf of the symbol identifier. | |
| TEST(GetIdentifierLeafFromTypeAssignmentTest, BasicTests) { | |
| constexpr int kTag = 1; // don't care | |
| const SyntaxTreeSearchTestCase kTestCases[] = { | |
| {"module foo; parameter type ", {kTag, "Bar"}, "; endmodule"}, | |
| {"module foo; localparam type ", {kTag, "Bar_1"}, "; endmodule"}, | |
| {"module foo #(parameter type ", {kTag, "HelloWorld1"}, "); endmodule"}, | |
| {"class foo #(parameter type ", {kTag, "Bar"}, "); endclass"}, | |
| {"class foo; parameter type ", {kTag, "HelloWorld_1"}, "; endclass"}, | |
| {"class foo; localparam type ", {kTag, "Bar_1_1"}, "; endclass"}, | |
| {"package foo; parameter type ", {kTag, "HELLO_WORLD"}, "; endpackage"}, | |
| {"parameter type ", {kTag, "Bar"}, ";"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| TestVerilogSyntaxRangeMatches( | |
| __FUNCTION__, test, [](const TextStructureView& text_structure) { | |
| const auto& root = text_structure.SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| std::vector<TreeSearchMatch> ids; | |
| for (const auto& decl : param_declarations) { | |
| const auto* type_assignment_symbol = | |
| GetTypeAssignmentFromParamDeclaration(*decl.match); | |
| ids.push_back(TreeSearchMatch{ | |
| GetIdentifierLeafFromTypeAssignment(*type_assignment_symbol), | |
| /* no context */}); | |
| } | |
| return ids; | |
| }); | |
| } | |
| } | |
| // Tests that GetParamTypeInfoSymbol correctly returns the kTypeInfo node. | |
| TEST(GetParamTypeInfoSymbolTest, BasicTests) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule"}, | |
| {"module foo; parameter int Bar = 1; endmodule"}, | |
| {"module foo #(parameter int Bar = 1); endmodule"}, | |
| {"module foo; localparam int Bar = 1; endmodule"}, | |
| {"class foo; parameter int Bar = 1; endclass"}, | |
| {"class foo; localparam int Bar = 1; endclass"}, | |
| {"package foo; parameter int Bar = 1; endpackage"}, | |
| {"parameter int Bar = 1;"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto* type_info_symbol = | |
| GetParamTypeInfoSymbol(*param_declarations.front().match); | |
| const auto t = type_info_symbol->Tag(); | |
| EXPECT_EQ(t.kind, verible::SymbolKind::kNode); | |
| EXPECT_EQ(NodeEnum(t.tag), NodeEnum::kTypeInfo); | |
| } | |
| } | |
| TEST(IsTypeInfoEmptyTest, EmptyTests) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; parameter Bar = 1; endmodule"}, | |
| {"module foo #(parameter Bar = 1); endmodule"}, | |
| {"module foo; localparam Bar = 1; endmodule"}, | |
| {"class foo; parameter Bar = 1; endclass"}, | |
| {"class foo; localparam Bar = 1; endclass"}, | |
| {"package foo; parameter Bar = 1; endpackage"}, | |
| {"parameter Bar = 1;"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto* type_info_symbol = | |
| GetParamTypeInfoSymbol(*param_declarations.front().match); | |
| const auto t = type_info_symbol->Tag(); | |
| EXPECT_EQ(t.kind, verible::SymbolKind::kNode); | |
| EXPECT_EQ(NodeEnum(t.tag), NodeEnum::kTypeInfo); | |
| EXPECT_TRUE(IsTypeInfoEmpty(*type_info_symbol)); | |
| } | |
| } | |
| TEST(IsTypeInfoEmptyTest, NonEmptyTests) { | |
| constexpr absl::string_view kTestCases[] = { | |
| {"module foo; localparam bit Bar = 1; endmodule"}, | |
| {"module foo #(parameter int Bar = 1); endmodule"}, | |
| {"module foo; parameter int Bar = 1; endmodule"}, | |
| {"class foo; parameter string Bar = \"Bar\"; endclass"}, | |
| {"class foo; localparam logic Bar = 1; endclass"}, | |
| {"parameter int Bar = 1;"}, | |
| {"parameter signed Bar = 1;"}, | |
| {"parameter unsigned Bar = 1;"}, | |
| {"parameter int unsigned Bar = 1;"}, | |
| {"parameter Other_t Bar = other_t::kEnum;"}, | |
| {"parameter pkg_p::Other_t Bar = other_t::kEnum;"}, | |
| {"module foo; localparam int signed Bar = 1; endmodule"}, | |
| {"module foo #(parameter signed Bar = 1); endmodule"}, | |
| {"module foo #(parameter int signed Bar = 1); endmodule"}, | |
| {"module foo #(parameter Other_t Bar); endmodule"}, | |
| {"module foo #(parameter pkg::Other_t Bar); endmodule"}, | |
| {"module foo #(parameter pkg::Other_t Bar = enum_e::value); endmodule"}, | |
| {"class foo #(parameter Other_t Bar); endclass"}, | |
| {"class foo #(parameter pkg::Other_t Bar); endclass"}, | |
| {"class foo #(parameter pkg::Other_t Bar = enum_e::value); endclass"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| VerilogAnalyzer analyzer(test, ""); | |
| ASSERT_OK(analyzer.Analyze()); | |
| const auto& root = analyzer.Data().SyntaxTree(); | |
| const auto param_declarations = FindAllParamDeclarations(*root); | |
| const auto* type_info_symbol = | |
| GetParamTypeInfoSymbol(*param_declarations.front().match); | |
| const auto t = type_info_symbol->Tag(); | |
| EXPECT_EQ(t.kind, verible::SymbolKind::kNode); | |
| EXPECT_EQ(NodeEnum(t.tag), NodeEnum::kTypeInfo); | |
| EXPECT_FALSE(IsTypeInfoEmpty(*type_info_symbol)); | |
| } | |
| } | |
| TEST(FindAllParamByNameTest, FindNamesOfParams) { | |
| constexpr int kTag = 1; // value doesn't matter | |
| const SyntaxTreeSearchTestCase kTestCases[] = { | |
| {""}, | |
| {"module m;\nendmodule\n"}, | |
| {"module m;\n module_type #(2, 2) y1();\nendmodule"}, | |
| {"module m;\n module_type #(.", | |
| {kTag, "P"}, | |
| "(2), .", | |
| {kTag, "P2"}, | |
| "(2)) y1();\nendmodule"}, | |
| {"module m;\n module_type #(.", | |
| {kTag, "P"}, | |
| "(2), .", | |
| {kTag, "P1"}, | |
| "(3)) y1();\nendmodule"}, | |
| {"module m;\n module_type #(x, y) y1();\nendmodule"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| TestVerilogSyntaxRangeMatches( | |
| __FUNCTION__, test, [](const TextStructureView& text_structure) { | |
| const auto& root = text_structure.SyntaxTree(); | |
| const auto& instances = FindAllNamedParams(*ABSL_DIE_IF_NULL(root)); | |
| std::vector<TreeSearchMatch> params; | |
| for (const auto& instance : instances) { | |
| const auto* decl = GetNamedParamFromActualParam(*instance.match); | |
| params.emplace_back(TreeSearchMatch{decl, {/* ignored context */}}); | |
| } | |
| return params; | |
| }); | |
| } | |
| } | |
| TEST(FindAllParamByNameTest, FindParenGroupOfNamedParam) { | |
| constexpr int kTag = 1; // value doesn't matter | |
| const SyntaxTreeSearchTestCase kTestCases[] = { | |
| {""}, | |
| {"module m;\nendmodule\n"}, | |
| {"module m;\n module_type #(2, 2) y1();\nendmodule"}, | |
| {"module m;\n module_type #(.P", | |
| {kTag, "(2)"}, | |
| ", .P2", | |
| {kTag, "(2)"}, | |
| ") y1();\nendmodule"}, | |
| {"module m;\n module_type #(.P", | |
| {kTag, "(2)"}, | |
| ", .P1", | |
| {kTag, "(3)"}, | |
| ") y1();\nendmodule"}, | |
| {"module m;\n module_type #(x, y) y1();\nendmodule"}, | |
| {"module m;\n module_type #(.x, .y) y1();\nendmodule"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| TestVerilogSyntaxRangeMatches( | |
| __FUNCTION__, test, [](const TextStructureView& text_structure) { | |
| const auto& root = text_structure.SyntaxTree(); | |
| const auto& instances = FindAllNamedParams(*ABSL_DIE_IF_NULL(root)); | |
| std::vector<TreeSearchMatch> paren_groups; | |
| for (const auto& instance : instances) { | |
| const auto* paren_group = | |
| GetParenGroupFromActualParam(*instance.match); | |
| if (paren_group == nullptr) { | |
| continue; | |
| } | |
| paren_groups.emplace_back( | |
| TreeSearchMatch{paren_group, {/* ignored context */}}); | |
| } | |
| return paren_groups; | |
| }); | |
| } | |
| } | |
| TEST(FindAllParamTest, FindExpressionFromParameterType) { | |
| constexpr int kTag = 1; // value doesn't matter | |
| const SyntaxTreeSearchTestCase kTestCases[] = { | |
| {""}, | |
| {"module m;\nendmodule\n"}, | |
| {"module foo; parameter type Bar = ", {kTag, "1"}, "; endmodule"}, | |
| {"module foo #(parameter type Bar = ", {kTag, "H.y"}, "); endmodule"}, | |
| {"module foo; localparam type Bar = ", {kTag, "var1"}, "; endmodule"}, | |
| {"class foo; parameter type Bar = ", {kTag, "1"}, "; endclass"}, | |
| {"class foo; localparam type Bar = ", {kTag, "1"}, "; endclass"}, | |
| {"package foo; parameter type Bar = ", {kTag, "1"}, "; endpackage"}, | |
| {"parameter type Bar = ", {kTag, "1"}, ";"}, | |
| {"module foo #(parameter type Bar = int); endmodule"}, | |
| {"module foo #(parameter type Bar = ", {kTag, "Foo#(1)"}, "); endmodule"}, | |
| {"module foo #(parameter type Bar = ", | |
| {kTag, "Foo#(int)"}, | |
| "); endmodule"}, | |
| {"module foo #(parameter type Bar = ", | |
| {kTag, "Foo#(Baz#(int))"}, | |
| "); endmodule"}, | |
| }; | |
| for (const auto& test : kTestCases) { | |
| TestVerilogSyntaxRangeMatches( | |
| __FUNCTION__, test, [](const TextStructureView& text_structure) { | |
| const auto& root = text_structure.SyntaxTree(); | |
| const auto& types = FindAllParamDeclarations(*ABSL_DIE_IF_NULL(root)); | |
| std::vector<TreeSearchMatch> expressions; | |
| for (const auto& type : types) { | |
| const auto* type_assignment = | |
| GetTypeAssignmentFromParamDeclaration(*type.match); | |
| if (type_assignment == nullptr) { | |
| continue; | |
| } | |
| const auto* expression = | |
| GetExpressionFromTypeAssignment(*type_assignment); | |
| if (expression == nullptr) { | |
| continue; | |
| } | |
| expressions.emplace_back( | |
| TreeSearchMatch{expression, {/* ignored context */}}); | |
| } | |
| return expressions; | |
| }); | |
| } | |
| } | |
| } // namespace | |
| } // namespace verilog |