forked from OSchip/llvm-project
[clangd] CodeCompleteTests cleanup: naming, ordering, helpers. NFC
llvm-svn: 322824
This commit is contained in:
parent
1f8c035d6b
commit
a15c2d683e
|
@ -97,8 +97,25 @@ Matcher<const std::vector<CompletionItem> &> Has(std::string Name,
|
||||||
}
|
}
|
||||||
MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
|
MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
|
||||||
|
|
||||||
|
std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
|
||||||
|
SymbolSlab::Builder Slab;
|
||||||
|
for (const auto &Sym : Symbols)
|
||||||
|
Slab.insert(Sym);
|
||||||
|
return MemIndex::build(std::move(Slab).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builds a server and runs code completion.
|
||||||
|
// If IndexSymbols is non-empty, an index will be built and passed to opts.
|
||||||
CompletionList completions(StringRef Text,
|
CompletionList completions(StringRef Text,
|
||||||
|
std::vector<Symbol> IndexSymbols = {},
|
||||||
clangd::CodeCompleteOptions Opts = {}) {
|
clangd::CodeCompleteOptions Opts = {}) {
|
||||||
|
std::unique_ptr<SymbolIndex> OverrideIndex;
|
||||||
|
if (!IndexSymbols.empty()) {
|
||||||
|
assert(!Opts.Index && "both Index and IndexSymbols given!");
|
||||||
|
OverrideIndex = memIndex(std::move(IndexSymbols));
|
||||||
|
Opts.Index = OverrideIndex.get();
|
||||||
|
}
|
||||||
|
|
||||||
MockFSProvider FS;
|
MockFSProvider FS;
|
||||||
MockCompilationDatabase CDB;
|
MockCompilationDatabase CDB;
|
||||||
IgnoreDiagnostics DiagConsumer;
|
IgnoreDiagnostics DiagConsumer;
|
||||||
|
@ -116,6 +133,27 @@ CompletionList completions(StringRef Text,
|
||||||
return CompletionList;
|
return CompletionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helpers to produce fake index symbols for memIndex() or completions().
|
||||||
|
Symbol sym(StringRef QName, index::SymbolKind Kind) {
|
||||||
|
Symbol Sym;
|
||||||
|
Sym.ID = SymbolID(QName);
|
||||||
|
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.CompletionPlainInsertText = Sym.Name;
|
||||||
|
Sym.CompletionLabel = Sym.Name;
|
||||||
|
Sym.SymInfo.Kind = Kind;
|
||||||
|
return Sym;
|
||||||
|
}
|
||||||
|
Symbol func(StringRef Name) { return sym(Name, index::SymbolKind::Function); }
|
||||||
|
Symbol cls(StringRef Name) { return sym(Name, index::SymbolKind::Class); }
|
||||||
|
Symbol var(StringRef Name) { return sym(Name, index::SymbolKind::Variable); }
|
||||||
|
|
||||||
TEST(CompletionTest, Limit) {
|
TEST(CompletionTest, Limit) {
|
||||||
clangd::CodeCompleteOptions Opts;
|
clangd::CodeCompleteOptions Opts;
|
||||||
Opts.Limit = 2;
|
Opts.Limit = 2;
|
||||||
|
@ -127,7 +165,7 @@ struct ClassWithMembers {
|
||||||
}
|
}
|
||||||
int main() { ClassWithMembers().^ }
|
int main() { ClassWithMembers().^ }
|
||||||
)cpp",
|
)cpp",
|
||||||
Opts);
|
/*IndexSymbols=*/{}, Opts);
|
||||||
|
|
||||||
EXPECT_TRUE(Results.isIncomplete);
|
EXPECT_TRUE(Results.isIncomplete);
|
||||||
EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
|
EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
|
||||||
|
@ -188,7 +226,7 @@ void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
|
||||||
ClassWithMembers().^
|
ClassWithMembers().^
|
||||||
}
|
}
|
||||||
)cpp",
|
)cpp",
|
||||||
Opts);
|
/*IndexSymbols=*/{}, Opts);
|
||||||
|
|
||||||
// Class members. The only items that must be present in after-dot
|
// Class members. The only items that must be present in after-dot
|
||||||
// completion.
|
// completion.
|
||||||
|
@ -233,7 +271,7 @@ void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
|
||||||
^
|
^
|
||||||
}
|
}
|
||||||
)cpp",
|
)cpp",
|
||||||
Opts);
|
/*IndexSymbols=*/{}, Opts);
|
||||||
|
|
||||||
// Class members. Should never be present in global completions.
|
// Class members. Should never be present in global completions.
|
||||||
EXPECT_THAT(Results.items,
|
EXPECT_THAT(Results.items,
|
||||||
|
@ -355,7 +393,7 @@ TEST(CompletionTest, Snippets) {
|
||||||
f.^
|
f.^
|
||||||
}
|
}
|
||||||
)cpp",
|
)cpp",
|
||||||
Opts);
|
/*IndexSymbols=*/{}, Opts);
|
||||||
EXPECT_THAT(Results.items,
|
EXPECT_THAT(Results.items,
|
||||||
HasSubsequence(Snippet("a"),
|
HasSubsequence(Snippet("a"),
|
||||||
Snippet("f(${1:int i}, ${2:const float f})")));
|
Snippet("f(${1:int i}, ${2:const float f})")));
|
||||||
|
@ -375,9 +413,6 @@ TEST(CompletionTest, Kinds) {
|
||||||
EXPECT_THAT(Results.items, Has("Struct", CompletionItemKind::Class));
|
EXPECT_THAT(Results.items, Has("Struct", CompletionItemKind::Class));
|
||||||
EXPECT_THAT(Results.items, Has("MACRO", CompletionItemKind::Text));
|
EXPECT_THAT(Results.items, Has("MACRO", CompletionItemKind::Text));
|
||||||
|
|
||||||
clangd::CodeCompleteOptions Opts;
|
|
||||||
Opts.EnableSnippets = true; // Needed for code patterns.
|
|
||||||
|
|
||||||
Results = completions("nam^");
|
Results = completions("nam^");
|
||||||
EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
|
EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
|
||||||
}
|
}
|
||||||
|
@ -406,6 +441,143 @@ TEST(CompletionTest, FuzzyRanking) {
|
||||||
EXPECT_THAT(Items, ElementsAre(Named("BigBang"), Named("Babble")));
|
EXPECT_THAT(Items, ElementsAre(Named("BigBang"), Named("Babble")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, NoIndex) {
|
||||||
|
auto Results = completions(R"cpp(
|
||||||
|
namespace ns { class Local {}; }
|
||||||
|
void f() { ns::^ }
|
||||||
|
)cpp");
|
||||||
|
EXPECT_THAT(Results.items, Has("Local"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, StaticAndDynamicIndex) {
|
||||||
|
clangd::CodeCompleteOptions Opts;
|
||||||
|
auto StaticIdx = memIndex({cls("ns::XYZ")});
|
||||||
|
auto DynamicIdx = memIndex({func("ns::foo")});
|
||||||
|
auto Merge = mergeIndex(DynamicIdx.get(), StaticIdx.get());
|
||||||
|
Opts.Index = Merge.get();
|
||||||
|
|
||||||
|
auto Results = completions(
|
||||||
|
R"cpp(
|
||||||
|
void f() { ::ns::^ }
|
||||||
|
)cpp",
|
||||||
|
/*IndexSymbols=*/{}, Opts);
|
||||||
|
EXPECT_THAT(Results.items, Contains(Labeled("[I]XYZ")));
|
||||||
|
EXPECT_THAT(Results.items, Contains(Labeled("[I]foo")));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, IndexScope) {
|
||||||
|
auto Results = completions(
|
||||||
|
R"cpp(
|
||||||
|
namespace ns { int local; }
|
||||||
|
void f() { ns::^ }
|
||||||
|
)cpp",
|
||||||
|
{cls("ns::XYZ"), cls("nx::XYZ"), func("ns::foo")});
|
||||||
|
EXPECT_THAT(Results.items,
|
||||||
|
UnorderedElementsAre(Named("XYZ"), Named("foo"), Named("local")));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, IndexBasedWithFilter) {
|
||||||
|
auto Results = completions(
|
||||||
|
R"cpp(
|
||||||
|
void f() { ns::x^ }
|
||||||
|
)cpp",
|
||||||
|
{cls("ns::XYZ"), func("ns::foo")});
|
||||||
|
EXPECT_THAT(Results.items,
|
||||||
|
UnorderedElementsAre(AllOf(Named("XYZ"), Filter("XYZ"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, IndexGlobalQualified) {
|
||||||
|
auto Results = completions(
|
||||||
|
R"cpp(
|
||||||
|
void f() { ::^ }
|
||||||
|
)cpp",
|
||||||
|
{cls("XYZ")});
|
||||||
|
EXPECT_THAT(Results.items, AllOf(Has("XYZ", CompletionItemKind::Class),
|
||||||
|
Has("f", CompletionItemKind::Function)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, IndexFullyQualifiedScope) {
|
||||||
|
auto Results = completions(
|
||||||
|
R"cpp(
|
||||||
|
void f() { ::ns::^ }
|
||||||
|
)cpp",
|
||||||
|
{cls("ns::XYZ")});
|
||||||
|
EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
|
||||||
|
MockFSProvider FS;
|
||||||
|
MockCompilationDatabase CDB;
|
||||||
|
IgnoreDiagnostics DiagConsumer;
|
||||||
|
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
|
||||||
|
/*StorePreamblesInMemory=*/true);
|
||||||
|
|
||||||
|
FS.Files[getVirtualTestFilePath("bar.h")] =
|
||||||
|
R"cpp(namespace ns { int preamble; })cpp";
|
||||||
|
auto File = getVirtualTestFilePath("foo.cpp");
|
||||||
|
Annotations Test(R"cpp(
|
||||||
|
#include "bar.h"
|
||||||
|
namespace ns { int local; }
|
||||||
|
void f() { ns::^ }
|
||||||
|
)cpp");
|
||||||
|
Server.addDocument(Context::empty(), File, Test.code()).wait();
|
||||||
|
clangd::CodeCompleteOptions Opts = {};
|
||||||
|
|
||||||
|
auto WithoutIndex =
|
||||||
|
Server.codeComplete(Context::empty(), File, Test.point(), Opts)
|
||||||
|
.get()
|
||||||
|
.second.Value;
|
||||||
|
EXPECT_THAT(WithoutIndex.items,
|
||||||
|
UnorderedElementsAre(Named("local"), Named("preamble")));
|
||||||
|
|
||||||
|
auto I = memIndex({var("ns::index")});
|
||||||
|
Opts.Index = I.get();
|
||||||
|
auto WithIndex =
|
||||||
|
Server.codeComplete(Context::empty(), File, Test.point(), Opts)
|
||||||
|
.get()
|
||||||
|
.second.Value;
|
||||||
|
EXPECT_THAT(WithIndex.items,
|
||||||
|
UnorderedElementsAre(Named("local"), Named("index")));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompletionTest, DynamicIndexMultiFile) {
|
||||||
|
MockFSProvider FS;
|
||||||
|
MockCompilationDatabase CDB;
|
||||||
|
IgnoreDiagnostics DiagConsumer;
|
||||||
|
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
|
||||||
|
/*StorePreamblesInMemory=*/true,
|
||||||
|
/*BuildDynamicSymbolIndex=*/true);
|
||||||
|
|
||||||
|
Server
|
||||||
|
.addDocument(Context::empty(), getVirtualTestFilePath("foo.cpp"), R"cpp(
|
||||||
|
namespace ns { class XYZ {}; void foo(int x) {} }
|
||||||
|
)cpp")
|
||||||
|
.wait();
|
||||||
|
|
||||||
|
auto File = getVirtualTestFilePath("bar.cpp");
|
||||||
|
Annotations Test(R"cpp(
|
||||||
|
namespace ns {
|
||||||
|
class XXX {};
|
||||||
|
/// Doooc
|
||||||
|
void fooooo() {}
|
||||||
|
}
|
||||||
|
void f() { ns::^ }
|
||||||
|
)cpp");
|
||||||
|
Server.addDocument(Context::empty(), File, Test.code()).wait();
|
||||||
|
|
||||||
|
auto Results = Server.codeComplete(Context::empty(), File, Test.point(), {})
|
||||||
|
.get()
|
||||||
|
.second.Value;
|
||||||
|
// "XYZ" and "foo" are not included in the file being completed but are still
|
||||||
|
// visible through the index.
|
||||||
|
EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
|
||||||
|
EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
|
||||||
|
EXPECT_THAT(Results.items, Has("XXX", CompletionItemKind::Class));
|
||||||
|
EXPECT_THAT(Results.items, Contains(AllOf(Named("fooooo"), Filter("fooooo"),
|
||||||
|
Kind(CompletionItemKind::Function),
|
||||||
|
Doc("Doooc"), Detail("void"))));
|
||||||
|
}
|
||||||
|
|
||||||
SignatureHelp signatures(StringRef Text) {
|
SignatureHelp signatures(StringRef Text) {
|
||||||
MockFSProvider FS;
|
MockFSProvider FS;
|
||||||
MockCompilationDatabase CDB;
|
MockCompilationDatabase CDB;
|
||||||
|
@ -481,185 +653,6 @@ TEST(SignatureHelpTest, ActiveArg) {
|
||||||
EXPECT_EQ(1, Results.activeParameter);
|
EXPECT_EQ(1, Results.activeParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SymbolIndex> simpleIndexFromSymbols(
|
|
||||||
std::vector<std::pair<std::string, index::SymbolKind>> Symbols) {
|
|
||||||
SymbolSlab::Builder Slab;
|
|
||||||
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.CompletionPlainInsertText = Sym.Name;
|
|
||||||
Sym.SymInfo.Kind = Pair.second;
|
|
||||||
Slab.insert(Sym);
|
|
||||||
}
|
|
||||||
return MemIndex::build(std::move(Slab).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CompletionTest, NoIndex) {
|
|
||||||
clangd::CodeCompleteOptions Opts;
|
|
||||||
Opts.Index = nullptr;
|
|
||||||
|
|
||||||
auto Results = completions(R"cpp(
|
|
||||||
namespace ns { class Local {}; }
|
|
||||||
void f() { ns::^ }
|
|
||||||
)cpp",
|
|
||||||
Opts);
|
|
||||||
EXPECT_THAT(Results.items, Has("Local"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CompletionTest, StaticAndDynamicIndex) {
|
|
||||||
clangd::CodeCompleteOptions Opts;
|
|
||||||
auto StaticIdx =
|
|
||||||
simpleIndexFromSymbols({{"ns::XYZ", index::SymbolKind::Class}});
|
|
||||||
auto DynamicIdx =
|
|
||||||
simpleIndexFromSymbols({{"ns::foo", index::SymbolKind::Function}});
|
|
||||||
auto Merge = mergeIndex(DynamicIdx.get(), StaticIdx.get());
|
|
||||||
Opts.Index = Merge.get();
|
|
||||||
|
|
||||||
auto Results = completions(R"cpp(
|
|
||||||
void f() { ::ns::^ }
|
|
||||||
)cpp",
|
|
||||||
Opts);
|
|
||||||
EXPECT_THAT(Results.items, Contains(Labeled("[I]XYZ")));
|
|
||||||
EXPECT_THAT(Results.items, Contains(Labeled("[I]foo")));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 { int local; }
|
|
||||||
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, Has("local"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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("XYZ"))));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
|
|
||||||
MockFSProvider FS;
|
|
||||||
MockCompilationDatabase CDB;
|
|
||||||
IgnoreDiagnostics DiagConsumer;
|
|
||||||
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
|
|
||||||
/*StorePreamblesInMemory=*/true);
|
|
||||||
|
|
||||||
FS.Files[getVirtualTestFilePath("bar.h")] =
|
|
||||||
R"cpp(namespace ns { int preamble; })cpp";
|
|
||||||
auto File = getVirtualTestFilePath("foo.cpp");
|
|
||||||
Annotations Test(R"cpp(
|
|
||||||
#include "bar.h"
|
|
||||||
namespace ns { int local; }
|
|
||||||
void f() { ns::^ }
|
|
||||||
)cpp");
|
|
||||||
Server.addDocument(Context::empty(), File, Test.code()).wait();
|
|
||||||
clangd::CodeCompleteOptions Opts = {};
|
|
||||||
|
|
||||||
auto WithoutIndex =
|
|
||||||
Server.codeComplete(Context::empty(), File, Test.point(), Opts)
|
|
||||||
.get()
|
|
||||||
.second.Value;
|
|
||||||
EXPECT_THAT(WithoutIndex.items,
|
|
||||||
UnorderedElementsAre(Named("local"), Named("preamble")));
|
|
||||||
|
|
||||||
auto I = simpleIndexFromSymbols({{"ns::index", index::SymbolKind::Variable}});
|
|
||||||
Opts.Index = I.get();
|
|
||||||
auto WithIndex =
|
|
||||||
Server.codeComplete(Context::empty(), File, Test.point(), Opts)
|
|
||||||
.get()
|
|
||||||
.second.Value;
|
|
||||||
EXPECT_THAT(WithIndex.items,
|
|
||||||
UnorderedElementsAre(Named("local"), Named("index")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CompletionTest, ASTIndexMultiFile) {
|
|
||||||
MockFSProvider FS;
|
|
||||||
MockCompilationDatabase CDB;
|
|
||||||
IgnoreDiagnostics DiagConsumer;
|
|
||||||
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
|
|
||||||
/*StorePreamblesInMemory=*/true,
|
|
||||||
/*BuildDynamicSymbolIndex=*/true);
|
|
||||||
|
|
||||||
Server
|
|
||||||
.addDocument(Context::empty(), getVirtualTestFilePath("foo.cpp"), R"cpp(
|
|
||||||
namespace ns { class XYZ {}; void foo(int x) {} }
|
|
||||||
)cpp")
|
|
||||||
.wait();
|
|
||||||
|
|
||||||
auto File = getVirtualTestFilePath("bar.cpp");
|
|
||||||
Annotations Test(R"cpp(
|
|
||||||
namespace ns {
|
|
||||||
class XXX {};
|
|
||||||
/// Doooc
|
|
||||||
void fooooo() {}
|
|
||||||
}
|
|
||||||
void f() { ns::^ }
|
|
||||||
)cpp");
|
|
||||||
Server.addDocument(Context::empty(), File, Test.code()).wait();
|
|
||||||
|
|
||||||
auto Results = Server.codeComplete(Context::empty(), File, Test.point(), {})
|
|
||||||
.get()
|
|
||||||
.second.Value;
|
|
||||||
// "XYZ" and "foo" are not included in the file being completed but are still
|
|
||||||
// visible through the index.
|
|
||||||
EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
|
|
||||||
EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
|
|
||||||
EXPECT_THAT(Results.items, Has("XXX", CompletionItemKind::Class));
|
|
||||||
EXPECT_THAT(Results.items, Contains(AllOf(Named("fooooo"), Filter("fooooo"),
|
|
||||||
Kind(CompletionItemKind::Function),
|
|
||||||
Doc("Doooc"), Detail("void"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace clangd
|
} // namespace clangd
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
Loading…
Reference in New Issue