diff --git a/src/indexer.cc b/src/indexer.cc index 22fe697f..066fc9f1 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -81,7 +81,8 @@ struct IndexParam { if (!vfs.Stamp(path, it->second.mtime, no_linkage ? 3 : 1)) return; - it->second.db = std::make_unique(path, it->second.content); + it->second.db = + std::make_unique(path, it->second.content, no_linkage); } } @@ -1173,11 +1174,12 @@ class IndexFrontendAction : public ASTFrontendAction { }; } // namespace -const int IndexFile::kMajorVersion = 20; +const int IndexFile::kMajorVersion = 21; const int IndexFile::kMinorVersion = 0; -IndexFile::IndexFile(const std::string &path, const std::string &contents) - : path(path), file_contents(contents) {} +IndexFile::IndexFile(const std::string &path, const std::string &contents, + bool no_linkage) + : path(path), no_linkage(no_linkage), file_contents(contents) {} IndexFunc &IndexFile::ToFunc(Usr usr) { auto [it, inserted] = usr2func.try_emplace(usr); @@ -1236,8 +1238,8 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, ok = false; // -fparse-all-comments enables documentation in the indexer and in // code completion. - if (g_config->index.comments > 1) - CI->getLangOpts()->CommentOpts.ParseAllComments = true; + CI->getLangOpts()->CommentOpts.ParseAllComments = g_config->index.comments > 1; + CI->getLangOpts()->RetainCommentsFromSystemHeaders = true; std::string buf = wfiles->GetContent(main); std::vector> Bufs; if (buf.size()) @@ -1249,12 +1251,18 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, DiagnosticConsumer DC; auto Clang = std::make_unique(PCH); Clang->setInvocation(std::move(CI)); - Clang->setVirtualFileSystem(FS); Clang->createDiagnostics(&DC, false); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); if (!Clang->hasTarget()) return {}; + Clang->getPreprocessorOpts().RetainRemappedFileBuffers = true; +#if LLVM_VERSION_MAJOR >= 9 // rC357037 + Clang->createFileManager(FS); +#else + Clang->setVirtualFileSystem(FS); + Clang->createFileManager(); +#endif IndexParam param(*vfs, no_linkage); auto DataConsumer = std::make_shared(param); @@ -1266,6 +1274,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, IndexOpts.IndexFunctionLocals = true; IndexOpts.IndexImplicitInstantiation = true; #if LLVM_VERSION_MAJOR >= 9 + IndexOpts.IndexParametersInDeclarations = g_config->index.parametersInDeclarations; IndexOpts.IndexTemplateParameters = true; @@ -1294,8 +1303,6 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, LOG_S(ERROR) << "failed to index " << main; return {}; } - for (auto &Buf : Bufs) - Buf.release(); std::vector> result; for (auto &it : param.UID2File) { diff --git a/src/indexer.hh b/src/indexer.hh index ca87c5d6..9796ea75 100644 --- a/src/indexer.hh +++ b/src/indexer.hh @@ -304,6 +304,7 @@ struct IndexFile { // This is unfortunately time_t as used by clang::FileEntry int64_t mtime = 0; LanguageId language = LanguageId::C; + bool no_linkage; // uid2lid_and_path is used to generate lid2path, but not serialized. std::unordered_map> @@ -328,7 +329,8 @@ struct IndexFile { // File contents at the time of index. Not serialized. std::string file_contents; - IndexFile(const std::string &path, const std::string &contents); + IndexFile(const std::string &path, const std::string &contents, + bool no_linkage); IndexFunc &ToFunc(Usr usr); IndexType &ToType(Usr usr); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index c0344a34..772b9127 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -226,8 +226,8 @@ void Reflect(JsonReader &reader, InitializeParam::Trace &value) { value = InitializeParam::Trace::Verbose; } -REFLECT_STRUCT(InitializeParam, rootUri, initializationOptions, capabilities, - trace, workspaceFolders); +// initializationOptions is deserialized separately. +REFLECT_STRUCT(InitializeParam, rootUri, capabilities, trace, workspaceFolders); struct InitializeResult { ServerCap capabilities; @@ -395,6 +395,17 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) { void MessageHandler::initialize(JsonReader &reader, ReplyOnce &reply) { InitializeParam param; Reflect(reader, param); + auto it = reader.m->FindMember("initializationOptions"); + if (it != reader.m->MemberEnd() && it->value.IsObject()) { + JsonReader m1(&it->value); + try { + Reflect(m1, param.initializationOptions); + } catch (std::invalid_argument &) { + reader.path_.push_back("initializationOptions"); + reader.path_.insert(reader.path_.end(), m1.path_.begin(), m1.path_.end()); + throw; + } + } if (!param.rootUri) { reply.Error(ErrorCode::InvalidRequest, "expected rootUri"); return; diff --git a/src/pipeline.cc b/src/pipeline.cc index 7bf0bd61..2791d1bc 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -298,7 +298,10 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, request.mode != IndexMode::Background); { std::lock_guard lock1(vfs->mutex); - vfs->state[path_to_index].loaded++; + VFS::State &st = vfs->state[path_to_index]; + st.loaded++; + if (prev->no_linkage) + st.step = 2; } lock.unlock(); @@ -317,6 +320,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, continue; st.loaded++; st.timestamp = prev->mtime; + if (prev->no_linkage) + st.step = 3; } IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), @@ -341,9 +346,9 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, std::vector> indexes; if (deleted) { - indexes.push_back(std::make_unique(request.path, "")); + indexes.push_back(std::make_unique(request.path, "", false)); if (request.path != path_to_index) - indexes.push_back(std::make_unique(path_to_index, "")); + indexes.push_back(std::make_unique(path_to_index, "", false)); } else { std::vector> remapped; if (g_config->index.onChange) { diff --git a/src/query.cc b/src/query.cc index 6adfb424..ca2d228f 100644 --- a/src/query.cc +++ b/src/query.cc @@ -128,7 +128,7 @@ QueryType::Def Convert(const IndexType::Def &o) { IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { IndexUpdate r; - static IndexFile empty(current->path, ""); + static IndexFile empty(current->path, "", false); if (previous) r.prev_lid2path = std::move(previous->lid2path); else diff --git a/src/sema_manager.cc b/src/sema_manager.cc index d78b5e06..d8e7608e 100644 --- a/src/sema_manager.cc +++ b/src/sema_manager.cc @@ -308,16 +308,21 @@ std::unique_ptr BuildCompilerInstance( auto Clang = std::make_unique(session.PCH); Clang->setInvocation(std::move(CI)); - Clang->setVirtualFileSystem(FS); Clang->createDiagnostics(&DC, false); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); if (!Clang->hasTarget()) return nullptr; + Clang->getPreprocessorOpts().RetainRemappedFileBuffers = true; // Construct SourceManager with UserFilesAreVolatile: true because otherwise // RequiresNullTerminator: true may cause out-of-bounds read when a file is // mmap'ed but is saved concurrently. +#if LLVM_VERSION_MAJOR >= 9 // rC357037 + Clang->createFileManager(FS); +#else + Clang->setVirtualFileSystem(FS); Clang->createFileManager(); +#endif Clang->setSourceManager(new SourceManager(Clang->getDiagnostics(), Clang->getFileManager(), true)); auto &IS = Clang->getFrontendOpts().Inputs; @@ -358,6 +363,7 @@ void BuildPreamble(Session &session, CompilerInvocation &CI, CI.getDiagnosticOpts().IgnoreWarnings = false; CI.getFrontendOpts().SkipFunctionBodies = true; CI.getLangOpts()->CommentOpts.ParseAllComments = g_config->index.comments > 1; + CI.getLangOpts()->RetainCommentsFromSystemHeaders = true; StoreDiags DC(task.path); IntrusiveRefCntPtr DE = @@ -489,7 +495,6 @@ void *CompletionMain(void *manager_) { Clang->setCodeCompletionConsumer(task->Consumer.release()); if (!Parse(*Clang)) continue; - Buf.release(); task->on_complete(&Clang->getCodeCompletionConsumer()); } @@ -579,7 +584,6 @@ void *DiagnosticMain(void *manager_) { continue; if (!Parse(*Clang)) continue; - Buf.release(); auto Fill = [](const DiagBase &d, Diagnostic &ret) { ret.range = lsRange{{d.range.start.line, d.range.start.column}, diff --git a/src/serializer.cc b/src/serializer.cc index 0dec4710..556ff242 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -374,6 +374,7 @@ template void Reflect1(TVisitor &vis, IndexFile &v) { if (!gTestOutputMode) { REFLECT_MEMBER(mtime); REFLECT_MEMBER(language); + REFLECT_MEMBER(no_linkage); REFLECT_MEMBER(lid2path); REFLECT_MEMBER(import_file); REFLECT_MEMBER(args); @@ -407,6 +408,11 @@ void Reflect(JsonWriter &vis, SerializeFormat &v) { } } +void ReflectMemberStart(JsonReader &vis) { + if (!vis.m->IsObject()) + throw std::invalid_argument("object"); +} + static BumpPtrAllocator Alloc; static DenseSet Strings; static std::mutex AllocMutex; @@ -482,7 +488,7 @@ Deserialize(SerializeFormat format, const std::string &path, if (major != IndexFile::kMajorVersion || minor != IndexFile::kMinorVersion) throw std::invalid_argument("Invalid version"); - file = std::make_unique(path, file_content); + file = std::make_unique(path, file_content, false); ReflectFile(reader, *file); } catch (std::invalid_argument &e) { LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what(); @@ -505,7 +511,7 @@ Deserialize(SerializeFormat format, const std::string &path, if (reader.HasParseError()) return nullptr; - file = std::make_unique(path, file_content); + file = std::make_unique(path, file_content, false); JsonReader json_reader{&reader}; try { ReflectFile(json_reader, *file); diff --git a/src/serializer.hh b/src/serializer.hh index de5c24ac..21e91136 100644 --- a/src/serializer.hh +++ b/src/serializer.hh @@ -379,6 +379,7 @@ template void Reflect(BinaryWriter &vis, std::vector &v) { // ReflectMember +void ReflectMemberStart(JsonReader &); template void ReflectMemberStart(T &) {} inline void ReflectMemberStart(JsonWriter &vis) { vis.StartObject(); }