blob: 7d5b7cb93048049ea2f9834838144e5225d21d6f [file] [log] [blame]
// 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/seq_block.h"
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
#include "common/analysis/syntax_tree_search.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/text_structure.h"
#include "common/util/logging.h"
#include "verilog/CST/verilog_matchers.h"
#include "verilog/CST/verilog_nonterminals.h"
#include "verilog/analysis/verilog_analyzer.h"
#undef ASSERT_OK
#define ASSERT_OK(value) ASSERT_TRUE((value).ok())
namespace verilog {
namespace {
static std::vector<verible::TreeSearchMatch> FindAllBeginStatements(
const verible::Symbol& root) {
return SearchSyntaxTree(root, NodekBegin());
}
TEST(GetMatchingEndTest, Simple) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin
end
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 1);
const auto matchingEnd =
GetMatchingEnd(*begin_statements[0].match, begin_statements[0].context);
EXPECT_EQ(NodeEnum(matchingEnd->Tag().tag), NodeEnum::kEnd);
}
TEST(GetBeginLabelTokenInfoTest, Single) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin : begin_label
end
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 1);
const auto* beginToken = GetBeginLabelTokenInfo(*begin_statements[0].match);
EXPECT_EQ(ABSL_DIE_IF_NULL(beginToken)->text(), "begin_label");
}
TEST(GetBeginLabelTokenInfoTest, SingleNoLabel) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin
end : begin_has_no_label
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 1);
const auto* beginToken = GetBeginLabelTokenInfo(*begin_statements[0].match);
EXPECT_EQ(beginToken, nullptr);
}
TEST(GetEndLabelTokenInfoTest, SingleNoLabel) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin : end_has_no_label
end
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 1);
const auto* matchingEnd =
GetMatchingEnd(*begin_statements[0].match, begin_statements[0].context);
ASSERT_EQ(NodeEnum(matchingEnd->Tag().tag), NodeEnum::kEnd);
const auto* endToken = GetEndLabelTokenInfo(*matchingEnd);
EXPECT_EQ(endToken, nullptr);
}
TEST(GetEndLabelTokenInfoTest, Single) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin
end : end_label
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 1);
const auto* matchingEnd =
GetMatchingEnd(*begin_statements[0].match, begin_statements[0].context);
ASSERT_EQ(NodeEnum(matchingEnd->Tag().tag), NodeEnum::kEnd);
const auto* endToken = GetEndLabelTokenInfo(*matchingEnd);
EXPECT_EQ(ABSL_DIE_IF_NULL(endToken)->text(), "end_label");
}
TEST(GetMatchingEndTest, Complex) {
VerilogAnalyzer analyzer(R"(
module foo;
initial begin : outer_begin_label
for(int i = 0; i < 5; ++i)
begin : inner_begin_label
end : inner_end_label
end : outer_end_label
endmodule)",
"");
ASSERT_OK(analyzer.Analyze());
const auto& root = analyzer.Data().SyntaxTree();
const auto begin_statements = FindAllBeginStatements(*root);
ASSERT_EQ(begin_statements.size(), 2);
const auto* matchingOuterEnd =
GetMatchingEnd(*begin_statements[0].match, begin_statements[0].context);
ASSERT_EQ(NodeEnum(matchingOuterEnd->Tag().tag), NodeEnum::kEnd);
const auto* matchingInnerEnd =
GetMatchingEnd(*begin_statements[1].match, begin_statements[1].context);
ASSERT_EQ(NodeEnum(matchingInnerEnd->Tag().tag), NodeEnum::kEnd);
const auto& outerBeginToken =
*ABSL_DIE_IF_NULL(GetBeginLabelTokenInfo(*begin_statements[0].match));
const auto& innerBeginToken =
*ABSL_DIE_IF_NULL(GetBeginLabelTokenInfo(*begin_statements[1].match));
const auto& outerEndToken =
*ABSL_DIE_IF_NULL(GetEndLabelTokenInfo(*matchingOuterEnd));
const auto& innerEndToken =
*ABSL_DIE_IF_NULL(GetEndLabelTokenInfo(*matchingInnerEnd));
EXPECT_EQ(outerBeginToken.text(), "outer_begin_label");
EXPECT_EQ(outerEndToken.text(), "outer_end_label");
EXPECT_EQ(innerBeginToken.text(), "inner_begin_label");
EXPECT_EQ(innerEndToken.text(), "inner_end_label");
}
} // namespace
} // namespace verilog