diff options
author | Ilya Biryukov <ibiryukov@google.com> | 2018-03-16 15:23:44 +0000 |
---|---|---|
committer | Ilya Biryukov <ibiryukov@google.com> | 2018-03-16 15:23:44 +0000 |
commit | 3b6826fe84373f6a101c5615771793c01510455d (patch) | |
tree | c218eba70b3e5cbdf4bfa0efca7b21e1fa03be6d | |
parent | 73d0e61849df642258421d89fea4b9e140871688 (diff) |
[clangd] Handle multiple callbacks from Sema's completion
Summary:
When parser backtracks, we might receive multiple code completion
callbacks.
Previously we had a failing assertion there, now we take first results
and hope they are good enough.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44567
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@327717 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | clangd/CodeComplete.cpp | 9 | ||||
-rw-r--r-- | unittests/clangd/CodeCompleteTests.cpp | 37 |
2 files changed, 45 insertions, 1 deletions
diff --git a/clangd/CodeComplete.cpp b/clangd/CodeComplete.cpp index 6edc0769..87536459 100644 --- a/clangd/CodeComplete.cpp +++ b/clangd/CodeComplete.cpp @@ -450,8 +450,15 @@ struct CompletionRecorder : public CodeCompleteConsumer { void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context, CodeCompletionResult *InResults, unsigned NumResults) override final { + if (CCSema) { + log(llvm::formatv( + "Multiple code complete callbacks (parser backtracked?). " + "Dropping results from context {0}, keeping results from {1}.", + getCompletionKindString(this->CCContext.getKind()), + getCompletionKindString(Context.getKind()))); + return; + } // Record the completion context. - assert(!CCSema && "ProcessCodeCompleteResults called multiple times!"); CCSema = &S; CCContext = Context; diff --git a/unittests/clangd/CodeCompleteTests.cpp b/unittests/clangd/CodeCompleteTests.cpp index 1e11db73..48771a38 100644 --- a/unittests/clangd/CodeCompleteTests.cpp +++ b/unittests/clangd/CodeCompleteTests.cpp @@ -608,6 +608,43 @@ TEST(CodeCompleteTest, NoColonColonAtTheEnd) { EXPECT_THAT(Results.items, Not(Contains(Labeled("clang::")))); } +TEST(CompletionTest, BacktrackCrashes) { + // Sema calls code completion callbacks twice in these cases. + auto Results = completions(R"cpp( + namespace ns { + struct FooBarBaz {}; + } // namespace ns + + int foo(ns::FooBar^ + )cpp"); + + EXPECT_THAT(Results.items, ElementsAre(Labeled("FooBarBaz"))); + + // Check we don't crash in that case too. + completions(R"cpp( + struct FooBarBaz {}; + void test() { + if (FooBarBaz * x^) {} + } +)cpp"); +} + +TEST(CompletionTest, CompleteInExcludedPPBranch) { + auto Results = completions(R"cpp( + int bar(int param_in_bar) { + } + + int foo(int param_in_foo) { +#if 0 + par^ +#endif + } +)cpp"); + + EXPECT_THAT(Results.items, Contains(Labeled("param_in_foo"))); + EXPECT_THAT(Results.items, Not(Contains(Labeled("param_in_bar")))); +} + SignatureHelp signatures(StringRef Text) { MockFSProvider FS; MockCompilationDatabase CDB; |