[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 llvm-svn: 327717
This commit is contained in:
parent
abbd54ce00
commit
94da7bdde6
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue