diff options
author | Eric Liu <ioeric@google.com> | 2017-12-19 16:50:37 +0000 |
---|---|---|
committer | Eric Liu <ioeric@google.com> | 2017-12-19 16:50:37 +0000 |
commit | a50f7cf406f7279f4bc875147e72aec4bd423f21 (patch) | |
tree | 3d74035ae2436a2da653635dd6c994f6ec7c3509 /unittests/clangd | |
parent | 81a5eb03e612b2aeb88bb6a4d32a26e0b2d9cdb8 (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.cpp | 101 | ||||
-rw-r--r-- | unittests/clangd/IndexTests.cpp | 9 |
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")); } |