summaryrefslogtreecommitdiffstats
path: root/unittests/clangd
diff options
context:
space:
mode:
authorEric Liu <ioeric@google.com>2017-12-19 16:50:37 +0000
committerEric Liu <ioeric@google.com>2017-12-19 16:50:37 +0000
commita50f7cf406f7279f4bc875147e72aec4bd423f21 (patch)
tree3d74035ae2436a2da653635dd6c994f6ec7c3509 /unittests/clangd
parent81a5eb03e612b2aeb88bb6a4d32a26e0b2d9cdb8 (diff)
[clangd] Index-based code completion.
Summary: Use symbol index to populate completion results for qualfified IDs e.g. "nx::A^". Reviewers: ilya-biryukov, sammccall Reviewed By: ilya-biryukov, sammccall Subscribers: rwols, klimek, mgorny, cfe-commits, sammccall Differential Revision: https://reviews.llvm.org/D41281 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@321083 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/clangd')
-rw-r--r--unittests/clangd/CodeCompleteTests.cpp101
-rw-r--r--unittests/clangd/IndexTests.cpp9
2 files changed, 105 insertions, 5 deletions
diff --git a/unittests/clangd/CodeCompleteTests.cpp b/unittests/clangd/CodeCompleteTests.cpp
index 8ba9ebb3..4e598d35 100644
--- a/unittests/clangd/CodeCompleteTests.cpp
+++ b/unittests/clangd/CodeCompleteTests.cpp
@@ -6,6 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#include "ClangdServer.h"
#include "Compiler.h"
#include "Context.h"
@@ -13,6 +14,7 @@
#include "Protocol.h"
#include "SourceCode.h"
#include "TestFS.h"
+#include "index/MemIndex.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -83,6 +85,7 @@ StringWithPos parseTextMarker(StringRef Text) {
MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
MATCHER_P(Kind, K, "") { return arg.kind == K; }
+MATCHER_P(Filter, F, "") { return arg.filterText == F; }
MATCHER_P(PlainText, Text, "") {
return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
arg.insertText == Text;
@@ -457,6 +460,104 @@ TEST(SignatureHelpTest, ActiveArg) {
EXPECT_EQ(1, Results.activeParameter);
}
+std::unique_ptr<SymbolIndex> simpleIndexFromSymbols(
+ std::vector<std::pair<std::string, index::SymbolKind>> Symbols) {
+ auto I = llvm::make_unique<MemIndex>();
+ struct Snapshot {
+ SymbolSlab Slab;
+ std::vector<const Symbol *> Pointers;
+ };
+ auto Snap = std::make_shared<Snapshot>();
+ for (const auto &Pair : Symbols) {
+ Symbol Sym;
+ Sym.ID = SymbolID(Pair.first);
+ llvm::StringRef QName = Pair.first;
+ size_t Pos = QName.rfind("::");
+ if (Pos == llvm::StringRef::npos) {
+ Sym.Name = QName;
+ Sym.Scope = "";
+ } else {
+ Sym.Name = QName.substr(Pos + 2);
+ Sym.Scope = QName.substr(0, Pos);
+ }
+ Sym.SymInfo.Kind = Pair.second;
+ Snap->Slab.insert(std::move(Sym));
+ }
+ for (auto &Iter : Snap->Slab)
+ Snap->Pointers.push_back(&Iter.second);
+ auto S = std::shared_ptr<std::vector<const Symbol *>>(std::move(Snap),
+ &Snap->Pointers);
+ I->build(std::move(S));
+ return I;
+}
+
+TEST(CompletionTest, NoIndex) {
+ clangd::CodeCompleteOptions Opts;
+ Opts.Index = nullptr;
+
+ auto Results = completions(R"cpp(
+ namespace ns { class No {}; }
+ void f() { ns::^ }
+ )cpp",
+ Opts);
+ EXPECT_THAT(Results.items, Has("No"));
+}
+
+TEST(CompletionTest, SimpleIndexBased) {
+ clangd::CodeCompleteOptions Opts;
+ auto I = simpleIndexFromSymbols({{"ns::XYZ", index::SymbolKind::Class},
+ {"nx::XYZ", index::SymbolKind::Class},
+ {"ns::foo", index::SymbolKind::Function}});
+ Opts.Index = I.get();
+
+ auto Results = completions(R"cpp(
+ namespace ns { class No {}; }
+ void f() { ns::^ }
+ )cpp",
+ Opts);
+ EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
+ EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
+ EXPECT_THAT(Results.items, Not(Has("No")));
+}
+
+TEST(CompletionTest, IndexBasedWithFilter) {
+ clangd::CodeCompleteOptions Opts;
+ auto I = simpleIndexFromSymbols({{"ns::XYZ", index::SymbolKind::Class},
+ {"ns::foo", index::SymbolKind::Function}});
+ Opts.Index = I.get();
+
+ auto Results = completions(R"cpp(
+ void f() { ns::x^ }
+ )cpp",
+ Opts);
+ EXPECT_THAT(Results.items, Contains(AllOf(Named("XYZ"), Filter("x"))));
+ EXPECT_THAT(Results.items, Not(Has("foo")));
+}
+
+TEST(CompletionTest, GlobalQualified) {
+ clangd::CodeCompleteOptions Opts;
+ auto I = simpleIndexFromSymbols({{"XYZ", index::SymbolKind::Class}});
+ Opts.Index = I.get();
+
+ auto Results = completions(R"cpp(
+ void f() { ::^ }
+ )cpp",
+ Opts);
+ EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
+}
+
+TEST(CompletionTest, FullyQualifiedScope) {
+ clangd::CodeCompleteOptions Opts;
+ auto I = simpleIndexFromSymbols({{"ns::XYZ", index::SymbolKind::Class}});
+ Opts.Index = I.get();
+
+ auto Results = completions(R"cpp(
+ void f() { ::ns::^ }
+ )cpp",
+ Opts);
+ EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/unittests/clangd/IndexTests.cpp b/unittests/clangd/IndexTests.cpp
index 2852da0b..ea0ea794 100644
--- a/unittests/clangd/IndexTests.cpp
+++ b/unittests/clangd/IndexTests.cpp
@@ -143,7 +143,7 @@ TEST(MemIndexTest, MatchQualifiedNamesWithGlobalScope) {
I.build(generateSymbols({"a::xyz", "b::yz", "yz"}));
FuzzyFindRequest Req;
Req.Query = "y";
- Req.Scopes.push_back("");
+ Req.Scopes = {""};
auto Matches = match(I, Req);
EXPECT_THAT(match(I, Req), UnorderedElementsAre("yz"));
}
@@ -153,7 +153,7 @@ TEST(MemIndexTest, MatchQualifiedNamesWithOneScope) {
I.build(generateSymbols({"a::xyz", "a::yy", "a::xz", "b::yz", "yz"}));
FuzzyFindRequest Req;
Req.Query = "y";
- Req.Scopes.push_back("a");
+ Req.Scopes = {"a"};
auto Matches = match(I, Req);
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz", "a::yy"));
}
@@ -163,8 +163,7 @@ TEST(MemIndexTest, MatchQualifiedNamesWithMultipleScopes) {
I.build(generateSymbols({"a::xyz", "a::yy", "a::xz", "b::yz", "yz"}));
FuzzyFindRequest Req;
Req.Query = "y";
- Req.Scopes.push_back("a");
- Req.Scopes.push_back("b");
+ Req.Scopes = {"a", "b"};
auto Matches = match(I, Req);
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz", "a::yy", "b::yz"));
}
@@ -174,7 +173,7 @@ TEST(MemIndexTest, NoMatchNestedScopes) {
I.build(generateSymbols({"a::xyz", "a::b::yy"}));
FuzzyFindRequest Req;
Req.Query = "y";
- Req.Scopes.push_back("a");
+ Req.Scopes = {"a"};
auto Matches = match(I, Req);
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz"));
}