Handle file deletion and register workspace/didChangeWatchedFiles

* In the "initialized" callback, send client/registerCapability with DidChangeWatchedFilesRegistrationOptions
* In workspace/didChangeWatchedFiles callback, call pipeline::Index
* In pipeline::Index, add a `deleted` status
This commit is contained in:
Fangrui Song 2018-12-20 20:53:50 -08:00
parent 828c21c8d7
commit cbd36aeedb
13 changed files with 160 additions and 81 deletions

View File

@ -82,8 +82,7 @@ struct IndexParam {
if (!vfs.Stamp(path, it->second.mtime, 1)) if (!vfs.Stamp(path, it->second.mtime, 1))
return; return;
it->second.db = std::make_unique<IndexFile>(File.getUniqueID(), path, it->second.db = std::make_unique<IndexFile>(path, it->second.content);
it->second.content);
} }
} }
@ -1186,9 +1185,8 @@ public:
const int IndexFile::kMajorVersion = 19; const int IndexFile::kMajorVersion = 19;
const int IndexFile::kMinorVersion = 1; const int IndexFile::kMinorVersion = 1;
IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, IndexFile::IndexFile(const std::string &path, const std::string &contents)
const std::string &contents) : path(path), file_contents(contents) {}
: UniqueID(UniqueID), path(path), file_contents(contents) {}
IndexFunc &IndexFile::ToFunc(Usr usr) { IndexFunc &IndexFile::ToFunc(Usr usr) {
auto [it, inserted] = usr2func.try_emplace(usr); auto [it, inserted] = usr2func.try_emplace(usr);

View File

@ -290,7 +290,6 @@ struct IndexFile {
// files accepted by newer ccls. // files accepted by newer ccls.
static const int kMinorVersion; static const int kMinorVersion;
llvm::sys::fs::UniqueID UniqueID;
std::string path; std::string path;
std::vector<const char *> args; std::vector<const char *> args;
// This is unfortunately time_t as used by clang::FileEntry // This is unfortunately time_t as used by clang::FileEntry
@ -320,8 +319,7 @@ struct IndexFile {
// File contents at the time of index. Not serialized. // File contents at the time of index. Not serialized.
std::string file_contents; std::string file_contents;
IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, IndexFile(const std::string &path, const std::string &contents);
const std::string &contents);
IndexFunc &ToFunc(Usr usr); IndexFunc &ToFunc(Usr usr);
IndexType &ToType(Usr usr); IndexType &ToType(Usr usr);

View File

@ -181,6 +181,7 @@ MessageHandler::MessageHandler() {
Bind("$ccls/vars", &MessageHandler::ccls_vars); Bind("$ccls/vars", &MessageHandler::ccls_vars);
Bind("exit", &MessageHandler::exit); Bind("exit", &MessageHandler::exit);
Bind("initialize", &MessageHandler::initialize); Bind("initialize", &MessageHandler::initialize);
Bind("initialized", &MessageHandler::initialized);
Bind("shutdown", &MessageHandler::shutdown); Bind("shutdown", &MessageHandler::shutdown);
Bind("textDocument/codeAction", &MessageHandler::textDocument_codeAction); Bind("textDocument/codeAction", &MessageHandler::textDocument_codeAction);
Bind("textDocument/codeLens", &MessageHandler::textDocument_codeLens); Bind("textDocument/codeLens", &MessageHandler::textDocument_codeLens);

View File

@ -250,6 +250,7 @@ private:
void ccls_vars(JsonReader &, ReplyOnce &); void ccls_vars(JsonReader &, ReplyOnce &);
void exit(EmptyParam &); void exit(EmptyParam &);
void initialize(JsonReader &, ReplyOnce &); void initialize(JsonReader &, ReplyOnce &);
void initialized(EmptyParam &);
void shutdown(EmptyParam &, ReplyOnce &); void shutdown(EmptyParam &, ReplyOnce &);
void textDocument_codeAction(CodeActionParam &, ReplyOnce &); void textDocument_codeAction(CodeActionParam &, ReplyOnce &);
void textDocument_codeLens(TextDocumentParam &, ReplyOnce &); void textDocument_codeLens(TextDocumentParam &, ReplyOnce &);

View File

@ -42,6 +42,8 @@ namespace {
enum class TextDocumentSyncKind { None = 0, Full = 1, Incremental = 2 }; enum class TextDocumentSyncKind { None = 0, Full = 1, Incremental = 2 };
REFLECT_UNDERLYING(TextDocumentSyncKind) REFLECT_UNDERLYING(TextDocumentSyncKind)
bool didChangeWatchedFiles;
struct ServerCap { struct ServerCap {
struct SaveOptions { struct SaveOptions {
bool includeText = false; bool includeText = false;
@ -239,6 +241,24 @@ struct InitializeResult {
}; };
REFLECT_STRUCT(InitializeResult, capabilities); REFLECT_STRUCT(InitializeResult, capabilities);
struct FileSystemWatcher {
std::string globPattern = "**/*";
};
struct DidChangeWatchedFilesRegistration {
std::string id = "didChangeWatchedFiles";
std::string method = "workspace/didChangeWatchedFiles";
struct Option {
std::vector<FileSystemWatcher> watchers = {{}};
} registerOptions;
};
struct RegistrationParam {
std::vector<DidChangeWatchedFilesRegistration> registrations = {{}};
};
REFLECT_STRUCT(FileSystemWatcher, globPattern);
REFLECT_STRUCT(DidChangeWatchedFilesRegistration::Option, watchers);
REFLECT_STRUCT(DidChangeWatchedFilesRegistration, id, method, registerOptions);
REFLECT_STRUCT(RegistrationParam, registrations);
void *Indexer(void *arg_) { void *Indexer(void *arg_) {
MessageHandler *h; MessageHandler *h;
int idx; int idx;
@ -298,6 +318,8 @@ void Initialize(MessageHandler *m, InitializeParam &param, ReplyOnce &reply) {
capabilities.textDocument.definition.linkSupport; capabilities.textDocument.definition.linkSupport;
g_config->client.snippetSupport &= g_config->client.snippetSupport &=
capabilities.textDocument.completion.completionItem.snippetSupport; capabilities.textDocument.completion.completionItem.snippetSupport;
didChangeWatchedFiles =
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration;
// Ensure there is a resource directory. // Ensure there is a resource directory.
if (g_config->clang.resourceDir.empty()) if (g_config->clang.resourceDir.empty())
@ -370,6 +392,13 @@ void StandaloneInitialize(MessageHandler &handler, const std::string &root) {
Initialize(&handler, param, reply); Initialize(&handler, param, reply);
} }
void MessageHandler::initialized(EmptyParam &) {
if (didChangeWatchedFiles) {
RegistrationParam param;
pipeline::Request("client/registerCapability", param);
}
}
void MessageHandler::shutdown(EmptyParam &, ReplyOnce &reply) { void MessageHandler::shutdown(EmptyParam &, ReplyOnce &reply) {
reply(JsonNull{}); reply(JsonNull{});
} }

View File

@ -25,7 +25,7 @@ void MessageHandler::textDocument_didChange(TextDocumentDidChangeParam &param) {
std::string path = param.textDocument.uri.GetPath(); std::string path = param.textDocument.uri.GetPath();
wfiles->OnChange(param); wfiles->OnChange(param);
if (g_config->index.onChange) if (g_config->index.onChange)
pipeline::Index(path, {}, IndexMode::OnChange); pipeline::Index(path, {}, IndexMode::OnChange, true);
manager->OnView(path); manager->OnView(path);
if (g_config->diagnostics.onChange >= 0) if (g_config->diagnostics.onChange >= 0)
manager->ScheduleDiag(path, g_config->diagnostics.onChange); manager->ScheduleDiag(path, g_config->diagnostics.onChange);
@ -56,14 +56,14 @@ void MessageHandler::textDocument_didOpen(DidOpenTextDocumentParam &param) {
std::pair<LanguageId, bool> lang = lookupExtension(path); std::pair<LanguageId, bool> lang = lookupExtension(path);
if ((lang.first != LanguageId::Unknown && !lang.second) || if ((lang.first != LanguageId::Unknown && !lang.second) ||
!pipeline::pending_index_requests) !pipeline::pending_index_requests)
pipeline::Index(path, {}, IndexMode::Normal); pipeline::Index(path, {}, IndexMode::Normal, false);
manager->OnView(path); manager->OnView(path);
} }
void MessageHandler::textDocument_didSave(TextDocumentParam &param) { void MessageHandler::textDocument_didSave(TextDocumentParam &param) {
const std::string &path = param.textDocument.uri.GetPath(); const std::string &path = param.textDocument.uri.GetPath();
pipeline::Index(path, {}, IndexMode::Normal); pipeline::Index(path, {}, IndexMode::Normal, false);
manager->OnSave(path); manager->OnSave(path);
} }
} // namespace ccls } // namespace ccls

View File

@ -23,11 +23,13 @@ limitations under the License.
#include <llvm/ADT/STLExtras.h> #include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/StringRef.h> #include <llvm/ADT/StringRef.h>
#include <llvm/Support/Path.h>
#include <algorithm> #include <algorithm>
#include <ctype.h> #include <ctype.h>
#include <functional> #include <functional>
#include <limits.h> #include <limits.h>
using namespace llvm;
namespace ccls { namespace ccls {
REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName); REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
@ -44,20 +46,30 @@ void MessageHandler::workspace_didChangeWatchedFiles(
DidChangeWatchedFilesParam &param) { DidChangeWatchedFilesParam &param) {
for (auto &event : param.changes) { for (auto &event : param.changes) {
std::string path = event.uri.GetPath(); std::string path = event.uri.GetPath();
if ((g_config->cacheDirectory.size() &&
StringRef(path).startswith(g_config->cacheDirectory)) ||
lookupExtension(path).first == LanguageId::Unknown)
return;
for (std::string cur = path; cur.size(); cur = sys::path::parent_path(cur))
if (cur[0] == '.')
return;
IndexMode mode = IndexMode mode =
wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::NonInteractive; wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::NonInteractive;
switch (event.type) { switch (event.type) {
case FileChangeType::Created: case FileChangeType::Created:
case FileChangeType::Changed: { case FileChangeType::Changed: {
pipeline::Index(path, {}, mode); pipeline::Index(path, {}, mode, true);
if (event.type == FileChangeType::Changed) {
if (mode == IndexMode::Normal) if (mode == IndexMode::Normal)
manager->OnSave(path); manager->OnSave(path);
else else
manager->OnClose(path); manager->OnClose(path);
}
break; break;
} }
case FileChangeType::Deleted: case FileChangeType::Deleted:
pipeline::Index(path, {}, mode); pipeline::Index(path, {}, mode, false);
manager->OnClose(path); manager->OnClose(path);
break; break;
} }

View File

@ -77,16 +77,16 @@ void StandaloneInitialize(MessageHandler &, const std::string &root);
namespace pipeline { namespace pipeline {
std::atomic<bool> quit; std::atomic<bool> quit;
std::atomic<int64_t> loaded_ts = ATOMIC_VAR_INIT(0), std::atomic<int64_t> loaded_ts{0}, pending_index_requests{0}, request_id{0};
pending_index_requests = ATOMIC_VAR_INIT(0);
int64_t tick = 0; int64_t tick = 0;
namespace { namespace {
struct Index_Request { struct IndexRequest {
std::string path; std::string path;
std::vector<const char *> args; std::vector<const char *> args;
IndexMode mode; IndexMode mode;
bool must_exist = false;
RequestId id; RequestId id;
int64_t ts = tick++; int64_t ts = tick++;
}; };
@ -99,7 +99,7 @@ MultiQueueWaiter *main_waiter;
MultiQueueWaiter *indexer_waiter; MultiQueueWaiter *indexer_waiter;
MultiQueueWaiter *stdout_waiter; MultiQueueWaiter *stdout_waiter;
ThreadedQueue<InMessage> *on_request; ThreadedQueue<InMessage> *on_request;
ThreadedQueue<Index_Request> *index_request; ThreadedQueue<IndexRequest> *index_request;
ThreadedQueue<IndexUpdate> *on_indexed; ThreadedQueue<IndexUpdate> *on_indexed;
ThreadedQueue<std::string> *for_stdout; ThreadedQueue<std::string> *for_stdout;
@ -184,7 +184,7 @@ std::mutex &GetFileMutex(const std::string &path) {
bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
Project *project, VFS *vfs, const GroupMatch &matcher) { Project *project, VFS *vfs, const GroupMatch &matcher) {
std::optional<Index_Request> opt_request = index_request->TryPopFront(); std::optional<IndexRequest> opt_request = index_request->TryPopFront();
if (!opt_request) if (!opt_request)
return false; return false;
auto &request = *opt_request; auto &request = *opt_request;
@ -206,23 +206,33 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
return false; return false;
} }
Project::Entry entry = project->FindEntry(request.path, true); // must_exist is currently unused.
Project::Entry entry = project->FindEntry(request.path, false);
if (request.must_exist && entry.filename.empty())
return true;
if (request.args.size()) if (request.args.size())
entry.args = request.args; entry.args = request.args;
std::string path_to_index = entry.filename; std::string path_to_index = entry.filename;
std::unique_ptr<IndexFile> prev; std::unique_ptr<IndexFile> prev;
bool deleted = false;
int reparse = 0;
std::optional<int64_t> write_time = LastWriteTime(path_to_index); std::optional<int64_t> write_time = LastWriteTime(path_to_index);
if (!write_time) if (!write_time) {
return true; deleted = true;
int reparse = vfs->Stamp(path_to_index, *write_time, 0); } else {
reparse = vfs->Stamp(path_to_index, *write_time, 0);
if (request.path != path_to_index) { if (request.path != path_to_index) {
std::optional<int64_t> mtime1 = LastWriteTime(request.path); std::optional<int64_t> mtime1 = LastWriteTime(request.path);
if (!mtime1) if (!mtime1)
return true; deleted = true;
if (vfs->Stamp(request.path, *mtime1, 0)) else if (vfs->Stamp(request.path, *mtime1, 0))
reparse = 2; reparse = 2;
} }
}
if (deleted)
reparse = 2;
if (g_config->index.onChange) { if (g_config->index.onChange) {
reparse = 2; reparse = 2;
std::lock_guard lock(vfs->mutex); std::lock_guard lock(vfs->mutex);
@ -306,9 +316,15 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
for (auto &arg : entry.args) for (auto &arg : entry.args)
(line += ' ') += arg; (line += ' ') += arg;
} }
LOG_S(INFO) << "parse " << path_to_index << line; LOG_S(INFO) << (deleted ? "delete " : "parse ") << path_to_index << line;
} }
std::vector<std::unique_ptr<IndexFile>> indexes;
if (deleted) {
indexes.push_back(std::make_unique<IndexFile>(request.path, ""));
if (request.path != path_to_index)
indexes.push_back(std::make_unique<IndexFile>(path_to_index, ""));
} else {
std::vector<std::pair<std::string, std::string>> remapped; std::vector<std::pair<std::string, std::string>> remapped;
if (g_config->index.onChange) { if (g_config->index.onChange) {
std::string content = wfiles->GetContent(path_to_index); std::string content = wfiles->GetContent(path_to_index);
@ -316,7 +332,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
remapped.emplace_back(path_to_index, content); remapped.emplace_back(path_to_index, content);
} }
bool ok; bool ok;
auto indexes = idx::Index(completion, wfiles, vfs, entry.directory, indexes = idx::Index(completion, wfiles, vfs, entry.directory,
path_to_index, entry.args, remapped, ok); path_to_index, entry.args, remapped, ok);
if (!ok) { if (!ok) {
@ -328,6 +344,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
} }
return true; return true;
} }
}
for (std::unique_ptr<IndexFile> &curr : indexes) { for (std::unique_ptr<IndexFile> &curr : indexes) {
std::string path = curr->path; std::string path = curr->path;
@ -336,8 +353,9 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
continue; continue;
} }
LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev if (!deleted)
<< ")"; LOG_IF_S(INFO, loud) << "store index for " << path
<< " (delta: " << !!prev << ")";
{ {
std::lock_guard lock(GetFileMutex(path)); std::lock_guard lock(GetFileMutex(path));
if (vfs->Loaded(path)) if (vfs->Loaded(path))
@ -351,10 +369,15 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
std::string().swap(it.first->second.index.file_contents); std::string().swap(it.first->second.index.file_contents);
} else { } else {
std::string cache_path = GetCachePath(path); std::string cache_path = GetCachePath(path);
if (deleted) {
(void)sys::fs::remove(cache_path);
(void)sys::fs::remove(AppendSerializationFormat(cache_path));
} else {
WriteToFile(cache_path, curr->file_contents); WriteToFile(cache_path, curr->file_contents);
WriteToFile(AppendSerializationFormat(cache_path), WriteToFile(AppendSerializationFormat(cache_path),
Serialize(g_config->cacheFormat, *curr)); Serialize(g_config->cacheFormat, *curr));
} }
}
on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()), on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()),
request.mode != IndexMode::NonInteractive); request.mode != IndexMode::NonInteractive);
{ {
@ -404,7 +427,7 @@ void Init() {
on_indexed = new ThreadedQueue<IndexUpdate>(main_waiter); on_indexed = new ThreadedQueue<IndexUpdate>(main_waiter);
indexer_waiter = new MultiQueueWaiter; indexer_waiter = new MultiQueueWaiter;
index_request = new ThreadedQueue<Index_Request>(indexer_waiter); index_request = new ThreadedQueue<IndexRequest>(indexer_waiter);
stdout_waiter = new MultiQueueWaiter; stdout_waiter = new MultiQueueWaiter;
for_stdout = new ThreadedQueue<std::string>(stdout_waiter); for_stdout = new ThreadedQueue<std::string>(stdout_waiter);
@ -637,9 +660,10 @@ void Standalone(const std::string &root) {
} }
void Index(const std::string &path, const std::vector<const char *> &args, void Index(const std::string &path, const std::vector<const char *> &args,
IndexMode mode, RequestId id) { IndexMode mode, bool must_exist, RequestId id) {
pending_index_requests++; pending_index_requests++;
index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); index_request->PushBack({path, args, mode, must_exist, id},
mode != IndexMode::NonInteractive);
} }
std::optional<std::string> LoadIndexedContent(const std::string &path) { std::optional<std::string> LoadIndexedContent(const std::string &path) {
@ -653,7 +677,8 @@ std::optional<std::string> LoadIndexedContent(const std::string &path) {
return ReadContent(GetCachePath(path)); return ReadContent(GetCachePath(path));
} }
void Notify(const char *method, const std::function<void(JsonWriter &)> &fn) { void NotifyOrRequest(const char *method, bool request,
const std::function<void(JsonWriter &)> &fn) {
rapidjson::StringBuffer output; rapidjson::StringBuffer output;
rapidjson::Writer<rapidjson::StringBuffer> w(output); rapidjson::Writer<rapidjson::StringBuffer> w(output);
w.StartObject(); w.StartObject();
@ -661,6 +686,10 @@ void Notify(const char *method, const std::function<void(JsonWriter &)> &fn) {
w.String("2.0"); w.String("2.0");
w.Key("method"); w.Key("method");
w.String(method); w.String(method);
if (request) {
w.Key("id");
w.Int64(request_id.fetch_add(1, std::memory_order_relaxed));
}
w.Key("params"); w.Key("params");
JsonWriter writer(&w); JsonWriter writer(&w);
fn(writer); fn(writer);

View File

@ -51,13 +51,17 @@ void MainLoop();
void Standalone(const std::string &root); void Standalone(const std::string &root);
void Index(const std::string &path, const std::vector<const char *> &args, void Index(const std::string &path, const std::vector<const char *> &args,
IndexMode mode, RequestId id = {}); IndexMode mode, bool must_exist, RequestId id = {});
std::optional<std::string> LoadIndexedContent(const std::string& path); std::optional<std::string> LoadIndexedContent(const std::string& path);
void Notify(const char *method, const std::function<void(JsonWriter &)> &fn); void NotifyOrRequest(const char *method, bool request,
const std::function<void(JsonWriter &)> &fn);
template <typename T> void Notify(const char *method, T &result) { template <typename T> void Notify(const char *method, T &result) {
Notify(method, [&](JsonWriter &w) { Reflect(w, result); }); NotifyOrRequest(method, false, [&](JsonWriter &w) { Reflect(w, result); });
}
template <typename T> void Request(const char *method, T &result) {
NotifyOrRequest(method, true, [&](JsonWriter &w) { Reflect(w, result); });
} }
void Reply(RequestId id, const std::function<void(JsonWriter &)> &fn); void Reply(RequestId id, const std::function<void(JsonWriter &)> &fn);

View File

@ -424,7 +424,7 @@ void Project::Load(const std::string &root) {
} }
Project::Entry Project::FindEntry(const std::string &path, Project::Entry Project::FindEntry(const std::string &path,
bool can_be_inferred) { bool must_exist) {
Project::Folder *best_folder = nullptr; Project::Folder *best_folder = nullptr;
const Entry *best = nullptr; const Entry *best = nullptr;
std::lock_guard lock(mtx); std::lock_guard lock(mtx);
@ -432,11 +432,12 @@ Project::Entry Project::FindEntry(const std::string &path,
auto it = folder.path2entry_index.find(path); auto it = folder.path2entry_index.find(path);
if (it != folder.path2entry_index.end()) { if (it != folder.path2entry_index.end()) {
Project::Entry &entry = folder.entries[it->second]; Project::Entry &entry = folder.entries[it->second];
if (can_be_inferred || entry.filename == path) if (!must_exist || entry.filename == path)
return entry; return entry;
} }
} }
bool exists = false;
std::string dir; std::string dir;
const std::vector<const char *> *extra = nullptr; const std::vector<const char *> *extra = nullptr;
Project::Entry ret; Project::Entry ret;
@ -444,11 +445,12 @@ Project::Entry Project::FindEntry(const std::string &path,
if (StringRef(path).startswith(root)) if (StringRef(path).startswith(root))
for (auto &[dir1, args] : folder.dot_ccls) for (auto &[dir1, args] : folder.dot_ccls)
if (StringRef(path).startswith(dir1)) { if (StringRef(path).startswith(dir1)) {
if (AppendToCDB(args)) {
dir = dir1; dir = dir1;
extra = &args; extra = &args;
if (AppendToCDB(args))
goto out; goto out;
} exists = true;
ret.root = ret.directory = root; ret.root = ret.directory = root;
ret.filename = path; ret.filename = path;
if (args.empty()) { if (args.empty()) {
@ -464,6 +466,8 @@ Project::Entry Project::FindEntry(const std::string &path,
return ret; return ret;
} }
out: out:
if (must_exist && !exists)
return ret;
if (!best) { if (!best) {
int best_score = INT_MIN; int best_score = INT_MIN;
@ -526,9 +530,10 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
if (match.Matches(entry.filename, &reason) && if (match.Matches(entry.filename, &reason) &&
match_i.Matches(entry.filename, &reason)) { match_i.Matches(entry.filename, &reason)) {
bool interactive = wfiles->GetFile(entry.filename) != nullptr; bool interactive = wfiles->GetFile(entry.filename) != nullptr;
pipeline::Index( pipeline::Index(entry.filename, entry.args,
entry.filename, entry.args, interactive ? IndexMode::Normal
interactive ? IndexMode::Normal : IndexMode::NonInteractive, id); : IndexMode::NonInteractive,
false, id);
} else { } else {
LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason
<< "; skip " << entry.filename; << "; skip " << entry.filename;
@ -541,6 +546,6 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
pipeline::loaded_ts = pipeline::tick; pipeline::loaded_ts = pipeline::tick;
// Dummy request to indicate that project is loaded and // Dummy request to indicate that project is loaded and
// trigger refreshing semantic highlight for all working files. // trigger refreshing semantic highlight for all working files.
pipeline::Index("", {}, IndexMode::NonInteractive); pipeline::Index("", {}, IndexMode::NonInteractive, false);
} }
} // namespace ccls } // namespace ccls

View File

@ -83,8 +83,7 @@ bool TryReplaceDef(llvm::SmallVectorImpl<Q> &def_list, Q &&def) {
IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
IndexUpdate r; IndexUpdate r;
static IndexFile empty(llvm::sys::fs::UniqueID(0, 0), current->path, static IndexFile empty(current->path, "<empty>");
"<empty>");
if (previous) if (previous)
r.prev_lid2path = std::move(previous->lid2path); r.prev_lid2path = std::move(previous->lid2path);
else else

View File

@ -302,7 +302,7 @@ public:
std::unique_ptr<CompilerInstance> BuildCompilerInstance( std::unique_ptr<CompilerInstance> BuildCompilerInstance(
Session &session, std::unique_ptr<CompilerInvocation> CI, Session &session, std::unique_ptr<CompilerInvocation> CI,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, DiagnosticConsumer &DC, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, DiagnosticConsumer &DC,
const PreambleData *preamble, const std::string &path, const PreambleData *preamble, const std::string &main,
std::unique_ptr<llvm::MemoryBuffer> &Buf) { std::unique_ptr<llvm::MemoryBuffer> &Buf) {
if (preamble) { if (preamble) {
#if LLVM_VERSION_MAJOR >= 7 #if LLVM_VERSION_MAJOR >= 7
@ -311,7 +311,7 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance(
preamble->Preamble.AddImplicitPreamble(*CI, FS, Buf.get()); preamble->Preamble.AddImplicitPreamble(*CI, FS, Buf.get());
#endif #endif
} else { } else {
CI->getPreprocessorOpts().addRemappedFile(path, Buf.get()); CI->getPreprocessorOpts().addRemappedFile(main, Buf.get());
} }
auto Clang = std::make_unique<CompilerInstance>(session.PCH); auto Clang = std::make_unique<CompilerInstance>(session.PCH);
@ -328,6 +328,11 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance(
Clang->createFileManager(); Clang->createFileManager();
Clang->setSourceManager(new SourceManager(Clang->getDiagnostics(), Clang->setSourceManager(new SourceManager(Clang->getDiagnostics(),
Clang->getFileManager(), true)); Clang->getFileManager(), true));
auto &IS = Clang->getFrontendOpts().Inputs;
if (IS.size()) {
assert(IS[0].isFile());
IS[0] = FrontendInputFile(main, IS[0].getKind(), IS[0].isSystem());
}
return Clang; return Clang;
} }
@ -702,7 +707,7 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
std::shared_ptr<ccls::Session> session = sessions.Get(path); std::shared_ptr<ccls::Session> session = sessions.Get(path);
if (!session) { if (!session) {
session = std::make_shared<ccls::Session>( session = std::make_shared<ccls::Session>(
project_->FindEntry(path, false), wfiles, PCH); project_->FindEntry(path, true), wfiles, PCH);
std::string line; std::string line;
if (LOG_V_ENABLED(1)) { if (LOG_V_ENABLED(1)) {
line = "\n "; line = "\n ";

View File

@ -482,8 +482,7 @@ Deserialize(SerializeFormat format, const std::string &path,
if (major != IndexFile::kMajorVersion || if (major != IndexFile::kMajorVersion ||
minor != IndexFile::kMinorVersion) minor != IndexFile::kMinorVersion)
throw std::invalid_argument("Invalid version"); throw std::invalid_argument("Invalid version");
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path, file = std::make_unique<IndexFile>(path, file_content);
file_content);
ReflectFile(reader, *file); ReflectFile(reader, *file);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what(); LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what();
@ -506,8 +505,7 @@ Deserialize(SerializeFormat format, const std::string &path,
if (reader.HasParseError()) if (reader.HasParseError())
return nullptr; return nullptr;
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path, file = std::make_unique<IndexFile>(path, file_content);
file_content);
JsonReader json_reader{&reader}; JsonReader json_reader{&reader};
try { try {
ReflectFile(json_reader, *file); ReflectFile(json_reader, *file);