completion: if preamble size changes, rebuild it

Fix #190

If a new header is added, the preamble size changes. Language clients may cache completion results, thus we rebuild preamble to avoid inaccurate results.
This commit is contained in:
Fangrui Song 2019-01-13 18:33:18 +08:00
parent 5a72ddda38
commit 118c5cea6a
2 changed files with 18 additions and 9 deletions

View File

@ -412,7 +412,9 @@ void *PreambleMain(void *manager_) {
BuildCompilerInvocation(task.path, session->file.args, FS)) BuildCompilerInvocation(task.path, session->file.args, FS))
BuildPreamble(*session, *CI, FS, task, std::move(stat_cache)); BuildPreamble(*session, *CI, FS, task, std::move(stat_cache));
if (task.from_diag) { if (task.comp_task) {
manager->comp_tasks.PushBack(std::move(task.comp_task));
} else if (task.from_diag) {
manager->ScheduleDiag(task.path, 0); manager->ScheduleDiag(task.path, 0);
} else { } else {
int debounce = int debounce =
@ -463,12 +465,18 @@ void *CompletionMain(void *manager_) {
DiagnosticConsumer DC; DiagnosticConsumer DC;
std::string content = manager->wfiles->GetContent(task->path); std::string content = manager->wfiles->GetContent(task->path);
auto Buf = llvm::MemoryBuffer::getMemBuffer(content); auto Buf = llvm::MemoryBuffer::getMemBuffer(content);
PreambleBounds Bounds =
ComputePreambleBounds(*CI->getLangOpts(), Buf.get(), 0);
bool in_preamble = bool in_preamble =
GetOffsetForPosition({task->position.line, task->position.character}, GetOffsetForPosition({task->position.line, task->position.character},
content) < content) < (int)Bounds.Size;
ComputePreambleBounds(*CI->getLangOpts(), Buf.get(), 0).Size; if (in_preamble) {
if (in_preamble)
preamble.reset(); preamble.reset();
} else if (preamble && Bounds.Size != preamble->Preamble.getBounds().Size) {
manager->preamble_tasks.PushBack({task->path, std::move(task), false},
true);
continue;
}
auto Clang = BuildCompilerInstance(*session, std::move(CI), FS, DC, auto Clang = BuildCompilerInstance(*session, std::move(CI), FS, DC,
preamble.get(), task->path, Buf); preamble.get(), task->path, Buf);
if (!Clang) if (!Clang)
@ -545,7 +553,7 @@ void *DiagnosticMain(void *manager_) {
} }
} }
if (rebuild) { if (rebuild) {
manager->preamble_tasks.PushBack({task.path, true}, true); manager->preamble_tasks.PushBack({task.path, nullptr, true}, true);
continue; continue;
} }
} }

View File

@ -102,10 +102,6 @@ struct SemaManager {
std::function<void(clang::CodeCompleteConsumer *OptConsumer)>; std::function<void(clang::CodeCompleteConsumer *OptConsumer)>;
using OnDropped = std::function<void(RequestId request_id)>; using OnDropped = std::function<void(RequestId request_id)>;
struct PreambleTask {
std::string path;
bool from_diag = false;
};
struct CompTask { struct CompTask {
CompTask(const RequestId &id, const std::string &path, CompTask(const RequestId &id, const std::string &path,
const Position &position, const Position &position,
@ -126,6 +122,11 @@ struct SemaManager {
int64_t wait_until; int64_t wait_until;
int64_t debounce; int64_t debounce;
}; };
struct PreambleTask {
std::string path;
std::unique_ptr<CompTask> comp_task;
bool from_diag = false;
};
SemaManager(Project *project, WorkingFiles *wfiles, SemaManager(Project *project, WorkingFiles *wfiles,
OnDiagnostic on_diagnostic, OnDropped on_dropped); OnDiagnostic on_diagnostic, OnDropped on_dropped);