| // 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 |