summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-11-14 09:05:19 +0000
committerSam McCall <sam.mccall@gmail.com>2018-11-14 09:05:19 +0000
commit39e86fa5e49005898c47ca6b23bc465f65fe66c7 (patch)
treebd4e2d51217cfd472fd3400daf6a7fee107d4804 /clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
parent2634bd599567842385e11d1fd70f5486c166f935 (diff)
downloadbcm5719-llvm-39e86fa5e49005898c47ca6b23bc465f65fe66c7.tar.gz
bcm5719-llvm-39e86fa5e49005898c47ca6b23bc465f65fe66c7.zip
[clangd] Improve code completion for ObjC methods
Summary: Previously code completion did not work well for Objective-C methods which contained multiple arguments as clangd did not expect to see multiple typed-text chunks when handling code completion. Note that even with this change, we do not consider selector fragments from previous arguments to be part of the signature (although we could in the future). Reviewers: sammccall Reviewed By: sammccall Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D53934 llvm-svn: 346836
Diffstat (limited to 'clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp')
-rw-r--r--clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp90
1 files changed, 86 insertions, 4 deletions
diff --git a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
index 03a0f59aa13..b1e164dad07 100644
--- a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
+++ b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp
@@ -67,6 +67,7 @@ MATCHER(InsertInclude, "") {
}
MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+MATCHER_P(Signature, S, "") { return arg.Signature == S; }
// Shorthand for Contains(Named(Name)).
Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
@@ -105,7 +106,8 @@ CodeCompleteResult completions(ClangdServer &Server, StringRef TestCode,
CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
std::vector<Symbol> IndexSymbols = {},
- clangd::CodeCompleteOptions Opts = {}) {
+ clangd::CodeCompleteOptions Opts = {},
+ PathRef FilePath = "foo.cpp") {
std::unique_ptr<SymbolIndex> OverrideIndex;
if (!IndexSymbols.empty()) {
assert(!Opts.Index && "both Index and IndexSymbols given!");
@@ -113,7 +115,7 @@ CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
Opts.Index = OverrideIndex.get();
}
- auto File = testPath("foo.cpp");
+ auto File = testPath(FilePath);
Annotations Test(Text);
runAddDocument(Server, File, Test.code());
auto CompletionList =
@@ -125,12 +127,14 @@ CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
// If IndexSymbols is non-empty, an index will be built and passed to opts.
CodeCompleteResult completions(StringRef Text,
std::vector<Symbol> IndexSymbols = {},
- clangd::CodeCompleteOptions Opts = {}) {
+ clangd::CodeCompleteOptions Opts = {},
+ PathRef FilePath = "foo.cpp") {
MockFSProvider FS;
MockCompilationDatabase CDB;
IgnoreDiagnostics DiagConsumer;
ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
- return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
+ return completions(Server, Text, std::move(IndexSymbols), std::move(Opts),
+ FilePath);
}
std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
@@ -2204,6 +2208,84 @@ TEST(CompletionTest, NoCompletionsForNewNames) {
{cls("naber"), cls("nx::naber")}, Opts);
EXPECT_THAT(Results.Completions, UnorderedElementsAre());
}
+
+TEST(CompletionTest, ObjectiveCMethodNoArguments) {
+ auto Results = completions(R"objc(
+ @interface Foo
+ @property(nonatomic, setter=setXToIgnoreComplete:) int value;
+ @end
+ Foo *foo = [Foo new]; int y = [foo v^]
+ )objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{},
+ "Foo.m");
+
+ auto C = Results.Completions;
+ EXPECT_THAT(C, ElementsAre(Named("value")));
+ EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
+ EXPECT_THAT(C, ElementsAre(ReturnType("int")));
+ EXPECT_THAT(C, ElementsAre(Signature("")));
+ EXPECT_THAT(C, ElementsAre(SnippetSuffix("")));
+}
+
+TEST(CompletionTest, ObjectiveCMethodOneArgument) {
+ auto Results = completions(R"objc(
+ @interface Foo
+ - (int)valueForCharacter:(char)c;
+ @end
+ Foo *foo = [Foo new]; int y = [foo v^]
+ )objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{},
+ "Foo.m");
+
+ auto C = Results.Completions;
+ EXPECT_THAT(C, ElementsAre(Named("valueForCharacter:")));
+ EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
+ EXPECT_THAT(C, ElementsAre(ReturnType("int")));
+ EXPECT_THAT(C, ElementsAre(Signature("(char)")));
+ EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(char)}")));
+}
+
+TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
+ auto Results = completions(R"objc(
+ @interface Foo
+ + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
+ @end
+ id val = [Foo foo^]
+ )objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{},
+ "Foo.m");
+
+ auto C = Results.Completions;
+ EXPECT_THAT(C, ElementsAre(Named("fooWithValue:")));
+ EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
+ EXPECT_THAT(C, ElementsAre(ReturnType("id")));
+ EXPECT_THAT(C, ElementsAre(Signature("(int) fooey:(unsigned int)")));
+ EXPECT_THAT(C,
+ ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
+}
+
+TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
+ auto Results = completions(R"objc(
+ @interface Foo
+ + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
+ @end
+ id val = [Foo fooWithValue:10 f^]
+ )objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{},
+ "Foo.m");
+
+ auto C = Results.Completions;
+ EXPECT_THAT(C, ElementsAre(Named("fooey:")));
+ EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
+ EXPECT_THAT(C, ElementsAre(ReturnType("id")));
+ EXPECT_THAT(C, ElementsAre(Signature("(unsigned int)")));
+ EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}")));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
OpenPOWER on IntegriCloud