[clang-tools-extra] r322824 - [clangd] CodeCompleteTests cleanup: naming, ordering, helpers. NFC
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 18 01:27:56 PST 2018
Author: sammccall
Date: Thu Jan 18 01:27:56 2018
New Revision: 322824
URL: http://llvm.org/viewvc/llvm-project?rev=322824&view=rev
Log:
[clangd] CodeCompleteTests cleanup: naming, ordering, helpers. NFC
Modified:
clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=322824&r1=322823&r2=322824&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Thu Jan 18 01:27:56 2018
@@ -97,8 +97,25 @@ Matcher<const std::vector<CompletionItem
}
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,
+ std::vector<Symbol> IndexSymbols = {},
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;
MockCompilationDatabase CDB;
IgnoreDiagnostics DiagConsumer;
@@ -116,6 +133,27 @@ CompletionList completions(StringRef Tex
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) {
clangd::CodeCompleteOptions Opts;
Opts.Limit = 2;
@@ -127,7 +165,7 @@ struct ClassWithMembers {
}
int main() { ClassWithMembers().^ }
)cpp",
- Opts);
+ /*IndexSymbols=*/{}, Opts);
EXPECT_TRUE(Results.isIncomplete);
EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
@@ -188,7 +226,7 @@ void TestAfterDotCompletion(clangd::Code
ClassWithMembers().^
}
)cpp",
- Opts);
+ /*IndexSymbols=*/{}, Opts);
// Class members. The only items that must be present in after-dot
// completion.
@@ -233,7 +271,7 @@ void TestGlobalScopeCompletion(clangd::C
^
}
)cpp",
- Opts);
+ /*IndexSymbols=*/{}, Opts);
// Class members. Should never be present in global completions.
EXPECT_THAT(Results.items,
@@ -355,7 +393,7 @@ TEST(CompletionTest, Snippets) {
f.^
}
)cpp",
- Opts);
+ /*IndexSymbols=*/{}, Opts);
EXPECT_THAT(Results.items,
HasSubsequence(Snippet("a"),
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("MACRO", CompletionItemKind::Text));
- clangd::CodeCompleteOptions Opts;
- Opts.EnableSnippets = true; // Needed for code patterns.
-
Results = completions("nam^");
EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
}
@@ -406,184 +441,67 @@ TEST(CompletionTest, FuzzyRanking) {
EXPECT_THAT(Items, ElementsAre(Named("BigBang"), Named("Babble")));
}
-SignatureHelp signatures(StringRef Text) {
- MockFSProvider FS;
- MockCompilationDatabase CDB;
- IgnoreDiagnostics DiagConsumer;
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true);
- auto File = getVirtualTestFilePath("foo.cpp");
- Annotations Test(Text);
- Server.addDocument(Context::empty(), File, Test.code());
- auto R = Server.signatureHelp(Context::empty(), File, Test.point());
- assert(R);
- return R.get().Value;
-}
-
-MATCHER_P(ParamsAre, P, "") {
- if (P.size() != arg.parameters.size())
- return false;
- for (unsigned I = 0; I < P.size(); ++I)
- if (P[I] != arg.parameters[I].label)
- return false;
- return true;
-}
-
-Matcher<SignatureInformation> Sig(std::string Label,
- std::vector<std::string> Params) {
- return AllOf(Labeled(Label), ParamsAre(Params));
-}
-
-TEST(SignatureHelpTest, Overloads) {
- auto Results = signatures(R"cpp(
- void foo(int x, int y);
- void foo(int x, float y);
- void foo(float x, int y);
- void foo(float x, float y);
- void bar(int x, int y = 0);
- int main() { foo(^); }
- )cpp");
- EXPECT_THAT(Results.signatures,
- UnorderedElementsAre(
- Sig("foo(float x, float y) -> void", {"float x", "float y"}),
- Sig("foo(float x, int y) -> void", {"float x", "int y"}),
- Sig("foo(int x, float y) -> void", {"int x", "float y"}),
- Sig("foo(int x, int y) -> void", {"int x", "int y"})));
- // We always prefer the first signature.
- EXPECT_EQ(0, Results.activeSignature);
- EXPECT_EQ(0, Results.activeParameter);
-}
-
-TEST(SignatureHelpTest, DefaultArgs) {
- auto Results = signatures(R"cpp(
- void bar(int x, int y = 0);
- void bar(float x = 0, int y = 42);
- int main() { bar(^
- )cpp");
- EXPECT_THAT(Results.signatures,
- UnorderedElementsAre(
- Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
- Sig("bar(float x = 0, int y = 42) -> void",
- {"float x = 0", "int y = 42"})));
- EXPECT_EQ(0, Results.activeSignature);
- EXPECT_EQ(0, Results.activeParameter);
-}
-
-TEST(SignatureHelpTest, ActiveArg) {
- auto Results = signatures(R"cpp(
- int baz(int a, int b, int c);
- int main() { baz(baz(1,2,3), ^); }
- )cpp");
- EXPECT_THAT(Results.signatures,
- ElementsAre(Sig("baz(int a, int b, int c) -> int",
- {"int a", "int b", "int c"})));
- EXPECT_EQ(0, Results.activeSignature);
- 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);
+ )cpp");
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 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",
- Opts);
+ 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, 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, 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) {
- 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")));
+ 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, 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, 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, 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);
+TEST(CompletionTest, IndexFullyQualifiedScope) {
+ auto Results = completions(
+ R"cpp(
+ void f() { ::ns::^ }
+ )cpp",
+ {cls("ns::XYZ")});
EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
}
@@ -612,7 +530,7 @@ TEST(CompletionTest, IndexSuppressesPrea
EXPECT_THAT(WithoutIndex.items,
UnorderedElementsAre(Named("local"), Named("preamble")));
- auto I = simpleIndexFromSymbols({{"ns::index", index::SymbolKind::Variable}});
+ auto I = memIndex({var("ns::index")});
Opts.Index = I.get();
auto WithIndex =
Server.codeComplete(Context::empty(), File, Test.point(), Opts)
@@ -622,7 +540,7 @@ TEST(CompletionTest, IndexSuppressesPrea
UnorderedElementsAre(Named("local"), Named("index")));
}
-TEST(CompletionTest, ASTIndexMultiFile) {
+TEST(CompletionTest, DynamicIndexMultiFile) {
MockFSProvider FS;
MockCompilationDatabase CDB;
IgnoreDiagnostics DiagConsumer;
@@ -660,6 +578,81 @@ TEST(CompletionTest, ASTIndexMultiFile)
Doc("Doooc"), Detail("void"))));
}
+SignatureHelp signatures(StringRef Text) {
+ MockFSProvider FS;
+ MockCompilationDatabase CDB;
+ IgnoreDiagnostics DiagConsumer;
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*StorePreamblesInMemory=*/true);
+ auto File = getVirtualTestFilePath("foo.cpp");
+ Annotations Test(Text);
+ Server.addDocument(Context::empty(), File, Test.code());
+ auto R = Server.signatureHelp(Context::empty(), File, Test.point());
+ assert(R);
+ return R.get().Value;
+}
+
+MATCHER_P(ParamsAre, P, "") {
+ if (P.size() != arg.parameters.size())
+ return false;
+ for (unsigned I = 0; I < P.size(); ++I)
+ if (P[I] != arg.parameters[I].label)
+ return false;
+ return true;
+}
+
+Matcher<SignatureInformation> Sig(std::string Label,
+ std::vector<std::string> Params) {
+ return AllOf(Labeled(Label), ParamsAre(Params));
+}
+
+TEST(SignatureHelpTest, Overloads) {
+ auto Results = signatures(R"cpp(
+ void foo(int x, int y);
+ void foo(int x, float y);
+ void foo(float x, int y);
+ void foo(float x, float y);
+ void bar(int x, int y = 0);
+ int main() { foo(^); }
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(
+ Sig("foo(float x, float y) -> void", {"float x", "float y"}),
+ Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+ Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+ Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+ // We always prefer the first signature.
+ EXPECT_EQ(0, Results.activeSignature);
+ EXPECT_EQ(0, Results.activeParameter);
+}
+
+TEST(SignatureHelpTest, DefaultArgs) {
+ auto Results = signatures(R"cpp(
+ void bar(int x, int y = 0);
+ void bar(float x = 0, int y = 42);
+ int main() { bar(^
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ UnorderedElementsAre(
+ Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+ Sig("bar(float x = 0, int y = 42) -> void",
+ {"float x = 0", "int y = 42"})));
+ EXPECT_EQ(0, Results.activeSignature);
+ EXPECT_EQ(0, Results.activeParameter);
+}
+
+TEST(SignatureHelpTest, ActiveArg) {
+ auto Results = signatures(R"cpp(
+ int baz(int a, int b, int c);
+ int main() { baz(baz(1,2,3), ^); }
+ )cpp");
+ EXPECT_THAT(Results.signatures,
+ ElementsAre(Sig("baz(int a, int b, int c) -> int",
+ {"int a", "int b", "int c"})));
+ EXPECT_EQ(0, Results.activeSignature);
+ EXPECT_EQ(1, Results.activeParameter);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list