2017-12-14 19:25:49 +08:00
|
|
|
//===-- IndexTests.cpp -------------------------------*- C++ -*-----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-08-20 22:39:32 +08:00
|
|
|
#include "TestIndex.h"
|
2017-12-14 19:25:49 +08:00
|
|
|
#include "index/Index.h"
|
|
|
|
#include "index/MemIndex.h"
|
2018-01-15 20:33:00 +08:00
|
|
|
#include "index/Merge.h"
|
2017-12-14 19:25:49 +08:00
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
using testing::Pointee;
|
2018-08-20 22:39:32 +08:00
|
|
|
using testing::UnorderedElementsAre;
|
2017-12-14 19:25:49 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
MATCHER_P(Named, N, "") { return arg.Name == N; }
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-12-14 19:25:49 +08:00
|
|
|
TEST(MemIndexTest, MemIndexSymbolsRecycled) {
|
|
|
|
MemIndex I;
|
|
|
|
std::weak_ptr<SlabAndPointers> Symbols;
|
|
|
|
I.build(generateNumSymbols(0, 10, &Symbols));
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "7";
|
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("7"));
|
|
|
|
|
|
|
|
EXPECT_FALSE(Symbols.expired());
|
|
|
|
// Release old symbols.
|
|
|
|
I.build(generateNumSymbols(0, 0));
|
|
|
|
EXPECT_TRUE(Symbols.expired());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, MemIndexDeduplicate) {
|
|
|
|
auto Symbols = generateNumSymbols(0, 10);
|
|
|
|
|
|
|
|
// Inject some duplicates and make sure we only match the same symbol once.
|
|
|
|
auto Sym = symbol("7");
|
|
|
|
Symbols->push_back(&Sym);
|
|
|
|
Symbols->push_back(&Sym);
|
|
|
|
Symbols->push_back(&Sym);
|
|
|
|
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "7";
|
|
|
|
MemIndex I;
|
|
|
|
I.build(std::move(Symbols));
|
|
|
|
auto Matches = match(I, Req);
|
|
|
|
EXPECT_EQ(Matches.size(), 1u);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, MemIndexLimitedNumMatches) {
|
|
|
|
MemIndex I;
|
|
|
|
I.build(generateNumSymbols(0, 100));
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "5";
|
|
|
|
Req.MaxCandidateCount = 3;
|
2018-02-19 21:04:41 +08:00
|
|
|
bool Incomplete;
|
|
|
|
auto Matches = match(I, Req, &Incomplete);
|
2017-12-14 19:25:49 +08:00
|
|
|
EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
|
2018-02-19 21:04:41 +08:00
|
|
|
EXPECT_TRUE(Incomplete);
|
2017-12-14 19:25:49 +08:00
|
|
|
}
|
|
|
|
|
2018-01-18 16:35:04 +08:00
|
|
|
TEST(MemIndexTest, FuzzyMatch) {
|
|
|
|
MemIndex I;
|
|
|
|
I.build(
|
|
|
|
generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "lol";
|
|
|
|
Req.MaxCandidateCount = 2;
|
|
|
|
EXPECT_THAT(match(I, Req),
|
|
|
|
UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
|
|
|
|
}
|
|
|
|
|
2017-12-19 19:37:40 +08:00
|
|
|
TEST(MemIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
|
|
|
|
MemIndex I;
|
2018-03-06 01:34:33 +08:00
|
|
|
I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
|
2017-12-19 19:37:40 +08:00
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "y";
|
2018-03-06 01:34:33 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
|
2017-12-19 19:37:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, MatchQualifiedNamesWithGlobalScope) {
|
|
|
|
MemIndex I;
|
2018-03-06 01:34:33 +08:00
|
|
|
I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
|
2017-12-19 19:37:40 +08:00
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "y";
|
2017-12-20 00:50:37 +08:00
|
|
|
Req.Scopes = {""};
|
2018-03-06 01:34:33 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("y3"));
|
2017-12-19 19:37:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, MatchQualifiedNamesWithOneScope) {
|
|
|
|
MemIndex I;
|
2018-03-06 01:34:33 +08:00
|
|
|
I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}));
|
2017-12-19 19:37:40 +08:00
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "y";
|
2018-03-14 17:48:05 +08:00
|
|
|
Req.Scopes = {"a::"};
|
2018-03-06 01:34:33 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2"));
|
2017-12-19 19:37:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, MatchQualifiedNamesWithMultipleScopes) {
|
|
|
|
MemIndex I;
|
2018-03-06 01:34:33 +08:00
|
|
|
I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}));
|
2017-12-19 19:37:40 +08:00
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "y";
|
2018-03-14 17:48:05 +08:00
|
|
|
Req.Scopes = {"a::", "b::"};
|
2018-03-06 01:34:33 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
|
2017-12-19 19:37:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MemIndexTest, NoMatchNestedScopes) {
|
|
|
|
MemIndex I;
|
2018-03-06 01:34:33 +08:00
|
|
|
I.build(generateSymbols({"a::y1", "a::b::y2"}));
|
2017-12-19 19:37:40 +08:00
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "y";
|
2018-03-14 17:48:05 +08:00
|
|
|
Req.Scopes = {"a::"};
|
2018-03-06 01:34:33 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1"));
|
2017-12-19 19:37:40 +08:00
|
|
|
}
|
|
|
|
|
2017-12-20 17:29:54 +08:00
|
|
|
TEST(MemIndexTest, IgnoreCases) {
|
|
|
|
MemIndex I;
|
|
|
|
I.build(generateSymbols({"ns::ABC", "ns::abc"}));
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = "AB";
|
2018-03-14 17:48:05 +08:00
|
|
|
Req.Scopes = {"ns::"};
|
2017-12-20 17:29:54 +08:00
|
|
|
EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
|
|
|
|
}
|
|
|
|
|
2018-03-14 17:48:05 +08:00
|
|
|
TEST(MemIndexTest, Lookup) {
|
|
|
|
MemIndex I;
|
|
|
|
I.build(generateSymbols({"ns::abc", "ns::xyz"}));
|
|
|
|
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(MergeIndexTest, Lookup) {
|
|
|
|
MemIndex I, J;
|
|
|
|
I.build(generateSymbols({"ns::A", "ns::B"}));
|
|
|
|
J.build(generateSymbols({"ns::B", "ns::C"}));
|
|
|
|
EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::A")),
|
|
|
|
UnorderedElementsAre("ns::A"));
|
|
|
|
EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::B")),
|
|
|
|
UnorderedElementsAre("ns::B"));
|
|
|
|
EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::C")),
|
|
|
|
UnorderedElementsAre("ns::C"));
|
|
|
|
EXPECT_THAT(
|
|
|
|
lookup(*mergeIndex(&I, &J), {SymbolID("ns::A"), SymbolID("ns::B")}),
|
|
|
|
UnorderedElementsAre("ns::A", "ns::B"));
|
|
|
|
EXPECT_THAT(
|
|
|
|
lookup(*mergeIndex(&I, &J), {SymbolID("ns::A"), SymbolID("ns::C")}),
|
|
|
|
UnorderedElementsAre("ns::A", "ns::C"));
|
|
|
|
EXPECT_THAT(lookup(*mergeIndex(&I, &J), SymbolID("ns::D")),
|
|
|
|
UnorderedElementsAre());
|
|
|
|
EXPECT_THAT(lookup(*mergeIndex(&I, &J), {}), UnorderedElementsAre());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MergeIndexTest, FuzzyFind) {
|
2018-01-15 20:33:00 +08:00
|
|
|
MemIndex I, J;
|
|
|
|
I.build(generateSymbols({"ns::A", "ns::B"}));
|
|
|
|
J.build(generateSymbols({"ns::B", "ns::C"}));
|
|
|
|
FuzzyFindRequest Req;
|
2018-03-14 17:48:05 +08:00
|
|
|
Req.Scopes = {"ns::"};
|
2018-01-15 20:33:00 +08:00
|
|
|
EXPECT_THAT(match(*mergeIndex(&I, &J), Req),
|
|
|
|
UnorderedElementsAre("ns::A", "ns::B", "ns::C"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MergeTest, Merge) {
|
|
|
|
Symbol L, R;
|
|
|
|
L.ID = R.ID = SymbolID("hello");
|
2018-08-20 22:39:32 +08:00
|
|
|
L.Name = R.Name = "Foo"; // same in both
|
2018-02-07 00:10:35 +08:00
|
|
|
L.CanonicalDeclaration.FileURI = "file:///left.h"; // differs
|
|
|
|
R.CanonicalDeclaration.FileURI = "file:///right.h";
|
2018-03-12 22:49:09 +08:00
|
|
|
L.References = 1;
|
|
|
|
R.References = 2;
|
2018-06-23 00:11:35 +08:00
|
|
|
L.Signature = "()"; // present in left only
|
|
|
|
R.CompletionSnippetSuffix = "{$1:0}"; // present in right only
|
2018-08-31 21:55:01 +08:00
|
|
|
R.Documentation = "--doc--";
|
2018-07-05 14:20:41 +08:00
|
|
|
L.Origin = SymbolOrigin::Dynamic;
|
|
|
|
R.Origin = SymbolOrigin::Static;
|
2018-01-15 20:33:00 +08:00
|
|
|
|
2018-08-31 21:55:01 +08:00
|
|
|
Symbol M = mergeSymbol(L, R);
|
2018-01-15 20:33:00 +08:00
|
|
|
EXPECT_EQ(M.Name, "Foo");
|
2018-02-07 00:10:35 +08:00
|
|
|
EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:///left.h");
|
2018-03-12 22:49:09 +08:00
|
|
|
EXPECT_EQ(M.References, 3u);
|
2018-06-23 00:11:35 +08:00
|
|
|
EXPECT_EQ(M.Signature, "()");
|
|
|
|
EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}");
|
2018-08-31 21:55:01 +08:00
|
|
|
EXPECT_EQ(M.Documentation, "--doc--");
|
2018-07-05 14:20:41 +08:00
|
|
|
EXPECT_EQ(M.Origin,
|
|
|
|
SymbolOrigin::Dynamic | SymbolOrigin::Static | SymbolOrigin::Merge);
|
2018-01-15 20:33:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-09 22:42:01 +08:00
|
|
|
TEST(MergeTest, PreferSymbolWithDefn) {
|
|
|
|
Symbol L, R;
|
|
|
|
|
|
|
|
L.ID = R.ID = SymbolID("hello");
|
|
|
|
L.CanonicalDeclaration.FileURI = "file:/left.h";
|
|
|
|
R.CanonicalDeclaration.FileURI = "file:/right.h";
|
2018-06-23 00:11:35 +08:00
|
|
|
L.Name = "left";
|
|
|
|
R.Name = "right";
|
2018-02-09 22:42:01 +08:00
|
|
|
|
2018-08-31 21:55:01 +08:00
|
|
|
Symbol M = mergeSymbol(L, R);
|
2018-02-09 22:42:01 +08:00
|
|
|
EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:/left.h");
|
|
|
|
EXPECT_EQ(M.Definition.FileURI, "");
|
2018-06-23 00:11:35 +08:00
|
|
|
EXPECT_EQ(M.Name, "left");
|
2018-02-09 22:42:01 +08:00
|
|
|
|
|
|
|
R.Definition.FileURI = "file:/right.cpp"; // Now right will be favored.
|
2018-08-31 21:55:01 +08:00
|
|
|
M = mergeSymbol(L, R);
|
2018-02-09 22:42:01 +08:00
|
|
|
EXPECT_EQ(M.CanonicalDeclaration.FileURI, "file:/right.h");
|
|
|
|
EXPECT_EQ(M.Definition.FileURI, "file:/right.cpp");
|
2018-06-23 00:11:35 +08:00
|
|
|
EXPECT_EQ(M.Name, "right");
|
2018-02-09 22:42:01 +08:00
|
|
|
}
|
|
|
|
|
2017-12-14 19:25:49 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|