blob: 027556d02713240637b71d2a009c52e0adc22882 [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/tools/kythe/scope_resolver.h"
#include <vector>
#include "gtest/gtest.h"
#include "verilog/tools/kythe/kythe_facts.h"
namespace verilog {
namespace kythe {
namespace {
constexpr absl::string_view names[] = {
"signature0", "signature1", "signature2", "signature3",
"signature4", "signature5", "signature6", "signature7",
"signature8", "signature9", "",
};
static const std::vector<Signature> signatures{
Signature(names[0]),
Signature(names[1]),
Signature(names[2]),
Signature(names[3]),
Signature(names[4]),
Signature(Signature(names[5]), names[6]),
Signature(Signature(Signature(names[7]), names[8]), names[9]),
Signature(names[10]),
};
static const std::vector<VName> vnames{
{.path = "", .root = "", .signature = signatures[0], .corpus = ""},
{.path = "", .root = "", .signature = signatures[1], .corpus = ""},
{.path = "", .root = "", .signature = signatures[2], .corpus = ""},
{.path = "", .root = "", .signature = signatures[3], .corpus = ""},
{.path = "", .root = "", .signature = signatures[4], .corpus = ""},
{.path = "", .root = "", .signature = signatures[5], .corpus = ""},
{.path = "", .root = "", .signature = signatures[6], .corpus = ""},
{.path = "", .root = "", .signature = signatures[7], .corpus = ""},
};
TEST(ScopeResolverTests, ScopeResolverLinkedList) {
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
ScopeResolver scope_resolver1(Signature("file1"), nullptr);
scope_resolver1.MapSignatureToScope(signatures[0], scope);
ScopeResolver scope_resolver(Signature("file2"), &scope_resolver1);
{
Scope global_scope(signatures[7]);
ScopeContext::AutoPop p1(&scope_resolver.GetMutableScopeContext(),
&global_scope);
scope_resolver.AddDefinitionToCurrentScope(vnames[0]);
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[1]});
EXPECT_EQ(vnames.size(), 2);
EXPECT_EQ(vnames[1].first->signature, signatures[1]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[2]});
EXPECT_EQ(vnames.size(), 2);
EXPECT_EQ(vnames[1].first->signature, signatures[2]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[3]});
EXPECT_EQ(vnames.size(), 1);
EXPECT_EQ(vnames[0].first->signature, signatures[0]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[2], names[1]});
EXPECT_TRUE(vnames.empty());
}
}
}
TEST(ScopesTest, AppendScope) {
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*
* signature[1] => {
* vnames[3], ==> signature[3];
* vnames[4], ==> signature[4];
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
Scope scope2(signatures[1]);
scope2.AddMemberItem(vnames[3]);
scope2.AddMemberItem(vnames[4]);
scope2.AppendScope(scope);
{
const VName* vname = scope2.SearchForDefinition(names[1]);
EXPECT_EQ(vname->signature, signatures[1]);
}
{
const VName* vname = scope2.SearchForDefinition(names[2]);
EXPECT_EQ(vname->signature, signatures[2]);
}
{
const VName* vname = scope2.SearchForDefinition(names[3]);
EXPECT_EQ(vname->signature, signatures[3]);
}
{
const VName* vname = scope2.SearchForDefinition(names[4]);
EXPECT_EQ(vname->signature, signatures[4]);
}
}
TEST(ScopesTest, RemoveMember) {
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*
* signature[1] => {
* vnames[3], ==> signature[3];
* vnames[4], ==> signature[4];
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
{
const VName* vname = scope.SearchForDefinition(names[1]);
EXPECT_EQ(vname->signature, signatures[1]);
}
{
scope.RemoveMember(vnames[1]);
const VName* vname = scope.SearchForDefinition(names[1]);
EXPECT_EQ(vname, nullptr);
}
{
const VName* vname = scope.SearchForDefinition(names[2]);
EXPECT_EQ(vname->signature, signatures[2]);
}
}
TEST(ScopeResolverTests, SearchForDefinition) {
ScopeResolver scope_resolver(Signature(""), nullptr);
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
{
Scope global_scope(signatures[7]);
ScopeContext::AutoPop p1(&scope_resolver.GetMutableScopeContext(),
&global_scope);
scope_resolver.AddDefinitionToCurrentScope(vnames[0]);
scope_resolver.MapSignatureToScope(signatures[0], scope);
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[1]});
EXPECT_EQ(vnames.size(), 2);
EXPECT_EQ(vnames[1].first->signature, signatures[1]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[2]});
EXPECT_EQ(vnames.size(), 2);
EXPECT_EQ(vnames[1].first->signature, signatures[2]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[3]});
EXPECT_EQ(vnames.size(), 1);
EXPECT_EQ(vnames[0].first->signature, signatures[0]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[2], names[1]});
EXPECT_TRUE(vnames.empty());
}
}
}
TEST(ScopeResolverTests, SearchForDefinitionInCurrentScope) {
ScopeResolver scope_resolver(Signature(""), nullptr);
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
{
ScopeContext::AutoPop p1(&scope_resolver.GetMutableScopeContext(), &scope);
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[1]);
EXPECT_EQ(vname->signature, signatures[1]);
}
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[2]);
EXPECT_EQ(vname->signature, signatures[2]);
}
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[3]);
EXPECT_EQ(vname, nullptr);
}
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[4]);
EXPECT_EQ(vname, nullptr);
}
}
}
TEST(ScopeResolverTests, DeleteDefinitionFromCurrentScope) {
ScopeResolver scope_resolver(Signature(""), nullptr);
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
{
ScopeContext::AutoPop p1(&scope_resolver.GetMutableScopeContext(), &scope);
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[1]);
EXPECT_EQ(vname->signature, signatures[1]);
}
{
scope_resolver.RemoveDefinitionFromCurrentScope(vnames[1]);
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[1]);
EXPECT_EQ(vname, nullptr);
}
{
const VName* vname =
scope_resolver.SearchForDefinitionInCurrentScope(names[2]);
EXPECT_EQ(vname->signature, signatures[2]);
}
}
}
TEST(ScopeResolverTests, SearchForNestedDefinition) {
ScopeResolver scope_resolver(Signature(""), nullptr);
/**
* signature[0] => {
* vnames[1], ==> signature[1]
* vnames[2], ==> signature[2]
* }
*
* signature[1] => {
* vnames[3], ==> signature[3];
* vnames[4], ==> signature[4];
* }
*
*/
Scope scope(signatures[0]);
scope.AddMemberItem(vnames[1]);
scope.AddMemberItem(vnames[2]);
Scope scope2(signatures[1]);
scope2.AddMemberItem(vnames[3]);
scope2.AddMemberItem(vnames[4]);
{
Scope global_scope(signatures[7]);
ScopeContext::AutoPop p1(&scope_resolver.GetMutableScopeContext(),
&global_scope);
scope_resolver.AddDefinitionToCurrentScope(vnames[0]);
scope_resolver.AddDefinitionToCurrentScope(vnames[1]);
scope_resolver.AddDefinitionToCurrentScope(vnames[5]);
scope_resolver.MapSignatureToScope(signatures[0], scope);
scope_resolver.MapSignatureToScope(signatures[1], scope2);
{
const Scope* found_scope = scope_resolver.SearchForScope(signatures[0]);
EXPECT_NE(found_scope, nullptr);
}
{
const Scope* found_scope = scope_resolver.SearchForScope(signatures[1]);
EXPECT_NE(found_scope, nullptr);
}
{
const Scope* found_scope = scope_resolver.SearchForScope(signatures[6]);
EXPECT_EQ(found_scope, nullptr);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[0], names[1]});
EXPECT_EQ(vnames[1].first->signature, signatures[1]);
}
{
const std::vector<std::pair<const VName*, const Scope*>> vnames =
scope_resolver.SearchForDefinitions({names[1], names[3]});
EXPECT_EQ(vnames[1].first->signature, signatures[3]);
}
}
}
TEST(VerticalScopeTests, SearchForDefinition) {
ScopeContext vertical_scope_resolver;
EXPECT_TRUE(vertical_scope_resolver.empty());
{
Scope scope;
ScopeContext::AutoPop p1(&vertical_scope_resolver, &scope);
vertical_scope_resolver.top().AddMemberItem(vnames[0]);
EXPECT_EQ(vertical_scope_resolver.top().GetSignature(), Signature(""));
EXPECT_EQ(vertical_scope_resolver.top().Members().size(), 1);
{
const VName* vname =
vertical_scope_resolver.SearchForDefinition(names[0]);
EXPECT_EQ(vname->signature, vnames[0].signature);
}
{
const VName* vname =
vertical_scope_resolver.SearchForDefinition(names[1]);
EXPECT_EQ(vname, nullptr);
}
vertical_scope_resolver.top().AddMemberItem(vnames[1]);
EXPECT_EQ(vertical_scope_resolver.top().Members().size(), 2);
{
const VName* vname =
vertical_scope_resolver.SearchForDefinition(names[1]);
EXPECT_EQ(vname->signature, signatures[1]);
}
}
EXPECT_TRUE(vertical_scope_resolver.empty());
}
TEST(ScopeResolverTests, NestedScopeSearch) {
ScopeContext scope_resolver;
EXPECT_TRUE(scope_resolver.empty());
Scope scope;
ScopeContext::AutoPop p1(&scope_resolver, &scope);
{
scope_resolver.top().AddMemberItem(vnames[0]);
EXPECT_EQ(scope_resolver.top().GetSignature(), Signature(""));
EXPECT_EQ(scope_resolver.top().Members().size(), 1);
const VName* vname = scope_resolver.SearchForDefinition(names[0]);
EXPECT_EQ(vname->signature, vnames[0].signature);
Scope scope(signatures[4]);
ScopeContext::AutoPop p1(&scope_resolver, &scope);
{
scope_resolver.top().AddMemberItem(vnames[6]);
EXPECT_EQ(scope_resolver.top().GetSignature(), signatures[4]);
EXPECT_EQ(scope_resolver.top().Members().size(), 1);
{
const VName* vname = scope_resolver.SearchForDefinition(names[9]);
EXPECT_EQ(vname->signature, vnames[6].signature);
}
{
const VName* vname = scope_resolver.SearchForDefinition(names[8]);
EXPECT_EQ(vname, nullptr);
}
{
const VName* vname = scope_resolver.SearchForDefinition(names[0]);
EXPECT_EQ(vname->signature, vnames[0].signature);
}
Scope scope(signatures[6]);
ScopeContext::AutoPop p1(&scope_resolver, &scope);
{
scope_resolver.top().AddMemberItem(vnames[2]);
EXPECT_EQ(scope_resolver.top().GetSignature(), signatures[6]);
EXPECT_EQ(scope_resolver.top().Members().size(), 1);
{
const VName* vname = scope_resolver.SearchForDefinition(names[2]);
EXPECT_EQ(vname->signature, vnames[2].signature);
}
{
const VName* vname = scope_resolver.SearchForDefinition(names[9]);
EXPECT_EQ(vname->signature, vnames[6].signature);
}
{
const VName* vname = scope_resolver.SearchForDefinition(names[8]);
EXPECT_EQ(vname, nullptr);
}
{
const VName* vname = scope_resolver.SearchForDefinition(names[0]);
EXPECT_EQ(vname->signature, vnames[0].signature);
}
}
}
EXPECT_EQ(scope_resolver.size(), 2);
}
EXPECT_EQ(scope_resolver.size(), 1);
}
} // namespace
} // namespace kythe
} // namespace verilog