mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									828c21c8d7
								
							
						
					
					
						commit
						cbd36aeedb
					
				@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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 &);
 | 
				
			||||||
 | 
				
			|||||||
@ -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 ¶m, 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{});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ void MessageHandler::textDocument_didChange(TextDocumentDidChangeParam ¶m) {
 | 
				
			|||||||
  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 ¶m) {
 | 
				
			|||||||
  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 ¶m) {
 | 
					void MessageHandler::textDocument_didSave(TextDocumentParam ¶m) {
 | 
				
			||||||
  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
 | 
				
			||||||
 | 
				
			|||||||
@ -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 ¶m) {
 | 
					    DidChangeWatchedFilesParam ¶m) {
 | 
				
			||||||
  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 (mode == IndexMode::Normal)
 | 
					      if (event.type == FileChangeType::Changed) {
 | 
				
			||||||
        manager->OnSave(path);
 | 
					        if (mode == IndexMode::Normal)
 | 
				
			||||||
      else
 | 
					          manager->OnSave(path);
 | 
				
			||||||
        manager->OnClose(path);
 | 
					        else
 | 
				
			||||||
 | 
					          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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										113
									
								
								src/pipeline.cc
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/pipeline.cc
									
									
									
									
									
								
							@ -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 {
 | 
				
			||||||
  if (request.path != path_to_index) {
 | 
					    reparse = vfs->Stamp(path_to_index, *write_time, 0);
 | 
				
			||||||
    std::optional<int64_t> mtime1 = LastWriteTime(request.path);
 | 
					    if (request.path != path_to_index) {
 | 
				
			||||||
    if (!mtime1)
 | 
					      std::optional<int64_t> mtime1 = LastWriteTime(request.path);
 | 
				
			||||||
      return true;
 | 
					      if (!mtime1)
 | 
				
			||||||
    if (vfs->Stamp(request.path, *mtime1, 0))
 | 
					        deleted = true;
 | 
				
			||||||
      reparse = 2;
 | 
					      else if (vfs->Stamp(request.path, *mtime1, 0))
 | 
				
			||||||
 | 
					        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,27 +316,34 @@ 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::pair<std::string, std::string>> remapped;
 | 
					  std::vector<std::unique_ptr<IndexFile>> indexes;
 | 
				
			||||||
  if (g_config->index.onChange) {
 | 
					  if (deleted) {
 | 
				
			||||||
    std::string content = wfiles->GetContent(path_to_index);
 | 
					    indexes.push_back(std::make_unique<IndexFile>(request.path, ""));
 | 
				
			||||||
    if (content.size())
 | 
					    if (request.path != path_to_index)
 | 
				
			||||||
      remapped.emplace_back(path_to_index, content);
 | 
					      indexes.push_back(std::make_unique<IndexFile>(path_to_index, ""));
 | 
				
			||||||
  }
 | 
					  } else {
 | 
				
			||||||
  bool ok;
 | 
					    std::vector<std::pair<std::string, std::string>> remapped;
 | 
				
			||||||
  auto indexes = idx::Index(completion, wfiles, vfs, entry.directory,
 | 
					    if (g_config->index.onChange) {
 | 
				
			||||||
                            path_to_index, entry.args, remapped, ok);
 | 
					      std::string content = wfiles->GetContent(path_to_index);
 | 
				
			||||||
 | 
					      if (content.size())
 | 
				
			||||||
  if (!ok) {
 | 
					        remapped.emplace_back(path_to_index, content);
 | 
				
			||||||
    if (request.id.Valid()) {
 | 
					    }
 | 
				
			||||||
      ResponseError err;
 | 
					    bool ok;
 | 
				
			||||||
      err.code = ErrorCode::InternalError;
 | 
					    indexes = idx::Index(completion, wfiles, vfs, entry.directory,
 | 
				
			||||||
      err.message = "failed to index " + path_to_index;
 | 
					                         path_to_index, entry.args, remapped, ok);
 | 
				
			||||||
      pipeline::ReplyError(request.id, err);
 | 
					
 | 
				
			||||||
 | 
					    if (!ok) {
 | 
				
			||||||
 | 
					      if (request.id.Valid()) {
 | 
				
			||||||
 | 
					        ResponseError err;
 | 
				
			||||||
 | 
					        err.code = ErrorCode::InternalError;
 | 
				
			||||||
 | 
					        err.message = "failed to index " + path_to_index;
 | 
				
			||||||
 | 
					        pipeline::ReplyError(request.id, err);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (std::unique_ptr<IndexFile> &curr : indexes) {
 | 
					  for (std::unique_ptr<IndexFile> &curr : indexes) {
 | 
				
			||||||
@ -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,9 +369,14 @@ 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);
 | 
				
			||||||
        WriteToFile(cache_path, curr->file_contents);
 | 
					        if (deleted) {
 | 
				
			||||||
        WriteToFile(AppendSerializationFormat(cache_path),
 | 
					          (void)sys::fs::remove(cache_path);
 | 
				
			||||||
          Serialize(g_config->cacheFormat, *curr));
 | 
					          (void)sys::fs::remove(AppendSerializationFormat(cache_path));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          WriteToFile(cache_path, curr->file_contents);
 | 
				
			||||||
 | 
					          WriteToFile(AppendSerializationFormat(cache_path),
 | 
				
			||||||
 | 
					                      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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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 ";
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user