diff options
Diffstat (limited to 'clang-tools-extra/unittests/clangd/IndexTests.cpp')
-rw-r--r-- | clang-tools-extra/unittests/clangd/IndexTests.cpp | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/clang-tools-extra/unittests/clangd/IndexTests.cpp b/clang-tools-extra/unittests/clangd/IndexTests.cpp deleted file mode 100644 index 2f67654e935..00000000000 --- a/clang-tools-extra/unittests/clangd/IndexTests.cpp +++ /dev/null @@ -1,408 +0,0 @@ -//===-- IndexTests.cpp -------------------------------*- C++ -*-----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Annotations.h" -#include "TestIndex.h" -#include "TestTU.h" -#include "index/FileIndex.h" -#include "index/Index.h" -#include "index/MemIndex.h" -#include "index/Merge.h" -#include "index/Symbol.h" -#include "clang/Index/IndexSymbol.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -using testing::_; -using testing::AllOf; -using testing::AnyOf; -using testing::ElementsAre; -using testing::IsEmpty; -using testing::Pair; -using testing::Pointee; -using testing::UnorderedElementsAre; - -namespace clang { -namespace clangd { -namespace { - -MATCHER_P(Named, N, "") { return arg.Name == N; } -MATCHER_P(RefRange, Range, "") { - return std::make_tuple(arg.Location.Start.line(), arg.Location.Start.column(), - arg.Location.End.line(), arg.Location.End.column()) == - std::make_tuple(Range.start.line, Range.start.character, - Range.end.line, Range.end.character); -} -MATCHER_P(FileURI, F, "") { return StringRef(arg.Location.FileURI) == F; } - -TEST(SymbolLocation, Position) { - using Position = SymbolLocation::Position; - Position Pos; - - Pos.setLine(1); - EXPECT_EQ(1u, Pos.line()); - Pos.setColumn(2); - EXPECT_EQ(2u, Pos.column()); - EXPECT_FALSE(Pos.hasOverflow()); - - Pos.setLine(Position::MaxLine + 1); // overflow - EXPECT_TRUE(Pos.hasOverflow()); - EXPECT_EQ(Pos.line(), Position::MaxLine); - Pos.setLine(1); // reset the overflowed line. - - Pos.setColumn(Position::MaxColumn + 1); // overflow - EXPECT_TRUE(Pos.hasOverflow()); - EXPECT_EQ(Pos.column(), Position::MaxColumn); -} - -TEST(SymbolSlab, FindAndIterate) { - SymbolSlab::Builder B; - B.insert(symbol("Z")); - B.insert(symbol("Y")); - B.insert(symbol("X")); - EXPECT_EQ(nullptr, B.find(SymbolID("W"))); - for (const char *Sym : {"X", "Y", "Z"}) - EXPECT_THAT(B.find(SymbolID(Sym)), Pointee(Named(Sym))); - - SymbolSlab S = std::move(B).build(); - EXPECT_THAT(S, UnorderedElementsAre(Named("X"), Named("Y"), Named("Z"))); - EXPECT_EQ(S.end(), S.find(SymbolID("W"))); - for (const char *Sym : {"X", "Y", "Z"}) - EXPECT_THAT(*S.find(SymbolID(Sym)), Named(Sym)); -} - -TEST(SwapIndexTest, OldIndexRecycled) { - auto Token = std::make_shared<int>(); - std::weak_ptr<int> WeakToken = Token; - - SwapIndex S(llvm::make_unique<MemIndex>( - SymbolSlab(), RefSlab(), std::move(Token), /*BackingDataSize=*/0)); - EXPECT_FALSE(WeakToken.expired()); // Current MemIndex keeps it alive. - S.reset(llvm::make_unique<MemIndex>()); // Now the MemIndex is destroyed. - EXPECT_TRUE(WeakToken.expired()); // So the token is too. -} - -TEST(MemIndexTest, MemIndexDeduplicate) { - std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"), - symbol("2") /* duplicate */}; - FuzzyFindRequest Req; - Req.Query = "2"; - Req.AnyScope = true; - MemIndex I(Symbols, RefSlab()); - EXPECT_THAT(match(I, Req), ElementsAre("2")); -} - -TEST(MemIndexTest, MemIndexLimitedNumMatches) { - auto I = MemIndex::build(generateNumSymbols(0, 100), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "5"; - Req.AnyScope = true; - Req.Limit = 3; - bool Incomplete; - auto Matches = match(*I, Req, &Incomplete); - EXPECT_TRUE(Req.Limit); - EXPECT_EQ(Matches.size(), *Req.Limit); - EXPECT_TRUE(Incomplete); -} - -TEST(MemIndexTest, FuzzyMatch) { - auto I = MemIndex::build( - generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}), - RefSlab()); - FuzzyFindRequest Req; - Req.Query = "lol"; - Req.AnyScope = true; - Req.Limit = 2; - EXPECT_THAT(match(*I, Req), - UnorderedElementsAre("LaughingOutLoud", "LittleOldLady")); -} - -TEST(MemIndexTest, MatchQualifiedNamesWithoutSpecificScope) { - auto I = - MemIndex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "y"; - Req.AnyScope = true; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3")); -} - -TEST(MemIndexTest, MatchQualifiedNamesWithGlobalScope) { - auto I = - MemIndex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "y"; - Req.Scopes = {""}; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3")); -} - -TEST(MemIndexTest, MatchQualifiedNamesWithOneScope) { - auto I = MemIndex::build( - generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "y"; - Req.Scopes = {"a::"}; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2")); -} - -TEST(MemIndexTest, MatchQualifiedNamesWithMultipleScopes) { - auto I = MemIndex::build( - generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "y"; - Req.Scopes = {"a::", "b::"}; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3")); -} - -TEST(MemIndexTest, NoMatchNestedScopes) { - auto I = MemIndex::build(generateSymbols({"a::y1", "a::b::y2"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "y"; - Req.Scopes = {"a::"}; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1")); -} - -TEST(MemIndexTest, IgnoreCases) { - auto I = MemIndex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab()); - FuzzyFindRequest Req; - Req.Query = "AB"; - Req.Scopes = {"ns::"}; - EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc")); -} - -TEST(MemIndexTest, Lookup) { - auto I = MemIndex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab()); - EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc")); - EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}), - UnorderedElementsAre("ns::abc", "ns::xyz")); - EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}), - UnorderedElementsAre("ns::xyz")); - EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre()); -} - -TEST(MemIndexTest, TemplateSpecialization) { - SymbolSlab::Builder B; - - Symbol S = symbol("TempSpec"); - S.ID = SymbolID("1"); - B.insert(S); - - S = symbol("TempSpec"); - S.ID = SymbolID("2"); - S.TemplateSpecializationArgs = "<int, bool>"; - S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( - index::SymbolProperty::TemplateSpecialization); - B.insert(S); - - S = symbol("TempSpec"); - S.ID = SymbolID("3"); - S.TemplateSpecializationArgs = "<int, U>"; - S.SymInfo.Properties = static_cast<index::SymbolPropertySet>( - index::SymbolProperty::TemplatePartialSpecialization); - B.insert(S); - - auto I = MemIndex::build(std::move(B).build(), RefSlab()); - FuzzyFindRequest Req; - Req.AnyScope = true; - - Req.Query = "TempSpec"; - EXPECT_THAT(match(*I, Req), - UnorderedElementsAre("TempSpec", "TempSpec<int, bool>", - "TempSpec<int, U>")); - - // FIXME: Add filtering for template argument list. - Req.Query = "TempSpec<int"; - EXPECT_THAT(match(*I, Req), IsEmpty()); -} - -TEST(MergeIndexTest, Lookup) { - auto I = MemIndex::build(generateSymbols({"ns::A", "ns::B"}), RefSlab()), - J = MemIndex::build(generateSymbols({"ns::B", "ns::C"}), RefSlab()); - MergedIndex M(I.get(), J.get()); - EXPECT_THAT(lookup(M, SymbolID("ns::A")), UnorderedElementsAre("ns::A")); - EXPECT_THAT(lookup(M, SymbolID("ns::B")), UnorderedElementsAre("ns::B")); - EXPECT_THAT(lookup(M, SymbolID("ns::C")), UnorderedElementsAre("ns::C")); - EXPECT_THAT(lookup(M, {SymbolID("ns::A"), SymbolID("ns::B")}), - UnorderedElementsAre("ns::A", "ns::B")); - EXPECT_THAT(lookup(M, {SymbolID("ns::A"), SymbolID("ns::C")}), - UnorderedElementsAre("ns::A", "ns::C")); - EXPECT_THAT(lookup(M, SymbolID("ns::D")), UnorderedElementsAre()); - EXPECT_THAT(lookup(M, {}), UnorderedElementsAre()); -} - -TEST(MergeIndexTest, FuzzyFind) { - auto I = MemIndex::build(generateSymbols({"ns::A", "ns::B"}), RefSlab()), - J = MemIndex::build(generateSymbols({"ns::B", "ns::C"}), RefSlab()); - FuzzyFindRequest Req; - Req.Scopes = {"ns::"}; - EXPECT_THAT(match(MergedIndex(I.get(), J.get()), Req), - UnorderedElementsAre("ns::A", "ns::B", "ns::C")); -} - -TEST(MergeTest, Merge) { - Symbol L, R; - L.ID = R.ID = SymbolID("hello"); - L.Name = R.Name = "Foo"; // same in both - L.CanonicalDeclaration.FileURI = "file:///left.h"; // differs - R.CanonicalDeclaration.FileURI = "file:///right.h"; - L.References = 1; - R.References = 2; - L.Signature = "()"; // present in left only - R.CompletionSnippetSuffix = "{$1:0}"; // present in right only - R.Documentation = "--doc--"; - L.Origin = SymbolOrigin::Dynamic; - R.Origin = SymbolOrigin::Static; - R.Type = "expectedType"; - - Symbol M = mergeSymbol(L, R); - EXPECT_EQ(M.Name, "Foo"); - EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:///left.h"); - EXPECT_EQ(M.References, 3u); - EXPECT_EQ(M.Signature, "()"); - EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}"); - EXPECT_EQ(M.Documentation, "--doc--"); - EXPECT_EQ(M.Type, "expectedType"); - EXPECT_EQ(M.Origin, - SymbolOrigin::Dynamic | SymbolOrigin::Static | SymbolOrigin::Merge); -} - -TEST(MergeTest, PreferSymbolWithDefn) { - Symbol L, R; - - L.ID = R.ID = SymbolID("hello"); - L.CanonicalDeclaration.FileURI = "file:/left.h"; - R.CanonicalDeclaration.FileURI = "file:/right.h"; - L.Name = "left"; - R.Name = "right"; - - Symbol M = mergeSymbol(L, R); - EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/left.h"); - EXPECT_EQ(StringRef(M.Definition.FileURI), ""); - EXPECT_EQ(M.Name, "left"); - - R.Definition.FileURI = "file:/right.cpp"; // Now right will be favored. - M = mergeSymbol(L, R); - EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/right.h"); - EXPECT_EQ(StringRef(M.Definition.FileURI), "file:/right.cpp"); - EXPECT_EQ(M.Name, "right"); -} - -TEST(MergeTest, PreferSymbolLocationInCodegenFile) { - Symbol L, R; - - L.ID = R.ID = SymbolID("hello"); - L.CanonicalDeclaration.FileURI = "file:/x.proto.h"; - R.CanonicalDeclaration.FileURI = "file:/x.proto"; - - Symbol M = mergeSymbol(L, R); - EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/x.proto"); - - // Prefer L if both have codegen suffix. - L.CanonicalDeclaration.FileURI = "file:/y.proto"; - M = mergeSymbol(L, R); - EXPECT_EQ(StringRef(M.CanonicalDeclaration.FileURI), "file:/y.proto"); -} - -TEST(MergeIndexTest, Refs) { - FileIndex Dyn; - FileIndex StaticIndex; - MergedIndex Merge(&Dyn, &StaticIndex); - - const char *HeaderCode = "class Foo;"; - auto HeaderSymbols = TestTU::withHeaderCode("class Foo;").headerSymbols(); - auto Foo = findSymbol(HeaderSymbols, "Foo"); - - // Build dynamic index for test.cc. - Annotations Test1Code(R"(class $Foo[[Foo]];)"); - TestTU Test; - Test.HeaderCode = HeaderCode; - Test.Code = Test1Code.code(); - Test.Filename = "test.cc"; - auto AST = Test.build(); - Dyn.updateMain(Test.Filename, AST); - - // Build static index for test.cc. - Test.HeaderCode = HeaderCode; - Test.Code = "// static\nclass Foo {};"; - Test.Filename = "test.cc"; - auto StaticAST = Test.build(); - // Add stale refs for test.cc. - StaticIndex.updateMain(Test.Filename, StaticAST); - - // Add refs for test2.cc - Annotations Test2Code(R"(class $Foo[[Foo]] {};)"); - TestTU Test2; - Test2.HeaderCode = HeaderCode; - Test2.Code = Test2Code.code(); - Test2.Filename = "test2.cc"; - StaticAST = Test2.build(); - StaticIndex.updateMain(Test2.Filename, StaticAST); - - RefsRequest Request; - Request.IDs = {Foo.ID}; - RefSlab::Builder Results; - Merge.refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); }); - EXPECT_THAT( - std::move(Results).build(), - ElementsAre(Pair( - _, UnorderedElementsAre(AllOf(RefRange(Test1Code.range("Foo")), - FileURI("unittest:///test.cc")), - AllOf(RefRange(Test2Code.range("Foo")), - FileURI("unittest:///test2.cc")))))); - - Request.Limit = 1; - RefSlab::Builder Results2; - Merge.refs(Request, [&](const Ref &O) { Results2.insert(Foo.ID, O); }); - EXPECT_THAT(std::move(Results2).build(), - ElementsAre(Pair( - _, ElementsAre(AnyOf(FileURI("unittest:///test.cc"), - FileURI("unittest:///test2.cc")))))); -} - -MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") { - return (arg.IncludeHeader == IncludeHeader) && (arg.References == References); -} - -TEST(MergeTest, MergeIncludesOnDifferentDefinitions) { - Symbol L, R; - L.Name = "left"; - R.Name = "right"; - L.ID = R.ID = SymbolID("hello"); - L.IncludeHeaders.emplace_back("common", 1); - R.IncludeHeaders.emplace_back("common", 1); - R.IncludeHeaders.emplace_back("new", 1); - - // Both have no definition. - Symbol M = mergeSymbol(L, R); - EXPECT_THAT(M.IncludeHeaders, - UnorderedElementsAre(IncludeHeaderWithRef("common", 2u), - IncludeHeaderWithRef("new", 1u))); - - // Only merge references of the same includes but do not merge new #includes. - L.Definition.FileURI = "file:/left.h"; - M = mergeSymbol(L, R); - EXPECT_THAT(M.IncludeHeaders, - UnorderedElementsAre(IncludeHeaderWithRef("common", 2u))); - - // Definitions are the same. - R.Definition.FileURI = "file:/right.h"; - M = mergeSymbol(L, R); - EXPECT_THAT(M.IncludeHeaders, - UnorderedElementsAre(IncludeHeaderWithRef("common", 2u), - IncludeHeaderWithRef("new", 1u))); - - // Definitions are different. - R.Definition.FileURI = "file:/right.h"; - M = mergeSymbol(L, R); - EXPECT_THAT(M.IncludeHeaders, - UnorderedElementsAre(IncludeHeaderWithRef("common", 2u), - IncludeHeaderWithRef("new", 1u))); -} - -} // namespace -} // namespace clangd -} // namespace clang |