From d4df372559adb0ba3c652e85817a50db707c9858 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Mon, 10 Feb 2020 11:52:42 +0100 Subject: [PATCH] [clangd] Expose completion range in code completion results (C++ API) Summary: Informative only, useful for positioning UI, interacting with other sources of completion etc. As requested by an embedder of clangd. Reviewers: usaxena95 Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D74305 --- clang-tools-extra/clangd/CodeComplete.cpp | 1 + clang-tools-extra/clangd/CodeComplete.h | 5 +++++ .../clangd/unittests/CodeCompleteTests.cpp | 23 ++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 4d4d15b..6fc6c5d 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1473,6 +1473,7 @@ private: } Output.HasMore = Incomplete; Output.Context = CCContextKind; + Output.CompletionRange = ReplacedRange; return Output; } diff --git a/clang-tools-extra/clangd/CodeComplete.h b/clang-tools-extra/clangd/CodeComplete.h index fd01dfd..3b3dca3 100644 --- a/clang-tools-extra/clangd/CodeComplete.h +++ b/clang-tools-extra/clangd/CodeComplete.h @@ -216,6 +216,11 @@ struct CodeCompleteResult { std::vector Completions; bool HasMore = false; CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other; + // The text that is being directly completed. + // Example: foo.pb^ -> foo.push_back() + // ~~ + // Typically matches the textEdit.range of Completions, but not guaranteed to. + llvm::Optional CompletionRange; // Usually the source will be parsed with a real C++ parser. // But heuristics may be used instead if e.g. the preamble is not ready. bool RanParser = true; diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 8863d9f..67b8abb 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -2134,6 +2134,7 @@ TEST(GuessCompletionPrefix, Filters) { "some text [[scope::more::]][[identif]]^ier", "some text [[scope::]][[mor]]^e::identifier", "weird case foo::[[::bar::]][[baz]]^", + "/* [[]][[]]^ */", }) { Annotations F(Case); auto Offset = cantFail(positionToOffset(F.code(), F.point())); @@ -2675,6 +2676,28 @@ TEST(CompletionTest, NoCrashWithIncompleteLambda) { EXPECT_THAT(Signatures, Contains(Sig("x() -> auto"))); } +TEST(CompletionTest, CompletionRange) { + const char *WithRange = "auto x = [[abc]]^"; + auto Completions = completions(WithRange); + EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range()); + Completions = completionsNoCompile(WithRange); + EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range()); + + const char *EmptyRange = "auto x = [[]]^"; + Completions = completions(EmptyRange); + EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range()); + Completions = completionsNoCompile(EmptyRange); + EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range()); + + // Sema doesn't trigger at all here, while the no-sema completion runs + // heuristics as normal and reports a range. It'd be nice to be consistent. + const char *NoCompletion = "/* [[]]^ */"; + Completions = completions(NoCompletion); + EXPECT_EQ(Completions.CompletionRange, llvm::None); + Completions = completionsNoCompile(NoCompletion); + EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range()); +} + TEST(NoCompileCompletionTest, Basic) { auto Results = completionsNoCompile(R"cpp( void func() { -- 2.7.4