From bd3e06796ee3445948958a7336e0b30bb052573a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 26 Aug 2018 17:22:45 -0700 Subject: [PATCH 01/66] SkipFunctionBodiesScope; improve fuzzy --- src/clang_tu.cc | 5 +++-- src/fuzzy_match.cc | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 28984f19..74130296 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -109,9 +109,10 @@ std::unique_ptr ClangTranslationUnit::Create( /*CacheCodeCompletionResults=*/true, g_config->index.comments, /*AllowPCHWithCompilerErrors=*/true, #if LLVM_VERSION_MAJOR >= 7 - SkipFunctionBodiesScope::None, + diagnostic ? SkipFunctionBodiesScope::None + : SkipFunctionBodiesScope::PreambleAndMainFile, #else - false, + !diagnostic, #endif /*SingleFileParse=*/false, /*UserFilesAreVolatile=*/true, false, diff --git a/src/fuzzy_match.cc b/src/fuzzy_match.cc index 3d69d925..577f6223 100644 --- a/src/fuzzy_match.cc +++ b/src/fuzzy_match.cc @@ -43,7 +43,7 @@ void CalculateRoles(std::string_view s, int roles[], int *class_set) { if (cur == Other) return None; // U(U)L is Head while U(U)U is Tail - return pre == Other || (cur == Upper && (pre == Lower || suc != Upper)) + return pre == Other || (cur == Upper && (pre == Lower || suc == Lower)) ? Head : Tail; }; From f808dd8f8acacfef92c1a58fddd61ffcc2e69a52 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 27 Aug 2018 22:42:40 -0700 Subject: [PATCH 02/66] Use StoreInMemory Preamble for CodeComplete --- src/clang_complete.cc | 186 ++++++++++++++++++++++++++++-------------- src/clang_complete.h | 34 ++++++-- src/clang_tu.cc | 5 +- src/working_files.cc | 8 ++ src/working_files.h | 1 + 5 files changed, 165 insertions(+), 69 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index c24f9c7a..e41c9fb9 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -22,6 +22,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -320,12 +321,12 @@ public: unsigned NumResults) override { ls_items.reserve(NumResults); for (unsigned i = 0; i != NumResults; i++) { + if (Results[i].Availability == CXAvailability_NotAccessible || + Results[i].Availability == CXAvailability_NotAvailable) + continue; CodeCompletionString *CCS = Results[i].CreateCodeCompletionString( S, Context, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); - if (CCS->getAvailability() == CXAvailability_NotAvailable) - continue; - lsCompletionItem ls_item; ls_item.kind = GetCompletionKind(Results[i].CursorKind); if (const char *brief = CCS->getBriefComment()) @@ -380,7 +381,7 @@ void TryEnsureDocumentParsed(ClangCompleteManager *manager, return; const auto &args = session->file.args; - WorkingFiles::Snapshot snapshot = session->working_files->AsSnapshot( + WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( {StripFileType(session->file.filename)}); LOG_S(INFO) << "create " << (diagnostic ? "diagnostic" : "completion") @@ -389,6 +390,23 @@ void TryEnsureDocumentParsed(ClangCompleteManager *manager, diagnostic); } +std::unique_ptr +buildCompilerInvocation(const std::vector &args, + IntrusiveRefCntPtr VFS) { + std::vector cargs; + for (auto &arg : args) + cargs.push_back(arg.c_str()); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(new DiagnosticOptions)); + std::unique_ptr CI = + createInvocationFromCommandLine(cargs, Diags, VFS); + if (CI) { + CI->getLangOpts()->CommentOpts.ParseAllComments = true; + CI->getLangOpts()->SpellChecking = false; + } + return CI; +} + void CompletionPreloadMain(ClangCompleteManager *completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. @@ -403,22 +421,14 @@ void CompletionPreloadMain(ClangCompleteManager *completion_manager) { if (!session) continue; - // Note: we only preload completion. We emit diagnostics for the - // completion preload though. - CompletionSession::Tu *tu = &session->completion; + const auto &args = session->file.args; + WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( + {StripFileType(session->file.filename)}); - // If we've parsed it more recently than the request time, don't bother - // reparsing. - if (tu->last_parsed_at && *tu->last_parsed_at > request.request_time) - continue; - - std::unique_ptr parsing; - TryEnsureDocumentParsed(completion_manager, session, &parsing, false); - - // Activate new translation unit. - std::lock_guard lock(tu->lock); - tu->last_parsed_at = std::chrono::high_resolution_clock::now(); - tu->tu = std::move(parsing); + LOG_S(INFO) << "create completion session for " << session->file.filename; + if (std::unique_ptr CI = + buildCompilerInvocation(args, session->FS)) + session->BuildPreamble(*CI); } } @@ -441,48 +451,70 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { completion_manager->TryGetSession(path, true /*mark_as_completion*/, true /*create_if_needed*/); - std::lock_guard lock(session->completion.lock); - TryEnsureDocumentParsed(completion_manager, session, - &session->completion.tu, false); - - // It is possible we failed to create the document despite - // |TryEnsureDocumentParsed|. - if (ClangTranslationUnit *tu = session->completion.tu.get()) { - WorkingFiles::Snapshot snapshot = - completion_manager->working_files_->AsSnapshot({StripFileType(path)}); - IntrusiveRefCntPtr FileMgr(&tu->Unit->getFileManager()); - IntrusiveRefCntPtr DiagOpts(new DiagnosticOptions()); - IntrusiveRefCntPtr Diag(new DiagnosticsEngine( - IntrusiveRefCntPtr(new DiagnosticIDs), &*DiagOpts)); - // StoreDiags Diags; - // IntrusiveRefCntPtr DiagE = - // CompilerInstance::createDiagnostics(DiagOpts.get(), &Diags, false); - - IntrusiveRefCntPtr SrcMgr( - new SourceManager(*Diag, *FileMgr)); - std::vector Remapped = GetRemapped(snapshot); - SmallVector Diagnostics; - SmallVector TemporaryBuffers; - - CodeCompleteOptions Opts; - LangOptions LangOpts; - Opts.IncludeBriefComments = true; + std::unique_ptr CI = + buildCompilerInvocation(session->file.args, session->FS); + if (!CI) + continue; + clang::CodeCompleteOptions CCOpts; #if LLVM_VERSION_MAJOR >= 7 - Opts.LoadExternal = true; - Opts.IncludeFixIts = true; + CCOpts.IncludeFixIts = true; #endif - CaptureCompletionResults capture(Opts); - tu->Unit->CodeComplete(session->file.filename, request->position.line + 1, - request->position.character + 1, Remapped, - /*IncludeMacros=*/true, - /*IncludeCodePatterns=*/false, - /*IncludeBriefComments=*/g_config->index.comments, - capture, tu->PCHCO, *Diag, LangOpts, *SrcMgr, - *FileMgr, Diagnostics, TemporaryBuffers); - request->on_complete(capture.ls_items, false /*is_cached_result*/); - // completion_manager->on_diagnostic_(session->file.filename, - // Diags.take()); + CCOpts.IncludeCodePatterns = true; + auto &FOpts = CI->getFrontendOpts(); + FOpts.DisableFree = false; + FOpts.CodeCompleteOpts = CCOpts; + FOpts.CodeCompletionAt.FileName = session->file.filename; + FOpts.CodeCompletionAt.Line = request->position.line + 1; + FOpts.CodeCompletionAt.Column = request->position.character + 1; + + WorkingFiles::Snapshot snapshot = + completion_manager->working_files_->AsSnapshot({StripFileType(path)}); + + std::vector> Bufs; + for (auto &file : snapshot.files) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); + if (file.filename == session->file.filename) { + if (auto Preamble = session->GetPreamble()) { +#if LLVM_VERSION_MAJOR >= 7 + Preamble->Preamble.OverridePreamble(*CI, session->FS, + Bufs.back().get()); +#else + Preamble->Preamble.AddImplicitPreamble(*CI, session->FS, + Bufs.back().get()); +#endif + } + else { + CI->getPreprocessorOpts().addRemappedFile( + CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get()); + } + } else { + CI->getPreprocessorOpts().addRemappedFile(file.filename, + Bufs.back().get()); + } } + + IgnoringDiagConsumer DC; + auto Clang = std::make_unique(session->PCH); + Clang->setInvocation(std::move(CI)); + Clang->createDiagnostics(&DC, false); + auto Consumer = new CaptureCompletionResults(CCOpts); + Clang->setCodeCompletionConsumer(Consumer); + Clang->setVirtualFileSystem(session->FS); + Clang->setTarget(TargetInfo::CreateTargetInfo( + Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); + if (!Clang->hasTarget()) + continue; + + SyntaxOnlyAction Action; + if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) + continue; + if (!Action.Execute()) + continue; + Action.EndSourceFile(); + for (auto &Buf : Bufs) + Buf.release(); + + request->on_complete(Consumer->ls_items, false /*is_cached_result*/); } } @@ -573,6 +605,37 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { } // namespace +std::shared_ptr CompletionSession::GetPreamble() { + std::lock_guard lock(completion.lock); + return completion.preamble; +} + +void CompletionSession::BuildPreamble(CompilerInvocation &CI) { + std::shared_ptr OldP = GetPreamble(); + std::string contents = wfiles->GetContent(file.filename); + std::unique_ptr Buf = + llvm::MemoryBuffer::getMemBuffer(contents); + auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0); + if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get())) + return; + CI.getFrontendOpts().SkipFunctionBodies = true; +#if LLVM_VERSION_MAJOR >= 7 + CI.getPreprocessorOpts().WriteCommentListToPCH = false; +#endif + + DiagnosticConsumer DC; + IntrusiveRefCntPtr PreambleDE = + CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), + &DC, false); + PreambleCallbacks PP; + if (auto NewPreamble = PrecompiledPreamble::Build( + CI, Buf.get(), Bounds, *PreambleDE, FS, PCH, true, PP)) { + std::lock_guard lock(completion.lock); + completion.preamble = + std::make_shared(std::move(*NewPreamble)); + } +} + ClangCompleteManager::ClangCompleteManager(Project *project, WorkingFiles *working_files, OnDiagnostic on_diagnostic, @@ -580,7 +643,8 @@ ClangCompleteManager::ClangCompleteManager(Project *project, : project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_dropped_(on_dropped), preloaded_sessions_(kMaxPreloadedSessions), - completion_sessions_(kMaxCompletionSessions) { + completion_sessions_(kMaxCompletionSessions), + PCH(std::make_shared()) { std::thread([&]() { set_thread_name("comp-query"); CompletionQueryMain(this); @@ -682,7 +746,7 @@ bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession( // No CompletionSession, create new one. auto session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_); + project_->FindCompilationEntryForFile(filename), working_files_, PCH); preloaded_sessions_.Insert(session->file.filename, session); return true; } @@ -713,7 +777,7 @@ ClangCompleteManager::TryGetSession(const std::string &filename, completion_sessions_.TryGet(filename); if (!completion_session && create_if_needed) { completion_session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_); + project_->FindCompilationEntryForFile(filename), working_files_, PCH); completion_sessions_.Insert(filename, completion_session); } diff --git a/src/clang_complete.h b/src/clang_complete.h index d3f03492..5fa0ba39 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -23,11 +23,19 @@ limitations under the License. #include "threaded_queue.h" #include "working_files.h" +#include +#include + #include #include #include #include +struct PreambleData { + PreambleData(clang::PrecompiledPreamble P) : Preamble(std::move(P)) {} + clang::PrecompiledPreamble Preamble; +}; + struct CompletionSession : public std::enable_shared_from_this { // Translation unit for clang. @@ -40,14 +48,28 @@ struct CompletionSession std::unique_ptr tu; }; - Project::Entry file; - WorkingFiles *working_files; + struct CU { + std::mutex lock; + std::shared_ptr preamble; + }; - Tu completion; + Project::Entry file; + WorkingFiles *wfiles; + + // TODO share + llvm::IntrusiveRefCntPtr FS = + clang::vfs::getRealFileSystem(); + std::shared_ptr PCH; + + CU completion; Tu diagnostics; - CompletionSession(const Project::Entry &file, WorkingFiles *wfiles) - : file(file), working_files(wfiles) {} + CompletionSession(const Project::Entry &file, WorkingFiles *wfiles, + std::shared_ptr PCH) + : file(file), wfiles(wfiles), PCH(PCH) {} + + std::shared_ptr GetPreamble(); + void BuildPreamble(clang::CompilerInvocation &CI); }; struct ClangCompleteManager { @@ -145,6 +167,8 @@ struct ClangCompleteManager { // Parse requests. The path may already be parsed, in which case it should be // reparsed. ThreadedQueue preload_requests_; + + std::shared_ptr PCH; }; // Cached completion information, so we can give fast completion results when diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 74130296..35f969a4 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -104,13 +104,12 @@ std::unique_ptr ClangTranslationUnit::Create( /*ResourceFilePath=*/g_config->clang.resourceDir, /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/diagnostic, Remapped, - /*RemappedFilesKeepOriginalName=*/true, 1, + /*RemappedFilesKeepOriginalName=*/true, 0, diagnostic ? TU_Complete : TU_Prefix, /*CacheCodeCompletionResults=*/true, g_config->index.comments, /*AllowPCHWithCompilerErrors=*/true, #if LLVM_VERSION_MAJOR >= 7 - diagnostic ? SkipFunctionBodiesScope::None - : SkipFunctionBodiesScope::PreambleAndMainFile, + SkipFunctionBodiesScope::None, #else !diagnostic, #endif diff --git a/src/working_files.cc b/src/working_files.cc index 4f6ca27a..74b9f30d 100644 --- a/src/working_files.cc +++ b/src/working_files.cc @@ -442,6 +442,14 @@ WorkingFiles::GetFileByFilenameNoLock(const std::string &filename) { return nullptr; } +std::string WorkingFiles::GetContent(const std::string &filename) { + std::lock_guard lock(files_mutex); + for (auto &file : files) + if (file->filename == filename) + return file->buffer_content; + return ""; +} + void WorkingFiles::DoAction(const std::function &action) { std::lock_guard lock(files_mutex); action(); diff --git a/src/working_files.h b/src/working_files.h index b0ed01c7..dcd8fa84 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -108,6 +108,7 @@ struct WorkingFiles { // Find the file with the given filename. WorkingFile *GetFileByFilename(const std::string &filename); WorkingFile *GetFileByFilenameNoLock(const std::string &filename); + std::string GetContent(const std::string &filename); // Run |action| under the lock. void DoAction(const std::function &action); From 87c5491536f36368811a0fadca576a5b5dcb1c0e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 28 Aug 2018 22:49:53 -0700 Subject: [PATCH 03/66] New diagnostics --- src/clang_complete.cc | 339 ++++++++++++++++++++++++++---------------- src/clang_complete.h | 48 +++--- src/clang_tu.cc | 75 +--------- src/clang_tu.h | 23 +-- 4 files changed, 238 insertions(+), 247 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index e41c9fb9..b9d93b64 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -34,6 +34,7 @@ using namespace llvm; #include #include +namespace ccls { namespace { std::string StripFileType(const std::string &path) { @@ -304,6 +305,38 @@ void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item, } } +bool LocationInRange(SourceLocation L, CharSourceRange R, + const SourceManager &M) { + assert(R.isCharRange()); + if (!R.isValid() || M.getFileID(R.getBegin()) != M.getFileID(R.getEnd()) || + M.getFileID(R.getBegin()) != M.getFileID(L)) + return false; + return L != R.getEnd() && M.isPointWithin(L, R.getBegin(), R.getEnd()); +} + +CharSourceRange DiagnosticRange(const clang::Diagnostic &D, const LangOptions &L) { + auto &M = D.getSourceManager(); + auto Loc = M.getFileLoc(D.getLocation()); + // Accept the first range that contains the location. + for (const auto &CR : D.getRanges()) { + auto R = Lexer::makeFileCharRange(CR, M, L); + if (LocationInRange(Loc, R, M)) + return R; + } + // The range may be given as a fixit hint instead. + for (const auto &F : D.getFixItHints()) { + auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L); + if (LocationInRange(Loc, R, M)) + return R; + } + // If no suitable range is found, just use the token at the location. + auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L); + if (!R.isValid()) // Fall back to location only, let the editor deal with it. + R = CharSourceRange::getCharRange(Loc); + return R; +} + + class CaptureCompletionResults : public CodeCompleteConsumer { std::shared_ptr Alloc; CodeCompletionTUInfo CCTUInfo; @@ -372,23 +405,83 @@ public: CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } }; -void TryEnsureDocumentParsed(ClangCompleteManager *manager, - std::shared_ptr session, - std::unique_ptr *tu, - bool diagnostic) { - // Nothing to do. We already have a translation unit. - if (*tu) - return; +class StoreDiags : public DiagnosticConsumer { + const LangOptions *LangOpts; + std::optional last; + std::vector output; + void Flush() { + if (!last) + return; + bool mentions = last->inside_main || last->edits.size(); + if (!mentions) + for (auto &N : last->notes) + if (N.inside_main) + mentions = true; + if (mentions) + output.push_back(std::move(*last)); + last.reset(); + } +public: + std::vector Take() { + return std::move(output); + } + void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override { + LangOpts = &Opts; + } + void EndSourceFile() override { + Flush(); + } + void HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) override { + DiagnosticConsumer::HandleDiagnostic(Level, Info); + SourceLocation L = Info.getLocation(); + if (!L.isValid()) return; + const SourceManager &SM = Info.getSourceManager(); + bool inside_main = SM.isInMainFile(L); + auto fillDiagBase = [&](DiagBase &d) { + llvm::SmallString<64> Message; + Info.FormatDiagnostic(Message); + d.range = + FromCharSourceRange(SM, *LangOpts, DiagnosticRange(Info, *LangOpts)); + d.message = Message.str(); + d.inside_main = inside_main; + d.file = SM.getFilename(Info.getLocation()); + d.level = Level; + d.category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); + }; - const auto &args = session->file.args; - WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( - {StripFileType(session->file.filename)}); + auto addFix = [&](bool SyntheticMessage) -> bool { + if (!inside_main) + return false; + for (const FixItHint &FixIt : Info.getFixItHints()) { + if (!SM.isInMainFile(FixIt.RemoveRange.getBegin())) + return false; + lsTextEdit edit; + edit.newText = FixIt.CodeToInsert; + auto r = FromCharSourceRange(SM, *LangOpts, FixIt.RemoveRange); + edit.range = + lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; + last->edits.push_back(std::move(edit)); + } + return true; + }; - LOG_S(INFO) << "create " << (diagnostic ? "diagnostic" : "completion") - << " TU for " << session->file.filename; - *tu = ClangTranslationUnit::Create(session->file.filename, args, snapshot, - diagnostic); -} + if (Level == DiagnosticsEngine::Note || Level == DiagnosticsEngine::Remark) { + if (Info.getFixItHints().size()) { + addFix(false); + } else { + Note &n = last->notes.emplace_back(); + fillDiagBase(n); + } + } else { + Flush(); + last = Diag(); + fillDiagBase(*last); + if (!Info.getFixItHints().empty()) + addFix(true); + } + } +}; std::unique_ptr buildCompilerInvocation(const std::vector &args, @@ -401,12 +494,61 @@ buildCompilerInvocation(const std::vector &args, std::unique_ptr CI = createInvocationFromCommandLine(cargs, Diags, VFS); if (CI) { + CI->getFrontendOpts().DisableFree = false; CI->getLangOpts()->CommentOpts.ParseAllComments = true; CI->getLangOpts()->SpellChecking = false; } return CI; } +std::unique_ptr +BuildCompilerInstance(CompletionSession &session, + std::unique_ptr CI, + DiagnosticConsumer &DC, + const WorkingFiles::Snapshot &snapshot, + std::vector> &Bufs) { + for (auto &file : snapshot.files) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); + if (file.filename == session.file.filename) { + if (auto Preamble = session.GetPreamble()) { +#if LLVM_VERSION_MAJOR >= 7 + Preamble->Preamble.OverridePreamble(*CI, session.FS, + Bufs.back().get()); +#else + Preamble->Preamble.AddImplicitPreamble(*CI, session->FS, + Bufs.back().get()); +#endif + } else { + CI->getPreprocessorOpts().addRemappedFile( + CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get()); + } + } else { + CI->getPreprocessorOpts().addRemappedFile(file.filename, + Bufs.back().get()); + } + } + + auto Clang = std::make_unique(session.PCH); + Clang->setInvocation(std::move(CI)); + Clang->setVirtualFileSystem(session.FS); + Clang->createDiagnostics(&DC, false); + Clang->setTarget(TargetInfo::CreateTargetInfo( + Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); + if (!Clang->hasTarget()) + return nullptr; + return Clang; +} + +bool Parse(CompilerInstance &Clang) { + SyntaxOnlyAction Action; + if (!Action.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0])) + return false; + if (!Action.Execute()) + return false; + Action.EndSourceFile(); + return true; +} + void CompletionPreloadMain(ClangCompleteManager *completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. @@ -461,56 +603,23 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { #endif CCOpts.IncludeCodePatterns = true; auto &FOpts = CI->getFrontendOpts(); - FOpts.DisableFree = false; FOpts.CodeCompleteOpts = CCOpts; FOpts.CodeCompletionAt.FileName = session->file.filename; FOpts.CodeCompletionAt.Line = request->position.line + 1; FOpts.CodeCompletionAt.Column = request->position.character + 1; + StoreDiags DC; WorkingFiles::Snapshot snapshot = completion_manager->working_files_->AsSnapshot({StripFileType(path)}); - std::vector> Bufs; - for (auto &file : snapshot.files) { - Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); - if (file.filename == session->file.filename) { - if (auto Preamble = session->GetPreamble()) { -#if LLVM_VERSION_MAJOR >= 7 - Preamble->Preamble.OverridePreamble(*CI, session->FS, - Bufs.back().get()); -#else - Preamble->Preamble.AddImplicitPreamble(*CI, session->FS, - Bufs.back().get()); -#endif - } - else { - CI->getPreprocessorOpts().addRemappedFile( - CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get()); - } - } else { - CI->getPreprocessorOpts().addRemappedFile(file.filename, - Bufs.back().get()); - } - } + auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs); + if (!Clang) + continue; - IgnoringDiagConsumer DC; - auto Clang = std::make_unique(session->PCH); - Clang->setInvocation(std::move(CI)); - Clang->createDiagnostics(&DC, false); auto Consumer = new CaptureCompletionResults(CCOpts); Clang->setCodeCompletionConsumer(Consumer); - Clang->setVirtualFileSystem(session->FS); - Clang->setTarget(TargetInfo::CreateTargetInfo( - Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); - if (!Clang->hasTarget()) + if (!Parse(*Clang)) continue; - - SyntaxOnlyAction Action; - if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) - continue; - if (!Action.Execute()) - continue; - Action.EndSourceFile(); for (auto &Buf : Bufs) Buf.release(); @@ -530,51 +639,31 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { std::shared_ptr session = manager->TryGetSession( path, true /*mark_as_completion*/, true /*create_if_needed*/); - // At this point, we must have a translation unit. Block until we have one. - std::lock_guard lock(session->diagnostics.lock); - TryEnsureDocumentParsed(manager, session, &session->diagnostics.tu, true); - - // It is possible we failed to create the document despite - // |TryEnsureDocumentParsed|. - ClangTranslationUnit *tu = session->diagnostics.tu.get(); - if (!tu) + std::unique_ptr CI = + buildCompilerInvocation(session->file.args, session->FS); + if (!CI) continue; - + StoreDiags DC; WorkingFiles::Snapshot snapshot = manager->working_files_->AsSnapshot({StripFileType(path)}); - llvm::CrashRecoveryContext CRC; - if (tu->Reparse(CRC, snapshot)) { - LOG_S(ERROR) << "Reparsing translation unit for diagnostics failed for " - << path; + std::vector> Bufs; + auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs); + if (!Clang) continue; - } + if (!Parse(*Clang)) + continue; + for (auto &Buf : Bufs) + Buf.release(); - auto &LangOpts = tu->Unit->getLangOpts(); std::vector ls_diags; - for (ASTUnit::stored_diag_iterator I = tu->Unit->stored_diag_begin(), - E = tu->Unit->stored_diag_end(); - I != E; ++I) { - FullSourceLoc FLoc = I->getLocation(); - if (!FLoc.isValid()) // why? + for (auto &d : DC.Take()) { + if (!d.inside_main) continue; - const FileEntry *FE = FLoc.getFileEntry(); - if (!FE || FileName(*FE) != path) - continue; - const auto &SM = FLoc.getManager(); - SourceRange R; - for (const auto &CR : I->getRanges()) { - auto RT = Lexer::makeFileCharRange(CR, SM, LangOpts); - if (SM.isPointWithin(FLoc, RT.getBegin(), RT.getEnd())) { - R = CR.getAsRange(); - break; - } - } - Range r = R.isValid() ? FromCharRange(SM, LangOpts, R) - : FromTokenRange(SM, LangOpts, {FLoc, FLoc}); - lsDiagnostic ls_diag; - ls_diag.range = - lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; - switch (I->getLevel()) { + lsDiagnostic &ls_diag = ls_diags.emplace_back(); + ls_diag.range = lsRange{{d.range.start.line, d.range.start.column}, + {d.range.end.line, d.range.end.column}}; + ls_diag.message = d.message; + switch (d.level) { case DiagnosticsEngine::Ignored: // llvm_unreachable case DiagnosticsEngine::Note: @@ -588,16 +677,8 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { case DiagnosticsEngine::Fatal: ls_diag.severity = lsDiagnosticSeverity::Error; } - ls_diag.message = I->getMessage().str(); - for (const FixItHint &FixIt : I->getFixIts()) { - lsTextEdit edit; - edit.newText = FixIt.CodeToInsert; - r = FromCharSourceRange(SM, LangOpts, FixIt.RemoveRange); - edit.range = - lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; - ls_diag.fixits_.push_back(edit); - } - ls_diags.push_back(ls_diag); + ls_diag.code = d.category; + ls_diag.fixits_ = d.edits; } manager->on_diagnostic_(path, ls_diags); } @@ -606,15 +687,15 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { } // namespace std::shared_ptr CompletionSession::GetPreamble() { - std::lock_guard lock(completion.lock); - return completion.preamble; + std::lock_guard lock(mutex); + return preamble; } void CompletionSession::BuildPreamble(CompilerInvocation &CI) { std::shared_ptr OldP = GetPreamble(); - std::string contents = wfiles->GetContent(file.filename); + std::string content = wfiles->GetContent(file.filename); std::unique_ptr Buf = - llvm::MemoryBuffer::getMemBuffer(contents); + llvm::MemoryBuffer::getMemBuffer(content); auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0); if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get())) return; @@ -623,19 +704,20 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) { CI.getPreprocessorOpts().WriteCommentListToPCH = false; #endif - DiagnosticConsumer DC; - IntrusiveRefCntPtr PreambleDE = - CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), - &DC, false); + StoreDiags DC; + IntrusiveRefCntPtr DE = + CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), &DC, false); PreambleCallbacks PP; - if (auto NewPreamble = PrecompiledPreamble::Build( - CI, Buf.get(), Bounds, *PreambleDE, FS, PCH, true, PP)) { - std::lock_guard lock(completion.lock); - completion.preamble = - std::make_shared(std::move(*NewPreamble)); + if (auto NewPreamble = PrecompiledPreamble::Build(CI, Buf.get(), Bounds, + *DE, FS, PCH, true, PP)) { + std::lock_guard lock(mutex); + preamble = + std::make_shared(std::move(*NewPreamble), DC.Take()); } } +} // namespace ccls + ClangCompleteManager::ClangCompleteManager(Project *project, WorkingFiles *working_files, OnDiagnostic on_diagnostic, @@ -647,17 +729,17 @@ ClangCompleteManager::ClangCompleteManager(Project *project, PCH(std::make_shared()) { std::thread([&]() { set_thread_name("comp-query"); - CompletionQueryMain(this); + ccls::CompletionQueryMain(this); }) .detach(); std::thread([&]() { set_thread_name("comp-preload"); - CompletionPreloadMain(this); + ccls::CompletionPreloadMain(this); }) .detach(); std::thread([&]() { set_thread_name("diag-query"); - DiagnosticQueryMain(this); + ccls::DiagnosticQueryMain(this); }) .detach(); } @@ -745,43 +827,42 @@ bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession( } // No CompletionSession, create new one. - auto session = std::make_shared( + auto session = std::make_shared( project_->FindCompilationEntryForFile(filename), working_files_, PCH); preloaded_sessions_.Insert(session->file.filename, session); return true; } -std::shared_ptr +std::shared_ptr ClangCompleteManager::TryGetSession(const std::string &filename, bool mark_as_completion, bool create_if_needed) { std::lock_guard lock(sessions_lock_); // Try to find a preloaded session. - std::shared_ptr preloaded_session = + std::shared_ptr preloaded = preloaded_sessions_.TryGet(filename); - if (preloaded_session) { + if (preloaded) { // If this request is for a completion, we should move it to // |completion_sessions|. if (mark_as_completion) { preloaded_sessions_.TryTake(filename); - completion_sessions_.Insert(filename, preloaded_session); + completion_sessions_.Insert(filename, preloaded); } - - return preloaded_session; + return preloaded; } // Try to find a completion session. If none create one. - std::shared_ptr completion_session = + std::shared_ptr session = completion_sessions_.TryGet(filename); - if (!completion_session && create_if_needed) { - completion_session = std::make_shared( + if (!session && create_if_needed) { + session = std::make_shared( project_->FindCompilationEntryForFile(filename), working_files_, PCH); - completion_sessions_.Insert(filename, completion_session); + completion_sessions_.Insert(filename, session); } - return completion_session; + return session; } void ClangCompleteManager::FlushSession(const std::string &filename) { diff --git a/src/clang_complete.h b/src/clang_complete.h index 5fa0ba39..92716e41 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -31,27 +31,33 @@ limitations under the License. #include #include +namespace ccls { +struct DiagBase { + Range range; + std::string message; + std::string file; + clang::DiagnosticsEngine::Level level = clang::DiagnosticsEngine::Note; + unsigned category; + bool inside_main = false; +}; +struct Note : DiagBase {}; +struct Diag : DiagBase { + std::vector notes; + std::vector edits; +}; + struct PreambleData { - PreambleData(clang::PrecompiledPreamble P) : Preamble(std::move(P)) {} + PreambleData(clang::PrecompiledPreamble P, std::vector diags) + : Preamble(std::move(P)), diags(std::move(diags)) {} clang::PrecompiledPreamble Preamble; + std::vector diags; }; struct CompletionSession : public std::enable_shared_from_this { - // Translation unit for clang. - struct Tu { - // When |tu| was last parsed. - std::optional> - last_parsed_at; - // Acquired when |tu| is being used. - std::mutex lock; - std::unique_ptr tu; - }; - - struct CU { - std::mutex lock; - std::shared_ptr preamble; - }; + std::mutex mutex; + std::shared_ptr preamble; + std::vector diags; Project::Entry file; WorkingFiles *wfiles; @@ -61,9 +67,6 @@ struct CompletionSession clang::vfs::getRealFileSystem(); std::shared_ptr PCH; - CU completion; - Tu diagnostics; - CompletionSession(const Project::Entry &file, WorkingFiles *wfiles, std::shared_ptr PCH) : file(file), wfiles(wfiles), PCH(PCH) {} @@ -71,6 +74,7 @@ struct CompletionSession std::shared_ptr GetPreamble(); void BuildPreamble(clang::CompilerInvocation &CI); }; +} struct ClangCompleteManager { using OnDiagnostic = std::function TryGetSession(const std::string &filename, - bool mark_as_completion, - bool create_if_needed); + std::shared_ptr + TryGetSession(const std::string &filename, bool mark_as_completion, + bool create_if_needed); // Flushes all saved sessions with the supplied filename void FlushSession(const std::string &filename); @@ -149,7 +153,7 @@ struct ClangCompleteManager { OnDiagnostic on_diagnostic_; OnDropped on_dropped_; - using LruSessionCache = LruCache; + using LruSessionCache = LruCache; // CompletionSession instances which are preloaded, ie, files which the user // has viewed but not requested code completion for. diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 35f969a4..3cb09e0e 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -16,12 +16,8 @@ limitations under the License. #include "clang_tu.h" #include "clang_utils.h" -#include "log.hh" -#include "platform.h" -#include "utils.h" -#include "working_files.h" -#include +#include using namespace clang; #include @@ -67,72 +63,3 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, return FromCharSourceRange(SM, LangOpts, CharSourceRange::getTokenRange(R), UniqueID); } - -std::vector -GetRemapped(const WorkingFiles::Snapshot &snapshot) { - std::vector Remapped; - for (auto &file : snapshot.files) { - std::unique_ptr MB = - llvm::MemoryBuffer::getMemBufferCopy(file.content, file.filename); - Remapped.emplace_back(file.filename, MB.release()); - } - return Remapped; -} - -std::unique_ptr ClangTranslationUnit::Create( - const std::string &filepath, const std::vector &args, - const WorkingFiles::Snapshot &snapshot, bool diagnostic) { - std::vector Args; - for (auto &arg : args) - Args.push_back(arg.c_str()); - Args.push_back("-fallow-editor-placeholders"); - if (!diagnostic) - Args.push_back("-fno-spell-checking"); - - auto ret = std::make_unique(); - IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions)); - std::vector Remapped = GetRemapped(snapshot); - - ret->PCHCO = std::make_shared(); - std::unique_ptr ErrUnit, Unit; - llvm::CrashRecoveryContext CRC; - auto parse = [&]() { - Unit.reset(ASTUnit::LoadFromCommandLine( - Args.data(), Args.data() + Args.size(), - /*PCHContainerOpts=*/ret->PCHCO, Diags, - /*ResourceFilePath=*/g_config->clang.resourceDir, - /*OnlyLocalDecls=*/false, - /*CaptureDiagnostics=*/diagnostic, Remapped, - /*RemappedFilesKeepOriginalName=*/true, 0, - diagnostic ? TU_Complete : TU_Prefix, - /*CacheCodeCompletionResults=*/true, g_config->index.comments, - /*AllowPCHWithCompilerErrors=*/true, -#if LLVM_VERSION_MAJOR >= 7 - SkipFunctionBodiesScope::None, -#else - !diagnostic, -#endif - /*SingleFileParse=*/false, - /*UserFilesAreVolatile=*/true, false, - ret->PCHCO->getRawReader().getFormat(), &ErrUnit)); - }; - if (!CRC.RunSafely(parse)) { - LOG_S(ERROR) << "clang crashed for " << filepath << "\n" - << StringJoin(args, " ") + " -fsyntax-only"; - return {}; - } - if (!Unit && !ErrUnit) - return {}; - - ret->Unit = std::move(Unit); - return ret; -} - -int ClangTranslationUnit::Reparse(llvm::CrashRecoveryContext &CRC, - const WorkingFiles::Snapshot &snapshot) { - int ret = 1; - (void)CRC.RunSafely( - [&]() { ret = Unit->Reparse(PCHCO, GetRemapped(snapshot)); }); - return ret; -} diff --git a/src/clang_tu.h b/src/clang_tu.h index fa7f4f7b..def8a397 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.h @@ -15,19 +15,10 @@ limitations under the License. #pragma once #include "position.h" -#include "working_files.h" -#include -#include -#include +#include -#include #include -#include -#include - -std::vector -GetRemapped(const WorkingFiles::Snapshot &snapshot); Range FromCharSourceRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, @@ -41,15 +32,3 @@ Range FromCharRange(const clang::SourceManager &SM, Range FromTokenRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, clang::SourceRange R, llvm::sys::fs::UniqueID *UniqueID = nullptr); - -struct ClangTranslationUnit { - static std::unique_ptr - Create(const std::string &filepath, const std::vector &args, - const WorkingFiles::Snapshot &snapshot, bool diagnostic); - - int Reparse(llvm::CrashRecoveryContext &CRC, - const WorkingFiles::Snapshot &snapshot); - - std::shared_ptr PCHCO; - std::unique_ptr Unit; -}; From 74790e2421a67a74fade74f99deb9feaaef81eae Mon Sep 17 00:00:00 2001 From: firstlove <37442588+FirstLoveLife@users.noreply.github.com> Date: Wed, 29 Aug 2018 23:33:20 +0800 Subject: [PATCH 04/66] fix clang_tu.h && clang_complete.cc (#61) --- src/clang_complete.cc | 2 +- src/clang_tu.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index b9d93b64..c062071b 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -515,7 +515,7 @@ BuildCompilerInstance(CompletionSession &session, Preamble->Preamble.OverridePreamble(*CI, session.FS, Bufs.back().get()); #else - Preamble->Preamble.AddImplicitPreamble(*CI, session->FS, + Preamble->Preamble.AddImplicitPreamble(*CI, session.FS, Bufs.back().get()); #endif } else { diff --git a/src/clang_tu.h b/src/clang_tu.h index def8a397..7d2b4b73 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.h @@ -16,6 +16,7 @@ limitations under the License. #pragma once #include "position.h" +#include #include #include From 1ae97c64ed5a73878ecbf09411a21b0a4b5b589d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 29 Aug 2018 21:20:27 -0700 Subject: [PATCH 05/66] detailed_name: "{\n}" -> "{}" ; completion --- index_tests/enums/enum_class_decl.cc | 2 +- index_tests/enums/enum_decl.cc | 2 +- index_tests/enums/enum_inherit.cc | 4 ++-- index_tests/enums/enum_usage.cc | 2 +- index_tests/foobar.cc | 4 ++-- index_tests/multi_file/funky_enum.cc | 2 +- index_tests/multi_file/impl.cc | 2 +- index_tests/namespaces/function_declaration.cc | 2 +- index_tests/namespaces/function_definition.cc | 2 +- index_tests/namespaces/method_declaration.cc | 2 +- index_tests/namespaces/method_definition.cc | 2 +- index_tests/namespaces/method_inline_declaration.cc | 2 +- index_tests/namespaces/namespace_alias.cc | 6 +++--- index_tests/namespaces/namespace_reference.cc | 2 +- index_tests/outline/static_function_in_type.cc | 4 ++-- index_tests/templates/implicit_variable_instantiation.cc | 4 ++-- ...template_class_template_func_usage_folded_into_one.cc | 2 +- .../namespace_template_type_usage_folded_into_one.cc | 2 +- index_tests/templates/specialization.cc | 2 +- .../template_class_type_usage_folded_into_one.cc | 4 ++-- .../templates/template_var_usage_folded_into_one.cc | 4 ++-- index_tests/usage/var_usage_cstyle_cast.cc | 2 +- src/clang_complete.cc | 9 +++++---- src/indexer.cc | 6 ++++++ 24 files changed, 41 insertions(+), 34 deletions(-) diff --git a/index_tests/enums/enum_class_decl.cc b/index_tests/enums/enum_class_decl.cc index 34a1c978..3f3f78ca 100644 --- a/index_tests/enums/enum_class_decl.cc +++ b/index_tests/enums/enum_class_decl.cc @@ -29,7 +29,7 @@ OUTPUT: "uses": [] }, { "usr": 16985894625255407295, - "detailed_name": "enum class Foo : uint8_t {\n}", + "detailed_name": "enum class Foo : uint8_t {}", "qual_name_offset": 11, "short_name": "Foo", "kind": 10, diff --git a/index_tests/enums/enum_decl.cc b/index_tests/enums/enum_decl.cc index 3b28d1aa..6e44da9b 100644 --- a/index_tests/enums/enum_decl.cc +++ b/index_tests/enums/enum_decl.cc @@ -11,7 +11,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum Foo {\n}", + "detailed_name": "enum Foo {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, diff --git a/index_tests/enums/enum_inherit.cc b/index_tests/enums/enum_inherit.cc index 195b93d9..08d84087 100644 --- a/index_tests/enums/enum_inherit.cc +++ b/index_tests/enums/enum_inherit.cc @@ -18,7 +18,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 2986879766914123941, - "detailed_name": "enum class E : int32_t {\n}", + "detailed_name": "enum class E : int32_t {}", "qual_name_offset": 11, "short_name": "E", "kind": 10, @@ -52,7 +52,7 @@ OUTPUT: "uses": [] }, { "usr": 16985894625255407295, - "detailed_name": "enum Foo : int {\n}", + "detailed_name": "enum Foo : int {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, diff --git a/index_tests/enums/enum_usage.cc b/index_tests/enums/enum_usage.cc index 2d602b45..bcee0c00 100644 --- a/index_tests/enums/enum_usage.cc +++ b/index_tests/enums/enum_usage.cc @@ -13,7 +13,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum class Foo : int {\n}", + "detailed_name": "enum class Foo : int {}", "qual_name_offset": 11, "short_name": "Foo", "kind": 10, diff --git a/index_tests/foobar.cc b/index_tests/foobar.cc index b1e571d1..f5d2e47b 100644 --- a/index_tests/foobar.cc +++ b/index_tests/foobar.cc @@ -16,7 +16,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, @@ -84,7 +84,7 @@ OUTPUT: "uses": [] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, diff --git a/index_tests/multi_file/funky_enum.cc b/index_tests/multi_file/funky_enum.cc index c76b4d47..69f5ebdc 100644 --- a/index_tests/multi_file/funky_enum.cc +++ b/index_tests/multi_file/funky_enum.cc @@ -81,7 +81,7 @@ OUTPUT: funky_enum.cc "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum Foo {\n}", + "detailed_name": "enum Foo {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, diff --git a/index_tests/multi_file/impl.cc b/index_tests/multi_file/impl.cc index cc53dabf..12a625b3 100644 --- a/index_tests/multi_file/impl.cc +++ b/index_tests/multi_file/impl.cc @@ -76,7 +76,7 @@ OUTPUT: header.h "uses": [] }, { "usr": 4481210672785600703, - "detailed_name": "enum Foo3 {\n}", + "detailed_name": "enum Foo3 {}", "qual_name_offset": 5, "short_name": "Foo3", "kind": 10, diff --git a/index_tests/namespaces/function_declaration.cc b/index_tests/namespaces/function_declaration.cc index 2438c99c..ec694bc9 100644 --- a/index_tests/namespaces/function_declaration.cc +++ b/index_tests/namespaces/function_declaration.cc @@ -23,7 +23,7 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, diff --git a/index_tests/namespaces/function_definition.cc b/index_tests/namespaces/function_definition.cc index 7afe9d29..ce784555 100644 --- a/index_tests/namespaces/function_definition.cc +++ b/index_tests/namespaces/function_definition.cc @@ -25,7 +25,7 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, diff --git a/index_tests/namespaces/method_declaration.cc b/index_tests/namespaces/method_declaration.cc index 48a8456e..de02f813 100644 --- a/index_tests/namespaces/method_declaration.cc +++ b/index_tests/namespaces/method_declaration.cc @@ -25,7 +25,7 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, diff --git a/index_tests/namespaces/method_definition.cc b/index_tests/namespaces/method_definition.cc index 2506e411..5a25f7a9 100644 --- a/index_tests/namespaces/method_definition.cc +++ b/index_tests/namespaces/method_definition.cc @@ -29,7 +29,7 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, diff --git a/index_tests/namespaces/method_inline_declaration.cc b/index_tests/namespaces/method_inline_declaration.cc index 55c95118..b4029c5f 100644 --- a/index_tests/namespaces/method_inline_declaration.cc +++ b/index_tests/namespaces/method_inline_declaration.cc @@ -27,7 +27,7 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, diff --git a/index_tests/namespaces/namespace_alias.cc b/index_tests/namespaces/namespace_alias.cc index b659f553..314890b8 100644 --- a/index_tests/namespaces/namespace_alias.cc +++ b/index_tests/namespaces/namespace_alias.cc @@ -51,7 +51,7 @@ OUTPUT: "uses": [] }, { "usr": 926793467007732869, - "detailed_name": "namespace foo {\n}", + "detailed_name": "namespace foo {}", "qual_name_offset": 10, "short_name": "foo", "kind": 3, @@ -81,7 +81,7 @@ OUTPUT: "uses": ["13:11-13:14|10818727483146447186|3|4"] }, { "usr": 14450849931009540802, - "detailed_name": "namespace foo::bar::baz {\n}", + "detailed_name": "namespace foo::bar::baz {}", "qual_name_offset": 10, "short_name": "baz", "kind": 3, @@ -99,7 +99,7 @@ OUTPUT: "uses": ["9:27-9:30|0|1|4", "12:21-12:24|10818727483146447186|3|4"] }, { "usr": 17805385787823406700, - "detailed_name": "namespace foo::bar {\n}", + "detailed_name": "namespace foo::bar {}", "qual_name_offset": 10, "short_name": "bar", "kind": 3, diff --git a/index_tests/namespaces/namespace_reference.cc b/index_tests/namespaces/namespace_reference.cc index 16949403..09919e03 100644 --- a/index_tests/namespaces/namespace_reference.cc +++ b/index_tests/namespaces/namespace_reference.cc @@ -62,7 +62,7 @@ OUTPUT: "uses": [] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, diff --git a/index_tests/outline/static_function_in_type.cc b/index_tests/outline/static_function_in_type.cc index 89842296..9826edca 100644 --- a/index_tests/outline/static_function_in_type.cc +++ b/index_tests/outline/static_function_in_type.cc @@ -42,7 +42,7 @@ OUTPUT: static_function_in_type.h "uses": ["6:24-6:31|17262466801709381811|2|4"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, @@ -116,7 +116,7 @@ OUTPUT: static_function_in_type.cc "uses": ["5:20-5:27|11072669167287398027|2|4"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, diff --git a/index_tests/templates/implicit_variable_instantiation.cc b/index_tests/templates/implicit_variable_instantiation.cc index db370e9f..36a97821 100644 --- a/index_tests/templates/implicit_variable_instantiation.cc +++ b/index_tests/templates/implicit_variable_instantiation.cc @@ -37,7 +37,7 @@ OUTPUT: "uses": [] }, { "usr": 1532099849728741556, - "detailed_name": "enum ns::VarType {\n}", + "detailed_name": "enum ns::VarType {}", "qual_name_offset": 5, "short_name": "VarType", "kind": 10, @@ -54,7 +54,7 @@ OUTPUT: "uses": ["6:22-6:29|12688716854043726585|2|4", "6:44-6:51|12688716854043726585|2|4", "10:18-10:25|11072669167287398027|2|4"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, diff --git a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc index 073ba344..d0fb3cb4 100644 --- a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc @@ -49,7 +49,7 @@ OUTPUT: "uses": [] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, diff --git a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc index 5b141b39..0476c03a 100644 --- a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc @@ -48,7 +48,7 @@ OUTPUT: "uses": [] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, diff --git a/index_tests/templates/specialization.cc b/index_tests/templates/specialization.cc index f5ca0f26..7b8960c1 100644 --- a/index_tests/templates/specialization.cc +++ b/index_tests/templates/specialization.cc @@ -204,7 +204,7 @@ OUTPUT: "uses": ["21:16-21:22|0|1|4", "30:1-30:7|0|1|4", "32:1-32:7|0|1|4"] }, { "usr": 9201299975592934124, - "detailed_name": "enum Enum {\n}", + "detailed_name": "enum Enum {}", "qual_name_offset": 5, "short_name": "Enum", "kind": 10, diff --git a/index_tests/templates/template_class_type_usage_folded_into_one.cc b/index_tests/templates/template_class_type_usage_folded_into_one.cc index 0dbec81c..7115ebc9 100644 --- a/index_tests/templates/template_class_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_type_usage_folded_into_one.cc @@ -35,7 +35,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, @@ -86,7 +86,7 @@ OUTPUT: "uses": ["9:1-9:4|0|1|4", "10:1-10:4|0|1|4"] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, diff --git a/index_tests/templates/template_var_usage_folded_into_one.cc b/index_tests/templates/template_var_usage_folded_into_one.cc index e325205d..844baece 100644 --- a/index_tests/templates/template_var_usage_folded_into_one.cc +++ b/index_tests/templates/template_var_usage_folded_into_one.cc @@ -38,7 +38,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, @@ -72,7 +72,7 @@ OUTPUT: "uses": [] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, diff --git a/index_tests/usage/var_usage_cstyle_cast.cc b/index_tests/usage/var_usage_cstyle_cast.cc index 1233becc..09991182 100644 --- a/index_tests/usage/var_usage_cstyle_cast.cc +++ b/index_tests/usage/var_usage_cstyle_cast.cc @@ -15,7 +15,7 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 5792006888140599735, - "detailed_name": "enum VarType {\n}", + "detailed_name": "enum VarType {}", "qual_name_offset": 5, "short_name": "VarType", "kind": 10, diff --git a/src/clang_complete.cc b/src/clang_complete.cc index c062071b..3cd01988 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -354,14 +354,15 @@ public: unsigned NumResults) override { ls_items.reserve(NumResults); for (unsigned i = 0; i != NumResults; i++) { - if (Results[i].Availability == CXAvailability_NotAccessible || - Results[i].Availability == CXAvailability_NotAvailable) + auto &R = Results[i]; + if (R.Availability == CXAvailability_NotAccessible || + R.Availability == CXAvailability_NotAvailable) continue; - CodeCompletionString *CCS = Results[i].CreateCodeCompletionString( + CodeCompletionString *CCS = R.CreateCodeCompletionString( S, Context, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); lsCompletionItem ls_item; - ls_item.kind = GetCompletionKind(Results[i].CursorKind); + ls_item.kind = GetCompletionKind(R.CursorKind); if (const char *brief = CCS->getBriefComment()) ls_item.documentation = brief; diff --git a/src/indexer.cc b/src/indexer.cc index d0893657..5c899342 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -462,6 +462,12 @@ public: std::string name = OS.str(); SimplifyAnonymous(name); + // Remove \n in DeclPrinter.cpp "{\n" + if(!TerseOutput)something + "}" + for (std::string::size_type i = 0;;) { + if ((i = name.find("{\n}", i)) == std::string::npos) + break; + name.replace(i, 3, "{}"); + } auto i = name.find(short_name); if (short_name.size()) while (i != std::string::npos && ((i && isalnum(name[i - 1])) || From 5cc3006a3ada2ef78044c3072d8da1d0d96d118a Mon Sep 17 00:00:00 2001 From: scturtle Date: Thu, 30 Aug 2018 23:47:48 +0800 Subject: [PATCH 06/66] Filter deps with `index.blacklist`. (#64) --- src/pipeline.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pipeline.cc b/src/pipeline.cc index 30c3e978..1754540a 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -153,7 +153,7 @@ std::unique_ptr RawCacheLoad(const std::string &path) { } bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, - Project *project, VFS *vfs) { + Project *project, VFS *vfs, const GroupMatch &matcher) { std::optional opt_request = index_request->TryPopFront(); if (!opt_request) return false; @@ -167,6 +167,11 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, return false; } + if (std::string reason; !matcher.IsMatch(request.path, &reason)) { + LOG_S(INFO) << "skip " << request.path << " for " << reason; + return false; + } + Project::Entry entry; { std::lock_guard lock(project->mutex_); @@ -259,6 +264,12 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, std::string path = curr->path; if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index)) continue; + if (std::string reason; !matcher.IsMatch(path, &reason)) { + LOG_S(INFO) << "skip emitting and storing index of " << path << " for " + << reason; + continue; + } + LOG_S(INFO) << "emit index for " << path; prev = RawCacheLoad(path); @@ -307,8 +318,9 @@ void Init() { void Indexer_Main(DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, WorkingFiles *working_files) { + GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); while (true) - if (!Indexer_Parse(diag_pub, working_files, project, vfs)) + if (!Indexer_Parse(diag_pub, working_files, project, vfs, matcher)) indexer_waiter->Wait(index_request); } From 407c7cc29d009d92ba29eedbbd128d0731fe07c5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 30 Aug 2018 00:29:08 -0700 Subject: [PATCH 07/66] Remove ASTUnit from indexer and clean up --- index_tests/_empty_test.cc | 8 +--- src/clang_complete.cc | 44 +++++------------- src/clang_tu.cc | 17 +++++++ src/clang_tu.h | 5 ++ src/indexer.cc | 95 ++++++++++++-------------------------- src/indexer.h | 2 - src/pipeline.cc | 6 --- src/project.cc | 3 -- src/test.cc | 34 -------------- 9 files changed, 65 insertions(+), 149 deletions(-) diff --git a/index_tests/_empty_test.cc b/index_tests/_empty_test.cc index d1ae7a6c..228b2674 100644 --- a/index_tests/_empty_test.cc +++ b/index_tests/_empty_test.cc @@ -1,10 +1,4 @@ /* OUTPUT: -{ - "includes": [], - "skipped_ranges": [], - "usr2func": [], - "usr2type": [], - "usr2var": [] -} +{} */ diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 3cd01988..cc15089a 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -21,7 +21,6 @@ limitations under the License. #include "platform.h" #include -#include #include #include #include @@ -397,10 +396,6 @@ public: } } - void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, - OverloadCandidate *Candidates, - unsigned NumCandidates) override {} - CodeCompletionAllocator &getAllocator() override { return *Alloc; } CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } @@ -484,30 +479,10 @@ public: } }; -std::unique_ptr -buildCompilerInvocation(const std::vector &args, - IntrusiveRefCntPtr VFS) { - std::vector cargs; - for (auto &arg : args) - cargs.push_back(arg.c_str()); - IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions)); - std::unique_ptr CI = - createInvocationFromCommandLine(cargs, Diags, VFS); - if (CI) { - CI->getFrontendOpts().DisableFree = false; - CI->getLangOpts()->CommentOpts.ParseAllComments = true; - CI->getLangOpts()->SpellChecking = false; - } - return CI; -} - -std::unique_ptr -BuildCompilerInstance(CompletionSession &session, - std::unique_ptr CI, - DiagnosticConsumer &DC, - const WorkingFiles::Snapshot &snapshot, - std::vector> &Bufs) { +std::unique_ptr BuildCompilerInstance( + CompletionSession &session, std::unique_ptr CI, + DiagnosticConsumer &DC, const WorkingFiles::Snapshot &snapshot, + std::vector> &Bufs) { for (auto &file : snapshot.files) { Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); if (file.filename == session.file.filename) { @@ -570,7 +545,7 @@ void CompletionPreloadMain(ClangCompleteManager *completion_manager) { LOG_S(INFO) << "create completion session for " << session->file.filename; if (std::unique_ptr CI = - buildCompilerInvocation(args, session->FS)) + BuildCompilerInvocation(args, session->FS)) session->BuildPreamble(*CI); } } @@ -595,10 +570,12 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { true /*create_if_needed*/); std::unique_ptr CI = - buildCompilerInvocation(session->file.args, session->FS); + BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; + CI->getDiagnosticOpts().IgnoreWarnings = true; clang::CodeCompleteOptions CCOpts; + CCOpts.IncludeBriefComments = true; #if LLVM_VERSION_MAJOR >= 7 CCOpts.IncludeFixIts = true; #endif @@ -608,6 +585,8 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { FOpts.CodeCompletionAt.FileName = session->file.filename; FOpts.CodeCompletionAt.Line = request->position.line + 1; FOpts.CodeCompletionAt.Column = request->position.character + 1; + FOpts.SkipFunctionBodies = true; + CI->getLangOpts()->CommentOpts.ParseAllComments = true; StoreDiags DC; WorkingFiles::Snapshot snapshot = @@ -641,7 +620,7 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { path, true /*mark_as_completion*/, true /*create_if_needed*/); std::unique_ptr CI = - buildCompilerInvocation(session->file.args, session->FS); + BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; StoreDiags DC; @@ -701,6 +680,7 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) { if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get())) return; CI.getFrontendOpts().SkipFunctionBodies = true; + CI.getLangOpts()->CommentOpts.ParseAllComments = true; #if LLVM_VERSION_MAJOR >= 7 CI.getPreprocessorOpts().WriteCommentListToPCH = false; #endif diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 3cb09e0e..be2f1679 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -63,3 +63,20 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, return FromCharSourceRange(SM, LangOpts, CharSourceRange::getTokenRange(R), UniqueID); } + +std::unique_ptr +BuildCompilerInvocation(const std::vector &args, + IntrusiveRefCntPtr VFS) { + std::vector cargs; + for (auto &arg : args) + cargs.push_back(arg.c_str()); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(new DiagnosticOptions)); + std::unique_ptr CI = + createInvocationFromCommandLine(cargs, Diags, VFS); + if (CI) { + CI->getFrontendOpts().DisableFree = false; + CI->getLangOpts()->SpellChecking = false; + } + return CI; +} diff --git a/src/clang_tu.h b/src/clang_tu.h index 7d2b4b73..ec4b5770 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.h @@ -18,6 +18,7 @@ limitations under the License. #include #include +#include #include @@ -33,3 +34,7 @@ Range FromCharRange(const clang::SourceManager &SM, Range FromTokenRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, clang::SourceRange R, llvm::sys::fs::UniqueID *UniqueID = nullptr); + +std::unique_ptr +BuildCompilerInvocation(const std::vector &args, + llvm::IntrusiveRefCntPtr VFS); diff --git a/src/indexer.cc b/src/indexer.cc index 5c899342..ae53369f 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -22,8 +22,6 @@ limitations under the License. using ccls::Intern; #include -#include -#include #include #include #include @@ -57,13 +55,10 @@ struct IndexParam { }; std::unordered_map Decl2Info; - ASTUnit &Unit; ASTContext *Ctx; - FileConsumer *file_consumer = nullptr; - IndexParam(ASTUnit &Unit, FileConsumer *file_consumer) - : Unit(Unit), file_consumer(file_consumer) {} + IndexParam(FileConsumer *file_consumer) : file_consumer(file_consumer) {} IndexFile *ConsumeFile(const FileEntry &File) { IndexFile *db = file_consumer->TryConsumeFile(File, &file_contents); @@ -1173,21 +1168,15 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, if (!g_config->index.enabled) return {}; - std::vector Args; - for (auto &arg : args) - Args.push_back(arg.c_str()); - auto PCHCO = std::make_shared(); - IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions)); - std::shared_ptr CI = - createInvocationFromCommandLine(Args, Diags); + auto PCH = std::make_shared(); + llvm::IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + std::shared_ptr CI = BuildCompilerInvocation(args, FS); if (!CI) return {}; // -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()->SpellChecking = false; { // FileSystemOptions& FSOpts = CI->getFileSystemOpts(); // if (FSOpts.WorkingDir.empty()) @@ -1200,20 +1189,18 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, // HSOpts.ResourceDir = g_config->clang.resourceDir; } - std::vector> BufOwner; - for (auto &c : file_contents) { - std::unique_ptr MB = - llvm::MemoryBuffer::getMemBufferCopy(c.content, c.path); - CI->getPreprocessorOpts().addRemappedFile(c.path, MB.get()); - BufOwner.push_back(std::move(MB)); - } - - auto Unit = ASTUnit::create(CI, Diags, true, true); - if (!Unit) + 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 {}; FileConsumer file_consumer(vfs, file); - IndexParam param(*Unit, &file_consumer); + IndexParam param(&file_consumer); auto DataConsumer = std::make_shared(param); index::IndexingOptions IndexOpts; @@ -1224,36 +1211,30 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, IndexOpts.IndexImplicitInstantiation = true; #endif - std::unique_ptr IndexAction = createIndexingAction( + std::unique_ptr Action = createIndexingAction( DataConsumer, IndexOpts, std::make_unique(param)); - DiagnosticErrorTrap DiagTrap(*Diags); - llvm::CrashRecoveryContext CRC; - auto compile = [&]() { - ASTUnit::LoadFromCompilerInvocationAction( - std::move(CI), PCHCO, Diags, IndexAction.get(), Unit.get(), - /*Persistent=*/true, /*ResourceDir=*/"", - /*OnlyLocalDecls=*/true, - /*CaptureDiagnostics=*/true, 0, false, false, - /*UserFilesAreVolatile=*/true); - }; - if (!CRC.RunSafely(compile)) { - LOG_S(ERROR) << "clang crashed for " << file; - return {}; + bool ok = false; + { + llvm::CrashRecoveryContext CRC; + auto parse = [&]() { + if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) + return; + if (!Action->Execute()) + return; + Action->EndSourceFile(); + ok = true; + }; + if (!CRC.RunSafely(parse)) { + LOG_S(ERROR) << "clang crashed for " << file; + return {}; + } } - if (!Unit) { + if (!ok) { LOG_S(ERROR) << "failed to index " << file; return {}; } - const SourceManager &SM = Unit->getSourceManager(); - const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID()); - IndexFile *main_file = param.ConsumeFile(*FE); - std::unordered_map inc_to_line; - if (main_file) - for (auto &inc : main_file->includes) - inc_to_line[inc.resolved_path] = inc.line; - auto result = param.file_consumer->TakeLocalState(); for (std::unique_ptr &entry : result) { entry->import_file = file; @@ -1276,22 +1257,6 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, for (auto &it : entry->usr2var) Uniquify(it.second.uses); - if (main_file) { - // If there are errors, show at least one at the include position. - auto it = inc_to_line.find(entry->path); - if (it != inc_to_line.end()) { - int line = it->second; - for (auto ls_diagnostic : entry->diagnostics_) { - if (ls_diagnostic.severity != lsDiagnosticSeverity::Error) - continue; - ls_diagnostic.range = - lsRange{lsPosition{line, 10}, lsPosition{line, 10}}; - main_file->diagnostics_.push_back(ls_diagnostic); - break; - } - } - } - // Update file contents and modification time. entry->last_write_time = param.file2write_time[entry->path]; diff --git a/src/indexer.h b/src/indexer.h index 151bb0b0..70a407a5 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -263,8 +263,6 @@ struct IndexFile { std::unordered_map usr2type; std::unordered_map usr2var; - // Diagnostics found when indexing this file. Not serialized. - std::vector diagnostics_; // File contents at the time of index. Not serialized. std::string file_contents; diff --git a/src/pipeline.cc b/src/pipeline.cc index 1754540a..e6f9b750 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -255,12 +255,6 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, } for (std::unique_ptr &curr : indexes) { - // Only emit diagnostics for non-interactive sessions, which makes it easier - // to identify indexing problems. For interactive sessions, diagnostics are - // handled by code completion. - if (!request.is_interactive) - diag_pub->Publish(working_files, curr->path, curr->diagnostics_); - std::string path = curr->path; if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index)) continue; diff --git a/src/project.cc b/src/project.cc index 581a8a1b..d7d6e3a5 100644 --- a/src/project.cc +++ b/src/project.cc @@ -128,9 +128,6 @@ struct ProjectProcessor { args.push_back("-resource-dir=" + g_config->clang.resourceDir); args.push_back("-working-directory=" + entry.directory); - // There could be a clang version mismatch between what the project uses and - // what ccls uses. Make sure we do not emit warnings for mismatched options. - args.push_back("-Wno-unknown-warning-option"); if (!command_set.insert(hash).second) { entry.args = std::move(args); diff --git a/src/test.cc b/src/test.cc index d2fb971a..b93a21b9 100644 --- a/src/test.cc +++ b/src/test.cc @@ -307,42 +307,8 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { const std::string &expected_path = entry.first; std::string expected_output = text_replacer.Apply(entry.second); - // FIXME: promote to utils, find and remove duplicates (ie, - // ccls_call_tree.cc, maybe something in project.cc). - auto basename = [](const std::string &path) -> std::string { - size_t last_index = path.find_last_of('/'); - if (last_index == std::string::npos) - return path; - return path.substr(last_index + 1); - }; - // Get output from index operation. IndexFile *db = FindDbForPathEnding(expected_path, dbs); - if (db && !db->diagnostics_.empty()) { - printf("For %s\n", path.c_str()); - for (const lsDiagnostic &diagnostic : db->diagnostics_) { - printf(" "); - if (diagnostic.severity) - switch (*diagnostic.severity) { - case lsDiagnosticSeverity::Error: - printf("error "); - break; - case lsDiagnosticSeverity::Warning: - printf("warning "); - break; - case lsDiagnosticSeverity::Information: - printf("information "); - break; - case lsDiagnosticSeverity::Hint: - printf("hint "); - break; - } - printf("%s:%s-%s:%s\n", basename(db->path).c_str(), - diagnostic.range.start.ToString().c_str(), - diagnostic.range.end.ToString().c_str(), - diagnostic.message.c_str()); - } - } std::string actual_output = "{}"; if (db) { VerifySerializeToFrom(db); From 11e92d52a898cde8cb788390034a033441e4ba12 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 1 Sep 2018 15:37:09 -0700 Subject: [PATCH 08/66] README --- README.md | 27 +++++++++++++++++---------- src/pipeline.cc | 3 --- src/serializer.cc | 6 +++--- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4f041e87..1f85d442 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,21 @@ ccls, which originates from [cquery](https://github.com/cquery-project/cquery), is a C/C++/Objective-C language server. * code completion (with both signature help and snippets) - * [definition](src/messages/text_document_definition.cc)/[references](src/messages/text_document_references.cc), and other cross references - * [call (caller/callee) hierarchy](src/messages/ccls_call_hierarchy.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritance_hierarchy.cc), [member hierarchy](src/messages/ccls_member_hierarchy.cc) - * [symbol rename](src/messages/text_document_rename.cc) - * [document symbols](src/messages/text_document_document_symbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) - * [hover information](src/messages/text_document_hover.cc) - * diagnostics - * code actions (clang FixIts) - * preprocessor skipped regions - * semantic highlighting, including support for [rainbow semantic highlighting](https://medium.com/@evnbr/coding-in-color-3a6db2743a1e) + * [definition](src/messages/textDocument_definition.cc)/[references](src/messages/textDcument_references.cc), and other cross references + * hierarchies: [call (caller/callee) hierarchy](src/messages/ccls_callHierarchy.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritanceHierarchy.cc), [member hierarchy](src/messages/ccls_memberHierarchy.cc) + * [symbol rename](src/messages/text_documentRename.cc) + * [document symbols](src/messages/textDocument_documentSymbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) + * [hover information](src/messages/textDocument_hover.cc) + * diagnostics and code actions (clang FixIts) + * semantic highlighting and preprocessor skipped regions -It makes use of C++17 features, has less third-party dependencies and slimmed-down code base. Cross reference features are strengthened, (see [wiki/FAQ](../../wiki/FAQ)). It currently uses libclang to index C++ code but will switch to Clang C++ API. Refactoring and formatting are non-goals as they can be provided by clang-format, clang-include-fixer and other Clang based tools. +It has a global view of the code base and support a lot of cross reference features, see [wiki/FAQ](../../wiki/FAQ). +It starts indexing the whole project (including subprojects if exist) parallelly when you open the first file, while the main thread can serve requests before the indexing is complete. +Saving files will incrementally update the index. + +Compared with cquery, it makes use of C++17 features, has less third-party dependencies and slimmed-down code base. +It leverages Clang C++ API as [clangd](https://clang.llvm.org/extra/clangd.html) does, which provides better support for code completion and diagnostics. +Refactoring and formatting are non-goals as they can be provided by clang-format, clang-include-fixer and other Clang based tools. The comparison with cquery as noted on 2018-07-15: @@ -35,4 +39,7 @@ cquery has system include path detection (through running the compiler driver) w * [Build](../../wiki/Build) * [Emacs](../../wiki/Emacs) +* [LanguageClient-neovim](../../wiki/LanguageClient-neovim) * [FAQ](../../wiki/FAQ) + +ccls can index itself (~180MiB RSS when ide, noted on 2018-09-01), FreeBSD, glibc, Linux, LLVM (~1800MiB RSS), musl (~60MiB RSS), ... with decent memory footprint. See [wiki/compile_commands.json](../../wiki/compile_commands.json) for examples. diff --git a/src/pipeline.cc b/src/pipeline.cc index e6f9b750..89eca566 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -270,13 +270,10 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, // Write current index to disk if requested. LOG_S(INFO) << "store index for " << path; { - static Timer timer("write", "store index"); - timer.startTimer(); std::string cache_path = GetCachePath(path); WriteToFile(cache_path, curr->file_contents); WriteToFile(AppendSerializationFormat(cache_path), Serialize(g_config->cacheFormat, *curr)); - timer.stopTimer(); } vfs->Reset(path); diff --git a/src/serializer.cc b/src/serializer.cc index e99b3815..487650b0 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -324,9 +324,9 @@ template void Reflect(TVisitor &visitor, IndexFile &value) { REFLECT_MEMBER_END(); } -void Reflect(Reader &visitor, SerializeFormat &value) { - std::string fmt = visitor.GetString(); - value = fmt[0] == 'b' ? SerializeFormat::Binary : SerializeFormat::Json; +void Reflect(Reader &vis, SerializeFormat &v) { + v = vis.GetString()[0] == 'j' ? SerializeFormat::Json + : SerializeFormat::Binary; } void Reflect(Writer &visitor, SerializeFormat &value) { From 145630ba1ad6c8132578f300b2eeb67cfec19a64 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 2 Sep 2018 14:51:25 -0700 Subject: [PATCH 09/66] Fix unaligned load/store; add index.multiVersion prototype, rename index.onParse to index.OnOpen Don't call getFieldOffset() on RD->isInvalidDecl() --- src/config.h | 22 ++---- src/indexer.cc | 105 ++++++++++++++++----------- src/indexer.h | 2 +- src/language.h | 2 +- src/messages/textDocument_didOpen.cc | 2 +- src/query.cc | 2 +- src/serializers/binary.h | 7 +- 7 files changed, 78 insertions(+), 64 deletions(-) diff --git a/src/config.h b/src/config.h index ab5eb5eb..67cf0972 100644 --- a/src/config.h +++ b/src/config.h @@ -149,8 +149,8 @@ struct Config { // xxx: at most every xxx milliseconds int frequencyMs = 0; - // If true, diagnostics from a full document parse will be reported. - bool onParse = true; + // If true, diagnostics will be reported in textDocument/didOpen. + bool onOpen = true; // If true, diagnostics from typing will be reported. bool onType = true; @@ -171,14 +171,6 @@ struct Config { } highlight; struct Index { - // Attempt to convert calls of make* functions to constructors based on - // hueristics. - // - // For example, this will show constructor calls for std::make_unique - // invocations. Specifically, ccls will try to attribute a ctor call - // whenever the function name starts with make (ignoring case). - bool attributeMakeCallsToCtor = true; - // If a translation unit's absolute path matches any EMCAScript regex in the // whitelist, or does not match any regex in the blacklist, it will be // indexed. To only index files in the whitelist, add ".*" to the blacklist. @@ -196,6 +188,9 @@ struct Config { // If false, the indexer will be disabled. bool enabled = true; + // If not 0, a file will be indexed in each tranlation unit that includes it. + int multiVersion = 0; + // Allow indexing on textDocument/didChange. // May be too slow for big projects, so it is off by default. bool onDidChange = false; @@ -238,12 +233,11 @@ MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, detailedLabel, filterAndSort, includeBlacklist, includeMaxPathSize, includeSuffixWhitelist, includeWhitelist); -MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onParse, +MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onOpen, onType, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) -MAKE_REFLECT_STRUCT(Config::Index, attributeMakeCallsToCtor, blacklist, - comments, enabled, onDidChange, reparseForDependency, - threads, whitelist); +MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, + onDidChange, reparseForDependency, threads, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, diff --git a/src/indexer.cc b/src/indexer.cc index ae53369f..581b1baf 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -60,9 +60,7 @@ struct IndexParam { IndexParam(FileConsumer *file_consumer) : file_consumer(file_consumer) {} - IndexFile *ConsumeFile(const FileEntry &File) { - IndexFile *db = file_consumer->TryConsumeFile(File, &file_contents); - + void SeenFile(const FileEntry &File) { // If this is the first time we have seen the file (ignoring if we are // generating an index for it): auto [it, inserted] = SeenUniqueID.try_emplace(File.getUniqueID()); @@ -77,8 +75,11 @@ struct IndexParam { if (write_time) file2write_time[file_name] = *write_time; } + } - return db; + IndexFile *ConsumeFile(const FileEntry &File) { + SeenFile(File); + return file_consumer->TryConsumeFile(File, &file_contents); } }; @@ -407,20 +408,20 @@ public: return it->second.usr; } - Use GetUse(IndexFile *db, Range range, const DeclContext *DC, + Use GetUse(IndexFile *db, int lid, Range range, const DeclContext *DC, Role role) const { if (!DC) - return Use{{range, 0, SymbolKind::File, role}}; + return {{range, 0, SymbolKind::File, role}, lid}; const Decl *D = cast(DC); switch (GetSymbolKind(D)) { case SymbolKind::Func: - return Use{{range, db->ToFunc(GetUsr(D)).usr, SymbolKind::Func, role}}; + return {{range, db->ToFunc(GetUsr(D)).usr, SymbolKind::Func, role}, lid}; case SymbolKind::Type: - return Use{{range, db->ToType(GetUsr(D)).usr, SymbolKind::Type, role}}; + return {{range, db->ToType(GetUsr(D)).usr, SymbolKind::Type, role}, lid}; case SymbolKind::Var: - return Use{{range, db->ToVar(GetUsr(D)).usr, SymbolKind::Var, role}}; + return {{range, db->ToVar(GetUsr(D)).usr, SymbolKind::Var, role}, lid}; default: - return Use{{range, 0, SymbolKind::File, role}}; + return {{range, 0, SymbolKind::File, role}, lid}; } } @@ -550,26 +551,32 @@ public: } } + static int GetFileLID(IndexFile *db, SourceManager &SM, const FileEntry &FE) { + auto [it, inserted] = db->uid2lid_and_path.try_emplace(FE.getUniqueID()); + if (inserted) { + it->second.first = db->uid2lid_and_path.size() - 1; + SmallString<256> Path = FE.tryGetRealPathName(); + if (Path.empty()) + Path = FE.getName(); + if (!llvm::sys::path::is_absolute(Path) && + !SM.getFileManager().makeAbsolutePath(Path)) + return -1; + it->second.second = Path.str(); + } + return it->second.first; + } + void AddMacroUse(IndexFile *db, SourceManager &SM, Usr usr, SymbolKind kind, SourceLocation Spell) const { const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Spell)); if (!FE) return; - auto UID = FE->getUniqueID(); - auto [it, inserted] = db->uid2lid_and_path.try_emplace(UID); - if (inserted) { - it->second.first = db->uid2lid_and_path.size() - 1; - SmallString<256> Path = FE->tryGetRealPathName(); - if (Path.empty()) - Path = FE->getName(); - if (!llvm::sys::path::is_absolute(Path) && - !SM.getFileManager().makeAbsolutePath(Path)) - return; - it->second.second = Path.str(); - } + int lid = GetFileLID(db, SM, *FE); + if (lid < 0) + return; Range spell = FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, Spell)); - Use use{{spell, 0, SymbolKind::File, Role::Dynamic}, it->second.first}; + Use use{{spell, 0, SymbolKind::File, Role::Dynamic}, lid}; switch (kind) { case SymbolKind::Func: db->ToFunc(usr).uses.push_back(use); @@ -630,15 +637,26 @@ public: FE = SM.getFileEntryForID(LocFID); if (!FE) return true; - IndexFile *db = param.ConsumeFile(*FE); - if (!db) - return true; + int lid = -1; + IndexFile *db; + if (g_config->index.multiVersion) { + db = param.ConsumeFile(*SM.getFileEntryForID(SM.getMainFileID())); + if (!db) + return true; + param.SeenFile(*FE); + if (!SM.isInMainFile(R.getBegin())) + lid = GetFileLID(db, SM, *FE); + } else { + db = param.ConsumeFile(*FE); + if (!db) + return true; + } const Decl *OrigD = ASTNode.OrigD; const DeclContext *SemDC = OrigD->getDeclContext(); const DeclContext *LexDC = ASTNode.ContainerDC; Role role = static_cast(Roles); - db->language = std::max(db->language, GetDeclLanguage(OrigD)); + db->language = LanguageId((int)db->language | (int)GetDeclLanguage(OrigD)); bool is_decl = Roles & uint32_t(index::SymbolRole::Declaration); bool is_def = Roles & uint32_t(index::SymbolRole::Definition); @@ -653,18 +671,18 @@ public: auto do_def_decl = [&](auto *entity) { if (is_def) { - entity->def.spell = GetUse(db, loc, SemDC, role); + entity->def.spell = GetUse(db, lid, loc, SemDC, role); SourceRange R = OrigD->getSourceRange(); entity->def.extent = - GetUse(db, + GetUse(db, lid, R.getBegin().isFileID() ? FromTokenRange(SM, Lang, OrigD->getSourceRange()) : loc, LexDC, Role::None); } else if (is_decl) { - entity->declarations.push_back(GetUse(db, loc, LexDC, role)); + entity->declarations.push_back(GetUse(db, lid, loc, LexDC, role)); } else { - entity->uses.push_back(GetUse(db, loc, LexDC, role)); + entity->uses.push_back(GetUse(db, lid, loc, LexDC, role)); return; } if (entity->def.comments[0] == '\0' && g_config->index.comments) @@ -750,10 +768,11 @@ public: if (SM.getFileID(R1.getBegin()) == LocFID) { IndexType &type1 = db->ToType(usr1); SourceLocation L1 = D1->getLocation(); - type1.def.spell = GetUse(db, FromTokenRange(SM, Lang, {L1, L1}), - SemDC, Role::Definition); - type1.def.extent = - GetUse(db, FromTokenRange(SM, Lang, R1), LexDC, Role::None); + type1.def.spell = + GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, + Role::Definition); + type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), + LexDC, Role::None); type1.def.detailed_name = Intern(info1->short_name); type1.def.short_name_size = int16_t(info1->short_name.size()); type1.def.kind = lsSymbolKind::TypeParameter; @@ -768,10 +787,10 @@ public: // e.g. lambda parameter SourceLocation L = OrigD->getLocation(); if (SM.getFileID(L) == LocFID) { - var->def.spell = GetUse(db, FromTokenRange(SM, Lang, {L, L}), SemDC, - Role::Definition); + var->def.spell = GetUse(db, lid, FromTokenRange(SM, Lang, {L, L}), + SemDC, Role::Definition); var->def.extent = - GetUse(db, FromTokenRange(SM, Lang, OrigD->getSourceRange()), + GetUse(db, lid, FromTokenRange(SM, Lang, OrigD->getSourceRange()), LexDC, Role::None); } } @@ -868,10 +887,10 @@ public: std::tie(RD, offset) = Stack.back(); Stack.pop_back(); if (!RD->isCompleteDefinition() || RD->isDependentType() || - !ValidateRecord(RD)) + RD->isInvalidDecl() || !ValidateRecord(RD)) offset = -1; for (FieldDecl *FD : RD->fields()) { - int offset1 = offset >= 0 ? offset + Ctx->getFieldOffset(FD) : -1; + int offset1 = offset < 0 ? -1 : offset + Ctx->getFieldOffset(FD); if (FD->getIdentifier()) type->def.vars.emplace_back(GetUsr(FD), offset1); else if (const auto *RT1 = FD->getType()->getAs()) { @@ -928,7 +947,8 @@ public: SourceLocation L1 = TSI->getTypeLoc().getBeginLoc(); if (SM.getFileID(L1) == LocFID) { Range loc1 = FromTokenRange(SM, Lang, {L1, L1}); - type1.uses.push_back(GetUse(db, loc1, LexDC, Role::Reference)); + type1.uses.push_back( + GetUse(db, lid, loc1, LexDC, Role::Reference)); } } } @@ -1081,8 +1101,7 @@ public: if (!FE) return; if (IndexFile *db = param.ConsumeFile(*FE)) { - auto [Name, usr] = GetMacro(Tok); - IndexVar &var = db->ToVar(usr); + IndexVar &var = db->ToVar(GetMacro(Tok).second); var.uses.push_back( {{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), 0, SymbolKind::File, Role::Dynamic}}); diff --git a/src/indexer.h b/src/indexer.h index 70a407a5..d1b1e712 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -241,7 +241,7 @@ struct IndexFile { std::string path; std::vector args; int64_t last_write_time = 0; - LanguageId language = LanguageId::Unknown; + LanguageId language = LanguageId::C; // uid2lid_and_path is used to generate lid2path, but not serialized. std::unordered_map> diff --git a/src/language.h b/src/language.h index 846185b5..d53b7920 100644 --- a/src/language.h +++ b/src/language.h @@ -22,7 +22,7 @@ limitations under the License. // Used to identify the language at a file level. The ordering is important, as // a file previously identified as `C`, will be changed to `Cpp` if it // encounters a c++ declaration. -enum class LanguageId { Unknown = 0, C = 1, Cpp = 2, ObjC = 3, ObjCpp = 4 }; +enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 }; MAKE_REFLECT_TYPE_PROXY(LanguageId); LanguageId SourceFileLanguage(std::string_view path); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index c9d63e8e..8120f4be 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -78,7 +78,7 @@ struct Handler_TextDocumentDidOpen } clang_complete->NotifyView(path); - if (g_config->diagnostics.onParse) + if (g_config->diagnostics.onOpen) clang_complete->DiagnosticsUpdate({params.textDocument.uri}); } }; diff --git a/src/query.cc b/src/query.cc index 026aacf9..1ce07c5f 100644 --- a/src/query.cc +++ b/src/query.cc @@ -29,7 +29,7 @@ limitations under the License. namespace { -void AssignFileId(const Lid2file_id &, int file_id, SymbolRef &ref) { +void AssignFileId(const Lid2file_id &lid2file_id, int file_id, SymbolRef &ref) { if (ref.kind == SymbolKind::File) ref.usr = file_id; } diff --git a/src/serializers/binary.h b/src/serializers/binary.h index 1b86fac8..a1c9266f 100644 --- a/src/serializers/binary.h +++ b/src/serializers/binary.h @@ -17,13 +17,14 @@ limitations under the License. #include "serializer.h" -#include +#include class BinaryReader : public Reader { const char *p_; template T Get() { - auto ret = *reinterpret_cast(p_); + T ret; + memcpy(&ret, p_, sizeof(T)); p_ += sizeof(T); return ret; } @@ -89,7 +90,7 @@ class BinaryWriter : public Writer { template void Pack(T x) { auto i = buf_.size(); buf_.resize(i + sizeof(x)); - *reinterpret_cast(buf_.data() + i) = x; + memcpy(buf_.data() + i, &x, sizeof(x)); } void VarUInt(uint64_t n) { From a33f4df404a9a129e566a65b3fea0bab3ce9b809 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 2 Sep 2018 19:11:10 -0700 Subject: [PATCH 10/66] index.multiVersion: int Before, QueryFile::Def::{all_symbols,outline} were built by indexers. Now, {symbol,outline}2refcnt are used instead, built by main thread. *_removed are augmented with Query*:Def to allow removal of old {symbol,outline}2refcnt entries. --- src/indexer.cc | 6 +- src/message_handler.cc | 4 +- src/messages/ccls_fileInfo.cc | 4 +- src/messages/textDocument_codeLens.cc | 3 +- src/messages/textDocument_definition.cc | 10 +- src/messages/textDocument_documentSymbol.cc | 19 +- src/query.cc | 252 ++++++++++---------- src/query.h | 31 ++- src/query_utils.cc | 25 +- 9 files changed, 181 insertions(+), 173 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index 581b1baf..4f3849e2 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -77,9 +77,9 @@ struct IndexParam { } } - IndexFile *ConsumeFile(const FileEntry &File) { - SeenFile(File); - return file_consumer->TryConsumeFile(File, &file_contents); + IndexFile *ConsumeFile(const FileEntry &FE) { + SeenFile(FE); + return file_consumer->TryConsumeFile(FE, &file_contents); } }; diff --git a/src/message_handler.cc b/src/message_handler.cc index 706bfe91..f4d6aae0 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -209,7 +209,9 @@ void EmitSemanticHighlighting(DB *db, // Group symbols together. std::unordered_map grouped_symbols; - for (SymbolRef sym : file->def->all_symbols) { + for (auto &sym_refcnt : file->symbol2refcnt) { + if (sym_refcnt.second <= 0) continue; + SymbolRef sym = sym_refcnt.first; std::string_view detailed_name; lsSymbolKind parent_kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown; diff --git a/src/messages/ccls_fileInfo.cc b/src/messages/ccls_fileInfo.cc index 493d7b27..5e4f546a 100644 --- a/src/messages/ccls_fileInfo.cc +++ b/src/messages/ccls_fileInfo.cc @@ -18,8 +18,8 @@ limitations under the License. #include "query_utils.h" using namespace ccls; -MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, outline, all_symbols, - skipped_ranges, dependencies); +MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges, + dependencies); namespace { MethodType kMethodType = "$ccls/fileInfo"; diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index e28928e4..0410c32c 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -116,7 +116,8 @@ struct Handler_TextDocumentCodeLens common.working_files = working_files; common.working_file = working_files->GetFileByFilename(file->def->path); - for (SymbolRef sym : file->def->outline) { + for (auto [sym, refcnt] : file->outline2refcnt) { + if (refcnt <= 0) continue; // NOTE: We OffsetColumn so that the code lens always show up in a // predictable order. Otherwise, the client may randomize it. Use use{{sym.range, sym.usr, sym.kind, sym.role}, file->id}; diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 7794bfd1..234a0a16 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -117,12 +117,14 @@ struct Handler_TextDocumentDefinition } auto locs = GetLsLocationExs(db, working_files, uses); out.result.insert(out.result.end(), locs.begin(), locs.end()); - if (!out.result.empty()) - break; } - // No symbols - check for includes. - if (out.result.empty()) { + if (out.result.size()) { + std::sort(out.result.begin(), out.result.end()); + out.result.erase(std::unique(out.result.begin(), out.result.end()), + out.result.end()); + } else { + // Check #include for (const IndexInclude &include : file->def->includes) { if (include.line == ls_pos.line) { lsLocationEx result; diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index 2704d914..51199c0c 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -65,20 +65,20 @@ struct Handler_TextDocumentDocumentSymbol if (params.startLine >= 0) { Out_SimpleDocumentSymbol out; out.id = request->id; - for (SymbolRef sym : file->def->all_symbols) - if (std::optional location = GetLsLocation( - db, working_files, - Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) { - if (params.startLine <= sym.range.start.line && - sym.range.start.line <= params.endLine) - out.result.push_back(location->range); - } + for (auto [sym, refcnt] : file->symbol2refcnt) + if (refcnt > 0 && params.startLine <= sym.range.start.line && + sym.range.start.line <= params.endLine) + if (auto ls_loc = GetLsLocation( + db, working_files, + Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) + out.result.push_back(ls_loc->range); std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); } else { Out_TextDocumentDocumentSymbol out; out.id = request->id; - for (SymbolRef sym : file->def->outline) + for (auto [sym, refcnt] : file->outline2refcnt) { + if (refcnt <= 0) continue; if (std::optional info = GetSymbolInfo(db, working_files, sym, false)) { if (sym.kind == SymbolKind::Var) { @@ -94,6 +94,7 @@ struct Handler_TextDocumentDocumentSymbol out.result.push_back(*info); } } + } pipeline::WriteStdout(kMethodType, out); } } diff --git a/src/query.cc b/src/query.cc index 1ce07c5f..7b349061 100644 --- a/src/query.cc +++ b/src/query.cc @@ -29,34 +29,13 @@ limitations under the License. namespace { -void AssignFileId(const Lid2file_id &lid2file_id, int file_id, SymbolRef &ref) { - if (ref.kind == SymbolKind::File) - ref.usr = file_id; -} - void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Use &use) { - if (use.kind == SymbolKind::File) - use.usr = file_id; if (use.file_id == -1) use.file_id = file_id; else use.file_id = lid2file_id.find(use.file_id)->second; -} - -template -void AssignFileId(const Lid2file_id &, int file_id, T &) {} - -template -void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Maybe &x) { - if (x) - AssignFileId(lid2file_id, file_id, *x); -} - -template -void AssignFileId(const Lid2file_id &lid2file_id, int file_id, - std::vector &xs) { - for (T &x : xs) - AssignFileId(lid2file_id, file_id, x); + if (use.kind == SymbolKind::File) + use.usr = use.file_id; } void AddRange(std::vector &into, const std::vector &from) { @@ -90,79 +69,6 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile &indexed) { for (auto &dep : indexed.dependencies) def.dependencies.push_back(dep.first()); def.language = indexed.language; - - auto add_all_symbols = [&](Use use, Usr usr, SymbolKind kind) { - def.all_symbols.push_back(SymbolRef{{use.range, usr, kind, use.role}}); - }; - auto add_outline = [&](Use use, Usr usr, SymbolKind kind) { - def.outline.push_back(SymbolRef{{use.range, usr, kind, use.role}}); - }; - - for (auto &it : indexed.usr2type) { - const IndexType &type = it.second; - if (type.def.spell) - add_all_symbols(*type.def.spell, type.usr, SymbolKind::Type); - if (type.def.extent) - add_outline(*type.def.extent, type.usr, SymbolKind::Type); - for (Use decl : type.declarations) { - add_all_symbols(decl, type.usr, SymbolKind::Type); - // Constructor positions have references to the class, - // which we do not want to show in textDocument/documentSymbol - if (!(decl.role & Role::Reference)) - add_outline(decl, type.usr, SymbolKind::Type); - } - for (Use use : type.uses) - if (use.file_id == -1) - add_all_symbols(use, type.usr, SymbolKind::Type); - } - for (auto &it : indexed.usr2func) { - const IndexFunc &func = it.second; - if (func.def.spell) - add_all_symbols(*func.def.spell, func.usr, SymbolKind::Func); - if (func.def.extent) - add_outline(*func.def.extent, func.usr, SymbolKind::Func); - for (Use use : func.declarations) { - add_all_symbols(use, func.usr, SymbolKind::Func); - add_outline(use, func.usr, SymbolKind::Func); - } - for (Use use : func.uses) - if (use.file_id == -1) { - // Make ranges of implicit function calls larger (spanning one more - // column to the left/right). This is hacky but useful. e.g. - // textDocument/definition on the space/semicolon in `A a;` or `return - // 42;` will take you to the constructor. - if (use.role & Role::Implicit) { - if (use.range.start.column > 0) - use.range.start.column--; - use.range.end.column++; - } - add_all_symbols(use, func.usr, SymbolKind::Func); - } - } - for (auto &it : indexed.usr2var) { - const IndexVar &var = it.second; - if (var.def.spell) - add_all_symbols(*var.def.spell, var.usr, SymbolKind::Var); - if (var.def.extent) - add_outline(*var.def.extent, var.usr, SymbolKind::Var); - for (Use decl : var.declarations) { - add_all_symbols(decl, var.usr, SymbolKind::Var); - add_outline(decl, var.usr, SymbolKind::Var); - } - for (Use use : var.uses) - if (use.file_id == -1) - add_all_symbols(use, var.usr, SymbolKind::Var); - } - - std::sort(def.outline.begin(), def.outline.end(), - [](const SymbolRef &a, const SymbolRef &b) { - return a.range.start < b.range.start; - }); - std::sort(def.all_symbols.begin(), def.all_symbols.end(), - [](const SymbolRef &a, const SymbolRef &b) { - return a.range.start < b.range.start; - }); - return {std::move(def), std::move(indexed.file_contents)}; } @@ -194,7 +100,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2func) { auto &func = it.second; if (func.def.detailed_name[0]) - r.funcs_removed.push_back(func.usr); + r.funcs_removed.emplace_back(func.usr, func.def); r.funcs_declarations[func.usr].first = std::move(func.declarations); r.funcs_uses[func.usr].first = std::move(func.uses); r.funcs_derived[func.usr].first = std::move(func.derived); @@ -212,7 +118,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2type) { auto &type = it.second; if (type.def.detailed_name[0]) - r.types_removed.push_back(type.usr); + r.types_removed.emplace_back(type.usr, type.def); r.types_declarations[type.usr].first = std::move(type.declarations); r.types_uses[type.usr].first = std::move(type.uses); r.types_derived[type.usr].first = std::move(type.derived); @@ -232,7 +138,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2var) { auto &var = it.second; if (var.def.detailed_name[0]) - r.vars_removed.push_back(var.usr); + r.vars_removed.emplace_back(var.usr, var.def); r.vars_declarations[var.usr].first = std::move(var.declarations); r.vars_uses[var.usr].first = std::move(var.uses); } @@ -247,11 +153,12 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { return r; } +template void DB::RemoveUsrs(SymbolKind kind, int file_id, - const std::vector &to_remove) { + const std::vector> &to_remove) { switch (kind) { case SymbolKind::Func: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasFunc(usr)) continue; @@ -265,7 +172,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id, break; } case SymbolKind::Type: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasType(usr)) continue; @@ -279,7 +186,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id, break; } case SymbolKind::Var: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasVar(usr)) continue; @@ -304,43 +211,68 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { if (R.second) \ C##s.emplace_back().usr = it.first; \ auto &entity = C##s[R.first->second]; \ - AssignFileId(prev_lid2file_id, u->file_id, it.second.first); \ RemoveRange(entity.F, it.second.first); \ - AssignFileId(lid2file_id, u->file_id, it.second.second); \ AddRange(entity.F, it.second.second); \ } std::unordered_map prev_lid2file_id, lid2file_id; for (auto &[lid, path] : u->prev_lid2path) prev_lid2file_id[lid] = GetFileId(path); - for (auto &[lid, path] : u->lid2path) - lid2file_id[lid] = GetFileId(path); + for (auto &[lid, path] : u->lid2path) { + int file_id = GetFileId(path); + lid2file_id[lid] = file_id; + if (!files[file_id].def) { + files[file_id].def = QueryFile::Def(); + files[file_id].def->path = path; + } + } + + // References (Use &use) in this function are important to update file_id. + auto Ref = [&](std::unordered_map &lid2fid, Usr usr, + SymbolKind kind, Use &use, int delta) { + use.file_id = + use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; + int &v = + files[use.file_id] + .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]; + v += delta; + assert(v >= 0); + }; + auto RefO = [&](std::unordered_map &lid2fid, Usr usr, + SymbolKind kind, Use &use, int delta) { + use.file_id = + use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; + files[use.file_id] + .outline2refcnt[SymbolRef{{use.range, usr, kind, use.role}}] += delta; + }; auto UpdateUses = [&](Usr usr, SymbolKind kind, llvm::DenseMap &entity_usr, - auto &entities, auto &p) { + auto &entities, auto &p, bool hint_implicit) { auto R = entity_usr.try_emplace({usr}, entity_usr.size()); if (R.second) vars.emplace_back().usr = usr; auto &entity = entities[R.first->second]; for (Use &use : p.first) { - if (use.file_id == -1) - use.file_id = u->file_id; - else { - use.file_id = prev_lid2file_id.find(use.file_id)->second; - files[use.file_id] - .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]--; + if (hint_implicit && use.role & Role::Implicit) { + // Make ranges of implicit function calls larger (spanning one more + // column to the left/right). This is hacky but useful. e.g. + // textDocument/definition on the space/semicolon in `A a;` or ` 42;` + // will take you to the constructor. + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; } + Ref(prev_lid2file_id, usr, kind, use, -1); } RemoveRange(entity.uses, p.first); for (Use &use : p.second) { - if (use.file_id == -1) - use.file_id = u->file_id; - else { - use.file_id = lid2file_id.find(use.file_id)->second; - files[use.file_id] - .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]++; + if (hint_implicit && use.role & Role::Implicit) { + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; } + Ref(lid2file_id, usr, kind, use, 1); } AddRange(entity.uses, p.second); }; @@ -359,36 +291,72 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { funcs.reserve(t); func_usr.reserve(t); } + for (auto &[usr, def] : u->funcs_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Func, *def.spell, -1); + if (def.extent) + RefO(prev_lid2file_id, usr, SymbolKind::Func, *def.extent, -1); + } RemoveUsrs(SymbolKind::Func, u->file_id, u->funcs_removed); Update(lid2file_id, u->file_id, std::move(u->funcs_def_update)); + for (auto &[usr, del_add]: u->funcs_declarations) { + for (Use &use : del_add.first) + Ref(prev_lid2file_id, usr, SymbolKind::Func, use, -1); + for (Use &use : del_add.second) + Ref(lid2file_id, usr, SymbolKind::Func, use, 1); + } REMOVE_ADD(func, declarations); REMOVE_ADD(func, derived); for (auto &[usr, p] : u->funcs_uses) - UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p); + UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p, true); if ((t = types.size() + u->types_hint) > types.capacity()) { t = size_t(t * grow); types.reserve(t); type_usr.reserve(t); } + for (auto &[usr, def] : u->types_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Type, *def.spell, -1); + if (def.extent) + RefO(prev_lid2file_id, usr, SymbolKind::Type, *def.extent, -1); + } RemoveUsrs(SymbolKind::Type, u->file_id, u->types_removed); Update(lid2file_id, u->file_id, std::move(u->types_def_update)); + for (auto &[usr, del_add]: u->types_declarations) { + for (Use &use : del_add.first) + Ref(prev_lid2file_id, usr, SymbolKind::Type, use, -1); + for (Use &use : del_add.second) + Ref(lid2file_id, usr, SymbolKind::Type, use, 1); + } REMOVE_ADD(type, declarations); REMOVE_ADD(type, derived); REMOVE_ADD(type, instances); for (auto &[usr, p] : u->types_uses) - UpdateUses(usr, SymbolKind::Type, type_usr, types, p); + UpdateUses(usr, SymbolKind::Type, type_usr, types, p, false); if ((t = vars.size() + u->vars_hint) > vars.capacity()) { t = size_t(t * grow); vars.reserve(t); var_usr.reserve(t); } + for (auto &[usr, def] : u->vars_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Var, *def.spell, -1); + if (def.extent) + RefO(prev_lid2file_id, usr, SymbolKind::Var, *def.extent, -1); + } RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed); Update(lid2file_id, u->file_id, std::move(u->vars_def_update)); + for (auto &[usr, del_add]: u->vars_declarations) { + for (Use &use : del_add.first) + Ref(prev_lid2file_id, usr, SymbolKind::Var, use, -1); + for (Use &use : del_add.second) + Ref(lid2file_id, usr, SymbolKind::Var, use, 1); + } REMOVE_ADD(var, declarations); for (auto &[usr, p] : u->vars_uses) - UpdateUses(usr, SymbolKind::Var, var_usr, vars, p); + UpdateUses(usr, SymbolKind::Var, var_usr, vars, p, false); #undef REMOVE_ADD } @@ -414,9 +382,17 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); - AssignFileId(lid2file_id, file_id, def.callees); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Func, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Func, def.extent->role}}]++; + } + auto R = func_usr.try_emplace({u.first}, func_usr.size()); if (R.second) funcs.emplace_back(); @@ -433,8 +409,16 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Type, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Type, def.extent->role}}]++; + } auto R = type_usr.try_emplace({u.first}, type_usr.size()); if (R.second) types.emplace_back(); @@ -451,8 +435,16 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Var, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Var, def.extent->role}}]++; + } auto R = var_usr.try_emplace({u.first}, var_usr.size()); if (R.second) vars.emplace_back(); diff --git a/src/query.h b/src/query.h index 1513da0f..5f0a5d24 100644 --- a/src/query.h +++ b/src/query.h @@ -21,6 +21,21 @@ limitations under the License. #include #include +namespace llvm { +template <> struct DenseMapInfo { + static inline SymbolRef getEmptyKey() { return {}; } + static inline SymbolRef getTombstoneKey() { + SymbolRef ret{}; + ret.usr = -1; + return ret; + } + static unsigned getHashValue(SymbolRef sym) { + return std::hash()(sym); + } + static bool isEqual(SymbolRef l, SymbolRef r) { return l == r; } +}; +} + struct QueryFile { struct Def { std::string path; @@ -28,10 +43,6 @@ struct QueryFile { LanguageId language; // Includes in the file. std::vector includes; - // Outline of the file (ie, for code lens). - std::vector outline; - // Every symbol found in the file (ie, for goto definition) - std::vector all_symbols; // Parts of the file which are disabled. std::vector skipped_ranges; // Used by |$ccls/freshenIndex|. @@ -42,7 +53,8 @@ struct QueryFile { int id = -1; std::optional def; - std::unordered_map symbol2refcnt; + llvm::DenseMap symbol2refcnt; + llvm::DenseMap outline2refcnt; }; template struct QueryEntity { @@ -109,7 +121,7 @@ struct IndexUpdate { // Function updates. int funcs_hint; - std::vector funcs_removed; + std::vector> funcs_removed; std::vector> funcs_def_update; UseUpdate funcs_declarations; UseUpdate funcs_uses; @@ -117,7 +129,7 @@ struct IndexUpdate { // Type updates. int types_hint; - std::vector types_removed; + std::vector> types_removed; std::vector> types_def_update; UseUpdate types_declarations; UseUpdate types_uses; @@ -126,7 +138,7 @@ struct IndexUpdate { // Variable updates. int vars_hint; - std::vector vars_removed; + std::vector> vars_removed; std::vector> vars_def_update; UseUpdate vars_declarations; UseUpdate vars_uses; @@ -154,8 +166,9 @@ struct DB { std::vector types; std::vector vars; + template void RemoveUsrs(SymbolKind kind, int file_id, - const std::vector &to_remove); + const std::vector> &to_remove); // Insert the contents of |update| into |db|. void ApplyIndexUpdate(IndexUpdate *update); int GetFileId(const std::string &path); diff --git a/src/query_utils.cc b/src/query_utils.cc index 23349d7c..c4fdc5d7 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -159,29 +159,28 @@ std::vector GetUsesForAllDerived(DB *db, QueryFunc &root) { return ret; } -std::optional GetLsPosition(WorkingFile *working_file, +std::optional GetLsPosition(WorkingFile *wfile, const Position &position) { - if (!working_file) + if (!wfile || wfile->index_lines.empty()) return lsPosition{position.line, position.column}; int column = position.column; if (std::optional start = - working_file->GetBufferPosFromIndexPos(position.line, &column, false)) + wfile->GetBufferPosFromIndexPos(position.line, &column, false)) return lsPosition{*start, column}; return std::nullopt; } -std::optional GetLsRange(WorkingFile *working_file, +std::optional GetLsRange(WorkingFile *wfile, const Range &location) { - if (!working_file) { + if (!wfile || wfile->index_lines.empty()) return lsRange{lsPosition{location.start.line, location.start.column}, lsPosition{location.end.line, location.end.column}}; - } int start_column = location.start.column, end_column = location.end.column; - std::optional start = working_file->GetBufferPosFromIndexPos( + std::optional start = wfile->GetBufferPosFromIndexPos( location.start.line, &start_column, false); - std::optional end = working_file->GetBufferPosFromIndexPos( + std::optional end = wfile->GetBufferPosFromIndexPos( location.end.line, &end_column, true); if (!start || !end) return std::nullopt; @@ -315,12 +314,13 @@ std::optional GetSymbolInfo(DB *db, return std::nullopt; } -std::vector FindSymbolsAtLocation(WorkingFile *working_file, +std::vector FindSymbolsAtLocation(WorkingFile *wfile, QueryFile *file, lsPosition &ls_pos) { std::vector symbols; - if (working_file) { - if (auto line = working_file->GetIndexPosFromBufferPos( + // If multiVersion > 0, index may not exist and thus index_lines is empty. + if (wfile && wfile->index_lines.size()) { + if (auto line = wfile->GetIndexPosFromBufferPos( ls_pos.line, &ls_pos.character, false)) { ls_pos.line = *line; } else { @@ -329,9 +329,6 @@ std::vector FindSymbolsAtLocation(WorkingFile *working_file, } } - for (SymbolRef sym : file->def->all_symbols) - if (sym.range.Contains(ls_pos.line, ls_pos.character)) - symbols.push_back(sym); for (auto [sym, refcnt] : file->symbol2refcnt) if (refcnt > 0 && sym.range.Contains(ls_pos.line, ls_pos.character)) symbols.push_back(sym); From aebf2dfaed4f0e7e92b21312d87ae1cbcb3fafff Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 3 Sep 2018 12:21:32 -0700 Subject: [PATCH 11/66] Add index.multiVersion{Black,White}list They allow files matching specified patterns to be indexed only once even if index.multiVersion > 0. An example is to exclude system headers with index.multiVersionBlacklist: ["^/usr/include"] --- src/config.h | 8 +++++++- src/indexer.cc | 18 +++++++++++++++++- src/indexer.h | 1 + src/messages/initialize.cc | 1 + 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/config.h b/src/config.h index 67cf0972..c22a99f8 100644 --- a/src/config.h +++ b/src/config.h @@ -191,6 +191,11 @@ struct Config { // If not 0, a file will be indexed in each tranlation unit that includes it. int multiVersion = 0; + // If multiVersion != 0, files that match blacklist but not whitelist will + // still only be indexed for one version. + std::vector multiVersionBlacklist; + std::vector multiVersionWhitelist; + // Allow indexing on textDocument/didChange. // May be too slow for big projects, so it is off by default. bool onDidChange = false; @@ -237,7 +242,8 @@ MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onOpen, onType, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, - onDidChange, reparseForDependency, threads, whitelist); + multiVersionBlacklist, multiVersionWhitelist, onDidChange, + reparseForDependency, threads, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, diff --git a/src/indexer.cc b/src/indexer.cc index 4f3849e2..ff711a0c 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -17,6 +17,7 @@ limitations under the License. #include "clang_tu.h" #include "log.hh" +#include "match.h" #include "platform.h" #include "serializer.h" using ccls::Intern; @@ -44,8 +45,11 @@ namespace { constexpr int kInitializerMaxLines = 3; +GroupMatch *multiVersionMatcher; + struct IndexParam { std::unordered_map SeenUniqueID; + std::unordered_map UID2multi; std::unordered_map file_contents; std::unordered_map file2write_time; struct DeclInfo { @@ -81,6 +85,13 @@ struct IndexParam { SeenFile(FE); return file_consumer->TryConsumeFile(FE, &file_contents); } + + bool UseMultiVersion(const FileEntry &FE) { + auto it = UID2multi.try_emplace(FE.getUniqueID()); + if (it.second) + it.first->second = multiVersionMatcher->IsMatch(FileName(FE)); + return it.first->second; + } }; StringRef GetSourceInRange(const SourceManager &SM, const LangOptions &LangOpts, @@ -639,7 +650,7 @@ public: return true; int lid = -1; IndexFile *db; - if (g_config->index.multiVersion) { + if (g_config->index.multiVersion && param.UseMultiVersion(*FE)) { db = param.ConsumeFile(*SM.getFileEntryForID(SM.getMainFileID())); if (!db) return true; @@ -1180,6 +1191,11 @@ template void Uniquify(std::vector &a) { } namespace ccls::idx { +void Init() { + multiVersionMatcher = new GroupMatch(g_config->index.multiVersionWhitelist, + g_config->index.multiVersionBlacklist); +} + std::vector> Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, diff --git a/src/indexer.h b/src/indexer.h index d1b1e712..355b5a98 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -277,6 +277,7 @@ struct IndexFile { }; namespace ccls::idx { +void Init(); std::vector> Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index b687b6a9..cfbca19e 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -478,6 +478,7 @@ struct Handler_Initialize : BaseMessageHandler { EscapeFileName(g_config->projectRoot)); diag_pub->Init(); + idx::Init(); semantic_cache->Init(); // Open up / load the project. From e92378df9c58aa1519dff62e207c055cd45c6249 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 3 Sep 2018 14:17:03 -0700 Subject: [PATCH 12/66] Add all: boolean to textDocument/documentSymbol --- src/messages/textDocument_documentSymbol.cc | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index 51199c0c..53b63960 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -22,17 +22,19 @@ using namespace clang; namespace { MethodType kMethodType = "textDocument/documentSymbol"; -struct lsDocumentSymbolParams { - lsTextDocumentIdentifier textDocument; - int startLine = -1; - int endLine = -1; -}; -MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument, startLine, endLine); - struct In_TextDocumentDocumentSymbol : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } - lsDocumentSymbolParams params; + struct Params { + lsTextDocumentIdentifier textDocument; + // false: outline; true: all symbols + bool all = false; + // If >= 0, return Range[] instead of SymbolInformation[] to reduce output. + int startLine = -1; + int endLine = -1; + } params; }; +MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol::Params, textDocument, all, + startLine, endLine); MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol, id, params); REGISTER_IN_MESSAGE(In_TextDocumentDocumentSymbol); @@ -62,10 +64,12 @@ struct Handler_TextDocumentDocumentSymbol params.textDocument.uri.GetPath(), &file, &file_id)) return; + const auto &symbol2refcnt = + params.all ? file->symbol2refcnt : file->outline2refcnt; if (params.startLine >= 0) { Out_SimpleDocumentSymbol out; out.id = request->id; - for (auto [sym, refcnt] : file->symbol2refcnt) + for (auto [sym, refcnt] : symbol2refcnt) if (refcnt > 0 && params.startLine <= sym.range.start.line && sym.range.start.line <= params.endLine) if (auto ls_loc = GetLsLocation( @@ -77,7 +81,7 @@ struct Handler_TextDocumentDocumentSymbol } else { Out_TextDocumentDocumentSymbol out; out.id = request->id; - for (auto [sym, refcnt] : file->outline2refcnt) { + for (auto [sym, refcnt] : symbol2refcnt) { if (refcnt <= 0) continue; if (std::optional info = GetSymbolInfo(db, working_files, sym, false)) { From 0a51424c5cdcd32be128129150e34d32462f3725 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 3 Sep 2018 15:08:34 -0700 Subject: [PATCH 13/66] Add $ccls/navigate and improve textDocument/definition --- CMakeLists.txt | 1 + src/messages/ccls_navigate.cc | 115 ++++++++++++++++++++++++ src/messages/textDocument_definition.cc | 11 ++- src/position.h | 1 + 4 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 src/messages/ccls_navigate.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index b202db78..d48f36b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,7 @@ target_sources(ccls PRIVATE src/messages/ccls_freshenIndex.cc src/messages/ccls_inheritanceHierarchy.cc src/messages/ccls_memberHierarchy.cc + src/messages/ccls_navigate.cc src/messages/ccls_vars.cc src/messages/exit.cc src/messages/initialize.cc diff --git a/src/messages/ccls_navigate.cc b/src/messages/ccls_navigate.cc new file mode 100644 index 00000000..921ffae1 --- /dev/null +++ b/src/messages/ccls_navigate.cc @@ -0,0 +1,115 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "query_utils.h" +using namespace ccls; + +namespace { +MethodType kMethodType = "$ccls/navigate"; + +struct In_CclsNavigate : public RequestInMessage { + MethodType GetMethodType() const override { return kMethodType; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsPosition position; + std::string direction; + } params; +}; +MAKE_REFLECT_STRUCT(In_CclsNavigate::Params, textDocument, position, direction); +MAKE_REFLECT_STRUCT(In_CclsNavigate, id, params); +REGISTER_IN_MESSAGE(In_CclsNavigate); + +struct Handler_CclsNavigate : BaseMessageHandler { + MethodType GetMethodType() const override { return kMethodType; } + void Run(In_CclsNavigate *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + + WorkingFile *wfile = + working_files->GetFileByFilename(file->def->path); + lsPosition ls_pos = request->params.position; + if (wfile && wfile->index_lines.size()) + if (auto line = wfile->GetIndexPosFromBufferPos( + ls_pos.line, &ls_pos.character, false)) + ls_pos.line = *line; + Position pos{(int16_t)ls_pos.line, (int16_t)ls_pos.character}; + + Maybe res; + switch (params.direction[0]) { + case 'D': { + Maybe parent; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end && + (!parent || parent->start < sym.range.start)) + parent = sym.range; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && pos < sym.range.start && + (!parent || sym.range.end <= parent->end) && + (!res || sym.range.start < res->start)) + res = sym.range; + break; + } + case 'L': + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.end <= pos && + (!res || (res->end == sym.range.end ? sym.range.start < res->start + : res->end < sym.range.end))) + res = sym.range; + break; + case 'R': { + Maybe parent; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end && + (!parent || parent->start < sym.range.start)) + parent = sym.range; + if (parent && parent->start.line == pos.line && pos < parent->end) { + pos = parent->end; + if (pos.column) + pos.column--; + } + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && pos < sym.range.start && + (!res || + (sym.range.start == res->start ? res->end < sym.range.end + : sym.range.start < res->start))) + res = sym.range; + break; + } + case 'U': + default: + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start < pos && pos < sym.range.end && + (!res || res->start < sym.range.start)) + res = sym.range; + break; + } + Out_LocationList out; + out.id = request->id; + if (res) + if (auto ls_range = GetLsRange(wfile, *res)) { + lsLocationEx &ls_loc = out.result.emplace_back(); + ls_loc.uri = params.textDocument.uri; + ls_loc.range = *ls_range; + } + pipeline::WriteStdout(kMethodType, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_CclsNavigate); +} // namespace diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 234a0a16..1b616c80 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -75,14 +75,17 @@ struct Handler_TextDocumentDefinition Out_TextDocumentDefinition out; out.id = request->id; + Maybe range; Maybe on_def; - bool has_symbol = false; WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); lsPosition &ls_pos = params.position; for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) { + if (!range) + range = sym.range; + else if (!(*range == sym.range)) + break; // Found symbol. Return definition. - has_symbol = true; // Special cases which are handled: // - symbol has declaration but no definition (ie, pure virtual) @@ -130,12 +133,12 @@ struct Handler_TextDocumentDefinition lsLocationEx result; result.uri = lsDocumentUri::FromPath(include.resolved_path); out.result.push_back(result); - has_symbol = true; + range = {{0, 0}, {0, 0}}; break; } } // Find the best match of the identifier at point. - if (!has_symbol) { + if (!range) { lsPosition position = request->params.position; const std::string &buffer = wfile->buffer_content; std::string_view query = LexIdentifierAroundPos(position, buffer); diff --git a/src/position.h b/src/position.h index 110676ca..5ff53515 100644 --- a/src/position.h +++ b/src/position.h @@ -40,6 +40,7 @@ struct Position { return line < o.line; return column < o.column; } + bool operator<=(const Position &o) const { return !(o < *this); } }; MAKE_HASHABLE(Position, t.line, t.column); From 56da577df92281fc04c34785041037c06e686510 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 4 Sep 2018 13:02:48 -0700 Subject: [PATCH 14/66] Add clang.excludeArgs and rename diagnostics.onType to onChange --- src/clang_complete.cc | 2 +- src/config.h | 17 ++++++++++------- src/project.cc | 3 ++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index cc15089a..39bc03c8 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -612,7 +612,7 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { // Fetching the completion request blocks until we have a request. ClangCompleteManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); - if (!g_config->diagnostics.onType) + if (!g_config->diagnostics.onChange) continue; std::string path = request.document.uri.GetPath(); diff --git a/src/config.h b/src/config.h index c22a99f8..3e22a0e9 100644 --- a/src/config.h +++ b/src/config.h @@ -59,6 +59,9 @@ struct Config { SerializeFormat cacheFormat = SerializeFormat::Binary; struct Clang { + // Arguments that should be excluded, e.g. ["-fopenmp", "-Wall"] + std::vector excludeArgs; + // Additional arguments to pass to clang. std::vector extraArgs; @@ -149,11 +152,11 @@ struct Config { // xxx: at most every xxx milliseconds int frequencyMs = 0; - // If true, diagnostics will be reported in textDocument/didOpen. - bool onOpen = true; + // If true, diagnostics will be reported for textDocument/didChange. + bool onChange = true; - // If true, diagnostics from typing will be reported. - bool onType = true; + // If true, diagnostics will be reported for textDocument/didOpen. + bool onOpen = true; std::vector whitelist; } diagnostics; @@ -231,15 +234,15 @@ struct Config { int maxNum = 2000; } xref; }; -MAKE_REFLECT_STRUCT(Config::Clang, extraArgs, resourceDir); +MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, resourceDir); MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, detailedLabel, filterAndSort, includeBlacklist, includeMaxPathSize, includeSuffixWhitelist, includeWhitelist); -MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onOpen, - onType, whitelist) +MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, + onOpen, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onDidChange, diff --git a/src/project.cc b/src/project.cc index d7d6e3a5..c25e97c9 100644 --- a/src/project.cc +++ b/src/project.cc @@ -32,6 +32,7 @@ using namespace ccls; #include #include #include +#include #include #include using namespace clang; @@ -96,7 +97,7 @@ struct ProjectProcessor { args.push_back(arg.substr(5)); } else if (arg == "%clang") { args.push_back(lang == LanguageId::Cpp ? "clang++" : "clang"); - } else { + } else if (!llvm::is_contained(g_config->clang.excludeArgs, arg)) { args.push_back(arg); } } From b77fba6ea854f594d76ea9f092a607e351fa83d2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 6 Sep 2018 00:22:40 -0700 Subject: [PATCH 15/66] Improve hover and documentSymbol --- src/messages/textDocument_hover.cc | 5 ++++ src/query.cc | 40 ++++++++++++++---------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/messages/textDocument_hover.cc b/src/messages/textDocument_hover.cc index 71dd0919..a368f846 100644 --- a/src/messages/textDocument_hover.cc +++ b/src/messages/textDocument_hover.cc @@ -36,6 +36,11 @@ GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) { break; } } + if (!def && entity.def.size()) { + def = &entity.def[0]; + if (def->comments[0]) + comments = def->comments; + } if (def) { lsMarkedString m; m.language = LanguageIdentifier(lang); diff --git a/src/query.cc b/src/query.cc index 7b349061..88a7e809 100644 --- a/src/query.cc +++ b/src/query.cc @@ -229,21 +229,19 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { // References (Use &use) in this function are important to update file_id. auto Ref = [&](std::unordered_map &lid2fid, Usr usr, - SymbolKind kind, Use &use, int delta) { + SymbolKind kind, Use &use, int delta, int k = 1) { use.file_id = use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; - int &v = - files[use.file_id] + if (k & 1) { + int &v = + files[use.file_id] .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]; - v += delta; - assert(v >= 0); - }; - auto RefO = [&](std::unordered_map &lid2fid, Usr usr, - SymbolKind kind, Use &use, int delta) { - use.file_id = - use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; - files[use.file_id] - .outline2refcnt[SymbolRef{{use.range, usr, kind, use.role}}] += delta; + v += delta; + assert(v >= 0); + } + if (k & 2) + files[use.file_id] + .outline2refcnt[SymbolRef{{use.range, usr, kind, use.role}}] += delta; }; auto UpdateUses = [&](Usr usr, SymbolKind kind, @@ -295,15 +293,15 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { if (def.spell) Ref(prev_lid2file_id, usr, SymbolKind::Func, *def.spell, -1); if (def.extent) - RefO(prev_lid2file_id, usr, SymbolKind::Func, *def.extent, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Func, *def.extent, -1, 2); } RemoveUsrs(SymbolKind::Func, u->file_id, u->funcs_removed); Update(lid2file_id, u->file_id, std::move(u->funcs_def_update)); for (auto &[usr, del_add]: u->funcs_declarations) { for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Func, use, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Func, use, -1, 3); for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Func, use, 1); + Ref(lid2file_id, usr, SymbolKind::Func, use, 1, 3); } REMOVE_ADD(func, declarations); REMOVE_ADD(func, derived); @@ -319,15 +317,15 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { if (def.spell) Ref(prev_lid2file_id, usr, SymbolKind::Type, *def.spell, -1); if (def.extent) - RefO(prev_lid2file_id, usr, SymbolKind::Type, *def.extent, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Type, *def.extent, -1, 2); } RemoveUsrs(SymbolKind::Type, u->file_id, u->types_removed); Update(lid2file_id, u->file_id, std::move(u->types_def_update)); for (auto &[usr, del_add]: u->types_declarations) { for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Type, use, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Type, use, -1, 3); for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Type, use, 1); + Ref(lid2file_id, usr, SymbolKind::Type, use, 1, 3); } REMOVE_ADD(type, declarations); REMOVE_ADD(type, derived); @@ -344,15 +342,15 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { if (def.spell) Ref(prev_lid2file_id, usr, SymbolKind::Var, *def.spell, -1); if (def.extent) - RefO(prev_lid2file_id, usr, SymbolKind::Var, *def.extent, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Var, *def.extent, -1, 2); } RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed); Update(lid2file_id, u->file_id, std::move(u->vars_def_update)); for (auto &[usr, del_add]: u->vars_declarations) { for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Var, use, -1); + Ref(prev_lid2file_id, usr, SymbolKind::Var, use, -1, 3); for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Var, use, 1); + Ref(lid2file_id, usr, SymbolKind::Var, use, 1, 3); } REMOVE_ADD(var, declarations); for (auto &[usr, p] : u->vars_uses) From 8b3ebf234b6b1aeaeee8d6d6c5ccc86da51910aa Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 7 Sep 2018 14:38:08 -0700 Subject: [PATCH 16/66] Remove $ccls/base and clean up; deduplicate codeLens --- CMakeLists.txt | 1 - src/clang_complete.cc | 14 +++--- src/indexer.cc | 1 - src/messages/ccls_base.cc | 66 --------------------------- src/messages/ccls_callHierarchy.cc | 1 - src/messages/textDocument_codeLens.cc | 24 +++++----- 6 files changed, 19 insertions(+), 88 deletions(-) delete mode 100644 src/messages/ccls_base.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d48f36b6..9574aad8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,6 @@ target_sources(ccls PRIVATE ) target_sources(ccls PRIVATE - src/messages/ccls_base.cc src/messages/ccls_callHierarchy.cc src/messages/ccls_callers.cc src/messages/ccls_fileInfo.cc diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 39bc03c8..4d6613af 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -550,7 +550,7 @@ void CompletionPreloadMain(ClangCompleteManager *completion_manager) { } } -void CompletionQueryMain(ClangCompleteManager *completion_manager) { +void CompletionMain(ClangCompleteManager *completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. std::unique_ptr request = @@ -588,7 +588,7 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { FOpts.SkipFunctionBodies = true; CI->getLangOpts()->CommentOpts.ParseAllComments = true; - StoreDiags DC; + DiagnosticConsumer DC; WorkingFiles::Snapshot snapshot = completion_manager->working_files_->AsSnapshot({StripFileType(path)}); std::vector> Bufs; @@ -607,7 +607,7 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) { } } -void DiagnosticQueryMain(ClangCompleteManager *manager) { +void DiagnosticMain(ClangCompleteManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. ClangCompleteManager::DiagnosticRequest request = @@ -709,8 +709,8 @@ ClangCompleteManager::ClangCompleteManager(Project *project, completion_sessions_(kMaxCompletionSessions), PCH(std::make_shared()) { std::thread([&]() { - set_thread_name("comp-query"); - ccls::CompletionQueryMain(this); + set_thread_name("comp"); + ccls::CompletionMain(this); }) .detach(); std::thread([&]() { @@ -719,8 +719,8 @@ ClangCompleteManager::ClangCompleteManager(Project *project, }) .detach(); std::thread([&]() { - set_thread_name("diag-query"); - ccls::DiagnosticQueryMain(this); + set_thread_name("diag"); + ccls::DiagnosticMain(this); }) .detach(); } diff --git a/src/indexer.cc b/src/indexer.cc index ff711a0c..ce53ad16 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1014,7 +1014,6 @@ public: break; case Decl::EnumConstant: var->def.kind = lsSymbolKind::EnumMember; - // TODO Pretty printer may print = if (is_def && strchr(var->def.detailed_name, '=') == nullptr) { auto *ECD = cast(D); const auto &Val = ECD->getInitVal(); diff --git a/src/messages/ccls_base.cc b/src/messages/ccls_base.cc deleted file mode 100644 index b5f2b8bb..00000000 --- a/src/messages/ccls_base.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { - -MethodType kMethodType = "$ccls/base"; - -struct In_CclsBase : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsBase, id, params); -REGISTER_IN_MESSAGE(In_CclsBase); - -struct Handler_CclsBase : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_CclsBase *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - WorkingFile *working_file = - working_files->GetFileByFilename(file->def->path); - - Out_LocationList out; - out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - if (sym.kind == SymbolKind::Type) { - if (const auto *def = db->GetType(sym).AnyDef()) - out.result = GetLsLocationExs(db, working_files, - GetTypeDeclarations(db, def->bases)); - break; - } else if (sym.kind == SymbolKind::Func) { - if (const auto *def = db->GetFunc(sym).AnyDef()) - out.result = GetLsLocationExs(db, working_files, - GetFuncDeclarations(db, def->bases)); - break; - } - } - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsBase); -} // namespace diff --git a/src/messages/ccls_callHierarchy.cc b/src/messages/ccls_callHierarchy.cc index 8b139eb4..ce593425 100644 --- a/src/messages/ccls_callHierarchy.cc +++ b/src/messages/ccls_callHierarchy.cc @@ -15,7 +15,6 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" -using namespace ccls; #include "query_utils.h" using namespace ccls; diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index 0410c32c..730441e7 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -20,19 +20,19 @@ limitations under the License. #include "query_utils.h" using namespace ccls; +#include + namespace { MethodType kMethodType = "textDocument/codeLens"; -struct lsDocumentCodeLensParams { - lsTextDocumentIdentifier textDocument; -}; -MAKE_REFLECT_STRUCT(lsDocumentCodeLensParams, textDocument); - using TCodeLens = lsCodeLens; struct In_TextDocumentCodeLens : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } - lsDocumentCodeLensParams params; + struct Params { + lsTextDocumentIdentifier textDocument; + } params; }; +MAKE_REFLECT_STRUCT(In_TextDocumentCodeLens::Params, textDocument); MAKE_REFLECT_STRUCT(In_TextDocumentCodeLens, id, params); REGISTER_IN_MESSAGE(In_TextDocumentCodeLens); @@ -96,19 +96,17 @@ struct Handler_TextDocumentCodeLens : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } void Run(In_TextDocumentCodeLens *request) override { + auto ¶ms = request->params; Out_TextDocumentCodeLens out; out.id = request->id; - lsDocumentUri file_as_uri = request->params.textDocument.uri; - std::string path = file_as_uri.GetPath(); - + std::string path = params.textDocument.uri.GetPath(); clang_complete->NotifyView(path); QueryFile *file; if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { + params.textDocument.uri.GetPath(), &file)) return; - } CommonCodeLensParams common; common.result = &out.result; @@ -116,8 +114,10 @@ struct Handler_TextDocumentCodeLens common.working_files = working_files; common.working_file = working_files->GetFileByFilename(file->def->path); + std::unordered_set seen; for (auto [sym, refcnt] : file->outline2refcnt) { - if (refcnt <= 0) continue; + if (refcnt <= 0 || !seen.insert(sym.range).second) + continue; // NOTE: We OffsetColumn so that the code lens always show up in a // predictable order. Otherwise, the client may randomize it. Use use{{sym.range, sym.usr, sym.kind, sym.role}, file->id}; From e20a8e7a1b5a4c8e9975284e5bae992197a4bb14 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 7 Sep 2018 22:29:36 -0700 Subject: [PATCH 17/66] Add DeclUse as element type of declarations --- index_tests/class_forward_declaration.cc | 6 +- index_tests/constructors/constructor.cc | 24 ++-- index_tests/constructors/destructor.cc | 24 ++-- .../constructors/implicit_constructor.cc | 24 ++-- index_tests/constructors/invalid_reference.cc | 10 +- index_tests/constructors/make_functions.cc | 68 +++++------ .../declaration_vs_definition/class.cc | 6 +- .../declaration_vs_definition/class_member.cc | 8 +- .../class_member_static.cc | 12 +- index_tests/declaration_vs_definition/func.cc | 6 +- .../func_associated_function_params.cc | 14 +-- .../declaration_vs_definition/method.cc | 16 +-- index_tests/enums/enum_class_decl.cc | 16 +-- index_tests/enums/enum_decl.cc | 12 +- index_tests/enums/enum_inherit.cc | 28 ++--- index_tests/enums/enum_usage.cc | 20 +-- index_tests/foobar.cc | 40 +++--- index_tests/function_declaration.cc | 2 +- .../function_declaration_definition.cc | 6 +- index_tests/function_definition.cc | 4 +- index_tests/inheritance/class_inherit.cc | 10 +- .../class_inherit_templated_parent.cc | 30 ++--- .../inheritance/class_multiple_inherit.cc | 22 ++-- index_tests/inheritance/function_override.cc | 16 +-- .../inheritance/interface_pure_virtual.cc | 6 +- .../inheritance/multiple_base_functions.cc | 30 ++--- index_tests/lambdas/lambda.cc | 28 ++--- index_tests/macros/complex.cc | 24 ++-- index_tests/macros/foo.cc | 26 ++-- index_tests/method_declaration.cc | 6 +- index_tests/method_definition.cc | 12 +- index_tests/method_inline_declaration.cc | 8 +- index_tests/multi_file/funky_enum.cc | 16 +-- index_tests/multi_file/impl.cc | 54 ++++----- index_tests/multi_file/simple_impl.cc | 8 +- index_tests/multi_file/static.cc | 12 +- index_tests/namespaces/anonymous_function.cc | 2 +- .../namespaces/function_declaration.cc | 4 +- index_tests/namespaces/function_definition.cc | 6 +- index_tests/namespaces/method_declaration.cc | 8 +- index_tests/namespaces/method_definition.cc | 14 +-- .../namespaces/method_inline_declaration.cc | 10 +- index_tests/namespaces/namespace_alias.cc | 34 +++--- index_tests/namespaces/namespace_reference.cc | 24 ++-- index_tests/operators/operator.cc | 16 +-- .../outline/static_function_in_type.cc | 26 ++-- index_tests/preprocessor/include_guard.cc | 4 +- .../func_specialized_template_param.cc | 18 +-- .../implicit_variable_instantiation.cc | 30 ++--- .../templates/member_ref_in_template.cc | 18 +-- ...ass_template_func_usage_folded_into_one.cc | 22 ++-- ...ace_template_type_usage_folded_into_one.cc | 24 ++-- index_tests/templates/specialization.cc | 114 +++++++++--------- .../templates/specialized_func_definition.cc | 16 +-- ...mplate_class_func_usage_folded_into_one.cc | 20 +-- ...ass_template_func_usage_folded_into_one.cc | 20 +-- ...mplate_class_type_usage_folded_into_one.cc | 40 +++--- ...emplate_class_var_usage_folded_into_one.cc | 18 +-- .../template_func_usage_folded_into_one.cc | 14 +-- .../template_type_usage_folded_into_one.cc | 22 ++-- .../template_var_usage_folded_into_one.cc | 30 ++--- index_tests/types/anonymous_struct.cc | 24 ++-- index_tests/types/typedefs.cc | 8 +- index_tests/unions/union_decl.cc | 12 +- index_tests/unions/union_usage.cc | 26 ++-- .../usage/func_called_from_constructor.cc | 18 +-- .../usage/func_called_from_macro_argument.cc | 14 +-- .../usage/func_called_from_template.cc | 14 +-- .../usage/func_called_implicit_ctor.cc | 20 +-- index_tests/usage/func_usage_addr_func.cc | 20 +-- index_tests/usage/func_usage_addr_method.cc | 18 +-- index_tests/usage/func_usage_call_func.cc | 10 +- index_tests/usage/func_usage_call_method.cc | 20 +-- .../usage/func_usage_class_inline_var_def.cc | 14 +-- .../usage/func_usage_forward_decl_func.cc | 8 +- .../usage/func_usage_forward_decl_method.cc | 20 +-- index_tests/usage/func_usage_template_func.cc | 8 +- .../usage/type_usage_as_template_parameter.cc | 36 +++--- ...ype_usage_as_template_parameter_complex.cc | 48 ++++---- ...type_usage_as_template_parameter_simple.cc | 18 +-- .../usage/type_usage_declare_extern.cc | 8 +- index_tests/usage/type_usage_declare_field.cc | 22 ++-- index_tests/usage/type_usage_declare_local.cc | 22 ++-- index_tests/usage/type_usage_declare_param.cc | 22 ++-- .../type_usage_declare_param_prototype.cc | 14 +-- .../usage/type_usage_declare_param_unnamed.cc | 8 +- .../usage/type_usage_declare_qualifiers.cc | 34 +++--- .../usage/type_usage_declare_static.cc | 10 +- .../usage/type_usage_on_return_type.cc | 36 +++--- .../usage/type_usage_typedef_and_using.cc | 42 +++---- .../type_usage_typedef_and_using_template.cc | 16 +-- index_tests/usage/type_usage_various.cc | 18 +-- index_tests/usage/usage_inside_of_call.cc | 38 +++--- .../usage/usage_inside_of_call_simple.cc | 14 +-- index_tests/usage/var_usage_call_function.cc | 16 +-- index_tests/usage/var_usage_class_member.cc | 36 +++--- .../usage/var_usage_class_member_static.cc | 18 +-- index_tests/usage/var_usage_cstyle_cast.cc | 18 +-- index_tests/usage/var_usage_extern.cc | 8 +- index_tests/usage/var_usage_func_parameter.cc | 10 +- index_tests/usage/var_usage_local.cc | 10 +- index_tests/usage/var_usage_shadowed_local.cc | 16 +-- .../usage/var_usage_shadowed_parameter.cc | 16 +-- index_tests/usage/var_usage_static.cc | 10 +- index_tests/vars/class_member.cc | 10 +- index_tests/vars/class_static_member.cc | 12 +- .../vars/class_static_member_decl_only.cc | 6 +- index_tests/vars/deduce_auto_type.cc | 18 +-- index_tests/vars/function_local.cc | 12 +- index_tests/vars/function_param.cc | 16 +-- index_tests/vars/function_param_unnamed.cc | 4 +- index_tests/vars/function_shadow_local.cc | 16 +-- index_tests/vars/function_shadow_param.cc | 12 +- index_tests/vars/global_variable.cc | 4 +- index_tests/vars/global_variable_decl_only.cc | 2 +- .../vars/type_instance_on_using_type.cc | 20 +-- src/indexer.cc | 64 +++++++--- src/indexer.h | 13 +- src/query.cc | 39 +++--- src/query.h | 15 ++- src/query_utils.cc | 16 ++- 121 files changed, 1177 insertions(+), 1128 deletions(-) diff --git a/index_tests/class_forward_declaration.cc b/index_tests/class_forward_declaration.cc index fd80cefb..0da90161 100644 --- a/index_tests/class_forward_declaration.cc +++ b/index_tests/class_forward_declaration.cc @@ -15,9 +15,9 @@ OUTPUT: "qual_name_offset": 6, "short_name": "Foo", "kind": 5, - "declarations": ["1:7-1:10|0|1|1", "2:7-2:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "3:7-3:10|0|1|2", - "extent": "3:1-3:13|0|1|0", + "declarations": ["1:7-1:10|1:1-1:10|0|1|1|-1", "2:7-2:10|2:1-2:10|0|1|1|-1", "4:7-4:10|4:1-4:10|0|1|1|-1"], + "spell": "3:7-3:10|0|1|2|-1", + "extent": "3:1-3:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/constructors/constructor.cc b/index_tests/constructors/constructor.cc index cf764596..72fcaf0d 100644 --- a/index_tests/constructors/constructor.cc +++ b/index_tests/constructors/constructor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "3:3-3:6|15041163540773201510|2|1026", - "extent": "3:3-3:11|15041163540773201510|2|0", + "spell": "3:3-3:6|15041163540773201510|2|1026|-1", + "extent": "3:3-3:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["7:7-7:8|4259594751088586730|3|16676", "8:17-8:20|4259594751088586730|3|16676"], + "uses": ["7:7-7:8|4259594751088586730|3|16676|-1", "8:17-8:20|4259594751088586730|3|16676|-1"], "callees": [] }, { "usr": 4259594751088586730, @@ -36,8 +36,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:6-6:9|0|1|2", - "extent": "6:1-9:2|0|1|0", + "spell": "6:6-6:9|0|1|2|-1", + "extent": "6:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10983126130596230582, 17165811951126099095], @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [3385168158331140247], "vars": [], "instances": [10983126130596230582, 17165811951126099095], - "uses": ["3:3-3:6|15041163540773201510|2|4", "7:3-7:6|4259594751088586730|3|4", "8:3-8:6|4259594751088586730|3|4", "8:17-8:20|4259594751088586730|3|4"] + "uses": ["3:3-3:6|15041163540773201510|2|4|-1", "7:3-7:6|4259594751088586730|3|4|-1", "8:3-8:6|4259594751088586730|3|4|-1", "8:17-8:20|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 10983126130596230582, @@ -68,8 +68,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "7:7-7:8|4259594751088586730|3|2", - "extent": "7:3-7:8|4259594751088586730|3|0", + "spell": "7:7-7:8|4259594751088586730|3|2|-1", + "extent": "7:3-7:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, @@ -81,8 +81,8 @@ OUTPUT: "short_name": "f2", "hover": "Foo *f2 = new Foo()", "declarations": [], - "spell": "8:8-8:10|4259594751088586730|3|2", - "extent": "8:3-8:22|4259594751088586730|3|0", + "spell": "8:8-8:10|4259594751088586730|3|2|-1", + "extent": "8:3-8:22|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/constructors/destructor.cc b/index_tests/constructors/destructor.cc index f7724c3b..3bb394d2 100644 --- a/index_tests/constructors/destructor.cc +++ b/index_tests/constructors/destructor.cc @@ -26,12 +26,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "3:3-3:6|15041163540773201510|2|1026", - "extent": "3:3-3:11|15041163540773201510|2|0", + "spell": "3:3-3:6|15041163540773201510|2|1026|-1", + "extent": "3:3-3:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:7-8:8|4259594751088586730|3|16676"], + "uses": ["8:7-8:8|4259594751088586730|3|16676|-1"], "callees": [] }, { "usr": 4259594751088586730, @@ -41,8 +41,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:9|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:6-7:9|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [1893354193220338759], @@ -56,8 +56,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "4:3-4:4|15041163540773201510|2|1026", - "extent": "4:3-4:12|15041163540773201510|2|0", + "spell": "4:3-4:4|15041163540773201510|2|1026|-1", + "extent": "4:3-4:12|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -71,8 +71,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -80,7 +80,7 @@ OUTPUT: "funcs": [3385168158331140247, 7440261702884428359], "vars": [], "instances": [1893354193220338759], - "uses": ["3:3-3:6|15041163540773201510|2|4", "4:4-4:7|15041163540773201510|2|4", "8:3-8:6|4259594751088586730|3|4"] + "uses": ["3:3-3:6|15041163540773201510|2|4|-1", "4:4-4:7|15041163540773201510|2|4|-1", "8:3-8:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 1893354193220338759, @@ -88,8 +88,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "8:7-8:8|4259594751088586730|3|2", - "extent": "8:3-8:8|4259594751088586730|3|0", + "spell": "8:7-8:8|4259594751088586730|3|2|-1", + "extent": "8:3-8:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/constructors/implicit_constructor.cc b/index_tests/constructors/implicit_constructor.cc index be98be7f..b3995cfd 100644 --- a/index_tests/constructors/implicit_constructor.cc +++ b/index_tests/constructors/implicit_constructor.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [449111627548814328, 17097499197730163115], @@ -35,12 +35,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "2:3-2:7|13487927231218873822|2|1026", - "extent": "2:3-2:12|13487927231218873822|2|0", + "spell": "2:3-2:7|13487927231218873822|2|1026|-1", + "extent": "2:3-2:12|13487927231218873822|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:8-6:12|3957104924306079513|3|16676", "7:15-7:19|3957104924306079513|3|16676"], + "uses": ["6:8-6:12|3957104924306079513|3|16676|-1", "7:15-7:19|3957104924306079513|3|16676|-1"], "callees": [] }], "usr2type": [{ @@ -50,8 +50,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [10530961286677896857], "vars": [], "instances": [449111627548814328, 17097499197730163115], - "uses": ["2:3-2:7|13487927231218873822|2|4", "6:3-6:7|3957104924306079513|3|4", "7:15-7:19|3957104924306079513|3|4"] + "uses": ["2:3-2:7|13487927231218873822|2|4|-1", "6:3-6:7|3957104924306079513|3|4|-1", "7:15-7:19|3957104924306079513|3|4|-1"] }], "usr2var": [{ "usr": 449111627548814328, @@ -67,8 +67,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "foo0", "declarations": [], - "spell": "6:8-6:12|3957104924306079513|3|2", - "extent": "6:3-6:12|3957104924306079513|3|0", + "spell": "6:8-6:12|3957104924306079513|3|2|-1", + "extent": "6:3-6:12|3957104924306079513|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -80,8 +80,8 @@ OUTPUT: "short_name": "foo1", "hover": "Type foo1 = Type()", "declarations": [], - "spell": "7:8-7:12|3957104924306079513|3|2", - "extent": "7:3-7:21|3957104924306079513|3|0", + "spell": "7:8-7:12|3957104924306079513|3|2|-1", + "extent": "7:3-7:21|3957104924306079513|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, diff --git a/index_tests/constructors/invalid_reference.cc b/index_tests/constructors/invalid_reference.cc index c6c933e1..dfb742c2 100644 --- a/index_tests/constructors/invalid_reference.cc +++ b/index_tests/constructors/invalid_reference.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "4:6-4:9|15041163540773201510|2|1026", - "extent": "4:1-4:11|15041163540773201510|2|0", + "spell": "4:6-4:9|15041163540773201510|2|1026|-1", + "extent": "4:1-4:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -35,8 +35,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -44,7 +44,7 @@ OUTPUT: "funcs": [17319723337446061757], "vars": [], "instances": [], - "uses": ["4:1-4:4|0|1|4", "4:6-4:9|15041163540773201510|2|4"] + "uses": ["4:1-4:4|0|1|4|-1", "4:6-4:9|15041163540773201510|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/constructors/make_functions.cc b/index_tests/constructors/make_functions.cc index e2e3be4c..c285c1d5 100644 --- a/index_tests/constructors/make_functions.cc +++ b/index_tests/constructors/make_functions.cc @@ -36,8 +36,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "7:3-7:9|14935975554338052500|2|1026", - "extent": "7:3-7:32|14935975554338052500|2|0", + "spell": "7:3-7:9|14935975554338052500|2|1026|-1", + "extent": "7:3-7:32|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "6:3-6:9|14935975554338052500|2|1026", - "extent": "6:3-6:17|14935975554338052500|2|0", + "spell": "6:3-6:9|14935975554338052500|2|1026|-1", + "extent": "6:3-6:17|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -66,8 +66,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "5:3-5:9|14935975554338052500|2|1026", - "extent": "5:3-5:14|14935975554338052500|2|0", + "spell": "5:3-5:9|14935975554338052500|2|1026|-1", + "extent": "5:3-5:14|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -81,8 +81,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "8:3-8:9|14935975554338052500|2|1026", - "extent": "8:3-8:30|14935975554338052500|2|0", + "spell": "8:3-8:9|14935975554338052500|2|1026|-1", + "extent": "8:3-8:30|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -96,8 +96,8 @@ OUTPUT: make_functions.h "short_name": "Bar", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -105,7 +105,7 @@ OUTPUT: make_functions.h "funcs": [], "vars": [], "instances": [], - "uses": ["7:17-7:20|14935975554338052500|2|4", "8:15-8:18|14935975554338052500|2|4"] + "uses": ["7:17-7:20|14935975554338052500|2|4|-1", "8:15-8:18|14935975554338052500|2|4|-1"] }, { "usr": 14935975554338052500, "detailed_name": "class Foobar {}", @@ -113,8 +113,8 @@ OUTPUT: make_functions.h "short_name": "Foobar", "kind": 5, "declarations": [], - "spell": "3:7-3:13|0|1|2", - "extent": "3:1-9:2|0|1|0", + "spell": "3:7-3:13|0|1|2|-1", + "extent": "3:1-9:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -122,7 +122,7 @@ OUTPUT: make_functions.h "funcs": [13131778807733950299, 13028995015627606181, 3765833212244435302, 17321436359755983845], "vars": [], "instances": [], - "uses": ["5:3-5:9|14935975554338052500|2|4", "6:3-6:9|14935975554338052500|2|4", "7:3-7:9|14935975554338052500|2|4", "8:3-8:9|14935975554338052500|2|4"] + "uses": ["5:3-5:9|14935975554338052500|2|4|-1", "6:3-6:9|14935975554338052500|2|4|-1", "7:3-7:9|14935975554338052500|2|4|-1", "8:3-8:9|14935975554338052500|2|4|-1"] }], "usr2var": [] } @@ -154,12 +154,12 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "9:4-9:15|0|1|2", - "extent": "9:1-11:2|0|1|0", + "spell": "9:4-9:15|0|1|2|-1", + "extent": "9:1-11:2|0|1|0|-1", "bases": [], "derived": [], "vars": [3908732770590594660], - "uses": ["17:3-17:14|2816883305867289955|3|16420"], + "uses": ["17:3-17:14|2816883305867289955|3|16420|-1"], "callees": [] }, { "usr": 2816883305867289955, @@ -169,8 +169,8 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "13:6-13:14|0|1|2", - "extent": "13:1-18:2|0|1|0", + "spell": "13:6-13:14|0|1|2|-1", + "extent": "13:1-18:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -210,12 +210,12 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "4:4-4:14|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:4-4:14|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "bases": [], "derived": [], "vars": [8463700030555379526], - "uses": ["14:3-14:13|2816883305867289955|3|16420", "15:3-15:13|2816883305867289955|3|16420", "16:3-16:13|2816883305867289955|3|16420"], + "uses": ["14:3-14:13|2816883305867289955|3|16420|-1", "15:3-15:13|2816883305867289955|3|16420|-1", "16:3-16:13|2816883305867289955|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -262,7 +262,7 @@ OUTPUT: make_functions.cc "funcs": [], "vars": [], "instances": [], - "uses": ["16:29-16:32|2816883305867289955|3|4", "17:30-17:33|2816883305867289955|3|4"] + "uses": ["16:29-16:32|2816883305867289955|3|4|-1", "17:30-17:33|2816883305867289955|3|4|-1"] }, { "usr": 14935975554338052500, "detailed_name": "class Foobar {}", @@ -277,7 +277,7 @@ OUTPUT: make_functions.cc "funcs": [], "vars": [], "instances": [], - "uses": ["14:14-14:20|2816883305867289955|3|4", "15:14-15:20|2816883305867289955|3|4", "16:14-16:20|2816883305867289955|3|4", "17:15-17:21|2816883305867289955|3|4"] + "uses": ["14:14-14:20|2816883305867289955|3|4|-1", "15:14-15:20|2816883305867289955|3|4|-1", "16:14-16:20|2816883305867289955|3|4|-1", "17:15-17:21|2816883305867289955|3|4|-1"] }], "usr2var": [{ "usr": 180270746871803062, @@ -285,8 +285,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 4, "short_name": "args", "declarations": [], - "spell": "9:24-9:28|11363675606380070883|3|1026", - "extent": "9:16-9:28|11363675606380070883|3|0", + "spell": "9:24-9:28|11363675606380070883|3|1026|-1", + "extent": "9:16-9:28|11363675606380070883|3|0|-1", "type": 87, "uses": [], "kind": 253, @@ -297,8 +297,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 6, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|768523651983844320|3|1026", - "extent": "4:15-4:29|768523651983844320|3|0", + "spell": "4:25-4:29|768523651983844320|3|1026|-1", + "extent": "4:15-4:29|768523651983844320|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -309,8 +309,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 8, "short_name": "args", "declarations": [], - "spell": "9:24-9:28|2532818908869373467|3|1026", - "extent": "9:16-9:28|2532818908869373467|3|0", + "spell": "9:24-9:28|2532818908869373467|3|1026|-1", + "extent": "9:16-9:28|2532818908869373467|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -321,8 +321,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 10, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|15793662558620604611|3|1026", - "extent": "4:15-4:29|15793662558620604611|3|0", + "spell": "4:25-4:29|15793662558620604611|3|1026|-1", + "extent": "4:15-4:29|15793662558620604611|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -333,8 +333,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 6, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|11138976705878544996|3|1026", - "extent": "4:15-4:29|11138976705878544996|3|0", + "spell": "4:25-4:29|11138976705878544996|3|1026|-1", + "extent": "4:15-4:29|11138976705878544996|3|0|-1", "type": 0, "uses": [], "kind": 253, diff --git a/index_tests/declaration_vs_definition/class.cc b/index_tests/declaration_vs_definition/class.cc index 42a44a88..51a35677 100644 --- a/index_tests/declaration_vs_definition/class.cc +++ b/index_tests/declaration_vs_definition/class.cc @@ -17,9 +17,9 @@ OUTPUT: "qual_name_offset": 6, "short_name": "Foo", "kind": 5, - "declarations": ["1:7-1:10|0|1|1", "2:7-2:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "3:7-3:10|0|1|2", - "extent": "3:1-3:13|0|1|0", + "declarations": ["1:7-1:10|1:1-1:10|0|1|1|-1", "2:7-2:10|2:1-2:10|0|1|1|-1", "4:7-4:10|4:1-4:10|0|1|1|-1"], + "spell": "3:7-3:10|0|1|2|-1", + "extent": "3:1-3:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/declaration_vs_definition/class_member.cc b/index_tests/declaration_vs_definition/class_member.cc index a4333abc..ef14ac7b 100644 --- a/index_tests/declaration_vs_definition/class_member.cc +++ b/index_tests/declaration_vs_definition/class_member.cc @@ -30,8 +30,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -50,8 +50,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "foo", "declarations": [], - "spell": "2:7-2:10|15041163540773201510|2|1026", - "extent": "2:3-2:10|15041163540773201510|2|0", + "spell": "2:7-2:10|15041163540773201510|2|1026|-1", + "extent": "2:3-2:10|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/declaration_vs_definition/class_member_static.cc b/index_tests/declaration_vs_definition/class_member_static.cc index c0ae1aa7..4655b4be 100644 --- a/index_tests/declaration_vs_definition/class_member_static.cc +++ b/index_tests/declaration_vs_definition/class_member_static.cc @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,16 +41,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:5-5:8|0|1|4"] + "uses": ["5:5-5:8|0|1|4|-1"] }], "usr2var": [{ "usr": 8942920329766232482, "detailed_name": "static int Foo::foo", "qual_name_offset": 11, "short_name": "foo", - "declarations": ["2:14-2:17|15041163540773201510|2|1025"], - "spell": "5:10-5:13|15041163540773201510|2|1026", - "extent": "5:1-5:13|15041163540773201510|2|0", + "declarations": ["2:14-2:17|2:3-2:17|15041163540773201510|2|1025|-1"], + "spell": "5:10-5:13|15041163540773201510|2|1026|-1", + "extent": "5:1-5:13|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/declaration_vs_definition/func.cc b/index_tests/declaration_vs_definition/func.cc index 718eaffa..aacda01c 100644 --- a/index_tests/declaration_vs_definition/func.cc +++ b/index_tests/declaration_vs_definition/func.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1", "2:6-2:9|0|1|1", "4:6-4:9|0|1|1"], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:14|0|1|0", + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1", "2:6-2:9|2:1-2:11|0|1|1|-1", "4:6-4:9|4:1-4:11|0|1|1|-1"], + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/declaration_vs_definition/func_associated_function_params.cc b/index_tests/declaration_vs_definition/func_associated_function_params.cc index a7cc5e0b..0aa1487e 100644 --- a/index_tests/declaration_vs_definition/func_associated_function_params.cc +++ b/index_tests/declaration_vs_definition/func_associated_function_params.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:5-1:8|0|1|1", "2:5-2:8|0|1|1", "4:5-4:8|0|1|1"], - "spell": "5:5-5:8|0|1|2", - "extent": "5:1-5:36|0|1|0", + "declarations": ["1:5-1:8|1:1-1:18|0|1|1|-1", "2:5-2:8|2:1-3:16|0|1|1|-1", "4:5-4:8|4:1-4:26|0|1|1|-1"], + "spell": "5:5-5:8|0|1|2|-1", + "extent": "5:1-5:36|0|1|0|-1", "bases": [], "derived": [], "vars": [14555488990109936920, 10963664335057337329], @@ -47,8 +47,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "b", "declarations": [], - "spell": "5:20-5:21|2747674671862363334|3|1026", - "extent": "5:16-5:21|2747674671862363334|3|0", + "spell": "5:20-5:21|2747674671862363334|3|1026|-1", + "extent": "5:16-5:21|2747674671862363334|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -59,8 +59,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:13-5:14|2747674671862363334|3|1026", - "extent": "5:9-5:14|2747674671862363334|3|0", + "spell": "5:13-5:14|2747674671862363334|3|1026|-1", + "extent": "5:9-5:14|2747674671862363334|3|0|-1", "type": 53, "uses": [], "kind": 253, diff --git a/index_tests/declaration_vs_definition/method.cc b/index_tests/declaration_vs_definition/method.cc index 18aed73a..da2b46fb 100644 --- a/index_tests/declaration_vs_definition/method.cc +++ b/index_tests/declaration_vs_definition/method.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "declonly", "kind": 6, "storage": 0, - "declarations": ["2:8-2:16|15041163540773201510|2|1025"], + "declarations": ["2:8-2:16|2:3-2:18|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: "short_name": "purevirtual", "kind": 6, "storage": 0, - "declarations": ["3:16-3:27|15041163540773201510|2|1089"], + "declarations": ["3:16-3:27|3:3-3:33|15041163540773201510|2|1089|-1"], "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "def", "kind": 6, "storage": 0, - "declarations": ["4:8-4:11|15041163540773201510|2|1025"], - "spell": "7:11-7:14|15041163540773201510|2|1026", - "extent": "7:1-7:19|15041163540773201510|2|0", + "declarations": ["4:8-4:11|4:3-4:13|15041163540773201510|2|1025|-1"], + "spell": "7:11-7:14|15041163540773201510|2|1026|-1", + "extent": "7:1-7:19|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -60,8 +60,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,7 +69,7 @@ OUTPUT: "funcs": [4012226004228259562, 10939323144126021546, 15416083548883122431], "vars": [], "instances": [], - "uses": ["7:6-7:9|0|1|4"] + "uses": ["7:6-7:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/enums/enum_class_decl.cc b/index_tests/enums/enum_class_decl.cc index 3f3f78ca..a31baff5 100644 --- a/index_tests/enums/enum_class_decl.cc +++ b/index_tests/enums/enum_class_decl.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "uint8_t", "kind": 252, "declarations": [], - "spell": "1:23-1:30|0|1|2", - "extent": "1:1-1:30|0|1|0", + "spell": "1:23-1:30|0|1|2|-1", + "extent": "1:1-1:30|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "2:12-2:15|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:12-2:15|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,8 +52,8 @@ OUTPUT: "short_name": "A", "hover": "Foo::A = 0", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:4|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -64,8 +64,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "4:3-4:4|16985894625255407295|2|1026", - "extent": "4:3-4:9|16985894625255407295|2|0", + "spell": "4:3-4:4|16985894625255407295|2|1026|-1", + "extent": "4:3-4:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_decl.cc b/index_tests/enums/enum_decl.cc index 6e44da9b..bf760444 100644 --- a/index_tests/enums/enum_decl.cc +++ b/index_tests/enums/enum_decl.cc @@ -16,8 +16,8 @@ OUTPUT: "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -46,8 +46,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_inherit.cc b/index_tests/enums/enum_inherit.cc index 08d84087..18cb37c0 100644 --- a/index_tests/enums/enum_inherit.cc +++ b/index_tests/enums/enum_inherit.cc @@ -23,8 +23,8 @@ OUTPUT: "short_name": "E", "kind": 10, "declarations": [], - "spell": "8:12-8:13|0|1|2", - "extent": "8:1-11:2|0|1|0", + "spell": "8:12-8:13|0|1|2|-1", + "extent": "8:1-11:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -40,8 +40,8 @@ OUTPUT: "short_name": "int32_t", "kind": 252, "declarations": [], - "spell": "6:13-6:20|0|1|2", - "extent": "6:1-6:20|0|1|0", + "spell": "6:13-6:20|0|1|2|-1", + "extent": "6:1-6:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,8 +57,8 @@ OUTPUT: "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -75,8 +75,8 @@ OUTPUT: "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -87,8 +87,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -100,8 +100,8 @@ OUTPUT: "short_name": "E0", "hover": "E::E0 = 0", "declarations": [], - "spell": "9:3-9:5|2986879766914123941|2|1026", - "extent": "9:3-9:5|2986879766914123941|2|0", + "spell": "9:3-9:5|2986879766914123941|2|1026|-1", + "extent": "9:3-9:5|2986879766914123941|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -112,8 +112,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "E20", "declarations": [], - "spell": "10:3-10:6|2986879766914123941|2|1026", - "extent": "10:3-10:11|2986879766914123941|2|0", + "spell": "10:3-10:6|2986879766914123941|2|1026|-1", + "extent": "10:3-10:11|2986879766914123941|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_usage.cc b/index_tests/enums/enum_usage.cc index bcee0c00..07475c77 100644 --- a/index_tests/enums/enum_usage.cc +++ b/index_tests/enums/enum_usage.cc @@ -18,8 +18,8 @@ OUTPUT: "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:12-1:15|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:12-1:15|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -27,7 +27,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [10677751717622394455], - "uses": ["6:1-6:4|0|1|4", "6:9-6:12|0|1|4"] + "uses": ["6:1-6:4|0|1|4|-1", "6:9-6:12|0|1|4|-1"] }], "usr2var": [{ "usr": 439339022761937396, @@ -36,10 +36,10 @@ OUTPUT: "short_name": "A", "hover": "Foo::A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, - "uses": ["6:14-6:15|0|1|4"], + "uses": ["6:14-6:15|0|1|4|-1"], "kind": 22, "storage": 0 }, { @@ -49,8 +49,8 @@ OUTPUT: "short_name": "x", "hover": "Foo x = Foo::A", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:15|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:15|0|1|0|-1", "type": 16985894625255407295, "uses": [], "kind": 13, @@ -61,8 +61,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/foobar.cc b/index_tests/foobar.cc index f5d2e47b..e92f23cf 100644 --- a/index_tests/foobar.cc +++ b/index_tests/foobar.cc @@ -21,8 +21,8 @@ OUTPUT: "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -30,7 +30,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:5-9:6|0|1|4"] + "uses": ["9:5-9:6|0|1|4|-1"] }, { "usr": 7074603899792463171, "detailed_name": "Inner", @@ -38,8 +38,8 @@ OUTPUT: "short_name": "Inner", "kind": 26, "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", + "spell": "6:10-6:15|0|1|2|-1", + "extent": "6:3-6:18|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -55,8 +55,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -64,7 +64,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:1-9:4|0|1|4", "10:1-10:4|0|1|4"] + "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] }, { "usr": 11976530632376795217, "detailed_name": "Foo", @@ -72,8 +72,8 @@ OUTPUT: "short_name": "Foo", "kind": 26, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -89,8 +89,8 @@ OUTPUT: "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,7 +98,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:5-10:6|0|1|4"] + "uses": ["10:5-10:6|0|1|4|-1"] }, { "usr": 13938528237873543349, "detailed_name": "struct Foo::Inner {}", @@ -106,8 +106,8 @@ OUTPUT: "short_name": "Inner", "kind": 23, "declarations": [], - "spell": "6:10-6:15|10528472276654770367|2|1026", - "extent": "6:3-6:18|10528472276654770367|2|0", + "spell": "6:10-6:15|10528472276654770367|2|1026|-1", + "extent": "6:3-6:18|10528472276654770367|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -115,7 +115,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:9-9:14|0|1|4"] + "uses": ["9:9-9:14|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -123,8 +123,8 @@ OUTPUT: "qual_name_offset": 7, "short_name": "b", "declarations": [], - "spell": "10:8-10:9|0|1|2", - "extent": "10:1-10:9|0|1|0", + "spell": "10:8-10:9|0|1|2|-1", + "extent": "10:1-10:9|0|1|0|-1", "type": 11976530632376795217, "uses": [], "kind": 13, @@ -135,8 +135,8 @@ OUTPUT: "qual_name_offset": 14, "short_name": "a", "declarations": [], - "spell": "9:15-9:16|0|1|2", - "extent": "9:1-9:16|0|1|0", + "spell": "9:15-9:16|0|1|2|-1", + "extent": "9:1-9:16|0|1|0|-1", "type": 7074603899792463171, "uses": [], "kind": 13, diff --git a/index_tests/function_declaration.cc b/index_tests/function_declaration.cc index 2d23e7d9..9c38f574 100644 --- a/index_tests/function_declaration.cc +++ b/index_tests/function_declaration.cc @@ -12,7 +12,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], + "declarations": ["1:6-1:9|1:1-1:23|0|1|1|-1"], "bases": [], "derived": [], "vars": [], diff --git a/index_tests/function_declaration_definition.cc b/index_tests/function_declaration_definition.cc index c35a6f77..1eb2ba75 100644 --- a/index_tests/function_declaration_definition.cc +++ b/index_tests/function_declaration_definition.cc @@ -14,9 +14,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:14|0|1|0", + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1"], + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/function_definition.cc b/index_tests/function_definition.cc index 1662c48a..7ceee636 100644 --- a/index_tests/function_definition.cc +++ b/index_tests/function_definition.cc @@ -13,8 +13,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/inheritance/class_inherit.cc b/index_tests/inheritance/class_inherit.cc index e38b20bd..701b0396 100644 --- a/index_tests/inheritance/class_inherit.cc +++ b/index_tests/inheritance/class_inherit.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "Parent", "kind": 5, "declarations": [], - "spell": "1:7-1:13|0|1|2", - "extent": "1:1-1:16|0|1|0", + "spell": "1:7-1:13|0|1|2|-1", + "extent": "1:1-1:16|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -23,7 +23,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:24-2:30|10963370434658308541|2|2052"] + "uses": ["2:24-2:30|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public Parent {}", @@ -31,8 +31,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "2:7-2:14|0|1|2", - "extent": "2:1-2:33|0|1|0", + "spell": "2:7-2:14|0|1|2|-1", + "extent": "2:1-2:33|0|1|0|-1", "alias_of": 0, "bases": [3866412049634585509], "derived": [], diff --git a/index_tests/inheritance/class_inherit_templated_parent.cc b/index_tests/inheritance/class_inherit_templated_parent.cc index 33b80bbb..4e20cd1b 100644 --- a/index_tests/inheritance/class_inherit_templated_parent.cc +++ b/index_tests/inheritance/class_inherit_templated_parent.cc @@ -25,8 +25,8 @@ OUTPUT: "short_name": "Derived1", "kind": 5, "declarations": [], - "spell": "8:7-8:15|0|1|2", - "extent": "8:1-8:29|0|1|0", + "spell": "8:7-8:15|0|1|2|-1", + "extent": "8:1-8:29|0|1|0|-1", "alias_of": 0, "bases": [11930058224338108382], "derived": [10963370434658308541], @@ -34,7 +34,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:43-13:51|10963370434658308541|2|2052"] + "uses": ["13:43-13:51|10963370434658308541|2|2052|-1"] }, { "usr": 10651399730831737929, "detailed_name": "class Derived2 : Base2 {}", @@ -42,8 +42,8 @@ OUTPUT: "short_name": "Derived2", "kind": 5, "declarations": [], - "spell": "11:7-11:15|0|1|2", - "extent": "11:1-11:29|0|1|0", + "spell": "11:7-11:15|0|1|2|-1", + "extent": "11:1-11:29|0|1|0|-1", "alias_of": 0, "bases": [11118288764693061434], "derived": [10963370434658308541], @@ -51,7 +51,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:56-13:64|10963370434658308541|2|2052"] + "uses": ["13:56-13:64|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : Base1<3>, Base2, Derived1<4>, Derived2 {}", @@ -59,8 +59,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "13:7-13:14|0|1|2", - "extent": "13:1-13:76|0|1|0", + "spell": "13:7-13:14|0|1|2|-1", + "extent": "13:1-13:76|0|1|0|-1", "alias_of": 0, "bases": [11930058224338108382, 11118288764693061434, 5863733211528032190, 10651399730831737929], "derived": [], @@ -68,7 +68,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:33-13:40|10963370434658308541|2|2052", "13:65-13:72|10963370434658308541|2|2052"] + "uses": ["13:33-13:40|10963370434658308541|2|2052|-1", "13:65-13:72|10963370434658308541|2|2052|-1"] }, { "usr": 11118288764693061434, "detailed_name": "class Base2 {}", @@ -76,8 +76,8 @@ OUTPUT: "short_name": "Base2", "kind": 5, "declarations": [], - "spell": "5:7-5:12|0|1|2", - "extent": "5:1-5:15|0|1|0", + "spell": "5:7-5:12|0|1|2|-1", + "extent": "5:1-5:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10651399730831737929, 10963370434658308541], @@ -85,7 +85,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:27-13:32|10963370434658308541|2|2052"] + "uses": ["13:27-13:32|10963370434658308541|2|2052|-1"] }, { "usr": 11930058224338108382, "detailed_name": "class Base1 {}", @@ -93,8 +93,8 @@ OUTPUT: "short_name": "Base1", "kind": 5, "declarations": [], - "spell": "2:7-2:12|0|1|2", - "extent": "2:1-2:15|0|1|0", + "spell": "2:7-2:12|0|1|2|-1", + "extent": "2:1-2:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [5863733211528032190, 10963370434658308541], @@ -102,7 +102,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:17-13:22|10963370434658308541|2|2052"] + "uses": ["13:17-13:22|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/inheritance/class_multiple_inherit.cc b/index_tests/inheritance/class_multiple_inherit.cc index ee1603b3..f8e171a2 100644 --- a/index_tests/inheritance/class_multiple_inherit.cc +++ b/index_tests/inheritance/class_multiple_inherit.cc @@ -16,8 +16,8 @@ OUTPUT: "short_name": "Root", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [11863524815063131483, 14022569716337624303], @@ -25,7 +25,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:24-2:28|11863524815063131483|2|2052", "3:24-3:28|14022569716337624303|2|2052"] + "uses": ["2:24-2:28|11863524815063131483|2|2052|-1", "3:24-3:28|14022569716337624303|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public MiddleA, public MiddleB {}", @@ -33,8 +33,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "4:7-4:14|0|1|2", - "extent": "4:1-4:50|0|1|0", + "spell": "4:7-4:14|0|1|2|-1", + "extent": "4:1-4:50|0|1|0|-1", "alias_of": 0, "bases": [11863524815063131483, 14022569716337624303], "derived": [], @@ -50,8 +50,8 @@ OUTPUT: "short_name": "MiddleA", "kind": 5, "declarations": [], - "spell": "2:7-2:14|0|1|2", - "extent": "2:1-2:31|0|1|0", + "spell": "2:7-2:14|0|1|2|-1", + "extent": "2:1-2:31|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [10963370434658308541], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:24-4:31|10963370434658308541|2|2052"] + "uses": ["4:24-4:31|10963370434658308541|2|2052|-1"] }, { "usr": 14022569716337624303, "detailed_name": "class MiddleB : public Root {}", @@ -67,8 +67,8 @@ OUTPUT: "short_name": "MiddleB", "kind": 5, "declarations": [], - "spell": "3:7-3:14|0|1|2", - "extent": "3:1-3:31|0|1|0", + "spell": "3:7-3:14|0|1|2|-1", + "extent": "3:1-3:31|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [10963370434658308541], @@ -76,7 +76,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:40-4:47|10963370434658308541|2|2052"] + "uses": ["4:40-4:47|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/inheritance/function_override.cc b/index_tests/inheritance/function_override.cc index 982a2cf1..14a5661a 100644 --- a/index_tests/inheritance/function_override.cc +++ b/index_tests/inheritance/function_override.cc @@ -18,8 +18,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "5:8-5:11|10963370434658308541|2|5186", - "extent": "5:3-5:25|10963370434658308541|2|0", + "spell": "5:8-5:11|10963370434658308541|2|5186|-1", + "extent": "5:3-5:25|10963370434658308541|2|0|-1", "bases": [9948027785633571339], "derived": [], "vars": [], @@ -32,7 +32,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:16-2:19|3897841498936210886|2|1089"], + "declarations": ["2:16-2:19|2:3-2:21|3897841498936210886|2|1089|-1"], "bases": [], "derived": [6666242542855173890], "vars": [], @@ -46,8 +46,8 @@ OUTPUT: "short_name": "Root", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -55,7 +55,7 @@ OUTPUT: "funcs": [9948027785633571339], "vars": [], "instances": [], - "uses": ["4:24-4:28|10963370434658308541|2|2052"] + "uses": ["4:24-4:28|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public Root {}", @@ -63,8 +63,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "4:7-4:14|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:7-4:14|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [], diff --git a/index_tests/inheritance/interface_pure_virtual.cc b/index_tests/inheritance/interface_pure_virtual.cc index d002b0bd..58ee1d4f 100644 --- a/index_tests/inheritance/interface_pure_virtual.cc +++ b/index_tests/inheritance/interface_pure_virtual.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:16-2:19|9949214233977131946|2|1089"], + "declarations": ["2:16-2:19|2:3-2:25|9949214233977131946|2|1089|-1"], "bases": [], "derived": [], "vars": [], @@ -28,8 +28,8 @@ OUTPUT: "short_name": "IFoo", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/inheritance/multiple_base_functions.cc b/index_tests/inheritance/multiple_base_functions.cc index dcc0e781..11719475 100644 --- a/index_tests/inheritance/multiple_base_functions.cc +++ b/index_tests/inheritance/multiple_base_functions.cc @@ -21,8 +21,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "5:11-5:12|15826803741381445676|2|1090", - "extent": "5:3-5:23|15826803741381445676|2|0", + "spell": "5:11-5:12|15826803741381445676|2|1090|-1", + "extent": "5:3-5:23|15826803741381445676|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -36,8 +36,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "8:3-8:4|10963370434658308541|2|5186", - "extent": "8:3-8:26|10963370434658308541|2|0", + "spell": "8:3-8:4|10963370434658308541|2|5186|-1", + "extent": "8:3-8:26|10963370434658308541|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:11-2:12|11628904180681204356|2|1090", - "extent": "2:3-2:23|11628904180681204356|2|0", + "spell": "2:11-2:12|11628904180681204356|2|1090|-1", + "extent": "2:3-2:23|11628904180681204356|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -66,8 +66,8 @@ OUTPUT: "short_name": "Derived", "kind": 23, "declarations": [], - "spell": "7:8-7:15|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:8-7:15|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "alias_of": 0, "bases": [11628904180681204356, 15826803741381445676], "derived": [], @@ -75,7 +75,7 @@ OUTPUT: "funcs": [13164726294460837993], "vars": [], "instances": [], - "uses": ["8:4-8:11|10963370434658308541|2|4"] + "uses": ["8:4-8:11|10963370434658308541|2|4|-1"] }, { "usr": 11628904180681204356, "detailed_name": "struct Base0 {}", @@ -83,8 +83,8 @@ OUTPUT: "short_name": "Base0", "kind": 23, "declarations": [], - "spell": "1:8-1:13|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:13|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -92,7 +92,7 @@ OUTPUT: "funcs": [16347272523198263017], "vars": [], "instances": [], - "uses": ["2:12-2:17|11628904180681204356|2|4", "7:18-7:23|10963370434658308541|2|2052"] + "uses": ["2:12-2:17|11628904180681204356|2|4|-1", "7:18-7:23|10963370434658308541|2|2052|-1"] }, { "usr": 15826803741381445676, "detailed_name": "struct Base1 {}", @@ -100,8 +100,8 @@ OUTPUT: "short_name": "Base1", "kind": 23, "declarations": [], - "spell": "4:8-4:13|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:13|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -109,7 +109,7 @@ OUTPUT: "funcs": [8401779086123965305], "vars": [], "instances": [], - "uses": ["5:12-5:17|15826803741381445676|2|4", "7:25-7:30|10963370434658308541|2|2052"] + "uses": ["5:12-5:17|15826803741381445676|2|4|-1", "7:25-7:30|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/lambdas/lambda.cc b/index_tests/lambdas/lambda.cc index 357d6e32..2f5371f9 100644 --- a/index_tests/lambdas/lambda.cc +++ b/index_tests/lambdas/lambda.cc @@ -24,8 +24,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-12:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-12:2|0|1|0|-1", "bases": [], "derived": [], "vars": [12666114896600231317, 2981279427664991319], @@ -42,7 +42,7 @@ OUTPUT: "bases": [], "derived": [], "vars": [], - "uses": ["9:14-9:15|4259594751088586730|3|16420", "10:14-10:15|4259594751088586730|3|16420", "11:14-11:15|4259594751088586730|3|16420"], + "uses": ["9:14-9:15|4259594751088586730|3|16420|-1", "10:14-10:15|4259594751088586730|3|16420|-1", "11:14-11:15|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -67,8 +67,8 @@ OUTPUT: "short_name": "", "kind": 26, "declarations": [], - "spell": "4:22-4:23|4259594751088586730|3|2", - "extent": "4:22-4:23|4259594751088586730|3|0", + "spell": "4:22-4:23|4259594751088586730|3|2|-1", + "extent": "4:22-4:23|4259594751088586730|3|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -85,10 +85,10 @@ OUTPUT: "short_name": "dosomething", "hover": "(lambda) dosomething", "declarations": [], - "spell": "4:8-4:19|4259594751088586730|3|2", - "extent": "4:3-7:4|4259594751088586730|3|0", + "spell": "4:8-4:19|4259594751088586730|3|2|-1", + "extent": "4:3-7:4|4259594751088586730|3|0|-1", "type": 14635009347499519042, - "uses": ["9:3-9:14|4259594751088586730|3|4", "10:3-10:14|4259594751088586730|3|4", "11:3-11:14|4259594751088586730|3|4"], + "uses": ["9:3-9:14|4259594751088586730|3|4|-1", "10:3-10:14|4259594751088586730|3|4|-1", "11:3-11:14|4259594751088586730|3|4|-1"], "kind": 13, "storage": 0 }, { @@ -97,10 +97,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["4:24-4:25|4259594751088586730|3|4", "5:7-5:8|4259594751088586730|3|28"], + "uses": ["4:24-4:25|4259594751088586730|3|4|-1", "5:7-5:8|4259594751088586730|3|28|-1"], "kind": 13, "storage": 0 }, { @@ -109,10 +109,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "y", "declarations": [], - "spell": "4:31-4:32|17926497908620168464|3|2", - "extent": "4:27-4:32|4259594751088586730|3|0", + "spell": "4:31-4:32|17926497908620168464|3|2|-1", + "extent": "4:27-4:32|4259594751088586730|3|0|-1", "type": 0, - "uses": ["6:7-6:8|4259594751088586730|3|28"], + "uses": ["6:7-6:8|4259594751088586730|3|28|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/macros/complex.cc b/index_tests/macros/complex.cc index a74be500..b88c3eaa 100644 --- a/index_tests/macros/complex.cc +++ b/index_tests/macros/complex.cc @@ -23,9 +23,9 @@ OUTPUT: "short_name": "a", "kind": 12, "storage": 0, - "declarations": ["12:1-12:20|0|1|1"], - "spell": "12:1-12:20|0|1|2", - "extent": "12:1-12:20|0|1|0", + "declarations": ["12:1-12:20|12:1-12:20|0|1|1|-1"], + "spell": "12:1-12:20|0|1|2|-1", + "extent": "12:1-12:20|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -39,12 +39,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:5-6:10|0|1|2", - "extent": "6:1-8:2|0|1|0", + "spell": "6:5-6:10|0|1|2|-1", + "extent": "6:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["12:5-12:10|9720930732776154610|3|16420", "12:5-12:10|0|1|64|0"], + "uses": ["12:5-12:10|9720930732776154610|3|16420|-1", "12:5-12:10|0|1|64|0"], "callees": [] }], "usr2type": [{ @@ -70,10 +70,10 @@ OUTPUT: "short_name": "make2", "hover": "const int make2 = 5", "declarations": [], - "spell": "9:11-9:16|0|1|2", - "extent": "9:1-9:20|0|1|0", + "spell": "9:11-9:16|0|1|2|-1", + "extent": "9:1-9:20|0|1|0|-1", "type": 53, - "uses": ["12:14-12:19|9720930732776154610|3|12", "12:14-12:19|0|1|64|0"], + "uses": ["12:14-12:19|9720930732776154610|3|12|-1", "12:14-12:19|0|1|64|0"], "kind": 13, "storage": 0 }, { @@ -83,10 +83,10 @@ OUTPUT: "short_name": "FOO", "hover": "#define FOO(aaa, bbb) \\\n int a();\\\n int a() { return aaa + bbb; }", "declarations": [], - "spell": "1:9-1:12|0|1|2", - "extent": "1:9-3:32|0|1|0", + "spell": "1:9-1:12|0|1|2|-1", + "extent": "1:9-3:32|0|1|0|-1", "type": 0, - "uses": ["12:1-12:4|0|1|64"], + "uses": ["12:1-12:4|0|1|64|-1"], "kind": 255, "storage": 0 }] diff --git a/index_tests/macros/foo.cc b/index_tests/macros/foo.cc index 7b7c8b04..156ab237 100644 --- a/index_tests/macros/foo.cc +++ b/index_tests/macros/foo.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "5:12-5:15|15041163540773201510|2|1026", - "extent": "5:12-5:15|15041163540773201510|2|0", + "spell": "5:12-5:15|15041163540773201510|2|1026|-1", + "extent": "5:12-5:15|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -50,8 +50,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [13788753348312146871], "vars": [], "instances": [], - "uses": ["5:12-5:15|15041163540773201510|2|4", "5:12-5:15|0|1|64|0"] + "uses": ["5:12-5:15|15041163540773201510|2|4|-1", "5:12-5:15|0|1|64|0"] }], "usr2var": [{ "usr": 1569772797058982873, @@ -68,10 +68,10 @@ OUTPUT: "short_name": "A", "hover": "#define A 5", "declarations": [], - "spell": "1:9-1:10|0|1|2", - "extent": "1:9-1:12|0|1|0", + "spell": "1:9-1:10|0|1|2|-1", + "extent": "1:9-1:12|0|1|0|-1", "type": 0, - "uses": ["8:9-8:10|0|1|64"], + "uses": ["8:9-8:10|0|1|64|-1"], "kind": 255, "storage": 0 }, { @@ -81,10 +81,10 @@ OUTPUT: "short_name": "DISALLOW", "hover": "#define DISALLOW(type) type(type&&) = delete;", "declarations": [], - "spell": "2:9-2:17|0|1|2", - "extent": "2:9-2:46|0|1|0", + "spell": "2:9-2:17|0|1|2|-1", + "extent": "2:9-2:46|0|1|0|-1", "type": 0, - "uses": ["5:3-5:11|0|1|64"], + "uses": ["5:3-5:11|0|1|64|-1"], "kind": 255, "storage": 0 }, { @@ -94,8 +94,8 @@ OUTPUT: "short_name": "x", "hover": "int x = A", "declarations": [], - "spell": "8:5-8:6|0|1|2", - "extent": "8:1-1:1|0|1|0", + "spell": "8:5-8:6|0|1|2|-1", + "extent": "8:1-1:1|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/method_declaration.cc b/index_tests/method_declaration.cc index 00edb4de..fae12cdc 100644 --- a/index_tests/method_declaration.cc +++ b/index_tests/method_declaration.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], + "declarations": ["2:8-2:11|2:3-2:13|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/method_definition.cc b/index_tests/method_definition.cc index b79e9ba3..895eac04 100644 --- a/index_tests/method_definition.cc +++ b/index_tests/method_definition.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], - "spell": "5:11-5:14|15041163540773201510|2|1026", - "extent": "5:1-5:25|15041163540773201510|2|0", + "declarations": ["2:8-2:11|2:3-2:19|15041163540773201510|2|1025|-1"], + "spell": "5:11-5:14|15041163540773201510|2|1026|-1", + "extent": "5:1-5:25|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,7 +41,7 @@ OUTPUT: "funcs": [6446764306530590711], "vars": [], "instances": [], - "uses": ["5:6-5:9|0|1|4"] + "uses": ["5:6-5:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/method_inline_declaration.cc b/index_tests/method_inline_declaration.cc index 64ced29b..f2294cd0 100644 --- a/index_tests/method_inline_declaration.cc +++ b/index_tests/method_inline_declaration.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:8-2:11|15041163540773201510|2|1026", - "extent": "2:3-2:16|15041163540773201510|2|0", + "spell": "2:8-2:11|15041163540773201510|2|1026|-1", + "extent": "2:3-2:16|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -30,8 +30,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/multi_file/funky_enum.cc b/index_tests/multi_file/funky_enum.cc index 69f5ebdc..784f210d 100644 --- a/index_tests/multi_file/funky_enum.cc +++ b/index_tests/multi_file/funky_enum.cc @@ -35,8 +35,8 @@ OUTPUT: funky_enum.h "hover": "A = 0", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "4:1-4:2|16985894625255407295|2|1026", - "extent": "4:1-4:2|16985894625255407295|2|0", + "spell": "4:1-4:2|16985894625255407295|2|1026|-1", + "extent": "4:1-4:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -49,8 +49,8 @@ OUTPUT: funky_enum.h "hover": "C = 2", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "6:1-6:2|16985894625255407295|2|1026", - "extent": "6:1-6:2|16985894625255407295|2|0", + "spell": "6:1-6:2|16985894625255407295|2|1026|-1", + "extent": "6:1-6:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -63,8 +63,8 @@ OUTPUT: funky_enum.h "hover": "B = 1", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "5:1-5:2|16985894625255407295|2|1026", - "extent": "5:1-5:2|16985894625255407295|2|0", + "spell": "5:1-5:2|16985894625255407295|2|1026|-1", + "extent": "5:1-5:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -86,8 +86,8 @@ OUTPUT: funky_enum.cc "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/multi_file/impl.cc b/index_tests/multi_file/impl.cc index 12a625b3..1ef51a20 100644 --- a/index_tests/multi_file/impl.cc +++ b/index_tests/multi_file/impl.cc @@ -17,8 +17,8 @@ OUTPUT: header.h "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:10|0|1|2", - "extent": "10:1-10:15|0|1|0", + "spell": "10:6-10:10|0|1|2|-1", + "extent": "10:1-10:15|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,8 +47,8 @@ OUTPUT: header.h "short_name": "Foo2", "kind": 23, "declarations": [], - "spell": "13:8-13:12|0|1|2", - "extent": "13:1-13:15|0|1|0", + "spell": "13:8-13:12|0|1|2|-1", + "extent": "13:1-13:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -64,8 +64,8 @@ OUTPUT: header.h "short_name": "Foo0", "kind": 252, "declarations": [], - "spell": "7:7-7:11|0|1|2", - "extent": "7:1-7:29|0|1|0", + "spell": "7:7-7:11|0|1|2|-1", + "extent": "7:1-7:29|0|1|0|-1", "alias_of": 16750616846959666305, "bases": [], "derived": [], @@ -81,8 +81,8 @@ OUTPUT: header.h "short_name": "Foo3", "kind": 10, "declarations": [], - "spell": "15:6-15:10|0|1|2", - "extent": "15:1-15:22|0|1|0", + "spell": "15:6-15:10|0|1|2|-1", + "extent": "15:1-15:22|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,8 +98,8 @@ OUTPUT: header.h "short_name": "Base", "kind": 23, "declarations": [], - "spell": "3:8-3:12|0|1|2", - "extent": "3:1-3:15|0|1|0", + "spell": "3:8-3:12|0|1|2|-1", + "extent": "3:1-3:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [16750616846959666305], @@ -107,7 +107,7 @@ OUTPUT: header.h "funcs": [], "vars": [], "instances": [], - "uses": ["5:26-5:30|16750616846959666305|2|2052"] + "uses": ["5:26-5:30|16750616846959666305|2|2052|-1"] }, { "usr": 16750616846959666305, "detailed_name": "struct SameFileDerived : Base {}", @@ -115,8 +115,8 @@ OUTPUT: header.h "short_name": "SameFileDerived", "kind": 23, "declarations": [], - "spell": "5:8-5:23|0|1|2", - "extent": "5:1-5:33|0|1|0", + "spell": "5:8-5:23|0|1|2|-1", + "extent": "5:1-5:33|0|1|0|-1", "alias_of": 0, "bases": [8420119006782424779], "derived": [], @@ -124,7 +124,7 @@ OUTPUT: header.h "funcs": [], "vars": [], "instances": [], - "uses": ["7:14-7:29|0|1|4"] + "uses": ["7:14-7:29|0|1|4|-1"] }], "usr2var": [{ "usr": 2638219001294786365, @@ -132,8 +132,8 @@ OUTPUT: header.h "qual_name_offset": 4, "short_name": "Foo4", "declarations": [], - "spell": "17:5-17:9|0|1|2", - "extent": "17:1-17:9|0|1|0", + "spell": "17:5-17:9|0|1|2|-1", + "extent": "17:1-17:9|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -145,8 +145,8 @@ OUTPUT: header.h "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "15:13-15:14|4481210672785600703|2|1026", - "extent": "15:13-15:14|4481210672785600703|2|0", + "spell": "15:13-15:14|4481210672785600703|2|1026|-1", + "extent": "15:13-15:14|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -158,8 +158,8 @@ OUTPUT: header.h "short_name": "C", "hover": "C = 2", "declarations": [], - "spell": "15:19-15:20|4481210672785600703|2|1026", - "extent": "15:19-15:20|4481210672785600703|2|0", + "spell": "15:19-15:20|4481210672785600703|2|1026|-1", + "extent": "15:19-15:20|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -170,8 +170,8 @@ OUTPUT: header.h "qual_name_offset": 11, "short_name": "Foo5", "declarations": [], - "spell": "18:12-18:16|0|1|2", - "extent": "18:1-18:16|0|1|0", + "spell": "18:12-18:16|0|1|2|-1", + "extent": "18:1-18:16|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -183,8 +183,8 @@ OUTPUT: header.h "short_name": "B", "hover": "B = 1", "declarations": [], - "spell": "15:16-15:17|4481210672785600703|2|1026", - "extent": "15:16-15:17|4481210672785600703|2|0", + "spell": "15:16-15:17|4481210672785600703|2|1026|-1", + "extent": "15:16-15:17|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -206,8 +206,8 @@ OUTPUT: impl.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -224,7 +224,7 @@ OUTPUT: impl.cc "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:7|5817708529036841195|3|16420"], + "uses": ["4:3-4:7|5817708529036841195|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/multi_file/simple_impl.cc b/index_tests/multi_file/simple_impl.cc index df6d723e..75b57e37 100644 --- a/index_tests/multi_file/simple_impl.cc +++ b/index_tests/multi_file/simple_impl.cc @@ -16,7 +16,7 @@ OUTPUT: simple_header.h "short_name": "header", "kind": 12, "storage": 0, - "declarations": ["3:6-3:12|0|1|1"], + "declarations": ["3:6-3:12|3:1-3:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -41,8 +41,8 @@ OUTPUT: simple_impl.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: simple_impl.cc "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:9|3373269392705484958|3|16420"], + "uses": ["4:3-4:9|3373269392705484958|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/multi_file/static.cc b/index_tests/multi_file/static.cc index 7b255c5d..7f8d6c72 100644 --- a/index_tests/multi_file/static.cc +++ b/index_tests/multi_file/static.cc @@ -14,7 +14,7 @@ OUTPUT: static.h "short_name": "CreateSharedBuffer", "kind": 254, "storage": 0, - "declarations": ["4:15-4:33|9411323049603567600|2|1025"], + "declarations": ["4:15-4:33|4:3-4:35|9411323049603567600|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -28,8 +28,8 @@ OUTPUT: static.h "short_name": "Buffer", "kind": 23, "declarations": [], - "spell": "3:8-3:14|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:14|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -56,8 +56,8 @@ OUTPUT: static.cc "kind": 254, "storage": 0, "declarations": [], - "spell": "3:14-3:32|9411323049603567600|2|1026", - "extent": "3:1-3:37|9411323049603567600|2|0", + "spell": "3:14-3:32|9411323049603567600|2|1026|-1", + "extent": "3:1-3:37|9411323049603567600|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -78,7 +78,7 @@ OUTPUT: static.cc "funcs": [14576076421851654759], "vars": [], "instances": [], - "uses": ["3:6-3:12|0|1|4"] + "uses": ["3:6-3:12|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/namespaces/anonymous_function.cc b/index_tests/namespaces/anonymous_function.cc index eb89d959..89d660a7 100644 --- a/index_tests/namespaces/anonymous_function.cc +++ b/index_tests/namespaces/anonymous_function.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["2:6-2:9|7144845543074395457|2|1"], + "declarations": ["2:6-2:9|2:1-2:11|7144845543074395457|2|1|-1"], "bases": [], "derived": [], "vars": [], diff --git a/index_tests/namespaces/function_declaration.cc b/index_tests/namespaces/function_declaration.cc index ec694bc9..9ca5a4d8 100644 --- a/index_tests/namespaces/function_declaration.cc +++ b/index_tests/namespaces/function_declaration.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["2:6-2:9|2029211996748007610|2|1025"], + "declarations": ["2:6-2:9|2:1-2:23|2029211996748007610|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -27,7 +27,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-3:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/function_definition.cc b/index_tests/namespaces/function_definition.cc index ce784555..e732b06e 100644 --- a/index_tests/namespaces/function_definition.cc +++ b/index_tests/namespaces/function_definition.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:9|2029211996748007610|2|1026", - "extent": "2:1-2:14|2029211996748007610|2|0", + "spell": "2:6-2:9|2029211996748007610|2|1026|-1", + "extent": "2:1-2:14|2029211996748007610|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -29,7 +29,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-3:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/method_declaration.cc b/index_tests/namespaces/method_declaration.cc index de02f813..b957b1d5 100644 --- a/index_tests/namespaces/method_declaration.cc +++ b/index_tests/namespaces/method_declaration.cc @@ -16,7 +16,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|4508214972876735896|2|1025"], + "declarations": ["3:8-3:11|3:3-3:13|4508214972876735896|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -29,7 +29,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-5:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -45,8 +45,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/method_definition.cc b/index_tests/namespaces/method_definition.cc index 5a25f7a9..00f55200 100644 --- a/index_tests/namespaces/method_definition.cc +++ b/index_tests/namespaces/method_definition.cc @@ -18,9 +18,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|4508214972876735896|2|1025"], - "spell": "6:11-6:14|4508214972876735896|2|1026", - "extent": "6:1-6:19|4508214972876735896|2|0", + "declarations": ["3:8-3:11|3:3-3:13|4508214972876735896|2|1025|-1"], + "spell": "6:11-6:14|4508214972876735896|2|1026|-1", + "extent": "6:1-6:19|4508214972876735896|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -33,7 +33,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -49,8 +49,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -58,7 +58,7 @@ OUTPUT: "funcs": [10487325150128053272], "vars": [], "instances": [], - "uses": ["6:6-6:9|2029211996748007610|2|4"] + "uses": ["6:6-6:9|2029211996748007610|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/namespaces/method_inline_declaration.cc b/index_tests/namespaces/method_inline_declaration.cc index b4029c5f..4d048be1 100644 --- a/index_tests/namespaces/method_inline_declaration.cc +++ b/index_tests/namespaces/method_inline_declaration.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "3:8-3:11|4508214972876735896|2|1026", - "extent": "3:3-3:16|4508214972876735896|2|0", + "spell": "3:8-3:11|4508214972876735896|2|1026|-1", + "extent": "3:3-3:16|4508214972876735896|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-5:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -47,8 +47,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/namespace_alias.cc b/index_tests/namespaces/namespace_alias.cc index 314890b8..b8cbce9c 100644 --- a/index_tests/namespaces/namespace_alias.cc +++ b/index_tests/namespaces/namespace_alias.cc @@ -26,8 +26,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "11:6-11:10|0|1|2", - "extent": "11:1-14:2|0|1|0", + "spell": "11:6-11:10|0|1|2|-1", + "extent": "11:1-14:2|0|1|0|-1", "bases": [], "derived": [], "vars": [6030927277961448585, 7657277353101371136], @@ -55,7 +55,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "foo", "kind": 3, - "declarations": ["1:11-1:14|0|1|1"], + "declarations": ["1:11-1:14|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [17805385787823406700], @@ -63,14 +63,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:17-9:20|0|1|4", "12:11-12:14|10818727483146447186|3|4"] + "uses": ["9:17-9:20|0|1|4|-1", "12:11-12:14|10818727483146447186|3|4|-1"] }, { "usr": 11879713791858506216, "detailed_name": "namespace fbz = foo::bar::baz", "qual_name_offset": 10, "short_name": "fbz", "kind": 252, - "declarations": ["9:11-9:14|0|1|1"], + "declarations": ["9:11-9:14|9:1-9:30|0|1|1|-1"], "alias_of": 14450849931009540802, "bases": [], "derived": [], @@ -78,14 +78,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:11-13:14|10818727483146447186|3|4"] + "uses": ["13:11-13:14|10818727483146447186|3|4|-1"] }, { "usr": 14450849931009540802, "detailed_name": "namespace foo::bar::baz {}", "qual_name_offset": 10, "short_name": "baz", "kind": 3, - "declarations": ["3:20-3:23|17805385787823406700|2|1025"], + "declarations": ["3:20-3:23|3:10-5:11|17805385787823406700|2|1025|-1"], "alias_of": 0, "bases": [17805385787823406700], "derived": [], @@ -96,14 +96,14 @@ OUTPUT: "R": -1 }], "instances": [], - "uses": ["9:27-9:30|0|1|4", "12:21-12:24|10818727483146447186|3|4"] + "uses": ["9:27-9:30|0|1|4|-1", "12:21-12:24|10818727483146447186|3|4|-1"] }, { "usr": 17805385787823406700, "detailed_name": "namespace foo::bar {}", "qual_name_offset": 10, "short_name": "bar", "kind": 3, - "declarations": ["2:15-2:18|926793467007732869|2|1025"], + "declarations": ["2:15-2:18|2:5-6:6|926793467007732869|2|1025|-1"], "alias_of": 0, "bases": [926793467007732869], "derived": [14450849931009540802], @@ -111,7 +111,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:22-9:25|0|1|4", "12:16-12:19|10818727483146447186|3|4"] + "uses": ["9:22-9:25|0|1|4|-1", "12:16-12:19|10818727483146447186|3|4|-1"] }], "usr2var": [{ "usr": 6030927277961448585, @@ -120,8 +120,8 @@ OUTPUT: "short_name": "a", "hover": "int a = foo::bar::baz::qux", "declarations": [], - "spell": "12:7-12:8|10818727483146447186|3|2", - "extent": "12:3-12:29|10818727483146447186|3|0", + "spell": "12:7-12:8|10818727483146447186|3|2|-1", + "extent": "12:3-12:29|10818727483146447186|3|0|-1", "type": 53, "uses": [], "kind": 13, @@ -133,8 +133,8 @@ OUTPUT: "short_name": "b", "hover": "int b = fbz::qux", "declarations": [], - "spell": "13:7-13:8|10818727483146447186|3|2", - "extent": "13:3-13:19|10818727483146447186|3|0", + "spell": "13:7-13:8|10818727483146447186|3|2|-1", + "extent": "13:3-13:19|10818727483146447186|3|0|-1", "type": 53, "uses": [], "kind": 13, @@ -146,10 +146,10 @@ OUTPUT: "short_name": "qux", "hover": "int foo::bar::baz::qux = 42", "declarations": [], - "spell": "4:18-4:21|14450849931009540802|2|1026", - "extent": "4:14-4:26|14450849931009540802|2|0", + "spell": "4:18-4:21|14450849931009540802|2|1026|-1", + "extent": "4:14-4:26|14450849931009540802|2|0|-1", "type": 53, - "uses": ["12:26-12:29|10818727483146447186|3|12", "13:16-13:19|10818727483146447186|3|12"], + "uses": ["12:26-12:29|10818727483146447186|3|12|-1", "13:16-13:19|10818727483146447186|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/namespaces/namespace_reference.cc b/index_tests/namespaces/namespace_reference.cc index 09919e03..4565040d 100644 --- a/index_tests/namespaces/namespace_reference.cc +++ b/index_tests/namespaces/namespace_reference.cc @@ -22,8 +22,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:6-6:12|0|1|2", - "extent": "6:1-10:2|0|1|0", + "spell": "6:6-6:12|0|1|2|-1", + "extent": "6:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -37,12 +37,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:8-3:14|11072669167287398027|2|1026", - "extent": "3:3-3:24|11072669167287398027|2|0", + "spell": "3:8-3:14|11072669167287398027|2|1026|-1", + "extent": "3:3-3:24|11072669167287398027|2|0|-1", "bases": [], "derived": [], "vars": [3649375698083002347], - "uses": ["7:7-7:13|631910859630953711|3|16420", "9:3-9:9|631910859630953711|3|16420"], + "uses": ["7:7-7:13|631910859630953711|3|16420|-1", "9:3-9:9|631910859630953711|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -66,7 +66,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-4:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -77,7 +77,7 @@ OUTPUT: "R": -1 }], "instances": [], - "uses": ["7:3-7:5|631910859630953711|3|4", "7:14-7:16|631910859630953711|3|4", "8:19-8:21|631910859630953711|3|4"] + "uses": ["7:3-7:5|631910859630953711|3|4|-1", "7:14-7:16|631910859630953711|3|4|-1", "8:19-8:21|631910859630953711|3|4|-1"] }], "usr2var": [{ "usr": 3649375698083002347, @@ -85,8 +85,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "3:19-3:20|17328473273923617489|3|1026", - "extent": "3:15-3:20|17328473273923617489|3|0", + "spell": "3:19-3:20|17328473273923617489|3|1026|-1", + "extent": "3:15-3:20|17328473273923617489|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -97,10 +97,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "Foo", "declarations": [], - "spell": "2:7-2:10|11072669167287398027|2|1026", - "extent": "2:3-2:10|11072669167287398027|2|0", + "spell": "2:7-2:10|11072669167287398027|2|1026|-1", + "extent": "2:3-2:10|11072669167287398027|2|0|-1", "type": 53, - "uses": ["7:18-7:21|631910859630953711|3|12", "9:10-9:13|631910859630953711|3|12"], + "uses": ["7:18-7:21|631910859630953711|3|12|-1", "9:10-9:13|631910859630953711|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/operators/operator.cc b/index_tests/operators/operator.cc index e05be650..3a569983 100644 --- a/index_tests/operators/operator.cc +++ b/index_tests/operators/operator.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "operator()", "kind": 6, "storage": 0, - "declarations": ["3:8-3:16|15041163540773201510|2|1025"], + "declarations": ["3:8-3:16|3:3-3:24|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: "short_name": "operator()", "kind": 6, "storage": 0, - "declarations": ["4:7-4:15|15041163540773201510|2|1025"], + "declarations": ["4:7-4:15|4:3-4:31|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -45,8 +45,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:8-2:16|15041163540773201510|2|1026", - "extent": "2:3-2:27|15041163540773201510|2|0", + "spell": "2:8-2:16|15041163540773201510|2|1026|-1", + "extent": "2:3-2:27|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: "short_name": "operator+=", "kind": 12, "storage": 0, - "declarations": ["7:6-7:14|0|1|1"], + "declarations": ["7:6-7:14|7:1-7:42|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -73,8 +73,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -82,7 +82,7 @@ OUTPUT: "funcs": [7874436189163837815, 3545323327609582678, 3986818119971932909], "vars": [], "instances": [], - "uses": ["7:1-7:4|0|1|4", "7:25-7:28|0|1|4"] + "uses": ["7:1-7:4|0|1|4|-1", "7:25-7:28|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/outline/static_function_in_type.cc b/index_tests/outline/static_function_in_type.cc index 9826edca..7bf971e6 100644 --- a/index_tests/outline/static_function_in_type.cc +++ b/index_tests/outline/static_function_in_type.cc @@ -18,7 +18,7 @@ OUTPUT: static_function_in_type.h "short_name": "Register", "kind": 254, "storage": 0, - "declarations": ["6:15-6:23|17262466801709381811|2|1025"], + "declarations": ["6:15-6:23|6:3-6:33|17262466801709381811|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: static_function_in_type.h "qual_name_offset": 6, "short_name": "Manager", "kind": 5, - "declarations": ["3:7-3:14|11072669167287398027|2|1025"], + "declarations": ["3:7-3:14|3:1-3:14|11072669167287398027|2|1025|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -39,14 +39,14 @@ OUTPUT: static_function_in_type.h "funcs": [], "vars": [], "instances": [], - "uses": ["6:24-6:31|17262466801709381811|2|4"] + "uses": ["6:24-6:31|17262466801709381811|2|4|-1"] }, { "usr": 11072669167287398027, "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-9:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -62,8 +62,8 @@ OUTPUT: static_function_in_type.h "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|11072669167287398027|2|1026", - "extent": "5:1-7:2|11072669167287398027|2|0", + "spell": "5:8-5:11|11072669167287398027|2|1026|-1", + "extent": "5:1-7:2|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -91,8 +91,8 @@ OUTPUT: static_function_in_type.cc "storage": 0, "comments": "static", "declarations": [], - "spell": "5:11-5:19|17262466801709381811|2|1026", - "extent": "5:1-6:2|17262466801709381811|2|0", + "spell": "5:11-5:19|17262466801709381811|2|1026|-1", + "extent": "5:1-6:2|17262466801709381811|2|0|-1", "bases": [], "derived": [], "vars": [13569879755236306838], @@ -113,14 +113,14 @@ OUTPUT: static_function_in_type.cc "funcs": [], "vars": [], "instances": [13569879755236306838], - "uses": ["5:20-5:27|11072669167287398027|2|4"] + "uses": ["5:20-5:27|11072669167287398027|2|4|-1"] }, { "usr": 11072669167287398027, "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["3:11-3:13|0|1|1"], + "declarations": ["3:11-3:13|3:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -143,7 +143,7 @@ OUTPUT: static_function_in_type.cc "funcs": [17019747379608639279], "vars": [], "instances": [], - "uses": ["5:6-5:9|11072669167287398027|2|4"] + "uses": ["5:6-5:9|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 13569879755236306838, @@ -151,8 +151,8 @@ OUTPUT: static_function_in_type.cc "qual_name_offset": 13, "short_name": "m", "declarations": [], - "spell": "5:29-5:30|17019747379608639279|3|1026", - "extent": "5:20-5:30|17019747379608639279|3|0", + "spell": "5:29-5:30|17019747379608639279|3|1026|-1", + "extent": "5:20-5:30|17019747379608639279|3|0|-1", "type": 1972401196751872203, "uses": [], "kind": 253, diff --git a/index_tests/preprocessor/include_guard.cc b/index_tests/preprocessor/include_guard.cc index 5b4ef807..d9d069f7 100644 --- a/index_tests/preprocessor/include_guard.cc +++ b/index_tests/preprocessor/include_guard.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "FOO", "hover": "#define FOO", "declarations": [], - "spell": "2:9-2:12|0|1|2", - "extent": "2:9-2:12|0|1|0", + "spell": "2:9-2:12|0|1|2|-1", + "extent": "2:9-2:12|0|1|0|-1", "type": 0, "uses": [], "kind": 255, diff --git a/index_tests/templates/func_specialized_template_param.cc b/index_tests/templates/func_specialized_template_param.cc index 7d5f44be..32222811 100644 --- a/index_tests/templates/func_specialized_template_param.cc +++ b/index_tests/templates/func_specialized_template_param.cc @@ -19,9 +19,9 @@ OUTPUT: "short_name": "Bar", "kind": 6, "storage": 0, - "declarations": ["5:8-5:11|15041163540773201510|2|1025"], - "spell": "8:11-8:14|15041163540773201510|2|1026", - "extent": "8:1-8:36|15041163540773201510|2|0", + "declarations": ["5:8-5:11|5:3-5:30|15041163540773201510|2|1025|-1"], + "spell": "8:11-8:14|15041163540773201510|2|1026|-1", + "extent": "8:1-8:36|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -42,7 +42,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:12-5:20|15041163540773201510|2|4", "8:15-8:23|0|1|4"] + "uses": ["5:12-5:20|15041163540773201510|2|4|-1", "8:15-8:23|0|1|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "struct Foo {}", @@ -50,8 +50,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [8412238651648388423], "vars": [], "instances": [], - "uses": ["8:6-8:9|0|1|4"] + "uses": ["8:6-8:9|0|1|4|-1"] }, { "usr": 17107291254533526269, "detailed_name": "class Template {}", @@ -67,8 +67,8 @@ OUTPUT: "short_name": "Template", "kind": 5, "declarations": [], - "spell": "2:7-2:15|0|1|2", - "extent": "2:1-2:18|0|1|0", + "spell": "2:7-2:15|0|1|2|-1", + "extent": "2:1-2:18|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/templates/implicit_variable_instantiation.cc b/index_tests/templates/implicit_variable_instantiation.cc index 36a97821..6548d39b 100644 --- a/index_tests/templates/implicit_variable_instantiation.cc +++ b/index_tests/templates/implicit_variable_instantiation.cc @@ -42,8 +42,8 @@ OUTPUT: "short_name": "VarType", "kind": 10, "declarations": [], - "spell": "2:8-2:15|11072669167287398027|2|1026", - "extent": "2:3-2:18|11072669167287398027|2|0", + "spell": "2:8-2:15|11072669167287398027|2|1026|-1", + "extent": "2:3-2:18|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -51,14 +51,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [4731849186641714451, 4731849186641714451], - "uses": ["6:22-6:29|12688716854043726585|2|4", "6:44-6:51|12688716854043726585|2|4", "10:18-10:25|11072669167287398027|2|4"] + "uses": ["6:22-6:29|12688716854043726585|2|4|-1", "6:44-6:51|12688716854043726585|2|4|-1", "10:18-10:25|11072669167287398027|2|4|-1"] }, { "usr": 11072669167287398027, "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-15:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -80,8 +80,8 @@ OUTPUT: "short_name": "Holder", "kind": 23, "declarations": [], - "spell": "5:10-5:16|11072669167287398027|2|1026", - "extent": "5:3-7:4|11072669167287398027|2|0", + "spell": "5:10-5:16|11072669167287398027|2|1026|-1", + "extent": "5:3-7:4|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -89,7 +89,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:26-10:32|11072669167287398027|2|4", "13:13-13:19|11072669167287398027|2|4", "14:14-14:20|11072669167287398027|2|4"] + "uses": ["10:26-10:32|11072669167287398027|2|4|-1", "13:13-13:19|11072669167287398027|2|4|-1", "14:14-14:20|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 4731849186641714451, @@ -97,11 +97,11 @@ OUTPUT: "qual_name_offset": 29, "short_name": "static_var", "hover": "static constexpr ns::VarType ns::Holder::static_var = (VarType)0x0", - "declarations": ["6:30-6:40|12688716854043726585|2|1025"], - "spell": "10:37-10:47|12688716854043726585|2|1026", - "extent": "9:3-10:47|12688716854043726585|2|0", + "declarations": ["6:30-6:40|6:5-6:55|12688716854043726585|2|1025|-1"], + "spell": "10:37-10:47|12688716854043726585|2|1026|-1", + "extent": "9:3-10:47|12688716854043726585|2|0|-1", "type": 1532099849728741556, - "uses": ["13:26-13:36|11072669167287398027|2|12", "14:27-14:37|11072669167287398027|2|12"], + "uses": ["13:26-13:36|11072669167287398027|2|12|-1", "14:27-14:37|11072669167287398027|2|12|-1"], "kind": 13, "storage": 2 }, { @@ -111,8 +111,8 @@ OUTPUT: "short_name": "Foo2", "hover": "int ns::Foo2 = Holder::static_var", "declarations": [], - "spell": "14:7-14:11|11072669167287398027|2|1026", - "extent": "14:3-14:37|11072669167287398027|2|0", + "spell": "14:7-14:11|11072669167287398027|2|1026|-1", + "extent": "14:3-14:37|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, @@ -124,8 +124,8 @@ OUTPUT: "short_name": "Foo", "hover": "int ns::Foo = Holder::static_var", "declarations": [], - "spell": "13:7-13:10|11072669167287398027|2|1026", - "extent": "13:3-13:36|11072669167287398027|2|0", + "spell": "13:7-13:10|11072669167287398027|2|1026|-1", + "extent": "13:3-13:36|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/member_ref_in_template.cc b/index_tests/templates/member_ref_in_template.cc index e4b59391..312441e2 100644 --- a/index_tests/templates/member_ref_in_template.cc +++ b/index_tests/templates/member_ref_in_template.cc @@ -33,8 +33,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-8:11|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-8:11|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,7 +47,7 @@ OUTPUT: "short_name": "bar", "kind": 6, "storage": 0, - "declarations": ["4:8-4:11|8402783583255987702|2|1025"], + "declarations": ["4:8-4:11|4:3-4:13|8402783583255987702|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -61,8 +61,8 @@ OUTPUT: "short_name": "C", "kind": 23, "declarations": [], - "spell": "2:8-2:9|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:8-2:9|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -81,8 +81,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "1:17-1:18|8402783583255987702|2|2", - "extent": "1:11-1:18|8402783583255987702|2|0", + "spell": "1:17-1:18|8402783583255987702|2|2|-1", + "extent": "1:11-1:18|8402783583255987702|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,8 +98,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "x", "declarations": [], - "spell": "3:5-3:6|8402783583255987702|2|1026", - "extent": "3:3-3:6|8402783583255987702|2|0", + "spell": "3:5-3:6|8402783583255987702|2|1026|-1", + "extent": "3:3-3:6|8402783583255987702|2|0|-1", "type": 14750650276757822712, "uses": [], "kind": 8, diff --git a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc index d0fb3cb4..a9005f18 100644 --- a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc @@ -24,12 +24,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "5:16-5:19|14042997404480181958|2|1026", - "extent": "5:5-7:6|14042997404480181958|2|0", + "spell": "5:16-5:19|14042997404480181958|2|1026|-1", + "extent": "5:5-7:6|14042997404480181958|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["10:21-10:24|11072669167287398027|2|36", "11:22-11:25|11072669167287398027|2|36"], + "uses": ["10:21-10:24|11072669167287398027|2|36|-1", "11:22-11:25|11072669167287398027|2|36|-1"], "callees": [] }], "usr2type": [{ @@ -53,7 +53,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-12:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -75,8 +75,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "3:10-3:13|11072669167287398027|2|1026", - "extent": "3:3-8:4|11072669167287398027|2|0", + "spell": "3:10-3:13|11072669167287398027|2|1026|-1", + "extent": "3:3-8:4|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -84,7 +84,7 @@ OUTPUT: "funcs": [8221803074608342407], "vars": [], "instances": [], - "uses": ["10:11-10:14|11072669167287398027|2|4", "11:11-11:14|11072669167287398027|2|4"] + "uses": ["10:11-10:14|11072669167287398027|2|4|-1", "11:11-11:14|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 3182917058194750998, @@ -93,8 +93,8 @@ OUTPUT: "short_name": "b", "hover": "int ns::b = Foo::foo()", "declarations": [], - "spell": "11:7-11:8|11072669167287398027|2|1026", - "extent": "11:3-11:35|11072669167287398027|2|0", + "spell": "11:7-11:8|11072669167287398027|2|1026|-1", + "extent": "11:3-11:35|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, @@ -106,8 +106,8 @@ OUTPUT: "short_name": "a", "hover": "int ns::a = Foo::foo()", "declarations": [], - "spell": "10:7-10:8|11072669167287398027|2|1026", - "extent": "10:3-10:33|11072669167287398027|2|0", + "spell": "10:7-10:8|11072669167287398027|2|1026|-1", + "extent": "10:3-10:33|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc index 0476c03a..c7ce4fae 100644 --- a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc @@ -19,8 +19,8 @@ OUTPUT: "short_name": "Foo", "kind": 26, "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2", - "extent": "2:3-3:15|11072669167287398027|2|0", + "spell": "3:9-3:12|11072669167287398027|2|2|-1", + "extent": "2:3-3:15|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -36,8 +36,8 @@ OUTPUT: "short_name": "Foo", "kind": 26, "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2", - "extent": "2:3-3:15|11072669167287398027|2|0", + "spell": "3:9-3:12|11072669167287398027|2|2|-1", + "extent": "2:3-3:15|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,7 +52,7 @@ OUTPUT: "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -74,8 +74,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|1026", - "extent": "3:3-3:15|11072669167287398027|2|0", + "spell": "3:9-3:12|11072669167287398027|2|1026|-1", + "extent": "3:3-3:15|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -83,7 +83,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:3-5:6|11072669167287398027|2|4", "6:3-6:6|11072669167287398027|2|4"] + "uses": ["5:3-5:6|11072669167287398027|2|4|-1", "6:3-6:6|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 3182917058194750998, @@ -91,8 +91,8 @@ OUTPUT: "qual_name_offset": 10, "short_name": "b", "declarations": [], - "spell": "6:13-6:14|11072669167287398027|2|1026", - "extent": "6:3-6:14|11072669167287398027|2|0", + "spell": "6:13-6:14|11072669167287398027|2|1026|-1", + "extent": "6:3-6:14|11072669167287398027|2|0|-1", "type": 3948666349864691553, "uses": [], "kind": 13, @@ -103,8 +103,8 @@ OUTPUT: "qual_name_offset": 9, "short_name": "a", "declarations": [], - "spell": "5:12-5:13|11072669167287398027|2|1026", - "extent": "5:3-5:13|11072669167287398027|2|0", + "spell": "5:12-5:13|11072669167287398027|2|1026|-1", + "extent": "5:3-5:13|11072669167287398027|2|0|-1", "type": 8224244241460152567, "uses": [], "kind": 13, diff --git a/index_tests/templates/specialization.cc b/index_tests/templates/specialization.cc index 7b8960c1..d597a78c 100644 --- a/index_tests/templates/specialization.cc +++ b/index_tests/templates/specialization.cc @@ -54,7 +54,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["43:6-43:9|0|1|1"], + "declarations": ["43:6-43:9|42:1-43:50|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -67,7 +67,7 @@ OUTPUT: "short_name": "clear", "kind": 6, "storage": 0, - "declarations": ["27:8-27:13|1663022413889915338|2|1025"], + "declarations": ["27:8-27:13|27:3-27:15|1663022413889915338|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -81,8 +81,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "39:6-39:9|0|1|2", - "extent": "39:1-39:21|0|1|0", + "spell": "39:6-39:9|0|1|2|-1", + "extent": "39:1-39:21|0|1|0|-1", "bases": [], "derived": [], "vars": [17826688417349629938], @@ -95,7 +95,7 @@ OUTPUT: "short_name": "clear", "kind": 6, "storage": 0, - "declarations": ["13:8-13:13|7440942986741176606|2|1025"], + "declarations": ["13:8-13:13|13:3-13:15|7440942986741176606|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -124,8 +124,8 @@ OUTPUT: "short_name": "function", "kind": 5, "declarations": [], - "spell": "5:7-5:15|0|1|2", - "extent": "4:1-5:30|0|1|0", + "spell": "5:7-5:15|0|1|2|-1", + "extent": "4:1-5:30|0|1|0|-1", "alias_of": 0, "bases": [15019211479263750068], "derived": [], @@ -133,7 +133,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["7:1-7:9|0|1|4"] + "uses": ["7:1-7:9|0|1|4|-1"] }, { "usr": 1663022413889915338, "detailed_name": "template<> class vector> {}", @@ -141,8 +141,8 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "26:7-26:13|0|1|2", - "extent": "25:1-28:2|0|1|0", + "spell": "26:7-26:13|0|1|2|-1", + "extent": "25:1-28:2|0|1|0|-1", "alias_of": 0, "bases": [7440942986741176606], "derived": [], @@ -150,7 +150,7 @@ OUTPUT: "funcs": [6113470698424012876], "vars": [], "instances": [15931696253641284761], - "uses": ["26:7-26:13|0|1|4", "33:1-33:7|0|1|4"] + "uses": ["26:7-26:13|0|1|4|-1", "33:1-33:7|0|1|4|-1"] }, { "usr": 3231449734830406187, "detailed_name": "function", @@ -158,8 +158,8 @@ OUTPUT: "short_name": "function", "kind": 26, "declarations": [], - "spell": "5:7-5:15|0|1|2", - "extent": "4:1-5:30|0|1|0", + "spell": "5:7-5:15|0|1|2|-1", + "extent": "4:1-5:30|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -175,8 +175,8 @@ OUTPUT: "short_name": "Z1", "kind": 23, "declarations": [], - "spell": "19:8-19:10|0|1|2", - "extent": "19:1-19:13|0|1|0", + "spell": "19:8-19:10|0|1|2|-1", + "extent": "19:1-19:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -184,7 +184,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["21:23-21:25|0|1|4", "32:8-32:10|0|1|4"] + "uses": ["21:23-21:25|0|1|4|-1", "32:8-32:10|0|1|4|-1"] }, { "usr": 7440942986741176606, "detailed_name": "class vector {}", @@ -192,8 +192,8 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "12:7-12:13|0|1|2", - "extent": "12:1-14:2|0|1|0", + "spell": "12:7-12:13|0|1|2|-1", + "extent": "12:1-14:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [16155717907537731864, 1663022413889915338], @@ -201,7 +201,7 @@ OUTPUT: "funcs": [18107614608385228556], "vars": [], "instances": [], - "uses": ["21:16-21:22|0|1|4", "30:1-30:7|0|1|4", "32:1-32:7|0|1|4"] + "uses": ["21:16-21:22|0|1|4|-1", "30:1-30:7|0|1|4|-1", "32:1-32:7|0|1|4|-1"] }, { "usr": 9201299975592934124, "detailed_name": "enum Enum {}", @@ -209,8 +209,8 @@ OUTPUT: "short_name": "Enum", "kind": 10, "declarations": [], - "spell": "35:6-35:10|0|1|2", - "extent": "35:1-37:2|0|1|0", + "spell": "35:6-35:10|0|1|2|-1", + "extent": "35:1-37:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -226,8 +226,8 @@ OUTPUT: "short_name": "Z2", "kind": 23, "declarations": [], - "spell": "23:8-23:10|0|1|2", - "extent": "23:1-23:13|0|1|0", + "spell": "23:8-23:10|0|1|2|-1", + "extent": "23:1-23:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -235,7 +235,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["26:14-26:16|0|1|4", "33:8-33:10|0|1|4"] + "uses": ["26:14-26:16|0|1|4|-1", "33:8-33:10|0|1|4|-1"] }, { "usr": 11153492883079050853, "detailed_name": "vector", @@ -243,8 +243,8 @@ OUTPUT: "short_name": "vector", "kind": 26, "declarations": [], - "spell": "17:7-17:13|0|1|2", - "extent": "16:1-17:20|0|1|0", + "spell": "17:7-17:13|0|1|2|-1", + "extent": "16:1-17:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -260,8 +260,8 @@ OUTPUT: "short_name": "vector", "kind": 26, "declarations": [], - "spell": "12:7-12:13|0|1|2", - "extent": "11:1-14:2|0|1|0", + "spell": "12:7-12:13|0|1|2|-1", + "extent": "11:1-14:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -277,8 +277,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "38:20-38:21|17498190318698490707|3|2", - "extent": "38:11-38:21|17498190318698490707|3|0", + "spell": "38:20-38:21|17498190318698490707|3|2|-1", + "extent": "38:11-38:21|17498190318698490707|3|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -293,7 +293,7 @@ OUTPUT: "qual_name_offset": 6, "short_name": "function", "kind": 5, - "declarations": ["2:7-2:15|0|1|1"], + "declarations": ["2:7-2:15|2:1-2:15|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [218068462278884837], @@ -309,8 +309,8 @@ OUTPUT: "short_name": "vector", "kind": 26, "declarations": [], - "spell": "21:16-21:22|0|1|2", - "extent": "21:1-21:26|0|1|0", + "spell": "21:16-21:22|0|1|2|-1", + "extent": "21:1-21:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -325,7 +325,7 @@ OUTPUT: "qual_name_offset": 6, "short_name": "allocator", "kind": 5, - "declarations": ["9:28-9:37|0|1|1"], + "declarations": ["9:28-9:37|9:22-9:37|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -341,8 +341,8 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "17:7-17:13|0|1|2", - "extent": "16:1-17:20|0|1|0", + "spell": "17:7-17:13|0|1|2|-1", + "extent": "16:1-17:20|0|1|0|-1", "alias_of": 0, "bases": [7440942986741176606], "derived": [], @@ -350,7 +350,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["31:1-31:7|0|1|4"] + "uses": ["31:1-31:7|0|1|4|-1"] }], "usr2var": [{ "usr": 86949563628772958, @@ -358,8 +358,8 @@ OUTPUT: "qual_name_offset": 14, "short_name": "vip", "declarations": [], - "spell": "31:14-31:17|0|1|2", - "extent": "31:1-31:17|0|1|0", + "spell": "31:14-31:17|0|1|2|-1", + "extent": "31:1-31:17|0|1|0|-1", "type": 11153492883079050853, "uses": [], "kind": 13, @@ -370,8 +370,8 @@ OUTPUT: "qual_name_offset": 21, "short_name": "f", "declarations": [], - "spell": "7:21-7:22|0|1|2", - "extent": "7:1-7:22|0|1|0", + "spell": "7:21-7:22|0|1|2|-1", + "extent": "7:1-7:22|0|1|0|-1", "type": 3231449734830406187, "uses": [], "kind": 13, @@ -382,8 +382,8 @@ OUTPUT: "qual_name_offset": 11, "short_name": "vz1", "declarations": [], - "spell": "32:12-32:15|0|1|2", - "extent": "32:1-32:15|0|1|0", + "spell": "32:12-32:15|0|1|2|-1", + "extent": "32:1-32:15|0|1|0|-1", "type": 15440970074034693939, "uses": [], "kind": 13, @@ -395,8 +395,8 @@ OUTPUT: "short_name": "Enum1", "hover": "Enum1 = 1", "declarations": [], - "spell": "36:10-36:15|9201299975592934124|2|1026", - "extent": "36:10-36:15|9201299975592934124|2|0", + "spell": "36:10-36:15|9201299975592934124|2|1026|-1", + "extent": "36:10-36:15|9201299975592934124|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -407,8 +407,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "vc", "declarations": [], - "spell": "30:14-30:16|0|1|2", - "extent": "30:1-30:16|0|1|0", + "spell": "30:14-30:16|0|1|2|-1", + "extent": "30:1-30:16|0|1|0|-1", "type": 13322943937025195708, "uses": [], "kind": 13, @@ -420,10 +420,10 @@ OUTPUT: "short_name": "kOnst", "hover": "static const int kOnst = 7", "declarations": [], - "spell": "41:18-41:23|0|1|2", - "extent": "41:1-41:27|0|1|0", + "spell": "41:18-41:23|0|1|2|-1", + "extent": "41:1-41:27|0|1|0|-1", "type": 53, - "uses": ["43:27-43:32|0|1|12"], + "uses": ["43:27-43:32|0|1|12|-1"], "kind": 13, "storage": 2 }, { @@ -433,10 +433,10 @@ OUTPUT: "short_name": "Enum0", "hover": "Enum0 = 0", "declarations": [], - "spell": "36:3-36:8|9201299975592934124|2|1026", - "extent": "36:3-36:8|9201299975592934124|2|0", + "spell": "36:3-36:8|9201299975592934124|2|1026|-1", + "extent": "36:3-36:8|9201299975592934124|2|0|-1", "type": 0, - "uses": ["43:20-43:25|0|1|4"], + "uses": ["43:20-43:25|0|1|4|-1"], "kind": 22, "storage": 0 }, { @@ -445,8 +445,8 @@ OUTPUT: "qual_name_offset": 11, "short_name": "vz2", "declarations": [], - "spell": "33:12-33:15|0|1|2", - "extent": "33:1-33:15|0|1|0", + "spell": "33:12-33:15|0|1|2|-1", + "extent": "33:1-33:15|0|1|0|-1", "type": 1663022413889915338, "uses": [], "kind": 13, @@ -457,8 +457,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "Value", "declarations": [], - "spell": "39:12-39:17|17498190318698490707|3|1026", - "extent": "39:10-39:17|17498190318698490707|3|0", + "spell": "39:12-39:17|17498190318698490707|3|1026|-1", + "extent": "39:10-39:17|17498190318698490707|3|0|-1", "type": 14111105212951082474, "uses": [], "kind": 253, diff --git a/index_tests/templates/specialized_func_definition.cc b/index_tests/templates/specialized_func_definition.cc index 07c0d475..17dfb783 100644 --- a/index_tests/templates/specialized_func_definition.cc +++ b/index_tests/templates/specialized_func_definition.cc @@ -30,8 +30,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "10:22-10:25|17649312483543982122|2|1026", - "extent": "9:1-10:30|17649312483543982122|2|0", + "spell": "10:22-10:25|17649312483543982122|2|1026|-1", + "extent": "9:1-10:30|17649312483543982122|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "Foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|17107291254533526269|2|1025"], - "spell": "7:19-7:22|17107291254533526269|2|1026", - "extent": "6:1-7:24|17107291254533526269|2|0", + "declarations": ["3:8-3:11|3:3-3:13|17107291254533526269|2|1025|-1"], + "spell": "7:19-7:22|17107291254533526269|2|1026|-1", + "extent": "6:1-7:24|17107291254533526269|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -60,8 +60,8 @@ OUTPUT: "short_name": "Template", "kind": 5, "declarations": [], - "spell": "2:7-2:15|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:7-2:15|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,7 +69,7 @@ OUTPUT: "funcs": [11994188353303124840], "vars": [], "instances": [], - "uses": ["7:6-7:14|0|1|4", "10:6-10:14|0|1|4"] + "uses": ["7:6-7:14|0|1|4|-1", "10:6-10:14|0|1|4|-1"] }, { "usr": 17649312483543982122, "detailed_name": "", diff --git a/index_tests/templates/template_class_func_usage_folded_into_one.cc b/index_tests/templates/template_class_func_usage_folded_into_one.cc index 93d12998..2297d996 100644 --- a/index_tests/templates/template_class_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_func_usage_folded_into_one.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "3:14-3:17|10528472276654770367|2|1026", - "extent": "3:3-5:4|10528472276654770367|2|0", + "spell": "3:14-3:17|10528472276654770367|2|1026|-1", + "extent": "3:3-5:4|10528472276654770367|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:19-8:22|0|1|36", "9:20-9:23|0|1|36"], + "uses": ["8:19-8:22|0|1|36|-1", "9:20-9:23|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-6:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [8340731781048851399], "vars": [], "instances": [], - "uses": ["8:9-8:12|0|1|4", "9:9-9:12|0|1|4"] + "uses": ["8:9-8:12|0|1|4|-1", "9:9-9:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -69,8 +69,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::foo()", "declarations": [], - "spell": "9:5-9:6|0|1|2", - "extent": "9:1-9:25|0|1|0", + "spell": "9:5-9:6|0|1|2|-1", + "extent": "9:1-9:25|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -82,8 +82,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::foo()", "declarations": [], - "spell": "8:5-8:6|0|1|2", - "extent": "8:1-8:24|0|1|0", + "spell": "8:5-8:6|0|1|2|-1", + "extent": "8:1-8:24|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_class_template_func_usage_folded_into_one.cc b/index_tests/templates/template_class_template_func_usage_folded_into_one.cc index a38322c3..3fcb3672 100644 --- a/index_tests/templates/template_class_template_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_template_func_usage_folded_into_one.cc @@ -22,12 +22,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "4:14-4:17|10528472276654770367|2|1026", - "extent": "4:3-6:4|10528472276654770367|2|0", + "spell": "4:14-4:17|10528472276654770367|2|1026|-1", + "extent": "4:3-6:4|10528472276654770367|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["9:19-9:22|0|1|36", "10:20-10:23|0|1|36"], + "uses": ["9:19-9:22|0|1|36|-1", "10:20-10:23|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -52,8 +52,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-7:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -61,7 +61,7 @@ OUTPUT: "funcs": [9034026360701857235], "vars": [], "instances": [], - "uses": ["9:9-9:12|0|1|4", "10:9-10:12|0|1|4"] + "uses": ["9:9-9:12|0|1|4|-1", "10:9-10:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -70,8 +70,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::foo()", "declarations": [], - "spell": "10:5-10:6|0|1|2", - "extent": "10:1-10:33|0|1|0", + "spell": "10:5-10:6|0|1|2|-1", + "extent": "10:1-10:33|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -83,8 +83,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::foo()", "declarations": [], - "spell": "9:5-9:6|0|1|2", - "extent": "9:1-9:31|0|1|0", + "spell": "9:5-9:6|0|1|2|-1", + "extent": "9:1-9:31|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_class_type_usage_folded_into_one.cc b/index_tests/templates/template_class_type_usage_folded_into_one.cc index 7115ebc9..e1b1b829 100644 --- a/index_tests/templates/template_class_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_type_usage_folded_into_one.cc @@ -40,8 +40,8 @@ OUTPUT: "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -49,7 +49,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:5-9:6|0|1|4"] + "uses": ["9:5-9:6|0|1|4|-1"] }, { "usr": 7074603899792463171, "detailed_name": "Inner", @@ -57,8 +57,8 @@ OUTPUT: "short_name": "Inner", "kind": 26, "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", + "spell": "6:10-6:15|0|1|2|-1", + "extent": "6:3-6:18|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -74,8 +74,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -83,7 +83,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:1-9:4|0|1|4", "10:1-10:4|0|1|4"] + "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] }, { "usr": 13892793056005362145, "detailed_name": "enum B {}", @@ -91,8 +91,8 @@ OUTPUT: "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -100,7 +100,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:5-10:6|0|1|4"] + "uses": ["10:5-10:6|0|1|4|-1"] }, { "usr": 13938528237873543349, "detailed_name": "struct Foo::Inner {}", @@ -108,8 +108,8 @@ OUTPUT: "short_name": "Inner", "kind": 23, "declarations": [], - "spell": "6:10-6:15|10528472276654770367|2|1026", - "extent": "6:3-6:18|10528472276654770367|2|0", + "spell": "6:10-6:15|10528472276654770367|2|1026|-1", + "extent": "6:3-6:18|10528472276654770367|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -117,7 +117,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:9-9:14|0|1|4", "10:9-10:14|0|1|4"] + "uses": ["9:9-9:14|0|1|4|-1", "10:9-10:14|0|1|4|-1"] }, { "usr": 15961308565836244174, "detailed_name": "Inner", @@ -125,8 +125,8 @@ OUTPUT: "short_name": "Inner", "kind": 26, "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", + "spell": "6:10-6:15|0|1|2|-1", + "extent": "6:3-6:18|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -142,8 +142,8 @@ OUTPUT: "qual_name_offset": 14, "short_name": "b", "declarations": [], - "spell": "10:15-10:16|0|1|2", - "extent": "10:1-10:16|0|1|0", + "spell": "10:15-10:16|0|1|2|-1", + "extent": "10:1-10:16|0|1|0|-1", "type": 15961308565836244174, "uses": [], "kind": 13, @@ -154,8 +154,8 @@ OUTPUT: "qual_name_offset": 14, "short_name": "a", "declarations": [], - "spell": "9:15-9:16|0|1|2", - "extent": "9:1-9:16|0|1|0", + "spell": "9:15-9:16|0|1|2|-1", + "extent": "9:1-9:16|0|1|0|-1", "type": 7074603899792463171, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_class_var_usage_folded_into_one.cc b/index_tests/templates/template_class_var_usage_folded_into_one.cc index fd172671..23d2ed6a 100644 --- a/index_tests/templates/template_class_var_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_var_usage_folded_into_one.cc @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:9-6:12|0|1|4", "7:9-7:12|0|1|4"] + "uses": ["6:9-6:12|0|1|4|-1", "7:9-7:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -52,8 +52,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::var", "declarations": [], - "spell": "7:5-7:6|0|1|2", - "extent": "7:1-7:23|0|1|0", + "spell": "7:5-7:6|0|1|2|-1", + "extent": "7:1-7:23|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -64,9 +64,9 @@ OUTPUT: "qual_name_offset": 21, "short_name": "var", "hover": "static constexpr int Foo::var = 3", - "declarations": ["3:24-3:27|10528472276654770367|2|1025"], + "declarations": ["3:24-3:27|3:3-3:31|10528472276654770367|2|1025|-1"], "type": 53, - "uses": ["6:19-6:22|0|1|12", "7:20-7:23|0|1|12"], + "uses": ["6:19-6:22|0|1|12|-1", "7:20-7:23|0|1|12|-1"], "kind": 13, "storage": 2 }, { @@ -76,8 +76,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::var", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:22|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:22|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_func_usage_folded_into_one.cc b/index_tests/templates/template_func_usage_folded_into_one.cc index 8fccd50a..c9329711 100644 --- a/index_tests/templates/template_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_func_usage_folded_into_one.cc @@ -22,12 +22,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:12-2:15|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:12-2:15|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:9-6:12|0|1|36", "7:9-7:12|0|1|36"], + "uses": ["6:9-6:12|0|1|36|-1", "7:9-7:12|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -53,8 +53,8 @@ OUTPUT: "short_name": "b", "hover": "int b = foo()", "declarations": [], - "spell": "7:5-7:6|0|1|2", - "extent": "7:1-7:20|0|1|0", + "spell": "7:5-7:6|0|1|2|-1", + "extent": "7:1-7:20|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -66,8 +66,8 @@ OUTPUT: "short_name": "a", "hover": "int a = foo()", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:19|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:19|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_type_usage_folded_into_one.cc b/index_tests/templates/template_type_usage_folded_into_one.cc index 0c83f7d8..bb9745e8 100644 --- a/index_tests/templates/template_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_type_usage_folded_into_one.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "Foo", "kind": 26, "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "1:1-2:13|0|1|0", + "spell": "2:7-2:10|0|1|2|-1", + "extent": "1:1-2:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "2:1-2:13|0|1|0", + "spell": "2:7-2:10|0|1|2|-1", + "extent": "2:1-2:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:1-4:4|0|1|4", "5:1-5:4|0|1|4"] + "uses": ["4:1-4:4|0|1|4|-1", "5:1-5:4|0|1|4|-1"] }, { "usr": 14134940367505932005, "detailed_name": "Foo", @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 26, "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "1:1-2:13|0|1|0", + "spell": "2:7-2:10|0|1|2|-1", + "extent": "1:1-2:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -68,8 +68,8 @@ OUTPUT: "qual_name_offset": 10, "short_name": "b", "declarations": [], - "spell": "5:11-5:12|0|1|2", - "extent": "5:1-5:12|0|1|0", + "spell": "5:11-5:12|0|1|2|-1", + "extent": "5:1-5:12|0|1|0|-1", "type": 14134940367505932005, "uses": [], "kind": 13, @@ -80,8 +80,8 @@ OUTPUT: "qual_name_offset": 9, "short_name": "a", "declarations": [], - "spell": "4:10-4:11|0|1|2", - "extent": "4:1-4:11|0|1|0", + "spell": "4:10-4:11|0|1|2|-1", + "extent": "4:1-4:11|0|1|0|-1", "type": 5123806965838456033, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_var_usage_folded_into_one.cc b/index_tests/templates/template_var_usage_folded_into_one.cc index 844baece..44489203 100644 --- a/index_tests/templates/template_var_usage_folded_into_one.cc +++ b/index_tests/templates/template_var_usage_folded_into_one.cc @@ -43,8 +43,8 @@ OUTPUT: "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,7 +52,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [16721564935990383768], - "uses": ["7:1-7:2|0|1|4", "7:11-7:12|0|1|4"] + "uses": ["7:1-7:2|0|1|4|-1", "7:11-7:12|0|1|4|-1"] }, { "usr": 11919899838872947844, "detailed_name": "T", @@ -60,8 +60,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "4:19-4:20|0|1|2", - "extent": "4:10-4:20|0|1|0", + "spell": "4:19-4:20|0|1|2|-1", + "extent": "4:10-4:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -77,8 +77,8 @@ OUTPUT: "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -86,7 +86,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [12028309045033782423], - "uses": ["8:1-8:2|0|1|4", "8:11-8:12|0|1|4"] + "uses": ["8:1-8:2|0|1|4|-1", "8:11-8:12|0|1|4|-1"] }], "usr2var": [{ "usr": 8096973118640070624, @@ -95,10 +95,10 @@ OUTPUT: "short_name": "var", "hover": "T var = T()", "declarations": [], - "spell": "5:3-5:6|0|1|2", - "extent": "5:1-5:12|0|1|0", + "spell": "5:3-5:6|0|1|2|-1", + "extent": "5:1-5:12|0|1|0|-1", "type": 11919899838872947844, - "uses": ["7:7-7:10|0|1|12", "8:7-8:10|0|1|12"], + "uses": ["7:7-7:10|0|1|12|-1", "8:7-8:10|0|1|12|-1"], "kind": 13, "storage": 0 }, { @@ -108,8 +108,8 @@ OUTPUT: "short_name": "b", "hover": "B b = var", "declarations": [], - "spell": "8:3-8:4|0|1|2", - "extent": "8:1-8:13|0|1|0", + "spell": "8:3-8:4|0|1|2|-1", + "extent": "8:1-8:13|0|1|0|-1", "type": 13892793056005362145, "uses": [], "kind": 13, @@ -121,8 +121,8 @@ OUTPUT: "short_name": "a", "hover": "A a = var", "declarations": [], - "spell": "7:3-7:4|0|1|2", - "extent": "7:1-7:13|0|1|0", + "spell": "7:3-7:4|0|1|2|-1", + "extent": "7:1-7:13|0|1|0|-1", "type": 6697181287623958829, "uses": [], "kind": 13, diff --git a/index_tests/types/anonymous_struct.cc b/index_tests/types/anonymous_struct.cc index 8a75ecf9..b3dbecc3 100644 --- a/index_tests/types/anonymous_struct.cc +++ b/index_tests/types/anonymous_struct.cc @@ -31,8 +31,8 @@ OUTPUT: "short_name": "", "kind": 23, "declarations": [], - "spell": "2:3-2:9|17937907487590875128|2|1026", - "extent": "2:3-2:28|17937907487590875128|2|0", + "spell": "2:3-2:9|17937907487590875128|2|1026|-1", + "extent": "2:3-2:28|17937907487590875128|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,8 +57,8 @@ OUTPUT: "short_name": "vector3", "kind": 5, "declarations": [], - "spell": "1:7-1:14|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:14|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -86,8 +86,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "v", "declarations": [], - "spell": "3:9-3:10|17937907487590875128|2|1026", - "extent": "3:3-3:13|17937907487590875128|2|0", + "spell": "3:9-3:10|17937907487590875128|2|1026|-1", + "extent": "3:3-3:13|17937907487590875128|2|0|-1", "type": 0, "uses": [], "kind": 8, @@ -98,8 +98,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "x", "declarations": [], - "spell": "2:18-2:19|1428566502523368801|2|1026", - "extent": "2:12-2:19|1428566502523368801|2|0", + "spell": "2:18-2:19|1428566502523368801|2|1026|-1", + "extent": "2:12-2:19|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, @@ -110,8 +110,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "y", "declarations": [], - "spell": "2:21-2:22|1428566502523368801|2|1026", - "extent": "2:12-2:22|1428566502523368801|2|0", + "spell": "2:21-2:22|1428566502523368801|2|1026|-1", + "extent": "2:12-2:22|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, @@ -122,8 +122,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "z", "declarations": [], - "spell": "2:24-2:25|1428566502523368801|2|1026", - "extent": "2:12-2:25|1428566502523368801|2|0", + "spell": "2:24-2:25|1428566502523368801|2|1026|-1", + "extent": "2:12-2:25|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, diff --git a/index_tests/types/typedefs.cc b/index_tests/types/typedefs.cc index 38505c29..17d3fcbd 100644 --- a/index_tests/types/typedefs.cc +++ b/index_tests/types/typedefs.cc @@ -13,7 +13,7 @@ OUTPUT: "short_name": "g", "kind": 12, "storage": 0, - "declarations": ["2:13-2:14|0|1|1"], + "declarations": ["2:13-2:14|2:1-2:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -27,8 +27,8 @@ OUTPUT: "short_name": "func", "kind": 252, "declarations": [], - "spell": "1:14-1:18|0|1|2", - "extent": "1:1-1:47|0|1|0", + "spell": "1:14-1:18|0|1|2|-1", + "extent": "1:1-1:47|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -36,7 +36,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:8-2:12|0|1|4"] + "uses": ["2:8-2:12|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/unions/union_decl.cc b/index_tests/unions/union_decl.cc index 83b94e90..7861f8ff 100644 --- a/index_tests/unions/union_decl.cc +++ b/index_tests/unions/union_decl.cc @@ -46,8 +46,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,8 +69,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "b", "declarations": [], - "spell": "3:8-3:9|8501689086387244262|2|1026", - "extent": "3:3-3:9|8501689086387244262|2|0", + "spell": "3:8-3:9|8501689086387244262|2|1026|-1", + "extent": "3:3-3:9|8501689086387244262|2|0|-1", "type": 37, "uses": [], "kind": 8, @@ -81,8 +81,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|8501689086387244262|2|1026", - "extent": "2:3-2:8|8501689086387244262|2|0", + "spell": "2:7-2:8|8501689086387244262|2|1026|-1", + "extent": "2:3-2:8|8501689086387244262|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/unions/union_usage.cc b/index_tests/unions/union_usage.cc index 253c4a34..248f5975 100644 --- a/index_tests/unions/union_usage.cc +++ b/index_tests/unions/union_usage.cc @@ -24,8 +24,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-10:2|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -69,8 +69,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -84,7 +84,7 @@ OUTPUT: "R": 0 }], "instances": [2933643612409209903], - "uses": ["6:1-6:4|0|1|4", "8:10-8:13|0|1|4"] + "uses": ["6:1-6:4|0|1|4|-1", "8:10-8:13|0|1|4|-1"] }], "usr2var": [{ "usr": 2933643612409209903, @@ -92,10 +92,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:6|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:6|0|1|0|-1", "type": 8501689086387244262, - "uses": ["9:3-9:4|13982179977217945200|3|4"], + "uses": ["9:3-9:4|13982179977217945200|3|4|-1"], "kind": 13, "storage": 0 }, { @@ -104,8 +104,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "b", "declarations": [], - "spell": "3:8-3:9|8501689086387244262|2|1026", - "extent": "3:3-3:13|8501689086387244262|2|0", + "spell": "3:8-3:9|8501689086387244262|2|1026|-1", + "extent": "3:3-3:13|8501689086387244262|2|0|-1", "type": 37, "uses": [], "kind": 8, @@ -116,10 +116,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|8501689086387244262|2|1026", - "extent": "2:3-2:12|8501689086387244262|2|0", + "spell": "2:7-2:8|8501689086387244262|2|1026|-1", + "extent": "2:3-2:12|8501689086387244262|2|0|-1", "type": 53, - "uses": ["9:5-9:6|13982179977217945200|3|20"], + "uses": ["9:5-9:6|13982179977217945200|3|20|-1"], "kind": 8, "storage": 0 }] diff --git a/index_tests/usage/func_called_from_constructor.cc b/index_tests/usage/func_called_from_constructor.cc index 69269d9e..53c43669 100644 --- a/index_tests/usage/func_called_from_constructor.cc +++ b/index_tests/usage/func_called_from_constructor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:3-8:9|3385168158331140247|3|16420"], + "uses": ["8:3-8:9|3385168158331140247|3|16420|-1"], "callees": [] }, { "usr": 3385168158331140247, @@ -35,9 +35,9 @@ OUTPUT: "short_name": "Foo", "kind": 9, "storage": 0, - "declarations": ["4:3-4:6|15041163540773201510|2|1025"], - "spell": "7:6-7:9|15041163540773201510|2|1026", - "extent": "7:1-9:2|15041163540773201510|2|0", + "declarations": ["4:3-4:6|4:3-4:8|15041163540773201510|2|1025|-1"], + "spell": "7:6-7:9|15041163540773201510|2|1026|-1", + "extent": "7:1-9:2|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "3:8-3:11|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:11|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [3385168158331140247], "vars": [], "instances": [], - "uses": ["4:3-4:6|15041163540773201510|2|4", "7:1-7:4|0|1|4", "7:6-7:9|15041163540773201510|2|4"] + "uses": ["4:3-4:6|15041163540773201510|2|4|-1", "7:1-7:4|0|1|4|-1", "7:6-7:9|15041163540773201510|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/func_called_from_macro_argument.cc b/index_tests/usage/func_called_from_macro_argument.cc index 1312ef95..868db9e8 100644 --- a/index_tests/usage/func_called_from_macro_argument.cc +++ b/index_tests/usage/func_called_from_macro_argument.cc @@ -18,11 +18,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["3:6-3:12|0|1|1"], + "declarations": ["3:6-3:12|3:1-3:28|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:14-6:20|11404881820527069090|3|16420", "6:14-6:20|0|1|64|0"], + "uses": ["6:14-6:20|11404881820527069090|3|16420|-1", "6:14-6:20|0|1|64|0"], "callees": [] }, { "usr": 11404881820527069090, @@ -32,8 +32,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:12|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:12|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -48,10 +48,10 @@ OUTPUT: "short_name": "MACRO_CALL", "hover": "#define MACRO_CALL(e) e", "declarations": [], - "spell": "1:9-1:19|0|1|2", - "extent": "1:9-1:24|0|1|0", + "spell": "1:9-1:19|0|1|2|-1", + "extent": "1:9-1:24|0|1|0|-1", "type": 0, - "uses": ["6:3-6:13|0|1|64"], + "uses": ["6:3-6:13|0|1|64|-1"], "kind": 255, "storage": 0 }] diff --git a/index_tests/usage/func_called_from_template.cc b/index_tests/usage/func_called_from_template.cc index becca51b..0d223bec 100644 --- a/index_tests/usage/func_called_from_template.cc +++ b/index_tests/usage/func_called_from_template.cc @@ -23,11 +23,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["5:3-5:9|10177235824697315808|3|16420"], + "uses": ["5:3-5:9|10177235824697315808|3|16420|-1"], "callees": [] }, { "usr": 2459767597003442547, @@ -50,8 +50,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-10:2|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -65,12 +65,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:12|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:6-4:12|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["9:3-9:9|4259594751088586730|3|16420"], + "uses": ["9:3-9:9|4259594751088586730|3|16420|-1"], "callees": ["5:3-5:9|468307235068920063|3|16420"] }], "usr2type": [], diff --git a/index_tests/usage/func_called_implicit_ctor.cc b/index_tests/usage/func_called_implicit_ctor.cc index 522158bd..63a13f2b 100644 --- a/index_tests/usage/func_called_implicit_ctor.cc +++ b/index_tests/usage/func_called_implicit_ctor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:5-5:11|0|1|2", - "extent": "5:1-5:27|0|1|0", + "spell": "5:5-5:11|0|1|2|-1", + "extent": "5:1-5:27|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:10-8:16|11404881820527069090|3|16420"], + "uses": ["8:10-8:16|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 10544127002917214589, @@ -35,11 +35,11 @@ OUTPUT: "short_name": "Wrapper", "kind": 9, "storage": 0, - "declarations": ["2:3-2:10|13611487872560323389|2|1025"], + "declarations": ["2:3-2:10|2:3-2:17|13611487872560323389|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["8:10-8:16|11404881820527069090|3|16676"], + "uses": ["8:10-8:16|11404881820527069090|3|16676|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -49,8 +49,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:9-7:15|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:9-7:15|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -64,8 +64,8 @@ OUTPUT: "short_name": "Wrapper", "kind": 23, "declarations": [], - "spell": "1:8-1:15|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:15|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -73,7 +73,7 @@ OUTPUT: "funcs": [10544127002917214589], "vars": [], "instances": [], - "uses": ["2:3-2:10|13611487872560323389|2|4", "7:1-7:8|0|1|4"] + "uses": ["2:3-2:10|13611487872560323389|2|4|-1", "7:1-7:8|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/func_usage_addr_func.cc b/index_tests/usage/func_usage_addr_func.cc index 294b6f5e..9d4efdb6 100644 --- a/index_tests/usage/func_usage_addr_func.cc +++ b/index_tests/usage/func_usage_addr_func.cc @@ -20,12 +20,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-3:15|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-3:15|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:18-6:22|9376923949268137283|3|132", "7:12-7:16|9376923949268137283|3|132"], + "uses": ["6:18-6:22|9376923949268137283|3|132|-1", "7:12-7:16|9376923949268137283|3|132|-1"], "callees": [] }, { "usr": 9376923949268137283, @@ -35,8 +35,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16088407831770615719], @@ -50,12 +50,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:13|0|1|2", - "extent": "1:1-1:28|0|1|0", + "spell": "1:6-1:13|0|1|2|-1", + "extent": "1:1-1:28|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["7:3-7:10|9376923949268137283|3|16420"], + "uses": ["7:3-7:10|9376923949268137283|3|16420|-1"], "callees": [] }], "usr2type": [], @@ -66,8 +66,8 @@ OUTPUT: "short_name": "x", "hover": "void (*x)() = &used", "declarations": [], - "spell": "6:10-6:11|9376923949268137283|3|2", - "extent": "6:3-6:22|9376923949268137283|3|0", + "spell": "6:10-6:11|9376923949268137283|3|2|-1", + "extent": "6:3-6:22|9376923949268137283|3|0|-1", "type": 0, "uses": [], "kind": 13, diff --git a/index_tests/usage/func_usage_addr_method.cc b/index_tests/usage/func_usage_addr_method.cc index 3dfdda35..e8242960 100644 --- a/index_tests/usage/func_usage_addr_method.cc +++ b/index_tests/usage/func_usage_addr_method.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [4636142131003982569], @@ -34,11 +34,11 @@ OUTPUT: "short_name": "Used", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:18-6:22|9376923949268137283|3|132"], + "uses": ["6:18-6:22|9376923949268137283|3|132|-1"], "callees": [] }], "usr2type": [{ @@ -48,8 +48,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,7 +57,7 @@ OUTPUT: "funcs": [18417145003926999463], "vars": [], "instances": [], - "uses": ["6:13-6:16|9376923949268137283|3|4"] + "uses": ["6:13-6:16|9376923949268137283|3|4|-1"] }], "usr2var": [{ "usr": 4636142131003982569, @@ -66,8 +66,8 @@ OUTPUT: "short_name": "x", "hover": "void (Foo::*)() x = &Foo::Used", "declarations": [], - "spell": "6:8-6:9|9376923949268137283|3|2", - "extent": "6:3-6:22|9376923949268137283|3|0", + "spell": "6:8-6:9|9376923949268137283|3|2|-1", + "extent": "6:3-6:22|9376923949268137283|3|0|-1", "type": 0, "uses": [], "kind": 13, diff --git a/index_tests/usage/func_usage_call_func.cc b/index_tests/usage/func_usage_call_func.cc index b6d82740..0ec91f0a 100644 --- a/index_tests/usage/func_usage_call_func.cc +++ b/index_tests/usage/func_usage_call_func.cc @@ -16,12 +16,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["3:3-3:9|11404881820527069090|3|16420"], + "uses": ["3:3-3:9|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -31,8 +31,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:12|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:6-2:12|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/usage/func_usage_call_method.cc b/index_tests/usage/func_usage_call_method.cc index e16be451..726f13fd 100644 --- a/index_tests/usage/func_usage_call_method.cc +++ b/index_tests/usage/func_usage_call_method.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14045150712868309451], @@ -34,11 +34,11 @@ OUTPUT: "short_name": "Used", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["7:6-7:10|9376923949268137283|3|16420"], + "uses": ["7:6-7:10|9376923949268137283|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -48,8 +48,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,7 +57,7 @@ OUTPUT: "funcs": [18417145003926999463], "vars": [], "instances": [14045150712868309451], - "uses": ["6:3-6:6|9376923949268137283|3|4"] + "uses": ["6:3-6:6|9376923949268137283|3|4|-1"] }], "usr2var": [{ "usr": 14045150712868309451, @@ -66,10 +66,10 @@ OUTPUT: "short_name": "f", "hover": "Foo *f = nullptr", "declarations": [], - "spell": "6:8-6:9|9376923949268137283|3|2", - "extent": "6:3-6:19|9376923949268137283|3|0", + "spell": "6:8-6:9|9376923949268137283|3|2|-1", + "extent": "6:3-6:19|9376923949268137283|3|0|-1", "type": 15041163540773201510, - "uses": ["7:3-7:4|9376923949268137283|3|12"], + "uses": ["7:3-7:4|9376923949268137283|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/func_usage_class_inline_var_def.cc b/index_tests/usage/func_usage_class_inline_var_def.cc index 41392385..6872016b 100644 --- a/index_tests/usage/func_usage_class_inline_var_def.cc +++ b/index_tests/usage/func_usage_class_inline_var_def.cc @@ -19,12 +19,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:12-1:18|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:12-1:18|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:11-6:17|15041163540773201510|2|36"], + "uses": ["6:11-6:17|15041163540773201510|2|36|-1"], "callees": [] }], "usr2type": [{ @@ -49,8 +49,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "5:7-5:10|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:7-5:10|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -70,8 +70,8 @@ OUTPUT: "short_name": "x", "hover": "int Foo::x = helper()", "declarations": [], - "spell": "6:7-6:8|15041163540773201510|2|1026", - "extent": "6:3-6:19|15041163540773201510|2|0", + "spell": "6:7-6:8|15041163540773201510|2|1026|-1", + "extent": "6:3-6:19|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/usage/func_usage_forward_decl_func.cc b/index_tests/usage/func_usage_forward_decl_func.cc index 775595fd..1e7cef98 100644 --- a/index_tests/usage/func_usage_forward_decl_func.cc +++ b/index_tests/usage/func_usage_forward_decl_func.cc @@ -15,11 +15,11 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:6|6767773193109753523|3|16420"], + "uses": ["4:3-4:6|6767773193109753523|3|16420|-1"], "callees": [] }, { "usr": 6767773193109753523, @@ -29,8 +29,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:11|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:11|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/usage/func_usage_forward_decl_method.cc b/index_tests/usage/func_usage_forward_decl_method.cc index d27dadec..9fdfb1ed 100644 --- a/index_tests/usage/func_usage_forward_decl_method.cc +++ b/index_tests/usage/func_usage_forward_decl_method.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:11|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:11|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16229832321010999607], @@ -33,11 +33,11 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], + "declarations": ["2:8-2:11|2:3-2:13|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["7:6-7:9|6767773193109753523|3|16420"], + "uses": ["7:6-7:9|6767773193109753523|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -47,8 +47,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -56,7 +56,7 @@ OUTPUT: "funcs": [17922201480358737771], "vars": [], "instances": [16229832321010999607], - "uses": ["6:3-6:6|6767773193109753523|3|4"] + "uses": ["6:3-6:6|6767773193109753523|3|4|-1"] }], "usr2var": [{ "usr": 16229832321010999607, @@ -65,10 +65,10 @@ OUTPUT: "short_name": "f", "hover": "Foo *f = nullptr", "declarations": [], - "spell": "6:8-6:9|6767773193109753523|3|2", - "extent": "6:3-6:19|6767773193109753523|3|0", + "spell": "6:8-6:9|6767773193109753523|3|2|-1", + "extent": "6:3-6:19|6767773193109753523|3|0|-1", "type": 15041163540773201510, - "uses": ["7:3-7:4|6767773193109753523|3|12"], + "uses": ["7:3-7:4|6767773193109753523|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/func_usage_template_func.cc b/index_tests/usage/func_usage_template_func.cc index 422d5952..72e6e670 100644 --- a/index_tests/usage/func_usage_template_func.cc +++ b/index_tests/usage/func_usage_template_func.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -33,11 +33,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["2:6-2:12|0|1|1"], + "declarations": ["2:6-2:12|2:1-2:15|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["5:3-5:9|4259594751088586730|3|16420", "6:3-6:9|4259594751088586730|3|16420"], + "uses": ["5:3-5:9|4259594751088586730|3|16420|-1", "6:3-6:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/usage/type_usage_as_template_parameter.cc b/index_tests/usage/type_usage_as_template_parameter.cc index 74d2c025..5c4dc824 100644 --- a/index_tests/usage/type_usage_as_template_parameter.cc +++ b/index_tests/usage/type_usage_as_template_parameter.cc @@ -23,8 +23,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "9:16-9:27|0|1|2", - "extent": "9:1-12:2|0|1|0", + "spell": "9:16-9:27|0|1|2|-1", + "extent": "9:1-12:2|0|1|0|-1", "bases": [], "derived": [], "vars": [3364438781074774169], @@ -38,8 +38,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "2:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "2:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -47,7 +47,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:8-6:18|0|1|4", "7:8-7:18|0|1|4", "9:1-9:11|0|1|4", "10:3-10:13|16359708726068806331|3|4"] + "uses": ["6:8-6:18|0|1|4|-1", "7:8-7:18|0|1|4|-1", "9:1-9:11|0|1|4|-1", "10:3-10:13|16359708726068806331|3|4|-1"] }, { "usr": 4186953406371619898, "detailed_name": "unique_ptr", @@ -55,8 +55,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 26, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "1:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -72,8 +72,8 @@ OUTPUT: "short_name": "S", "kind": 23, "declarations": [], - "spell": "4:8-4:9|0|1|2", - "extent": "4:1-4:12|0|1|0", + "spell": "4:8-4:9|0|1|2|-1", + "extent": "4:1-4:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -81,7 +81,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["7:19-7:20|0|1|4", "9:12-9:13|0|1|4", "10:14-10:15|16359708726068806331|3|4"] + "uses": ["7:19-7:20|0|1|4|-1", "9:12-9:13|0|1|4|-1", "10:14-10:15|16359708726068806331|3|4|-1"] }, { "usr": 16848604152578034754, "detailed_name": "unique_ptr", @@ -89,8 +89,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 26, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "1:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -106,8 +106,8 @@ OUTPUT: "qual_name_offset": 15, "short_name": "local", "declarations": [], - "spell": "10:18-10:23|16359708726068806331|3|2", - "extent": "10:3-10:23|16359708726068806331|3|0", + "spell": "10:18-10:23|16359708726068806331|3|2|-1", + "extent": "10:3-10:23|16359708726068806331|3|0|-1", "type": 4186953406371619898, "uses": [], "kind": 13, @@ -118,8 +118,8 @@ OUTPUT: "qual_name_offset": 24, "short_name": "f0", "declarations": [], - "spell": "6:25-6:27|0|1|2", - "extent": "6:1-6:27|0|1|0", + "spell": "6:25-6:27|0|1|2|-1", + "extent": "6:1-6:27|0|1|0|-1", "type": 16848604152578034754, "uses": [], "kind": 13, @@ -130,8 +130,8 @@ OUTPUT: "qual_name_offset": 21, "short_name": "f1", "declarations": [], - "spell": "7:22-7:24|0|1|2", - "extent": "7:1-7:24|0|1|0", + "spell": "7:22-7:24|0|1|2|-1", + "extent": "7:1-7:24|0|1|0|-1", "type": 4186953406371619898, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_as_template_parameter_complex.cc b/index_tests/usage/type_usage_as_template_parameter_complex.cc index 7b5ebc54..0b4e20e0 100644 --- a/index_tests/usage/type_usage_as_template_parameter_complex.cc +++ b/index_tests/usage/type_usage_as_template_parameter_complex.cc @@ -91,8 +91,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "33:37-33:51|0|1|2", - "extent": "33:1-33:92|0|1|0", + "spell": "33:37-33:51|0|1|2|-1", + "extent": "33:1-33:92|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -106,8 +106,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "40:6-40:20|0|1|2", - "extent": "40:1-40:28|0|1|0", + "spell": "40:6-40:20|0|1|2|-1", + "extent": "40:1-40:28|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -120,9 +120,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["65:23-65:26|15041163540773201510|2|1025"], - "spell": "79:26-79:29|15041163540773201510|2|1026", - "extent": "79:1-79:51|15041163540773201510|2|0", + "declarations": ["65:23-65:26|65:3-65:28|15041163540773201510|2|1025|-1"], + "spell": "79:26-79:29|15041163540773201510|2|1026|-1", + "extent": "79:1-79:51|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -136,8 +136,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "53:6-53:11|0|1|2", - "extent": "53:1-55:2|0|1|0", + "spell": "53:6-53:11|0|1|2|-1", + "extent": "53:1-55:2|0|1|0|-1", "bases": [], "derived": [], "vars": [500112618220246], @@ -150,7 +150,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "S1", "kind": 23, - "declarations": ["4:8-4:10|0|1|1"], + "declarations": ["4:8-4:10|4:1-4:10|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -158,7 +158,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["15:30-15:32|0|1|4", "33:23-33:25|0|1|4", "33:63-33:65|0|1|4", "54:25-54:27|18320186404467436976|3|4", "65:14-65:16|15041163540773201510|2|4", "79:12-79:14|0|1|4"] + "uses": ["15:30-15:32|0|1|4|-1", "33:23-33:25|0|1|4|-1", "33:63-33:65|0|1|4|-1", "54:25-54:27|18320186404467436976|3|4|-1", "65:14-65:16|15041163540773201510|2|4|-1", "79:12-79:14|0|1|4|-1"] }, { "usr": 7147635971744144194, "detailed_name": "template<> class unique_ptr", @@ -173,14 +173,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["15:19-15:29|0|1|4", "33:12-33:22|0|1|4", "33:52-33:62|0|1|4", "54:14-54:24|18320186404467436976|3|4", "65:3-65:13|15041163540773201510|2|4", "79:1-79:11|0|1|4"] + "uses": ["15:19-15:29|0|1|4|-1", "33:12-33:22|0|1|4|-1", "33:52-33:62|0|1|4|-1", "54:14-54:24|18320186404467436976|3|4|-1", "65:3-65:13|15041163540773201510|2|4|-1", "79:1-79:11|0|1|4|-1"] }, { "usr": 12728490517004312484, "detailed_name": "struct S2", "qual_name_offset": 7, "short_name": "S2", "kind": 23, - "declarations": ["5:8-5:10|0|1|1"], + "declarations": ["5:8-5:10|5:1-5:10|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -188,14 +188,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["15:34-15:36|0|1|4", "15:39-15:41|0|1|4", "33:27-33:29|0|1|4", "33:32-33:34|0|1|4", "33:67-33:69|0|1|4", "54:29-54:31|18320186404467436976|3|4", "54:34-54:36|18320186404467436976|3|4", "65:18-65:20|15041163540773201510|2|4", "79:16-79:18|0|1|4"] + "uses": ["15:34-15:36|0|1|4|-1", "15:39-15:41|0|1|4|-1", "33:27-33:29|0|1|4|-1", "33:32-33:34|0|1|4|-1", "33:67-33:69|0|1|4|-1", "54:29-54:31|18320186404467436976|3|4|-1", "54:34-54:36|18320186404467436976|3|4|-1", "65:18-65:20|15041163540773201510|2|4|-1", "79:16-79:18|0|1|4|-1"] }, { "usr": 14209198335088845323, "detailed_name": "class unique_ptr", "qual_name_offset": 6, "short_name": "unique_ptr", "kind": 5, - "declarations": ["2:7-2:17|0|1|1"], + "declarations": ["2:7-2:17|2:1-2:17|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -211,8 +211,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "64:7-64:10|0|1|2", - "extent": "64:1-66:2|0|1|0", + "spell": "64:7-64:10|0|1|2|-1", + "extent": "64:1-66:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -220,7 +220,7 @@ OUTPUT: "funcs": [17922201480358737771], "vars": [], "instances": [], - "uses": ["79:21-79:24|0|1|4"] + "uses": ["79:21-79:24|0|1|4|-1"] }, { "usr": 18153735331422331128, "detailed_name": "unique_ptr", @@ -228,8 +228,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:17|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "1:1-2:17|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -237,7 +237,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [2933643612409209903, 500112618220246], - "uses": ["15:8-15:18|0|1|4", "33:1-33:11|0|1|4", "54:3-54:13|18320186404467436976|3|4"] + "uses": ["15:8-15:18|0|1|4|-1", "33:1-33:11|0|1|4|-1", "54:3-54:13|18320186404467436976|3|4|-1"] }], "usr2var": [{ "usr": 500112618220246, @@ -245,8 +245,8 @@ OUTPUT: "qual_name_offset": 36, "short_name": "local", "declarations": [], - "spell": "54:39-54:44|18320186404467436976|3|2", - "extent": "54:3-54:44|18320186404467436976|3|0", + "spell": "54:39-54:44|18320186404467436976|3|2|-1", + "extent": "54:3-54:44|18320186404467436976|3|0|-1", "type": 18153735331422331128, "uses": [], "kind": 13, @@ -256,7 +256,7 @@ OUTPUT: "detailed_name": "extern unique_ptr, S2> f", "qual_name_offset": 42, "short_name": "f", - "declarations": ["15:43-15:44|0|1|1"], + "declarations": ["15:43-15:44|15:1-15:44|0|1|1|-1"], "type": 18153735331422331128, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_as_template_parameter_simple.cc b/index_tests/usage/type_usage_as_template_parameter_simple.cc index 1b904ef7..1893c26e 100644 --- a/index_tests/usage/type_usage_as_template_parameter_simple.cc +++ b/index_tests/usage/type_usage_as_template_parameter_simple.cc @@ -18,8 +18,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "2:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "2:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -27,7 +27,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:8-6:18|0|1|4"] + "uses": ["6:8-6:18|0|1|4|-1"] }, { "usr": 4186953406371619898, "detailed_name": "unique_ptr", @@ -35,8 +35,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 26, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "1:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -51,7 +51,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "S", "kind": 23, - "declarations": ["4:8-4:9|0|1|1"], + "declarations": ["4:8-4:9|4:1-4:9|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:19-6:20|0|1|4"] + "uses": ["6:19-6:20|0|1|4|-1"] }], "usr2var": [{ "usr": 3398408600781120939, @@ -67,8 +67,8 @@ OUTPUT: "qual_name_offset": 21, "short_name": "foo", "declarations": [], - "spell": "6:22-6:25|0|1|2", - "extent": "6:1-6:25|0|1|0", + "spell": "6:22-6:25|0|1|2|-1", + "extent": "6:1-6:25|0|1|0|-1", "type": 4186953406371619898, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_declare_extern.cc b/index_tests/usage/type_usage_declare_extern.cc index 2fd67216..4d09cd85 100644 --- a/index_tests/usage/type_usage_declare_extern.cc +++ b/index_tests/usage/type_usage_declare_extern.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "T", "kind": 23, "declarations": [], - "spell": "1:8-1:9|0|1|2", - "extent": "1:1-1:12|0|1|0", + "spell": "1:8-1:9|0|1|2|-1", + "extent": "1:1-1:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -23,14 +23,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [1346710425945444872], - "uses": ["3:8-3:9|0|1|4"] + "uses": ["3:8-3:9|0|1|4|-1"] }], "usr2var": [{ "usr": 1346710425945444872, "detailed_name": "extern T t", "qual_name_offset": 9, "short_name": "t", - "declarations": ["3:10-3:11|0|1|1"], + "declarations": ["3:10-3:11|3:1-3:11|0|1|1|-1"], "type": 5673439900521455039, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_declare_field.cc b/index_tests/usage/type_usage_declare_field.cc index 114d6a86..09cae9e5 100644 --- a/index_tests/usage/type_usage_declare_field.cc +++ b/index_tests/usage/type_usage_declare_field.cc @@ -19,8 +19,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -28,14 +28,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [14727441168849658842], - "uses": ["6:3-6:18|15041163540773201510|2|4"] + "uses": ["6:3-6:18|15041163540773201510|2|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [14314859014962085433], - "uses": ["5:3-5:14|15041163540773201510|2|4"] + "uses": ["5:3-5:14|15041163540773201510|2|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "struct Foo {}", @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -74,8 +74,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "a", "declarations": [], - "spell": "5:16-5:17|15041163540773201510|2|1026", - "extent": "5:3-5:17|15041163540773201510|2|0", + "spell": "5:16-5:17|15041163540773201510|2|1026|-1", + "extent": "5:3-5:17|15041163540773201510|2|0|-1", "type": 13749354388332789217, "uses": [], "kind": 8, @@ -86,8 +86,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "b", "declarations": [], - "spell": "6:19-6:20|15041163540773201510|2|1026", - "extent": "6:3-6:20|15041163540773201510|2|0", + "spell": "6:19-6:20|15041163540773201510|2|1026|-1", + "extent": "6:3-6:20|15041163540773201510|2|0|-1", "type": 8508299082070213750, "uses": [], "kind": 8, diff --git a/index_tests/usage/type_usage_declare_local.cc b/index_tests/usage/type_usage_declare_local.cc index 0b037bc5..39fd917d 100644 --- a/index_tests/usage/type_usage_declare_local.cc +++ b/index_tests/usage/type_usage_declare_local.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16374832544037266261, 2580122838476012357], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,14 +43,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [2580122838476012357], - "uses": ["6:3-6:18|4654328188330986029|3|4"] + "uses": ["6:3-6:18|4654328188330986029|3|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -58,7 +58,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [16374832544037266261], - "uses": ["5:3-5:14|4654328188330986029|3|4"] + "uses": ["5:3-5:14|4654328188330986029|3|4|-1"] }], "usr2var": [{ "usr": 2580122838476012357, @@ -66,8 +66,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "b", "declarations": [], - "spell": "6:19-6:20|4654328188330986029|3|2", - "extent": "6:3-6:20|4654328188330986029|3|0", + "spell": "6:19-6:20|4654328188330986029|3|2|-1", + "extent": "6:3-6:20|4654328188330986029|3|0|-1", "type": 8508299082070213750, "uses": [], "kind": 13, @@ -78,8 +78,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "a", "declarations": [], - "spell": "5:16-5:17|4654328188330986029|3|2", - "extent": "5:3-5:17|4654328188330986029|3|0", + "spell": "5:16-5:17|4654328188330986029|3|2|-1", + "extent": "5:3-5:17|4654328188330986029|3|0|-1", "type": 13749354388332789217, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_declare_param.cc b/index_tests/usage/type_usage_declare_param.cc index 4495b5ed..1570ef02 100644 --- a/index_tests/usage/type_usage_declare_param.cc +++ b/index_tests/usage/type_usage_declare_param.cc @@ -16,8 +16,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-4:47|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-4:47|0|1|0|-1", "bases": [], "derived": [], "vars": [13058491096576226774, 11055777568039014776], @@ -31,8 +31,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -40,14 +40,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [11055777568039014776], - "uses": ["4:26-4:41|0|1|4"] + "uses": ["4:26-4:41|0|1|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -55,7 +55,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13058491096576226774], - "uses": ["4:10-4:21|0|1|4"] + "uses": ["4:10-4:21|0|1|4|-1"] }], "usr2var": [{ "usr": 11055777568039014776, @@ -63,8 +63,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "a", "declarations": [], - "spell": "4:42-4:43|1699390678058422036|3|1026", - "extent": "4:26-4:43|1699390678058422036|3|0", + "spell": "4:42-4:43|1699390678058422036|3|1026|-1", + "extent": "4:26-4:43|1699390678058422036|3|0|-1", "type": 8508299082070213750, "uses": [], "kind": 253, @@ -75,8 +75,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "f", "declarations": [], - "spell": "4:23-4:24|1699390678058422036|3|1026", - "extent": "4:10-4:24|1699390678058422036|3|0", + "spell": "4:23-4:24|1699390678058422036|3|1026|-1", + "extent": "4:10-4:24|1699390678058422036|3|0|-1", "type": 13749354388332789217, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_param_prototype.cc b/index_tests/usage/type_usage_declare_param_prototype.cc index cee27557..3f205c9d 100644 --- a/index_tests/usage/type_usage_declare_param_prototype.cc +++ b/index_tests/usage/type_usage_declare_param_prototype.cc @@ -20,9 +20,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["3:6-3:9|0|1|1"], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-4:26|0|1|0", + "declarations": ["3:6-3:9|3:1-3:23|0|1|1|-1"], + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-4:26|0|1|0|-1", "bases": [], "derived": [], "vars": [13823260660189154978], @@ -35,7 +35,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13823260660189154978], - "uses": ["3:10-3:13|0|1|4", "3:18-3:21|0|1|4", "4:10-4:13|0|1|4", "4:18-4:21|0|1|4"] + "uses": ["3:10-3:13|0|1|4|-1", "3:18-3:21|0|1|4|-1", "4:10-4:13|0|1|4|-1", "4:18-4:21|0|1|4|-1"] }], "usr2var": [{ "usr": 13823260660189154978, @@ -51,8 +51,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "f", "declarations": [], - "spell": "4:15-4:16|8908726657907936744|3|1026", - "extent": "4:10-4:16|8908726657907936744|3|0", + "spell": "4:15-4:16|8908726657907936744|3|1026|-1", + "extent": "4:10-4:16|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_param_unnamed.cc b/index_tests/usage/type_usage_declare_param_unnamed.cc index f0cda536..f50fab00 100644 --- a/index_tests/usage/type_usage_declare_param_unnamed.cc +++ b/index_tests/usage/type_usage_declare_param_unnamed.cc @@ -13,8 +13,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:9|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:6-2:9|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -27,7 +27,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -35,7 +35,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:10-2:21|0|1|4"] + "uses": ["2:10-2:21|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_declare_qualifiers.cc b/index_tests/usage/type_usage_declare_qualifiers.cc index 41dfc325..ec1f4d9c 100644 --- a/index_tests/usage/type_usage_declare_qualifiers.cc +++ b/index_tests/usage/type_usage_declare_qualifiers.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-8:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [7997456978847868736, 17228576662112939520, 15429032129697337561, 6081981442495435784, 5004072032239834773, 14939253431683105646], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-1:15|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-1:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [7997456978847868736, 17228576662112939520, 15429032129697337561, 6081981442495435784, 5004072032239834773, 14939253431683105646], - "uses": ["3:10-3:14|0|1|4", "3:26-3:30|0|1|4", "4:3-4:7|16858540520096802573|3|4", "5:3-5:7|16858540520096802573|3|4", "6:9-6:13|16858540520096802573|3|4", "7:9-7:13|16858540520096802573|3|4"] + "uses": ["3:10-3:14|0|1|4|-1", "3:26-3:30|0|1|4|-1", "4:3-4:7|16858540520096802573|3|4|-1", "5:3-5:7|16858540520096802573|3|4|-1", "6:9-6:13|16858540520096802573|3|4|-1", "7:9-7:13|16858540520096802573|3|4|-1"] }], "usr2var": [{ "usr": 5004072032239834773, @@ -51,8 +51,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "a4", "declarations": [], - "spell": "6:15-6:17|16858540520096802573|3|2", - "extent": "6:3-6:17|16858540520096802573|3|0", + "spell": "6:15-6:17|16858540520096802573|3|2|-1", + "extent": "6:3-6:17|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -63,8 +63,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "a3", "declarations": [], - "spell": "5:9-5:11|16858540520096802573|3|2", - "extent": "5:3-5:11|16858540520096802573|3|0", + "spell": "5:9-5:11|16858540520096802573|3|2|-1", + "extent": "5:3-5:11|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -75,8 +75,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "a0", "declarations": [], - "spell": "3:16-3:18|16858540520096802573|3|1026", - "extent": "3:10-3:18|16858540520096802573|3|0", + "spell": "3:16-3:18|16858540520096802573|3|1026|-1", + "extent": "3:10-3:18|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 253, @@ -88,8 +88,8 @@ OUTPUT: "short_name": "a5", "hover": "const Type *const a5 = nullptr", "declarations": [], - "spell": "7:21-7:23|16858540520096802573|3|2", - "extent": "7:3-7:33|16858540520096802573|3|0", + "spell": "7:21-7:23|16858540520096802573|3|2|-1", + "extent": "7:3-7:33|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -100,8 +100,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "a2", "declarations": [], - "spell": "4:8-4:10|16858540520096802573|3|2", - "extent": "4:3-4:10|16858540520096802573|3|0", + "spell": "4:8-4:10|16858540520096802573|3|2|-1", + "extent": "4:3-4:10|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -112,8 +112,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "a1", "declarations": [], - "spell": "3:32-3:34|16858540520096802573|3|1026", - "extent": "3:20-3:34|16858540520096802573|3|0", + "spell": "3:32-3:34|16858540520096802573|3|1026|-1", + "extent": "3:20-3:34|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_static.cc b/index_tests/usage/type_usage_declare_static.cc index 102c156a..ccff19e2 100644 --- a/index_tests/usage/type_usage_declare_static.cc +++ b/index_tests/usage/type_usage_declare_static.cc @@ -13,8 +13,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-1:15|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-1:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -22,7 +22,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [6601831367240627080], - "uses": ["2:8-2:12|0|1|4"] + "uses": ["2:8-2:12|0|1|4|-1"] }], "usr2var": [{ "usr": 6601831367240627080, @@ -30,8 +30,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "t", "declarations": [], - "spell": "2:13-2:14|0|1|2", - "extent": "2:1-2:14|0|1|0", + "spell": "2:13-2:14|0|1|2|-1", + "extent": "2:1-2:14|0|1|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_on_return_type.cc b/index_tests/usage/type_usage_on_return_type.cc index 04e84860..7a07f973 100644 --- a/index_tests/usage/type_usage_on_return_type.cc +++ b/index_tests/usage/type_usage_on_return_type.cc @@ -29,9 +29,9 @@ OUTPUT: "short_name": "Empty", "kind": 6, "storage": 0, - "declarations": ["9:8-9:13|15041163540773201510|2|1025"], - "spell": "13:11-13:16|15041163540773201510|2|1026", - "extent": "13:1-13:21|15041163540773201510|2|0", + "declarations": ["9:8-9:13|9:3-9:15|15041163540773201510|2|1025|-1"], + "spell": "13:11-13:16|15041163540773201510|2|1026|-1", + "extent": "13:1-13:21|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["3:7-3:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "5:7-5:10|0|1|2", - "extent": "5:1-5:32|0|1|0", + "declarations": ["3:7-3:10|3:1-3:12|0|1|1|-1", "4:7-4:10|4:1-4:12|0|1|1|-1"], + "spell": "5:7-5:10|0|1|2|-1", + "extent": "5:1-5:32|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: "short_name": "external", "kind": 12, "storage": 0, - "declarations": ["15:20-15:28|0|1|1"], + "declarations": ["15:20-15:28|15:1-15:30|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -72,9 +72,9 @@ OUTPUT: "short_name": "Get", "kind": 6, "storage": 0, - "declarations": ["8:9-8:12|15041163540773201510|2|1025"], - "spell": "12:12-12:15|15041163540773201510|2|1026", - "extent": "12:1-12:40|15041163540773201510|2|0", + "declarations": ["8:9-8:12|8:3-8:17|15041163540773201510|2|1025|-1"], + "spell": "12:12-12:15|15041163540773201510|2|1026|-1", + "extent": "12:1-12:40|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -87,9 +87,9 @@ OUTPUT: "short_name": "bar", "kind": 12, "storage": 0, - "declarations": ["17:14-17:17|0|1|1"], - "spell": "18:14-18:17|0|1|2", - "extent": "18:1-18:39|0|1|0", + "declarations": ["17:14-17:17|17:1-17:19|0|1|1|-1"], + "spell": "18:14-18:17|0|1|2|-1", + "extent": "18:1-18:39|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -102,7 +102,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Type", "kind": 23, - "declarations": ["1:8-1:12|0|1|1"], + "declarations": ["1:8-1:12|1:1-1:12|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -110,7 +110,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["3:1-3:5|0|1|4", "4:1-4:5|0|1|4", "5:1-5:5|0|1|4", "8:3-8:7|15041163540773201510|2|4", "12:1-12:5|0|1|4", "15:14-15:18|0|1|4", "17:8-17:12|0|1|4", "18:8-18:12|0|1|4"] + "uses": ["3:1-3:5|0|1|4|-1", "4:1-4:5|0|1|4|-1", "5:1-5:5|0|1|4|-1", "8:3-8:7|15041163540773201510|2|4|-1", "12:1-12:5|0|1|4|-1", "15:14-15:18|0|1|4|-1", "17:8-17:12|0|1|4|-1", "18:8-18:12|0|1|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "class Foo {}", @@ -118,8 +118,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "7:7-7:10|0|1|2", - "extent": "7:1-10:2|0|1|0", + "spell": "7:7-7:10|0|1|2|-1", + "extent": "7:1-10:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -127,7 +127,7 @@ OUTPUT: "funcs": [13402221340333431092, 4240751906910175539], "vars": [], "instances": [], - "uses": ["12:7-12:10|0|1|4", "13:6-13:9|0|1|4"] + "uses": ["12:7-12:10|0|1|4|-1", "13:6-13:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_typedef_and_using.cc b/index_tests/usage/type_usage_typedef_and_using.cc index ded74f43..65ca72f3 100644 --- a/index_tests/usage/type_usage_typedef_and_using.cc +++ b/index_tests/usage/type_usage_typedef_and_using.cc @@ -22,8 +22,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:13|0|1|2", - "extent": "8:1-8:23|0|1|0", + "spell": "8:6-8:13|0|1|2|-1", + "extent": "8:1-8:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -37,8 +37,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:12|0|1|2", - "extent": "7:1-7:21|0|1|0", + "spell": "7:6-7:12|0|1|2|-1", + "extent": "7:1-7:21|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -52,8 +52,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "9:6-9:13|0|1|2", - "extent": "9:1-9:23|0|1|0", + "spell": "9:6-9:13|0|1|2|-1", + "extent": "9:1-9:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -67,8 +67,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:13|0|1|2", - "extent": "10:1-10:23|0|1|0", + "spell": "10:6-10:13|0|1|2|-1", + "extent": "10:1-10:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -82,8 +82,8 @@ OUTPUT: "short_name": "Foo1", "kind": 252, "declarations": [], - "spell": "2:7-2:11|0|1|2", - "extent": "2:1-2:18|0|1|0", + "spell": "2:7-2:11|0|1|2|-1", + "extent": "2:1-2:18|0|1|0|-1", "alias_of": 15041163540773201510, "bases": [], "derived": [], @@ -91,7 +91,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:14-4:18|0|1|4", "8:14-8:18|0|1|4"] + "uses": ["4:14-4:18|0|1|4|-1", "8:14-8:18|0|1|4|-1"] }, { "usr": 2638219001294786365, "detailed_name": "using Foo4 = int", @@ -99,8 +99,8 @@ OUTPUT: "short_name": "Foo4", "kind": 252, "declarations": [], - "spell": "5:7-5:11|0|1|2", - "extent": "5:1-5:17|0|1|0", + "spell": "5:7-5:11|0|1|2|-1", + "extent": "5:1-5:17|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -115,7 +115,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -123,7 +123,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:14-2:17|0|1|4", "3:9-3:12|0|1|4", "7:13-7:16|0|1|4"] + "uses": ["2:14-2:17|0|1|4|-1", "3:9-3:12|0|1|4|-1", "7:13-7:16|0|1|4|-1"] }, { "usr": 15466821155413653804, "detailed_name": "typedef Foo Foo2", @@ -131,8 +131,8 @@ OUTPUT: "short_name": "Foo2", "kind": 252, "declarations": [], - "spell": "3:13-3:17|0|1|2", - "extent": "3:1-3:17|0|1|0", + "spell": "3:13-3:17|0|1|2|-1", + "extent": "3:1-3:17|0|1|0|-1", "alias_of": 15041163540773201510, "bases": [], "derived": [], @@ -140,7 +140,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:14-9:18|0|1|4"] + "uses": ["9:14-9:18|0|1|4|-1"] }, { "usr": 17897026942631673064, "detailed_name": "using Foo3 = Foo1", @@ -148,8 +148,8 @@ OUTPUT: "short_name": "Foo3", "kind": 252, "declarations": [], - "spell": "4:7-4:11|0|1|2", - "extent": "4:1-4:18|0|1|0", + "spell": "4:7-4:11|0|1|2|-1", + "extent": "4:1-4:18|0|1|0|-1", "alias_of": 1544499294580512394, "bases": [], "derived": [], @@ -157,7 +157,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:14-10:18|0|1|4"] + "uses": ["10:14-10:18|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_typedef_and_using_template.cc b/index_tests/usage/type_usage_typedef_and_using_template.cc index c9328477..e7043557 100644 --- a/index_tests/usage/type_usage_typedef_and_using_template.cc +++ b/index_tests/usage/type_usage_typedef_and_using_template.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "Foo1", "kind": 252, "declarations": [], - "spell": "4:7-4:11|0|1|2", - "extent": "4:1-4:22|0|1|0", + "spell": "4:7-4:11|0|1|2|-1", + "extent": "4:1-4:22|0|1|0|-1", "alias_of": 5123806965838456033, "bases": [], "derived": [], @@ -26,7 +26,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:13-5:17|0|1|4"] + "uses": ["5:13-5:17|0|1|4|-1"] }, { "usr": 5123806965838456033, "detailed_name": "template<> struct Foo", @@ -41,14 +41,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:14-4:17|0|1|4"] + "uses": ["4:14-4:17|0|1|4|-1"] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo", "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["2:8-2:11|0|1|1"], + "declarations": ["2:8-2:11|2:1-2:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -71,7 +71,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:9-5:12|0|1|4"] + "uses": ["5:9-5:12|0|1|4|-1"] }, { "usr": 15933698173231330933, "detailed_name": "typedef Foo Foo2", @@ -79,8 +79,8 @@ OUTPUT: "short_name": "Foo2", "kind": 252, "declarations": [], - "spell": "5:19-5:23|0|1|2", - "extent": "5:1-5:23|0|1|0", + "spell": "5:19-5:23|0|1|2|-1", + "extent": "5:1-5:23|0|1|0|-1", "alias_of": 14491685842684954828, "bases": [], "derived": [], diff --git a/index_tests/usage/type_usage_various.cc b/index_tests/usage/type_usage_various.cc index fead6f19..5baaf0f8 100644 --- a/index_tests/usage/type_usage_various.cc +++ b/index_tests/usage/type_usage_various.cc @@ -21,9 +21,9 @@ OUTPUT: "short_name": "make", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], - "spell": "5:11-5:15|15041163540773201510|2|1026", - "extent": "5:1-8:2|15041163540773201510|2|0", + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], + "spell": "5:11-5:15|15041163540773201510|2|1026|-1", + "extent": "5:1-8:2|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [16380484338511689669], @@ -37,8 +37,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -46,14 +46,14 @@ OUTPUT: "funcs": [9488177941273031343], "vars": [], "instances": [16380484338511689669, 14455976355866885943], - "uses": ["2:3-2:6|15041163540773201510|2|4", "5:1-5:4|0|1|4", "5:6-5:9|0|1|4", "6:3-6:6|9488177941273031343|3|4", "10:8-10:11|0|1|4"] + "uses": ["2:3-2:6|15041163540773201510|2|4|-1", "5:1-5:4|0|1|4|-1", "5:6-5:9|0|1|4|-1", "6:3-6:6|9488177941273031343|3|4|-1", "10:8-10:11|0|1|4|-1"] }], "usr2var": [{ "usr": 14455976355866885943, "detailed_name": "extern Foo foo", "qual_name_offset": 11, "short_name": "foo", - "declarations": ["10:12-10:15|0|1|1"], + "declarations": ["10:12-10:15|10:1-10:15|0|1|1|-1"], "type": 15041163540773201510, "uses": [], "kind": 13, @@ -64,8 +64,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "6:7-6:8|9488177941273031343|3|2", - "extent": "6:3-6:8|9488177941273031343|3|0", + "spell": "6:7-6:8|9488177941273031343|3|2|-1", + "extent": "6:3-6:8|9488177941273031343|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/usage/usage_inside_of_call.cc b/index_tests/usage/usage_inside_of_call.cc index 036671a4..39ef7456 100644 --- a/index_tests/usage/usage_inside_of_call.cc +++ b/index_tests/usage/usage_inside_of_call.cc @@ -27,8 +27,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "12:6-12:9|0|1|2", - "extent": "12:1-15:2|0|1|0", + "spell": "12:6-12:9|0|1|2|-1", + "extent": "12:1-15:2|0|1|0|-1", "bases": [], "derived": [], "vars": [8039186520399841081], @@ -41,11 +41,11 @@ OUTPUT: "short_name": "gen", "kind": 12, "storage": 0, - "declarations": ["3:5-3:8|0|1|1"], + "declarations": ["3:5-3:8|3:1-3:10|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:14-14:17|4259594751088586730|3|16420"], + "uses": ["14:14-14:17|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 18319417758892371313, @@ -54,11 +54,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:19|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:3-14:9|4259594751088586730|3|16420"], + "uses": ["14:3-14:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -83,8 +83,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -95,7 +95,7 @@ OUTPUT: "R": 0 }], "instances": [], - "uses": ["10:5-10:8|0|1|4", "14:22-14:25|4259594751088586730|3|4", "14:40-14:43|4259594751088586730|3|4"] + "uses": ["10:5-10:8|0|1|4|-1", "14:22-14:25|4259594751088586730|3|4|-1", "14:40-14:43|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 8039186520399841081, @@ -104,10 +104,10 @@ OUTPUT: "short_name": "a", "hover": "int a = 5", "declarations": [], - "spell": "13:7-13:8|4259594751088586730|3|2", - "extent": "13:3-13:12|4259594751088586730|3|0", + "spell": "13:7-13:8|4259594751088586730|3|2|-1", + "extent": "13:3-13:12|4259594751088586730|3|0|-1", "type": 53, - "uses": ["14:10-14:11|4259594751088586730|3|12"], + "uses": ["14:10-14:11|4259594751088586730|3|12|-1"], "kind": 13, "storage": 0 }, { @@ -116,10 +116,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "field_var", "declarations": [], - "spell": "7:7-7:16|15041163540773201510|2|1026", - "extent": "7:3-7:16|15041163540773201510|2|0", + "spell": "7:7-7:16|15041163540773201510|2|1026|-1", + "extent": "7:3-7:16|15041163540773201510|2|0|-1", "type": 53, - "uses": ["14:28-14:37|4259594751088586730|3|12"], + "uses": ["14:28-14:37|4259594751088586730|3|12|-1"], "kind": 8, "storage": 0 }, { @@ -127,11 +127,11 @@ OUTPUT: "detailed_name": "static int Foo::static_var", "qual_name_offset": 11, "short_name": "static_var", - "declarations": ["6:14-6:24|15041163540773201510|2|1025"], - "spell": "10:10-10:20|15041163540773201510|2|1026", - "extent": "10:1-10:24|15041163540773201510|2|0", + "declarations": ["6:14-6:24|6:3-6:24|15041163540773201510|2|1025|-1"], + "spell": "10:10-10:20|15041163540773201510|2|1026|-1", + "extent": "10:1-10:24|15041163540773201510|2|0|-1", "type": 53, - "uses": ["14:45-14:55|4259594751088586730|3|12"], + "uses": ["14:45-14:55|4259594751088586730|3|12|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/usage/usage_inside_of_call_simple.cc b/index_tests/usage/usage_inside_of_call_simple.cc index 9bb67ba9..db2c738e 100644 --- a/index_tests/usage/usage_inside_of_call_simple.cc +++ b/index_tests/usage/usage_inside_of_call_simple.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:9|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:9|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -34,12 +34,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:5-3:8|0|1|2", - "extent": "3:1-3:24|0|1|0", + "spell": "3:5-3:8|0|1|2|-1", + "extent": "3:1-3:24|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:10-6:13|4259594751088586730|3|16420", "6:18-6:21|4259594751088586730|3|16420"], + "uses": ["6:10-6:13|4259594751088586730|3|16420|-1", "6:18-6:21|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 18319417758892371313, @@ -48,11 +48,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:19|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:3-6:9|4259594751088586730|3|16420"], + "uses": ["6:3-6:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/usage/var_usage_call_function.cc b/index_tests/usage/var_usage_call_function.cc index 5ac9d0fa..e28d0954 100644 --- a/index_tests/usage/var_usage_call_function.cc +++ b/index_tests/usage/var_usage_call_function.cc @@ -20,12 +20,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["4:13-4:19|11404881820527069090|3|132", "7:3-7:9|11404881820527069090|3|16420"], + "uses": ["4:13-4:19|11404881820527069090|3|132|-1", "7:3-7:9|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -35,8 +35,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:12|0|1|2", - "extent": "3:1-8:2|0|1|0", + "spell": "3:6-3:12|0|1|2|-1", + "extent": "3:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [9121974011454213596], @@ -51,10 +51,10 @@ OUTPUT: "short_name": "x", "hover": "auto x = &called", "declarations": [], - "spell": "4:8-4:9|11404881820527069090|3|2", - "extent": "4:3-4:19|11404881820527069090|3|0", + "spell": "4:8-4:9|11404881820527069090|3|2|-1", + "extent": "4:3-4:19|11404881820527069090|3|0|-1", "type": 0, - "uses": ["5:3-5:4|11404881820527069090|3|16428"], + "uses": ["5:3-5:4|11404881820527069090|3|16428|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_class_member.cc b/index_tests/usage/var_usage_class_member.cc index 93667b6d..1a25fe9f 100644 --- a/index_tests/usage/var_usage_class_member.cc +++ b/index_tests/usage/var_usage_class_member.cc @@ -30,8 +30,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:9|0|1|2", - "extent": "10:1-18:2|0|1|0", + "spell": "10:6-10:9|0|1|2|-1", + "extent": "10:1-18:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14669930844300034456], @@ -44,11 +44,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["8:6-8:12|0|1|1"], + "declarations": ["8:6-8:12|8:1-8:18|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["16:3-16:9|4259594751088586730|3|16420"], + "uses": ["16:3-16:9|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 17175780305784503374, @@ -57,11 +57,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["7:6-7:12|0|1|1"], + "declarations": ["7:6-7:12|7:1-7:17|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:3-14:9|4259594751088586730|3|16420", "15:3-15:9|4259594751088586730|3|16420", "17:3-17:9|4259594751088586730|3|16420"], + "uses": ["14:3-14:9|4259594751088586730|3|16420|-1", "15:3-15:9|4259594751088586730|3|16420|-1", "17:3-17:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -86,8 +86,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -101,7 +101,7 @@ OUTPUT: "R": 32 }], "instances": [14669930844300034456], - "uses": ["11:3-11:6|4259594751088586730|3|4"] + "uses": ["11:3-11:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 3873837747174060388, @@ -109,10 +109,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "y", "declarations": [], - "spell": "4:7-4:8|15041163540773201510|2|1026", - "extent": "4:3-4:8|15041163540773201510|2|0", + "spell": "4:7-4:8|15041163540773201510|2|1026|-1", + "extent": "4:3-4:8|15041163540773201510|2|0|-1", "type": 53, - "uses": ["17:12-17:13|4259594751088586730|3|12"], + "uses": ["17:12-17:13|4259594751088586730|3|12|-1"], "kind": 8, "storage": 0 }, { @@ -121,10 +121,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "3:7-3:8|15041163540773201510|2|1026", - "extent": "3:3-3:8|15041163540773201510|2|0", + "spell": "3:7-3:8|15041163540773201510|2|1026|-1", + "extent": "3:3-3:8|15041163540773201510|2|0|-1", "type": 53, - "uses": ["12:5-12:6|4259594751088586730|3|20", "13:5-13:6|4259594751088586730|3|4", "14:12-14:13|4259594751088586730|3|12", "15:12-15:13|4259594751088586730|3|12", "16:13-16:14|4259594751088586730|3|132"], + "uses": ["12:5-12:6|4259594751088586730|3|20|-1", "13:5-13:6|4259594751088586730|3|4|-1", "14:12-14:13|4259594751088586730|3|12|-1", "15:12-15:13|4259594751088586730|3|12|-1", "16:13-16:14|4259594751088586730|3|132|-1"], "kind": 8, "storage": 0 }, { @@ -133,10 +133,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "11:7-11:8|4259594751088586730|3|2", - "extent": "11:3-11:8|4259594751088586730|3|0", + "spell": "11:7-11:8|4259594751088586730|3|2|-1", + "extent": "11:3-11:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, - "uses": ["12:3-12:4|4259594751088586730|3|4", "13:3-13:4|4259594751088586730|3|4", "14:10-14:11|4259594751088586730|3|4", "15:10-15:11|4259594751088586730|3|4", "16:11-16:12|4259594751088586730|3|4", "17:10-17:11|4259594751088586730|3|4"], + "uses": ["12:3-12:4|4259594751088586730|3|4|-1", "13:3-13:4|4259594751088586730|3|4|-1", "14:10-14:11|4259594751088586730|3|4|-1", "15:10-15:11|4259594751088586730|3|4|-1", "16:11-16:12|4259594751088586730|3|4|-1", "17:10-17:11|4259594751088586730|3|4|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_class_member_static.cc b/index_tests/usage/var_usage_class_member_static.cc index 6f2eee7d..8c21456f 100644 --- a/index_tests/usage/var_usage_class_member_static.cc +++ b/index_tests/usage/var_usage_class_member_static.cc @@ -21,8 +21,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:9|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:6-7:9|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -35,11 +35,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["5:6-5:12|0|1|1"], + "declarations": ["5:6-5:12|5:1-5:17|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["8:3-8:9|4259594751088586730|3|16420"], + "uses": ["8:3-8:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -64,8 +64,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -73,16 +73,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["8:10-8:13|4259594751088586730|3|4"] + "uses": ["8:10-8:13|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 8599782646965457351, "detailed_name": "static int Foo::x", "qual_name_offset": 11, "short_name": "x", - "declarations": ["2:14-2:15|15041163540773201510|2|1025"], + "declarations": ["2:14-2:15|2:3-2:15|15041163540773201510|2|1025|-1"], "type": 53, - "uses": ["8:15-8:16|4259594751088586730|3|12"], + "uses": ["8:15-8:16|4259594751088586730|3|12|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/usage/var_usage_cstyle_cast.cc b/index_tests/usage/var_usage_cstyle_cast.cc index 09991182..dd3fe708 100644 --- a/index_tests/usage/var_usage_cstyle_cast.cc +++ b/index_tests/usage/var_usage_cstyle_cast.cc @@ -20,8 +20,8 @@ OUTPUT: "short_name": "VarType", "kind": 10, "declarations": [], - "spell": "1:6-1:13|0|1|2", - "extent": "1:1-1:16|0|1|0", + "spell": "1:6-1:13|0|1|2|-1", + "extent": "1:1-1:16|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -29,7 +29,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [7057400933868440116, 7057400933868440116], - "uses": ["4:20-4:27|10028537921178202800|2|4", "4:42-4:49|10028537921178202800|2|4", "7:7-7:14|0|1|4"] + "uses": ["4:20-4:27|10028537921178202800|2|4|-1", "4:42-4:49|10028537921178202800|2|4|-1", "7:7-7:14|0|1|4|-1"] }, { "usr": 10028537921178202800, "detailed_name": "struct Holder {}", @@ -37,8 +37,8 @@ OUTPUT: "short_name": "Holder", "kind": 23, "declarations": [], - "spell": "3:8-3:14|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:14|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -46,7 +46,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["7:15-7:21|0|1|4"] + "uses": ["7:15-7:21|0|1|4|-1"] }], "usr2var": [{ "usr": 7057400933868440116, @@ -54,9 +54,9 @@ OUTPUT: "qual_name_offset": 25, "short_name": "static_var", "hover": "static constexpr VarType Holder::static_var = (VarType)0x0", - "declarations": ["4:28-4:38|10028537921178202800|2|1025"], - "spell": "7:23-7:33|10028537921178202800|2|1026", - "extent": "7:1-7:33|10028537921178202800|2|0", + "declarations": ["4:28-4:38|4:3-4:53|10028537921178202800|2|1025|-1"], + "spell": "7:23-7:33|10028537921178202800|2|1026|-1", + "extent": "7:1-7:33|10028537921178202800|2|0|-1", "type": 5792006888140599735, "uses": [], "kind": 13, diff --git a/index_tests/usage/var_usage_extern.cc b/index_tests/usage/var_usage_extern.cc index 09442598..0d3469e6 100644 --- a/index_tests/usage/var_usage_extern.cc +++ b/index_tests/usage/var_usage_extern.cc @@ -16,8 +16,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -45,9 +45,9 @@ OUTPUT: "detailed_name": "extern int a", "qual_name_offset": 11, "short_name": "a", - "declarations": ["1:12-1:13|0|1|1"], + "declarations": ["1:12-1:13|1:1-1:13|0|1|1|-1"], "type": 53, - "uses": ["4:3-4:4|4259594751088586730|3|20"], + "uses": ["4:3-4:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 1 }] diff --git a/index_tests/usage/var_usage_func_parameter.cc b/index_tests/usage/var_usage_func_parameter.cc index 9bfd50aa..2a5e0867 100644 --- a/index_tests/usage/var_usage_func_parameter.cc +++ b/index_tests/usage/var_usage_func_parameter.cc @@ -14,8 +14,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10063793875496522529], @@ -44,10 +44,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, - "uses": ["2:3-2:4|11998306017310352355|3|4"], + "uses": ["2:3-2:4|11998306017310352355|3|4|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/usage/var_usage_local.cc b/index_tests/usage/var_usage_local.cc index f6eb9d02..b4ed3842 100644 --- a/index_tests/usage/var_usage_local.cc +++ b/index_tests/usage/var_usage_local.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14014650769929566957], @@ -45,10 +45,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_shadowed_local.cc b/index_tests/usage/var_usage_shadowed_local.cc index d0f9a35f..2aaf27be 100644 --- a/index_tests/usage/var_usage_shadowed_local.cc +++ b/index_tests/usage/var_usage_shadowed_local.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-9:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [13311055950748663970, 14036425367303419504], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20", "8:3-8:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1", "8:3-8:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:9-5:10|4259594751088586730|3|2", - "extent": "5:5-5:10|4259594751088586730|3|0", + "spell": "5:9-5:10|4259594751088586730|3|2|-1", + "extent": "5:5-5:10|4259594751088586730|3|0|-1", "type": 53, - "uses": ["6:5-6:6|4259594751088586730|3|20"], + "uses": ["6:5-6:6|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_shadowed_parameter.cc b/index_tests/usage/var_usage_shadowed_parameter.cc index 8a99171d..801f3a75 100644 --- a/index_tests/usage/var_usage_shadowed_parameter.cc +++ b/index_tests/usage/var_usage_shadowed_parameter.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-8:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [11608231465452906059, 6997229590862003559], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "4:9-4:10|11998306017310352355|3|2", - "extent": "4:5-4:10|11998306017310352355|3|0", + "spell": "4:9-4:10|11998306017310352355|3|2|-1", + "extent": "4:5-4:10|11998306017310352355|3|0|-1", "type": 53, - "uses": ["5:5-5:6|11998306017310352355|3|20"], + "uses": ["5:5-5:6|11998306017310352355|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, - "uses": ["2:3-2:4|11998306017310352355|3|20", "7:3-7:4|11998306017310352355|3|20"], + "uses": ["2:3-2:4|11998306017310352355|3|20|-1", "7:3-7:4|11998306017310352355|3|20|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/usage/var_usage_static.cc b/index_tests/usage/var_usage_static.cc index 9c825830..396f3ded 100644 --- a/index_tests/usage/var_usage_static.cc +++ b/index_tests/usage/var_usage_static.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,10 +47,10 @@ OUTPUT: "qual_name_offset": 11, "short_name": "a", "declarations": [], - "spell": "1:12-1:13|0|1|2", - "extent": "1:1-1:13|0|1|0", + "spell": "1:12-1:13|0|1|2|-1", + "extent": "1:1-1:13|0|1|0|-1", "type": 53, - "uses": ["4:3-4:4|4259594751088586730|3|20"], + "uses": ["4:3-4:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/vars/class_member.cc b/index_tests/vars/class_member.cc index 4b3925a7..7bb7bc97 100644 --- a/index_tests/vars/class_member.cc +++ b/index_tests/vars/class_member.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -26,7 +26,7 @@ OUTPUT: "R": 0 }], "instances": [13799811842374292251], - "uses": ["2:3-2:6|15041163540773201510|2|4"] + "uses": ["2:3-2:6|15041163540773201510|2|4|-1"] }], "usr2var": [{ "usr": 13799811842374292251, @@ -34,8 +34,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "member", "declarations": [], - "spell": "2:8-2:14|15041163540773201510|2|1026", - "extent": "2:3-2:14|15041163540773201510|2|0", + "spell": "2:8-2:14|15041163540773201510|2|1026|-1", + "extent": "2:3-2:14|15041163540773201510|2|0|-1", "type": 15041163540773201510, "uses": [], "kind": 8, diff --git a/index_tests/vars/class_static_member.cc b/index_tests/vars/class_static_member.cc index 1dcb0699..86e09041 100644 --- a/index_tests/vars/class_static_member.cc +++ b/index_tests/vars/class_static_member.cc @@ -16,8 +16,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -25,16 +25,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [5844987037615239736, 5844987037615239736], - "uses": ["2:10-2:13|15041163540773201510|2|4", "4:1-4:4|0|1|4", "4:6-4:9|0|1|4"] + "uses": ["2:10-2:13|15041163540773201510|2|4|-1", "4:1-4:4|0|1|4|-1", "4:6-4:9|0|1|4|-1"] }], "usr2var": [{ "usr": 5844987037615239736, "detailed_name": "static Foo *Foo::member", "qual_name_offset": 12, "short_name": "member", - "declarations": ["2:15-2:21|15041163540773201510|2|1025"], - "spell": "4:11-4:17|15041163540773201510|2|1026", - "extent": "4:1-4:27|15041163540773201510|2|0", + "declarations": ["2:15-2:21|2:3-2:21|15041163540773201510|2|1025|-1"], + "spell": "4:11-4:17|15041163540773201510|2|1026|-1", + "extent": "4:1-4:27|15041163540773201510|2|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/class_static_member_decl_only.cc b/index_tests/vars/class_static_member_decl_only.cc index b0f84d67..d01c6220 100644 --- a/index_tests/vars/class_static_member_decl_only.cc +++ b/index_tests/vars/class_static_member_decl_only.cc @@ -29,8 +29,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -45,7 +45,7 @@ OUTPUT: "detailed_name": "static int Foo::member", "qual_name_offset": 11, "short_name": "member", - "declarations": ["2:14-2:20|15041163540773201510|2|1025"], + "declarations": ["2:14-2:20|2:3-2:20|15041163540773201510|2|1025|-1"], "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/deduce_auto_type.cc b/index_tests/vars/deduce_auto_type.cc index 3823df90..f76c0460 100644 --- a/index_tests/vars/deduce_auto_type.cc +++ b/index_tests/vars/deduce_auto_type.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10601729374837386290, 18422884837902130475], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-1:13|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-1:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,7 +41,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [10601729374837386290, 18422884837902130475], - "uses": ["3:16-3:19|880549676430489861|3|4", "4:17-4:20|880549676430489861|3|4"] + "uses": ["3:16-3:19|880549676430489861|3|4|-1", "4:17-4:20|880549676430489861|3|4|-1"] }], "usr2var": [{ "usr": 10601729374837386290, @@ -50,8 +50,8 @@ OUTPUT: "short_name": "x", "hover": "auto x = new Foo()", "declarations": [], - "spell": "3:8-3:9|880549676430489861|3|2", - "extent": "3:3-3:21|880549676430489861|3|0", + "spell": "3:8-3:9|880549676430489861|3|2|-1", + "extent": "3:3-3:21|880549676430489861|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, @@ -63,8 +63,8 @@ OUTPUT: "short_name": "y", "hover": "Foo *y = new Foo()", "declarations": [], - "spell": "4:9-4:10|880549676430489861|3|2", - "extent": "4:3-4:22|880549676430489861|3|0", + "spell": "4:9-4:10|880549676430489861|3|2|-1", + "extent": "4:3-4:22|880549676430489861|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/function_local.cc b/index_tests/vars/function_local.cc index b6197c40..66b96573 100644 --- a/index_tests/vars/function_local.cc +++ b/index_tests/vars/function_local.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [13198746475679542317], @@ -31,7 +31,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -39,7 +39,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13198746475679542317], - "uses": ["4:3-4:6|4259594751088586730|3|4"] + "uses": ["4:3-4:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 13198746475679542317, @@ -47,8 +47,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "a", "declarations": [], - "spell": "4:8-4:9|4259594751088586730|3|2", - "extent": "4:3-4:9|4259594751088586730|3|0", + "spell": "4:8-4:9|4259594751088586730|3|2|-1", + "extent": "4:3-4:9|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/function_param.cc b/index_tests/vars/function_param.cc index 96a844ad..a9c8683f 100644 --- a/index_tests/vars/function_param.cc +++ b/index_tests/vars/function_param.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:30|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:30|0|1|0|-1", "bases": [], "derived": [], "vars": [8730439006497971620, 2525014371090380500], @@ -29,7 +29,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -37,7 +37,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [8730439006497971620, 2525014371090380500], - "uses": ["3:10-3:13|0|1|4", "3:19-3:22|0|1|4"] + "uses": ["3:10-3:13|0|1|4|-1", "3:19-3:22|0|1|4|-1"] }], "usr2var": [{ "usr": 2525014371090380500, @@ -45,8 +45,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "p1", "declarations": [], - "spell": "3:24-3:26|8908726657907936744|3|1026", - "extent": "3:19-3:26|8908726657907936744|3|0", + "spell": "3:24-3:26|8908726657907936744|3|1026|-1", + "extent": "3:19-3:26|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, @@ -57,8 +57,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "p0", "declarations": [], - "spell": "3:15-3:17|8908726657907936744|3|1026", - "extent": "3:10-3:17|8908726657907936744|3|0", + "spell": "3:15-3:17|8908726657907936744|3|1026|-1", + "extent": "3:10-3:17|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, diff --git a/index_tests/vars/function_param_unnamed.cc b/index_tests/vars/function_param_unnamed.cc index 6ecfe2fa..48b4f60b 100644 --- a/index_tests/vars/function_param_unnamed.cc +++ b/index_tests/vars/function_param_unnamed.cc @@ -12,8 +12,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-1:22|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-1:22|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/vars/function_shadow_local.cc b/index_tests/vars/function_shadow_local.cc index 27c7b00b..d6ffa4ef 100644 --- a/index_tests/vars/function_shadow_local.cc +++ b/index_tests/vars/function_shadow_local.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-9:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [1894874819807168345, 4508045017817092115], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20", "8:3-8:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1", "8:3-8:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:9-5:10|4259594751088586730|3|2", - "extent": "5:5-5:10|4259594751088586730|3|0", + "spell": "5:9-5:10|4259594751088586730|3|2|-1", + "extent": "5:5-5:10|4259594751088586730|3|0|-1", "type": 53, - "uses": ["6:5-6:6|4259594751088586730|3|20"], + "uses": ["6:5-6:6|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/vars/function_shadow_param.cc b/index_tests/vars/function_shadow_param.cc index f2d52211..9ef35ec9 100644 --- a/index_tests/vars/function_shadow_param.cc +++ b/index_tests/vars/function_shadow_param.cc @@ -14,8 +14,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [5875271969926422921, 11404600766177939811], @@ -44,8 +44,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "p", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -57,8 +57,8 @@ OUTPUT: "short_name": "p", "hover": "int p = 0", "declarations": [], - "spell": "2:9-2:10|11998306017310352355|3|2", - "extent": "2:5-2:14|11998306017310352355|3|0", + "spell": "2:9-2:10|11998306017310352355|3|2|-1", + "extent": "2:5-2:14|11998306017310352355|3|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/global_variable.cc b/index_tests/vars/global_variable.cc index c76dd406..0f563a73 100644 --- a/index_tests/vars/global_variable.cc +++ b/index_tests/vars/global_variable.cc @@ -28,8 +28,8 @@ OUTPUT: "short_name": "global", "hover": "static int global = 0", "declarations": [], - "spell": "1:12-1:18|0|1|2", - "extent": "1:1-1:22|0|1|0", + "spell": "1:12-1:18|0|1|2|-1", + "extent": "1:1-1:22|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/global_variable_decl_only.cc b/index_tests/vars/global_variable_decl_only.cc index 8ca10b9e..0ecf84a2 100644 --- a/index_tests/vars/global_variable_decl_only.cc +++ b/index_tests/vars/global_variable_decl_only.cc @@ -26,7 +26,7 @@ OUTPUT: "detailed_name": "extern int global", "qual_name_offset": 11, "short_name": "global", - "declarations": ["1:12-1:18|0|1|1"], + "declarations": ["1:12-1:18|1:1-1:18|0|1|1|-1"], "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/type_instance_on_using_type.cc b/index_tests/vars/type_instance_on_using_type.cc index 7a6ebcf6..b924afd5 100644 --- a/index_tests/vars/type_instance_on_using_type.cc +++ b/index_tests/vars/type_instance_on_using_type.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [6975456769752895964], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "S", "kind": 23, "declarations": [], - "spell": "1:8-1:9|0|1|2", - "extent": "1:1-1:12|0|1|0", + "spell": "1:8-1:9|0|1|2|-1", + "extent": "1:1-1:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:11-2:12|0|1|4"] + "uses": ["2:11-2:12|0|1|4|-1"] }, { "usr": 7434820806199665424, "detailed_name": "using F = S", @@ -51,8 +51,8 @@ OUTPUT: "short_name": "F", "kind": 252, "declarations": [], - "spell": "2:7-2:8|0|1|2", - "extent": "2:1-2:12|0|1|0", + "spell": "2:7-2:8|0|1|2|-1", + "extent": "2:1-2:12|0|1|0|-1", "alias_of": 4750332761459066907, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [6975456769752895964], - "uses": ["4:3-4:4|4654328188330986029|3|4"] + "uses": ["4:3-4:4|4654328188330986029|3|4|-1"] }], "usr2var": [{ "usr": 6975456769752895964, @@ -68,8 +68,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "a", "declarations": [], - "spell": "4:5-4:6|4654328188330986029|3|2", - "extent": "4:3-4:6|4654328188330986029|3|0", + "spell": "4:5-4:6|4654328188330986029|3|2|-1", + "extent": "4:3-4:6|4654328188330986029|3|0|-1", "type": 7434820806199665424, "uses": [], "kind": 13, diff --git a/src/indexer.cc b/src/indexer.cc index ce53ad16..ad3580cc 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -686,12 +686,13 @@ public: SourceRange R = OrigD->getSourceRange(); entity->def.extent = GetUse(db, lid, - R.getBegin().isFileID() - ? FromTokenRange(SM, Lang, OrigD->getSourceRange()) - : loc, + R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc, LexDC, Role::None); } else if (is_decl) { - entity->declarations.push_back(GetUse(db, lid, loc, LexDC, role)); + DeclRef &dr = entity->declarations.emplace_back(); + static_cast(dr) = GetUse(db, lid, loc, LexDC, role); + SourceRange R = OrigD->getSourceRange(); + dr.extent = R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc; } else { entity->uses.push_back(GetUse(db, lid, loc, LexDC, role)); return; @@ -1085,8 +1086,11 @@ public: IndexVar &var = db->ToVar(usr); auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID); var.def.kind = lsSymbolKind::Macro; - if (var.def.spell) - var.declarations.push_back(*var.def.spell); + if (var.def.spell) { + DeclRef &d = var.declarations.emplace_back(); + static_cast(d) = *var.def.spell; + d.extent = var.def.spell->range; + } var.def.spell = Use{{range, 0, SymbolKind::File, Role::Definition}}; const MacroInfo *MI = MD->getMacroInfo(); SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); @@ -1148,8 +1152,8 @@ public: }; } // namespace -const int IndexFile::kMajorVersion = 17; -const int IndexFile::kMinorVersion = 1; +const int IndexFile::kMajorVersion = 18; +const int IndexFile::kMinorVersion = 0; IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, const std::string &contents) @@ -1348,8 +1352,7 @@ void Reflect(Reader &vis, Use &v) { v.usr = strtoull(s + 1, &s, 10); v.kind = static_cast(strtol(s + 1, &s, 10)); v.role = static_cast(strtol(s + 1, &s, 10)); - if (*s == '|') - v.file_id = static_cast(strtol(s + 1, &s, 10)); + v.file_id = static_cast(strtol(s + 1, &s, 10)); } else { Reflect(vis, static_cast(v)); Reflect(vis, v.file_id); @@ -1358,13 +1361,9 @@ void Reflect(Reader &vis, Use &v) { void Reflect(Writer &vis, Use &v) { if (vis.Format() == SerializeFormat::Json) { char buf[99]; - if (v.file_id == -1) - snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", - v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role)); - else - snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d|%d", - v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role), - v.file_id); + snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d|%d", + v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role), + v.file_id); std::string s(buf); Reflect(vis, s); } else { @@ -1372,3 +1371,34 @@ void Reflect(Writer &vis, Use &v) { Reflect(vis, v.file_id); } } + +void Reflect(Reader &vis, DeclRef &v) { + if (vis.Format() == SerializeFormat::Json) { + std::string t = vis.GetString(); + char *s = const_cast(t.c_str()); + v.range = Range::FromString(s); + s = strchr(s, '|') + 1; + v.extent = Range::FromString(s); + s = strchr(s, '|') + 1; + v.usr = strtoull(s, &s, 10); + v.kind = static_cast(strtol(s + 1, &s, 10)); + v.role = static_cast(strtol(s + 1, &s, 10)); + v.file_id = static_cast(strtol(s + 1, &s, 10)); + } else { + Reflect(vis, static_cast(v)); + Reflect(vis, v.extent); + } +} +void Reflect(Writer &vis, DeclRef &v) { + if (vis.Format() == SerializeFormat::Json) { + char buf[99]; + snprintf(buf, sizeof buf, "%s|%s|%" PRIu64 "|%d|%d|%d", + v.range.ToString().c_str(), v.extent.ToString().c_str(), v.usr, + int(v.kind), int(v.role), v.file_id); + std::string s(buf); + Reflect(vis, s); + } else { + Reflect(vis, static_cast(v)); + Reflect(vis, v.extent); + } +} diff --git a/src/indexer.h b/src/indexer.h index 355b5a98..4051e541 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -82,10 +82,17 @@ struct Use : Reference { }; MAKE_HASHABLE(Use, t.range, t.file_id) +struct DeclRef : Use { + Range extent; +}; +MAKE_HASHABLE(DeclRef, t.range, t.file_id) + void Reflect(Reader &visitor, Reference &value); void Reflect(Writer &visitor, Reference &value); void Reflect(Reader &visitor, Use &value); void Reflect(Writer &visitor, Use &value); +void Reflect(Reader &visitor, DeclRef &value); +void Reflect(Writer &visitor, DeclRef &value); template struct NameMixin { std::string_view Name(bool qualified) const { @@ -134,7 +141,7 @@ struct IndexFunc : NameMixin { using Def = FuncDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; }; @@ -174,7 +181,7 @@ struct IndexType { using Def = TypeDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; std::vector instances; @@ -216,7 +223,7 @@ struct IndexVar { using Def = VarDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; }; diff --git a/src/query.cc b/src/query.cc index 88a7e809..be657184 100644 --- a/src/query.cc +++ b/src/query.cc @@ -38,13 +38,8 @@ void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Use &use) { use.usr = use.file_id; } -void AddRange(std::vector &into, const std::vector &from) { - into.reserve(into.size() + from.size()); - for (Use use : from) - into.push_back(use); -} - -void AddRange(std::vector &into, const std::vector &from) { +template +void AddRange(std::vector &into, const std::vector &from) { into.insert(into.end(), from.begin(), from.end()); } @@ -243,6 +238,12 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { files[use.file_id] .outline2refcnt[SymbolRef{{use.range, usr, kind, use.role}}] += delta; }; + auto RefDecl = [&](std::unordered_map &lid2fid, Usr usr, + SymbolKind kind, DeclRef &dr, int delta) { + Ref(lid2fid, usr, kind, dr, delta, 1); + files[dr.file_id] + .outline2refcnt[SymbolRef{{dr.extent, usr, kind, dr.role}}] += delta; + }; auto UpdateUses = [&](Usr usr, SymbolKind kind, llvm::DenseMap &entity_usr, @@ -298,10 +299,10 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { RemoveUsrs(SymbolKind::Func, u->file_id, u->funcs_removed); Update(lid2file_id, u->file_id, std::move(u->funcs_def_update)); for (auto &[usr, del_add]: u->funcs_declarations) { - for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Func, use, -1, 3); - for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Func, use, 1, 3); + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Func, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Func, dr, 1); } REMOVE_ADD(func, declarations); REMOVE_ADD(func, derived); @@ -322,10 +323,10 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { RemoveUsrs(SymbolKind::Type, u->file_id, u->types_removed); Update(lid2file_id, u->file_id, std::move(u->types_def_update)); for (auto &[usr, del_add]: u->types_declarations) { - for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Type, use, -1, 3); - for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Type, use, 1, 3); + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Type, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Type, dr, 1); } REMOVE_ADD(type, declarations); REMOVE_ADD(type, derived); @@ -347,10 +348,10 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed); Update(lid2file_id, u->file_id, std::move(u->vars_def_update)); for (auto &[usr, del_add]: u->vars_declarations) { - for (Use &use : del_add.first) - Ref(prev_lid2file_id, usr, SymbolKind::Var, use, -1, 3); - for (Use &use : del_add.second) - Ref(lid2file_id, usr, SymbolKind::Var, use, 1, 3); + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Var, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Var, dr, 1); } REMOVE_ADD(var, declarations); for (auto &[usr, p] : u->vars_uses) diff --git a/src/query.h b/src/query.h index 5f0a5d24..7cf17018 100644 --- a/src/query.h +++ b/src/query.h @@ -73,6 +73,9 @@ template struct QueryEntity { } }; +using DeclRefUpdate = + std::unordered_map, std::vector>>; using UseUpdate = std::unordered_map, std::vector>>; using UsrUpdate = @@ -81,7 +84,7 @@ using UsrUpdate = struct QueryFunc : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; }; @@ -89,7 +92,7 @@ struct QueryFunc : QueryEntity { struct QueryType : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; std::vector instances; @@ -98,7 +101,7 @@ struct QueryType : QueryEntity { struct QueryVar : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; }; @@ -123,7 +126,7 @@ struct IndexUpdate { int funcs_hint; std::vector> funcs_removed; std::vector> funcs_def_update; - UseUpdate funcs_declarations; + DeclRefUpdate funcs_declarations; UseUpdate funcs_uses; UsrUpdate funcs_derived; @@ -131,7 +134,7 @@ struct IndexUpdate { int types_hint; std::vector> types_removed; std::vector> types_def_update; - UseUpdate types_declarations; + DeclRefUpdate types_declarations; UseUpdate types_uses; UsrUpdate types_derived; UsrUpdate types_instances; @@ -140,7 +143,7 @@ struct IndexUpdate { int vars_hint; std::vector> vars_removed; std::vector> vars_def_update; - UseUpdate vars_declarations; + DeclRefUpdate vars_declarations; UseUpdate vars_uses; }; diff --git a/src/query_utils.cc b/src/query_utils.cc index c4fdc5d7..af885525 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -105,16 +105,24 @@ std::vector GetVarDeclarations(DB *db, const std::vector &usrs, } std::vector GetNonDefDeclarations(DB *db, SymbolIdx sym) { + std::vector ret; switch (sym.kind) { case SymbolKind::Func: - return db->GetFunc(sym).declarations; + for (auto &d : db->GetFunc(sym).declarations) + ret.push_back(d); + break; case SymbolKind::Type: - return db->GetType(sym).declarations; + for (auto &d : db->GetType(sym).declarations) + ret.push_back(d); + break; case SymbolKind::Var: - return db->GetVar(sym).declarations; + for (auto &d : db->GetVar(sym).declarations) + ret.push_back(d); + break; default: - return {}; + break; } + return ret; } std::vector GetUsesForAllBases(DB *db, QueryFunc &root) { From 82d31a201250d8e7ac75acb9b90e5cabd61889cd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 7 Sep 2018 23:40:22 -0700 Subject: [PATCH 18/66] Implement index.onChange: true; enable spell checking for diagnostics --- src/clang_complete.cc | 1 + src/config.h | 4 +- src/indexer.cc | 19 +++++-- src/indexer.h | 4 +- src/messages/textDocument_didChange.cc | 4 +- src/messages/textDocument_didOpen.cc | 6 +-- src/messages/textDocument_didSave.cc | 24 ++------- .../workspace_didChangeWatchedFiles.cc | 12 +++-- src/pipeline.cc | 52 ++++++++++++------- src/pipeline.hh | 15 ++++-- src/project.cc | 8 +-- 11 files changed, 83 insertions(+), 66 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 4d6613af..a5456c53 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -623,6 +623,7 @@ void DiagnosticMain(ClangCompleteManager *manager) { BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; + CI->getLangOpts()->SpellChecking = true; StoreDiags DC; WorkingFiles::Snapshot snapshot = manager->working_files_->AsSnapshot({StripFileType(path)}); diff --git a/src/config.h b/src/config.h index 3e22a0e9..79e7ee75 100644 --- a/src/config.h +++ b/src/config.h @@ -201,7 +201,7 @@ struct Config { // Allow indexing on textDocument/didChange. // May be too slow for big projects, so it is off by default. - bool onDidChange = false; + bool onChange = false; // Whether to reparse a file if write times of its dependencies have // changed. The file will always be reparsed if its own write time changes. @@ -245,7 +245,7 @@ MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, onOpen, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, - multiVersionBlacklist, multiVersionWhitelist, onDidChange, + multiVersionBlacklist, multiVersionWhitelist, onChange, reparseForDependency, threads, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); diff --git a/src/indexer.cc b/src/indexer.cc index ad3580cc..177d4be5 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1131,9 +1131,10 @@ public: void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { llvm::sys::fs::UniqueID UniqueID; auto range = FromCharRange(SM, param.Ctx->getLangOpts(), Range, &UniqueID); - const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Range.getBegin())); - if (IndexFile *db = param.ConsumeFile(*FE)) - db->skipped_ranges.push_back(range); + if (const FileEntry *FE = + SM.getFileEntryForID(SM.getFileID(Range.getBegin()))) + if (IndexFile *db = param.ConsumeFile(*FE)) + db->skipped_ranges.push_back(range); } }; @@ -1202,7 +1203,7 @@ void Init() { std::vector> Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, - const std::vector &file_contents) { + const std::vector> &remapped) { if (!g_config->index.enabled) return {}; @@ -1226,6 +1227,14 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, // HSOpts.UseBuiltinIncludes) // HSOpts.ResourceDir = g_config->clang.resourceDir; } + std::vector> Bufs; + for (auto &[filename, content] : remapped) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content)); + CI->getPreprocessorOpts().addRemappedFile( + filename == file ? CI->getFrontendOpts().Inputs[0].getFile() + : StringRef(filename), + Bufs.back().get()); + } DiagnosticConsumer DC; auto Clang = std::make_unique(PCH); @@ -1272,6 +1281,8 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, LOG_S(ERROR) << "failed to index " << file; return {}; } + for (auto &Buf : Bufs) + Buf.release(); auto result = param.file_consumer->TakeLocalState(); for (std::unique_ptr &entry : result) { diff --git a/src/indexer.h b/src/indexer.h index 4051e541..dc4fe774 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -288,5 +288,5 @@ void Init(); std::vector> Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, - const std::vector &file_contents); -} + const std::vector>& remapped); +} // namespace ccls::idx diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc index a0690a2c..1704282d 100644 --- a/src/messages/textDocument_didChange.cc +++ b/src/messages/textDocument_didChange.cc @@ -38,9 +38,9 @@ struct Handler_TextDocumentDidChange void Run(In_TextDocumentDidChange *request) override { std::string path = request->params.textDocument.uri.GetPath(); working_files->OnChange(request->params); - if (g_config->index.onDidChange) { + if (g_config->index.onChange) { Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, true); + pipeline::Index(entry.filename, entry.args, IndexMode::OnChange); } clang_complete->NotifyEdit(path); clang_complete->DiagnosticsUpdate( diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 8120f4be..b88d3b94 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -35,8 +35,7 @@ struct In_TextDocumentDidOpen : public NotificationInMessage { // If specified (e.g. ["clang++", "-DM", "a.cc"]), it overrides the project // entry (e.g. loaded from compile_commands.json or .ccls). std::vector args; - }; - Params params; + } params; }; MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen::Params, textDocument, args); MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen, params); @@ -72,7 +71,8 @@ struct Handler_TextDocumentDidOpen if (SourceFileLanguage(path) != LanguageId::Unknown) { Project::Entry entry = project->FindCompilationEntryForFile(path); pipeline::Index(entry.filename, - params.args.size() ? params.args : entry.args, true); + params.args.size() ? params.args : entry.args, + IndexMode::Normal); clang_complete->FlushSession(entry.filename); } diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 17bb53ff..023d1bb3 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -32,8 +32,7 @@ struct In_TextDocumentDidSave : public NotificationInMessage { // Optional the content when saved. Depends on the includeText value // when the save notifcation was requested. // std::string text; - }; - Params params; + } params; }; MAKE_REFLECT_STRUCT(In_TextDocumentDidSave::Params, textDocument); MAKE_REFLECT_STRUCT(In_TextDocumentDidSave, params); @@ -47,25 +46,8 @@ struct Handler_TextDocumentDidSave const auto ¶ms = request->params; std::string path = params.textDocument.uri.GetPath(); - // Send out an index request, and copy the current buffer state so we - // can update the cached index contents when the index is done. - // - // We also do not index if there is already an index request or if - // the client requested indexing on didChange instead. - // - // TODO: Cancel outgoing index request. Might be tricky to make - // efficient since we have to cancel. - // - we could have an |atomic active_cancellations| variable - // that all of the indexers check before accepting an index. if - // zero we don't slow down fast-path. if non-zero we acquire - // mutex and check to see if we should skip the current request. - // if so, ignore that index response. - // TODO: send as priority request - if (!g_config->index.onDidChange) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, true); - } - + Project::Entry entry = project->FindCompilationEntryForFile(path); + pipeline::Index(entry.filename, entry.args, IndexMode::Normal); clang_complete->NotifySave(path); } }; diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index c25078b9..b2c3eef5 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -62,18 +62,20 @@ struct Handler_WorkspaceDidChangeWatchedFiles continue; entry = project->entries[it->second]; } - bool is_interactive = - working_files->GetFileByFilename(entry.filename) != nullptr; + IndexMode mode = + working_files->GetFileByFilename(entry.filename) != nullptr + ? IndexMode::Normal + : IndexMode::NonInteractive; switch (event.type) { case lsFileChangeType::Created: case lsFileChangeType::Changed: { - pipeline::Index(path, entry.args, is_interactive); - if (is_interactive) + pipeline::Index(path, entry.args, mode); + if (mode == IndexMode::Normal) clang_complete->NotifySave(path); break; } case lsFileChangeType::Deleted: - pipeline::Index(path, entry.args, is_interactive); + pipeline::Index(path, entry.args, mode); break; } } diff --git a/src/pipeline.cc b/src/pipeline.cc index 89eca566..c9f5c370 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -78,7 +78,7 @@ namespace { struct Index_Request { std::string path; std::vector args; - bool is_interactive; + IndexMode mode; lsRequestId id; }; @@ -158,6 +158,7 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, if (!opt_request) return false; auto &request = *opt_request; + bool loud = request.mode != IndexMode::OnChange; // Dummy one to trigger refresh semantic highlight. if (request.path.empty()) { @@ -168,7 +169,7 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, } if (std::string reason; !matcher.IsMatch(request.path, &reason)) { - LOG_S(INFO) << "skip " << request.path << " for " << reason; + LOG_IF_S(INFO, loud) << "skip " << request.path << " for " << reason; return false; } @@ -191,6 +192,8 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, if (!write_time) return true; int reparse = vfs->Stamp(path_to_index, *write_time); + if (g_config->index.onChange) + reparse = 2; if (!vfs->Mark(path_to_index, g_thread_id, 1) && !reparse) return true; @@ -226,21 +229,29 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, auto dependencies = prev->dependencies; if (reparse) { IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), request.is_interactive); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); } for (const auto &dep : dependencies) if (vfs->Mark(dep.first().str(), 0, 2) && (prev = RawCacheLoad(dep.first().str()))) { IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), request.is_interactive); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); } return true; } - LOG_S(INFO) << "parse " << path_to_index; + LOG_IF_S(INFO, loud) << "parse " << path_to_index; + std::vector> remapped; + if (g_config->index.onChange) { + std::string content = working_files->GetContent(request.path); + if (content.size()) + remapped.emplace_back(request.path, content); + } auto indexes = - idx::Index(vfs, entry.directory, path_to_index, entry.args, {}); + idx::Index(vfs, entry.directory, path_to_index, entry.args, remapped); if (indexes.empty()) { if (g_config->index.enabled && request.id.Valid()) { @@ -259,16 +270,15 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index)) continue; if (std::string reason; !matcher.IsMatch(path, &reason)) { - LOG_S(INFO) << "skip emitting and storing index of " << path << " for " - << reason; + LOG_IF_S(INFO, loud) << "skip emitting and storing index of " << path << " for " + << reason; continue; } - LOG_S(INFO) << "emit index for " << path; + LOG_IF_S(INFO, loud) << "emit index for " << path; prev = RawCacheLoad(path); // Write current index to disk if requested. - LOG_S(INFO) << "store index for " << path; { std::string cache_path = GetCachePath(path); WriteToFile(cache_path, curr->file_contents); @@ -285,9 +295,11 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, // Build delta update. IndexUpdate update = IndexUpdate::CreateDelta(prev.get(), curr.get()); - LOG_S(INFO) << "built index for " << path << " (is_delta=" << !!prev << ")"; + LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev + << ")"; - on_indexed->PushBack(std::move(update), request.is_interactive); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); } return true; @@ -340,12 +352,14 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, // Update indexed content, skipped ranges, and semantic highlighting. if (update->files_def_update) { auto &def_u = *update->files_def_update; - LOG_S(INFO) << "apply index for " << def_u.first.path; - if (WorkingFile *working_file = + if (WorkingFile *wfile = working_files->GetFileByFilename(def_u.first.path)) { - working_file->SetIndexContent(def_u.second); - EmitSkippedRanges(working_file, def_u.first.skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, working_file, + // FIXME With index.onChange: true, use buffer_content only for + // request.path + wfile->SetIndexContent(g_config->index.onChange ? wfile->buffer_content + : def_u.second); + EmitSkippedRanges(wfile, def_u.first.skipped_ranges); + EmitSemanticHighlighting(db, semantic_cache, wfile, &db->files[update->file_id]); } } @@ -492,8 +506,8 @@ void MainLoop() { } void Index(const std::string &path, const std::vector &args, - bool interactive, lsRequestId id) { - index_request->PushBack({path, args, interactive, id}, interactive); + IndexMode mode, lsRequestId id) { + index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } std::optional LoadCachedFileContents(const std::string &path) { diff --git a/src/pipeline.hh b/src/pipeline.hh index d3c7dcf4..3ad96636 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -26,8 +26,14 @@ class DiagnosticsPublisher { std::vector diagnostics); }; -namespace ccls::pipeline { +namespace ccls { +enum class IndexMode { + NonInteractive, + OnChange, + Normal, +}; +namespace pipeline { void Init(); void LaunchStdin(); void LaunchStdout(); @@ -37,11 +43,10 @@ void Indexer_Main(DiagnosticsPublisher* diag_pub, WorkingFiles* working_files); void MainLoop(); -void Index(const std::string& path, - const std::vector& args, - bool is_interactive, - lsRequestId id = {}); +void Index(const std::string &path, const std::vector &args, + IndexMode mode, lsRequestId id = {}); std::optional LoadCachedFileContents(const std::string& path); void WriteStdout(MethodType method, lsBaseOutMessage& response); } +} diff --git a/src/project.cc b/src/project.cc index c25e97c9..173ec597 100644 --- a/src/project.cc +++ b/src/project.cc @@ -460,10 +460,12 @@ void Project::ForAllFilteredFiles( void Project::Index(WorkingFiles *wfiles, lsRequestId id) { ForAllFilteredFiles([&](int i, const Project::Entry &entry) { - bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; - pipeline::Index(entry.filename, entry.args, is_interactive, id); + bool interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; + pipeline::Index(entry.filename, entry.args, + interactive ? IndexMode::Normal : IndexMode::NonInteractive, + id); }); // Dummy request to indicate that project is loaded and // trigger refreshing semantic highlight for all working files. - pipeline::Index("", {}, false); + pipeline::Index("", {}, IndexMode::NonInteractive); } From 58191fd33536cca23c25e1008f04e96b516e5f77 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 8 Sep 2018 10:37:48 -0700 Subject: [PATCH 19/66] Support empty cacheDirectory and fix cache load --- src/clang_complete.cc | 7 ++- src/clang_tu.cc | 1 + src/config.h | 14 +++--- src/file_consumer.h | 1 + src/indexer.cc | 14 ++---- src/indexer.h | 3 +- src/messages/ccls_freshenIndex.cc | 3 +- src/messages/initialize.cc | 19 ++++---- src/messages/textDocument_didChange.cc | 12 ++--- src/messages/textDocument_didOpen.cc | 2 +- src/pipeline.cc | 62 +++++++++++++++++++++----- src/pipeline.hh | 9 ++-- src/serializer.cc | 2 +- src/utils.cc | 15 ++----- src/utils.h | 1 - 15 files changed, 97 insertions(+), 68 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index a5456c53..9f9b671f 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -573,7 +573,6 @@ void CompletionMain(ClangCompleteManager *completion_manager) { BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; - CI->getDiagnosticOpts().IgnoreWarnings = true; clang::CodeCompleteOptions CCOpts; CCOpts.IncludeBriefComments = true; #if LLVM_VERSION_MAJOR >= 7 @@ -612,8 +611,6 @@ void DiagnosticMain(ClangCompleteManager *manager) { // Fetching the completion request blocks until we have a request. ClangCompleteManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); - if (!g_config->diagnostics.onChange) - continue; std::string path = request.document.uri.GetPath(); std::shared_ptr session = manager->TryGetSession( @@ -623,7 +620,8 @@ void DiagnosticMain(ClangCompleteManager *manager) { BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; - CI->getLangOpts()->SpellChecking = true; + CI->getDiagnosticOpts().IgnoreWarnings = false; + CI->getLangOpts()->SpellChecking = g_config->diagnostics.spellChecking; StoreDiags DC; WorkingFiles::Snapshot snapshot = manager->working_files_->AsSnapshot({StripFileType(path)}); @@ -680,6 +678,7 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) { auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0); if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get())) return; + CI.getDiagnosticOpts().IgnoreWarnings = false; CI.getFrontendOpts().SkipFunctionBodies = true; CI.getLangOpts()->CommentOpts.ParseAllComments = true; #if LLVM_VERSION_MAJOR >= 7 diff --git a/src/clang_tu.cc b/src/clang_tu.cc index be2f1679..d4646705 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -75,6 +75,7 @@ BuildCompilerInvocation(const std::vector &args, std::unique_ptr CI = createInvocationFromCommandLine(cargs, Diags, VFS); if (CI) { + CI->getDiagnosticOpts().IgnoreWarnings = true; CI->getFrontendOpts().DisableFree = false; CI->getLangOpts()->SpellChecking = false; } diff --git a/src/config.h b/src/config.h index 79e7ee75..ae234f72 100644 --- a/src/config.h +++ b/src/config.h @@ -21,14 +21,7 @@ limitations under the License. /* The language client plugin needs to send initialization options in the -`initialize` request to the ccls language server. The only required option is -`cacheDirectory`, which is where index files will be stored. - - { - "initializationOptions": { - "cacheDirectory": "/tmp/ccls" - } - } +`initialize` request to the ccls language server. If necessary, the command line option --init can be used to override initialization options specified by the client. For example, in shell syntax: @@ -47,6 +40,7 @@ struct Config { std::string compilationDatabaseDirectory; // Cache directory for indexed files, either absolute or relative to the // project root. + // If empty, cache will be stored in memory. std::string cacheDirectory = ".ccls-cache"; // Cache serialization format. // @@ -54,12 +48,14 @@ struct Config { // printed with jq. // // "binary" uses a compact binary serialization format. - // It is not schema-aware and you need to re-index whenever a struct + // It is not schema-aware and you need to re-index whenever an internal struct // member has changed. SerializeFormat cacheFormat = SerializeFormat::Binary; struct Clang { // Arguments that should be excluded, e.g. ["-fopenmp", "-Wall"] + // + // e.g. If your project is built by GCC and has an option thag clang does not understand. std::vector excludeArgs; // Additional arguments to pass to clang. diff --git a/src/file_consumer.h b/src/file_consumer.h index b0292084..d2c75894 100644 --- a/src/file_consumer.h +++ b/src/file_consumer.h @@ -45,6 +45,7 @@ struct VFS { int64_t timestamp; int owner; int stage; + bool loaded = false; }; mutable std::unordered_map state; mutable std::mutex mutex; diff --git a/src/indexer.cc b/src/indexer.cc index 177d4be5..567dcf50 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -51,7 +51,7 @@ struct IndexParam { std::unordered_map SeenUniqueID; std::unordered_map UID2multi; std::unordered_map file_contents; - std::unordered_map file2write_time; + std::unordered_map file2mtime; struct DeclInfo { Usr usr; std::string short_name; @@ -71,13 +71,7 @@ struct IndexParam { if (inserted) { std::string file_name = FileName(File); it->second = file_name; - - // Set modification time. - std::optional write_time = LastWriteTime(file_name); - LOG_IF_S(ERROR, !write_time) - << "failed to fetch write time for " << file_name; - if (write_time) - file2write_time[file_name] = *write_time; + file2mtime[file_name] = File.getModificationTime(); } } @@ -1307,13 +1301,13 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, Uniquify(it.second.uses); // Update file contents and modification time. - entry->last_write_time = param.file2write_time[entry->path]; + entry->mtime = param.file2mtime[entry->path]; // Update dependencies for the file. Do not include the file in its own // dependency set. for (auto &[_, path] : param.SeenUniqueID) if (path != entry->path && path != entry->import_file) - entry->dependencies[path] = param.file2write_time[path]; + entry->dependencies[path] = param.file2mtime[path]; } return result; diff --git a/src/indexer.h b/src/indexer.h index dc4fe774..797b0096 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -247,7 +247,8 @@ struct IndexFile { llvm::sys::fs::UniqueID UniqueID; std::string path; std::vector args; - int64_t last_write_time = 0; + // This is unfortunately time_t as used by clang::FileEntry + int64_t mtime = 0; LanguageId language = LanguageId::C; // uid2lid_and_path is used to generate lid2path, but not serialized. diff --git a/src/messages/ccls_freshenIndex.cc b/src/messages/ccls_freshenIndex.cc index edf23b4d..a49e0243 100644 --- a/src/messages/ccls_freshenIndex.cc +++ b/src/messages/ccls_freshenIndex.cc @@ -69,7 +69,8 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler { q.pop(); need_index.insert(file->def->path); - std::optional write_time = LastWriteTime(file->def->path); + std::optional write_time = + pipeline::LastWriteTime(file->def->path); if (!write_time) continue; { diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index cfbca19e..fdbfa349 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -438,10 +438,7 @@ struct Handler_Initialize : BaseMessageHandler { Reflect(json_writer, *g_config); LOG_S(INFO) << "initializationOptions: " << output.GetString(); - if (g_config->cacheDirectory.empty()) { - LOG_S(ERROR) << "cacheDirectory cannot be empty."; - exit(1); - } else { + if (g_config->cacheDirectory.size()) { g_config->cacheDirectory = NormalizePath(g_config->cacheDirectory); EnsureEndsInSlash(g_config->cacheDirectory); } @@ -470,12 +467,14 @@ struct Handler_Initialize : BaseMessageHandler { // Set project root. EnsureEndsInSlash(project_path); g_config->projectRoot = project_path; - // Create two cache directories for files inside and outside of the - // project. - sys::fs::create_directories(g_config->cacheDirectory + - EscapeFileName(g_config->projectRoot)); - sys::fs::create_directories(g_config->cacheDirectory + '@' + - EscapeFileName(g_config->projectRoot)); + if (g_config->cacheDirectory.size()) { + // Create two cache directories for files inside and outside of the + // project. + sys::fs::create_directories(g_config->cacheDirectory + + EscapeFileName(g_config->projectRoot)); + sys::fs::create_directories(g_config->cacheDirectory + '@' + + EscapeFileName(g_config->projectRoot)); + } diag_pub->Init(); idx::Init(); diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc index 1704282d..f010ae04 100644 --- a/src/messages/textDocument_didChange.cc +++ b/src/messages/textDocument_didChange.cc @@ -36,15 +36,17 @@ struct Handler_TextDocumentDidChange MethodType GetMethodType() const override { return kMethodType; } void Run(In_TextDocumentDidChange *request) override { - std::string path = request->params.textDocument.uri.GetPath(); - working_files->OnChange(request->params); + const auto ¶ms = request->params; + std::string path = params.textDocument.uri.GetPath(); + working_files->OnChange(params); if (g_config->index.onChange) { Project::Entry entry = project->FindCompilationEntryForFile(path); pipeline::Index(entry.filename, entry.args, IndexMode::OnChange); } - clang_complete->NotifyEdit(path); - clang_complete->DiagnosticsUpdate( - request->params.textDocument.AsTextDocumentIdentifier()); + clang_complete->NotifyView(path); + if (g_config->diagnostics.onChange) + clang_complete->DiagnosticsUpdate( + params.textDocument.AsTextDocumentIdentifier()); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index b88d3b94..2dc25c01 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -53,7 +53,7 @@ struct Handler_TextDocumentDidOpen WorkingFile *working_file = working_files->OnOpen(params.textDocument); if (std::optional cached_file_contents = - pipeline::LoadCachedFileContents(path)) + pipeline::LoadIndexedContent(path)) working_file->SetIndexContent(*cached_file_contents); QueryFile *file = nullptr; diff --git a/src/pipeline.cc b/src/pipeline.cc index c9f5c370..c973f564 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -95,12 +95,18 @@ ThreadedQueue *index_request; ThreadedQueue *on_indexed; ThreadedQueue *for_stdout; +struct InMemoryIndexFile { + std::string content; + IndexFile index; +}; +std::unordered_map g_index; + bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path, const std::vector &args, const std::optional &from) { { std::lock_guard lock(vfs->mutex); - if (prev->last_write_time < vfs->state[path].timestamp) { + if (prev->mtime < vfs->state[path].timestamp) { LOG_S(INFO) << "timestamp changed for " << path << (from ? " (via " + *from + ")" : std::string()); return true; @@ -140,6 +146,13 @@ std::string GetCachePath(const std::string &source_file) { } std::unique_ptr RawCacheLoad(const std::string &path) { + if (g_config->cacheDirectory.empty()) { + auto it = g_index.find(path); + if (it == g_index.end()) + return nullptr; + return std::make_unique(it->second.index); + } + std::string cache_path = GetCachePath(path); std::optional file_content = ReadContent(cache_path); std::optional serialized_indexed_content = @@ -267,7 +280,18 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, for (std::unique_ptr &curr : indexes) { std::string path = curr->path; - if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index)) + bool do_update = path == path_to_index, loaded; + { + std::lock_guard lock(vfs->mutex); + VFS::State &st = vfs->state[path]; + if (st.timestamp < curr->mtime) { + st.timestamp = curr->mtime; + do_update = true; + } + loaded = st.loaded; + st.loaded = true; + } + if (!do_update) continue; if (std::string reason; !matcher.IsMatch(path, &reason)) { LOG_IF_S(INFO, loud) << "skip emitting and storing index of " << path << " for " @@ -275,15 +299,22 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, continue; } - LOG_IF_S(INFO, loud) << "emit index for " << path; - prev = RawCacheLoad(path); + prev.reset(); + if (loaded) + prev = RawCacheLoad(path); - // Write current index to disk if requested. - { + // Store current index. + LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev + << ")"; + if (g_config->cacheDirectory.empty()) { + auto it = g_index.insert_or_assign( + path, InMemoryIndexFile{curr->file_contents, *curr}); + std::string().swap(it.first->second.index.file_contents); + } else { std::string cache_path = GetCachePath(path); WriteToFile(cache_path, curr->file_contents); WriteToFile(AppendSerializationFormat(cache_path), - Serialize(g_config->cacheFormat, *curr)); + Serialize(g_config->cacheFormat, *curr)); } vfs->Reset(path); @@ -295,8 +326,6 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, // Build delta update. IndexUpdate update = IndexUpdate::CreateDelta(prev.get(), curr.get()); - LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev - << ")"; on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); @@ -510,7 +539,20 @@ void Index(const std::string &path, const std::vector &args, index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } -std::optional LoadCachedFileContents(const std::string &path) { +std::optional LastWriteTime(const std::string &path) { + sys::fs::file_status Status; + if (sys::fs::status(path, Status)) + return {}; + return sys::toTimeT(Status.getLastModificationTime()); +} + +std::optional LoadIndexedContent(const std::string &path) { + if (g_config->cacheDirectory.empty()) { + auto it = g_index.find(path); + if (it == g_index.end()) + return {}; + return it->second.content; + } return ReadContent(GetCachePath(path)); } diff --git a/src/pipeline.hh b/src/pipeline.hh index 3ad96636..3c49285c 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -46,7 +46,8 @@ void MainLoop(); void Index(const std::string &path, const std::vector &args, IndexMode mode, lsRequestId id = {}); -std::optional LoadCachedFileContents(const std::string& path); -void WriteStdout(MethodType method, lsBaseOutMessage& response); -} -} +std::optional LastWriteTime(const std::string &path); +std::optional LoadIndexedContent(const std::string& path); +void WriteStdout(MethodType method, lsBaseOutMessage &response); +} // namespace pipeline +} // namespace ccls diff --git a/src/serializer.cc b/src/serializer.cc index 487650b0..41c10d9a 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -309,7 +309,7 @@ bool ReflectMemberStart(Writer &visitor, IndexFile &value) { template void Reflect(TVisitor &visitor, IndexFile &value) { REFLECT_MEMBER_START(); if (!gTestOutputMode) { - REFLECT_MEMBER(last_write_time); + REFLECT_MEMBER(mtime); REFLECT_MEMBER(language); REFLECT_MEMBER(lid2path); REFLECT_MEMBER(import_file); diff --git a/src/utils.cc b/src/utils.cc index 36a7e0e4..df5b98c8 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -15,13 +15,13 @@ limitations under the License. #include "utils.h" -#include "filesystem.hh" -using namespace llvm; #include "log.hh" #include "platform.h" #include +#include "llvm/ADT/StringRef.h" + #include #include #include @@ -29,7 +29,6 @@ using namespace llvm; #include #include #include -using namespace std::placeholders; void TrimInPlace(std::string &s) { auto f = [](char c) { return !isspace(c); }; @@ -69,7 +68,8 @@ bool StartsWith(std::string_view s, std::string_view prefix) { } bool EndsWithAny(std::string_view s, const std::vector &ss) { - return std::any_of(ss.begin(), ss.end(), std::bind(EndsWith, s, _1)); + return std::any_of(ss.begin(), ss.end(), + std::bind(EndsWith, s, std::placeholders::_1)); } bool FindAnyPartial(const std::string &value, @@ -147,13 +147,6 @@ void WriteToFile(const std::string &filename, const std::string &content) { fclose(f); } -std::optional LastWriteTime(const std::string &filename) { - sys::fs::file_status Status; - if (sys::fs::status(filename, Status)) - return {}; - return Status.getLastModificationTime().time_since_epoch().count(); -} - // Find discontinous |search| in |content|. // Return |found| and the count of skipped chars before found. int ReverseSubseqMatch(std::string_view pat, std::string_view text, diff --git a/src/utils.h b/src/utils.h index 973243fd..40352e1a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -75,7 +75,6 @@ std::string EscapeFileName(std::string path); std::optional ReadContent(const std::string &filename); void WriteToFile(const std::string &filename, const std::string &content); -std::optional LastWriteTime(const std::string &filename); int ReverseSubseqMatch(std::string_view pat, std::string_view text, int case_sensitivity); From da982a6506fccef9c947f1825d8a05abbe7c9d97 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 8 Sep 2018 12:07:43 -0700 Subject: [PATCH 20/66] Reuse preamble (built by "comp-preload") in indexer --- src/clang_complete.cc | 86 ++++++++----------- src/{clang_complete.h => clang_complete.hh} | 20 ++--- src/config.h | 4 +- src/indexer.cc | 37 ++++++-- src/indexer.h | 10 ++- src/message_handler.h | 4 +- src/messages/initialize.cc | 4 +- src/messages/textDocument_codeLens.cc | 2 +- src/messages/textDocument_completion.cc | 6 +- src/messages/textDocument_didChange.cc | 2 +- src/messages/textDocument_didClose.cc | 2 +- src/messages/textDocument_didOpen.cc | 2 +- src/messages/textDocument_didSave.cc | 2 +- src/messages/textDocument_signatureHelp.cc | 4 +- .../workspace_didChangeConfiguration.cc | 2 +- .../workspace_didChangeWatchedFiles.cc | 2 +- src/pipeline.cc | 19 ++-- src/pipeline.hh | 8 +- src/test.cc | 7 +- 19 files changed, 121 insertions(+), 102 deletions(-) rename src/{clang_complete.h => clang_complete.hh} (91%) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 9f9b671f..f6a84820 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "clang_utils.h" #include "filesystem.hh" @@ -525,7 +525,7 @@ bool Parse(CompilerInstance &Clang) { return true; } -void CompletionPreloadMain(ClangCompleteManager *completion_manager) { +void CompletionPreloadMain(CompletionManager *completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. auto request = completion_manager->preload_requests_.Dequeue(); @@ -550,10 +550,10 @@ void CompletionPreloadMain(ClangCompleteManager *completion_manager) { } } -void CompletionMain(ClangCompleteManager *completion_manager) { +void CompletionMain(CompletionManager *completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. - std::unique_ptr request = + std::unique_ptr request = completion_manager->completion_request_.Dequeue(); // Drop older requests if we're not buffering. @@ -606,10 +606,10 @@ void CompletionMain(ClangCompleteManager *completion_manager) { } } -void DiagnosticMain(ClangCompleteManager *manager) { +void DiagnosticMain(CompletionManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. - ClangCompleteManager::DiagnosticRequest request = + CompletionManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); std::string path = request.document.uri.GetPath(); @@ -699,10 +699,10 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) { } // namespace ccls -ClangCompleteManager::ClangCompleteManager(Project *project, - WorkingFiles *working_files, - OnDiagnostic on_diagnostic, - OnDropped on_dropped) +CompletionManager::CompletionManager(Project *project, + WorkingFiles *working_files, + OnDiagnostic on_diagnostic, + OnDropped on_dropped) : project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_dropped_(on_dropped), preloaded_sessions_(kMaxPreloadedSessions), @@ -725,7 +725,7 @@ ClangCompleteManager::ClangCompleteManager(Project *project, .detach(); } -void ClangCompleteManager::CodeComplete( +void CompletionManager::CodeComplete( const lsRequestId &id, const lsTextDocumentPositionParams &completion_location, const OnComplete &on_complete) { @@ -734,7 +734,7 @@ void ClangCompleteManager::CodeComplete( on_complete)); } -void ClangCompleteManager::DiagnosticsUpdate( +void CompletionManager::DiagnosticsUpdate( const lsTextDocumentIdentifier &document) { bool has = false; diagnostic_request_.Iterate([&](const DiagnosticRequest &request) { @@ -746,29 +746,13 @@ void ClangCompleteManager::DiagnosticsUpdate( true /*priority*/); } -void ClangCompleteManager::NotifyView(const std::string &filename) { - // - // On view, we reparse only if the file has not been parsed. The existence of - // a CompletionSession instance implies the file is already parsed or will be - // parsed soon. - // - +void CompletionManager::NotifyView(const std::string &path) { // Only reparse the file if we create a new CompletionSession. - if (EnsureCompletionOrCreatePreloadSession(filename)) - preload_requests_.PushBack(PreloadRequest(filename), true); + if (EnsureCompletionOrCreatePreloadSession(path)) + preload_requests_.PushBack(PreloadRequest(path), true); } -void ClangCompleteManager::NotifyEdit(const std::string &filename) { - // - // We treat an edit like a view, because the completion logic will handle - // moving the CompletionSession instance from preloaded to completion - // storage. - // - - NotifyView(filename); -} - -void ClangCompleteManager::NotifySave(const std::string &filename) { +void CompletionManager::NotifySave(const std::string &filename) { // // On save, always reparse. // @@ -777,7 +761,7 @@ void ClangCompleteManager::NotifySave(const std::string &filename) { preload_requests_.PushBack(PreloadRequest(filename), true); } -void ClangCompleteManager::NotifyClose(const std::string &filename) { +void CompletionManager::NotifyClose(const std::string &filename) { // // On close, we clear any existing CompletionSession instance. // @@ -797,63 +781,63 @@ void ClangCompleteManager::NotifyClose(const std::string &filename) { assert((preloaded_ptr && completion_ptr) == false); } -bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession( - const std::string &filename) { +bool CompletionManager::EnsureCompletionOrCreatePreloadSession( + const std::string &path) { std::lock_guard lock(sessions_lock_); // Check for an existing CompletionSession. - if (preloaded_sessions_.TryGet(filename) || - completion_sessions_.TryGet(filename)) { + if (preloaded_sessions_.TryGet(path) || + completion_sessions_.TryGet(path)) { return false; } // No CompletionSession, create new one. auto session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_, PCH); + project_->FindCompilationEntryForFile(path), working_files_, PCH); preloaded_sessions_.Insert(session->file.filename, session); return true; } std::shared_ptr -ClangCompleteManager::TryGetSession(const std::string &filename, - bool mark_as_completion, - bool create_if_needed) { +CompletionManager::TryGetSession(const std::string &path, + bool mark_as_completion, + bool create_if_needed) { std::lock_guard lock(sessions_lock_); // Try to find a preloaded session. std::shared_ptr preloaded = - preloaded_sessions_.TryGet(filename); + preloaded_sessions_.TryGet(path); if (preloaded) { // If this request is for a completion, we should move it to // |completion_sessions|. if (mark_as_completion) { - preloaded_sessions_.TryTake(filename); - completion_sessions_.Insert(filename, preloaded); + preloaded_sessions_.TryTake(path); + completion_sessions_.Insert(path, preloaded); } return preloaded; } // Try to find a completion session. If none create one. std::shared_ptr session = - completion_sessions_.TryGet(filename); + completion_sessions_.TryGet(path); if (!session && create_if_needed) { session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_, PCH); - completion_sessions_.Insert(filename, session); + project_->FindCompilationEntryForFile(path), working_files_, PCH); + completion_sessions_.Insert(path, session); } return session; } -void ClangCompleteManager::FlushSession(const std::string &filename) { +void CompletionManager::FlushSession(const std::string &path) { std::lock_guard lock(sessions_lock_); - preloaded_sessions_.TryTake(filename); - completion_sessions_.TryTake(filename); + preloaded_sessions_.TryTake(path); + completion_sessions_.TryTake(path); } -void ClangCompleteManager::FlushAllSessions() { +void CompletionManager::FlushAllSessions() { LOG_S(INFO) << "flush all clang complete sessions"; std::lock_guard lock(sessions_lock_); diff --git a/src/clang_complete.h b/src/clang_complete.hh similarity index 91% rename from src/clang_complete.h rename to src/clang_complete.hh index 92716e41..94e9fc36 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.hh @@ -76,7 +76,7 @@ struct CompletionSession }; } -struct ClangCompleteManager { +struct CompletionManager { using OnDiagnostic = std::function diagnostics)>; using OnComplete = std::function - TryGetSession(const std::string &filename, bool mark_as_completion, + TryGetSession(const std::string &path, bool mark_as_completion, bool create_if_needed); // Flushes all saved sessions with the supplied filename - void FlushSession(const std::string &filename); + void FlushSession(const std::string &path); // Flushes all saved sessions void FlushAllSessions(void); diff --git a/src/config.h b/src/config.h index ae234f72..565c671c 100644 --- a/src/config.h +++ b/src/config.h @@ -154,6 +154,8 @@ struct Config { // If true, diagnostics will be reported for textDocument/didOpen. bool onOpen = true; + bool spellChecking = true; + std::vector whitelist; } diagnostics; @@ -238,7 +240,7 @@ MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, includeMaxPathSize, includeSuffixWhitelist, includeWhitelist); MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, - onOpen, whitelist) + onOpen, spellChecking, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, diff --git a/src/indexer.cc b/src/indexer.cc index 567dcf50..55586691 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -15,12 +15,13 @@ limitations under the License. #include "indexer.h" +#include "clang_complete.hh" #include "clang_tu.h" #include "log.hh" #include "match.h" #include "platform.h" #include "serializer.h" -using ccls::Intern; +using namespace ccls; #include #include @@ -1195,7 +1196,8 @@ void Init() { } std::vector> -Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, +Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, + const std::string &opt_wdir, const std::string &file, const std::vector &args, const std::vector> &remapped) { if (!g_config->index.enabled) @@ -1221,13 +1223,32 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, // HSOpts.UseBuiltinIncludes) // HSOpts.ResourceDir = g_config->clang.resourceDir; } + std::string buf = wfiles->GetContent(file); std::vector> Bufs; - for (auto &[filename, content] : remapped) { - Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content)); - CI->getPreprocessorOpts().addRemappedFile( - filename == file ? CI->getFrontendOpts().Inputs[0].getFile() - : StringRef(filename), - Bufs.back().get()); + if (buf.size()) { + // If there is a completion session, reuse its preamble if exists. + bool done_remap = false; + std::shared_ptr session = + completion->TryGetSession(file, false, false); + if (session) + if (auto preamble = session->GetPreamble()) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(buf)); + auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), Bufs.back().get(), 0); + if (preamble->Preamble.CanReuse(*CI, Bufs.back().get(), Bounds, + FS.get())) { + preamble->Preamble.AddImplicitPreamble(*CI, FS, Bufs.back().get()); + done_remap = true; + } + } + for (auto &[filename, content] : remapped) { + if (filename == file && done_remap) + continue; + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content)); + CI->getPreprocessorOpts().addRemappedFile( + filename == file ? CI->getFrontendOpts().Inputs[0].getFile() + : StringRef(filename), + Bufs.back().get()); + } } DiagnosticConsumer DC; diff --git a/src/indexer.h b/src/indexer.h index 797b0096..ab20ba30 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -284,10 +284,14 @@ struct IndexFile { std::string ToString(); }; +struct CompletionManager; +struct WorkingFiles; + namespace ccls::idx { void Init(); std::vector> -Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, +Index(CompletionManager *complete, WorkingFiles *wfiles, VFS *vfs, + const std::string &opt_wdir, const std::string &file, const std::vector &args, - const std::vector>& remapped); -} // namespace ccls::idx + const std::vector> &remapped); +} diff --git a/src/message_handler.h b/src/message_handler.h index 99da9d30..3d314222 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -26,7 +26,7 @@ limitations under the License. #include #include -struct ClangCompleteManager; +struct CompletionManager; struct CodeCompleteCache; struct Config; class DiagnosticsPublisher; @@ -119,7 +119,7 @@ struct MessageHandler { ImportManager *import_manager = nullptr; SemanticHighlightSymbolCache *semantic_cache = nullptr; WorkingFiles *working_files = nullptr; - ClangCompleteManager *clang_complete = nullptr; + CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; CodeCompleteCache *global_code_complete_cache = nullptr; CodeCompleteCache *non_global_code_complete_cache = nullptr; diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index fdbfa349..332f8c5b 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_complete.hh" #include "filesystem.hh" #include "include_complete.h" #include "log.hh" @@ -495,7 +496,8 @@ struct Handler_Initialize : BaseMessageHandler { g_thread_id = i + 1; std::string name = "indexer" + std::to_string(i); set_thread_name(name.c_str()); - pipeline::Indexer_Main(diag_pub, vfs, project, working_files); + pipeline::Indexer_Main(clang_complete, diag_pub, vfs, project, + working_files); }) .detach(); } diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index 730441e7..ccf235fd 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "lsp_code_action.h" #include "message_handler.h" #include "pipeline.hh" diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 9582b578..78383969 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "fuzzy_match.h" #include "include_complete.h" #include "message_handler.h" @@ -380,7 +380,7 @@ struct Handler_TextDocumentCompletion : MessageHandler { pipeline::WriteStdout(kMethodType, out); } else { - ClangCompleteManager::OnComplete callback = std::bind( + CompletionManager::OnComplete callback = std::bind( [this, request, params, is_global_completion, existing_completion, has_open_paren](const std::vector &results, bool is_cached_result) { @@ -420,7 +420,7 @@ struct Handler_TextDocumentCompletion : MessageHandler { !global_code_complete_cache->cached_results_.empty(); }); if (is_cache_match) { - ClangCompleteManager::OnComplete freshen_global = + CompletionManager::OnComplete freshen_global = [this](std::vector results, bool is_cached_result) { assert(!is_cached_result); diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc index f010ae04..5b50714c 100644 --- a/src/messages/textDocument_didChange.cc +++ b/src/messages/textDocument_didChange.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" diff --git a/src/messages/textDocument_didClose.cc b/src/messages/textDocument_didClose.cc index 8187ee7d..8e3f504f 100644 --- a/src/messages/textDocument_didClose.cc +++ b/src/messages/textDocument_didClose.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "working_files.h" diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 2dc25c01..146c22c0 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "include_complete.h" #include "message_handler.h" #include "pipeline.hh" diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 023d1bb3..0badb21c 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 8799a542..1a763e21 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" using namespace ccls; @@ -114,7 +114,7 @@ struct Handler_TextDocumentSignatureHelp : MessageHandler { if (search.empty()) return; - ClangCompleteManager::OnComplete callback = std::bind( + CompletionManager::OnComplete callback = std::bind( [this](InMessage *message, std::string search, int active_param, const std::vector &results, bool is_cached_result) { diff --git a/src/messages/workspace_didChangeConfiguration.cc b/src/messages/workspace_didChangeConfiguration.cc index eb5b2d88..9b9ba474 100644 --- a/src/messages/workspace_didChangeConfiguration.cc +++ b/src/messages/workspace_didChangeConfiguration.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index b2c3eef5..5d872859 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" diff --git a/src/pipeline.cc b/src/pipeline.cc index c973f564..ffab9e29 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -15,7 +15,7 @@ limitations under the License. #include "pipeline.hh" -#include "clang_complete.h" +#include "clang_complete.hh" #include "config.h" #include "include_complete.h" #include "log.hh" @@ -165,7 +165,8 @@ std::unique_ptr RawCacheLoad(const std::string &path) { IndexFile::kMajorVersion); } -bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, +bool Indexer_Parse(CompletionManager *completion, + DiagnosticsPublisher *diag_pub, WorkingFiles *wfiles, Project *project, VFS *vfs, const GroupMatch &matcher) { std::optional opt_request = index_request->TryPopFront(); if (!opt_request) @@ -259,12 +260,12 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, std::vector> remapped; if (g_config->index.onChange) { - std::string content = working_files->GetContent(request.path); + std::string content = wfiles->GetContent(request.path); if (content.size()) remapped.emplace_back(request.path, content); } - auto indexes = - idx::Index(vfs, entry.directory, path_to_index, entry.args, remapped); + auto indexes = idx::Index(completion, wfiles, vfs, entry.directory, + path_to_index, entry.args, remapped); if (indexes.empty()) { if (g_config->index.enabled && request.id.Valid()) { @@ -348,11 +349,13 @@ void Init() { for_stdout = new ThreadedQueue(stdout_waiter); } -void Indexer_Main(DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, +void Indexer_Main(CompletionManager *completion, + DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, WorkingFiles *working_files) { GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); while (true) - if (!Indexer_Parse(diag_pub, working_files, project, vfs, matcher)) + if (!Indexer_Parse(completion, diag_pub, working_files, project, vfs, + matcher)) indexer_waiter->Wait(index_request); } @@ -464,7 +467,7 @@ void MainLoop() { VFS vfs; DiagnosticsPublisher diag_pub; - ClangCompleteManager clang_complete( + CompletionManager clang_complete( &project, &working_files, [&](std::string path, std::vector diagnostics) { diag_pub.Publish(&working_files, path, diagnostics); diff --git a/src/pipeline.hh b/src/pipeline.hh index 3c49285c..da9bfc9e 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -8,6 +8,7 @@ #include #include +struct CompletionManager; struct GroupMatch; struct VFS; struct Project; @@ -37,10 +38,9 @@ namespace pipeline { void Init(); void LaunchStdin(); void LaunchStdout(); -void Indexer_Main(DiagnosticsPublisher* diag_pub, - VFS* vfs, - Project* project, - WorkingFiles* working_files); +void Indexer_Main(CompletionManager *complete, + DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, + WorkingFiles *working_files); void MainLoop(); void Index(const std::string &path, const std::vector &args, diff --git a/src/test.cc b/src/test.cc index b93a21b9..19d52a9e 100644 --- a/src/test.cc +++ b/src/test.cc @@ -15,6 +15,7 @@ limitations under the License. #include "test.h" +#include "clang_complete.hh" #include "filesystem.hh" #include "indexer.h" #include "platform.h" @@ -301,7 +302,11 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { // Run test. g_config = new Config; VFS vfs; - auto dbs = ccls::idx::Index(&vfs, "", path, flags, {}); + CompletionManager completion( + nullptr, nullptr, [&](std::string, std::vector) {}, + [](lsRequestId id) {}); + WorkingFiles wfiles; + auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, flags, {}); for (const auto &entry : all_expected_output) { const std::string &expected_path = entry.first; From 92ee7f3e0fbad1b23e125abda42abcfc9206cf7a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 8 Sep 2018 16:00:14 -0700 Subject: [PATCH 21/66] Add diagnostics.onSave --- src/config.h | 5 ++++- src/messages/initialize.cc | 3 +-- src/messages/textDocument_didSave.cc | 2 ++ src/pipeline.cc | 11 ++++------- src/pipeline.hh | 5 ++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/config.h b/src/config.h index 565c671c..310d8dba 100644 --- a/src/config.h +++ b/src/config.h @@ -154,6 +154,9 @@ struct Config { // If true, diagnostics will be reported for textDocument/didOpen. bool onOpen = true; + // If true, diagnostics will be reported for textDocument/didSave. + bool onSave = true; + bool spellChecking = true; std::vector whitelist; @@ -240,7 +243,7 @@ MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, includeMaxPathSize, includeSuffixWhitelist, includeWhitelist); MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, - onOpen, spellChecking, whitelist) + onOpen, onSave, spellChecking, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 332f8c5b..c4516ef1 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -496,8 +496,7 @@ struct Handler_Initialize : BaseMessageHandler { g_thread_id = i + 1; std::string name = "indexer" + std::to_string(i); set_thread_name(name.c_str()); - pipeline::Indexer_Main(clang_complete, diag_pub, vfs, project, - working_files); + pipeline::Indexer_Main(clang_complete, vfs, project, working_files); }) .detach(); } diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 0badb21c..08520a92 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -49,6 +49,8 @@ struct Handler_TextDocumentDidSave Project::Entry entry = project->FindCompilationEntryForFile(path); pipeline::Index(entry.filename, entry.args, IndexMode::Normal); clang_complete->NotifySave(path); + if (g_config->diagnostics.onSave) + clang_complete->DiagnosticsUpdate(params.textDocument); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); diff --git a/src/pipeline.cc b/src/pipeline.cc index ffab9e29..e6df6fd9 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -165,8 +165,7 @@ std::unique_ptr RawCacheLoad(const std::string &path) { IndexFile::kMajorVersion); } -bool Indexer_Parse(CompletionManager *completion, - DiagnosticsPublisher *diag_pub, WorkingFiles *wfiles, +bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, Project *project, VFS *vfs, const GroupMatch &matcher) { std::optional opt_request = index_request->TryPopFront(); if (!opt_request) @@ -349,13 +348,11 @@ void Init() { for_stdout = new ThreadedQueue(stdout_waiter); } -void Indexer_Main(CompletionManager *completion, - DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, - WorkingFiles *working_files) { +void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, + WorkingFiles *wfiles) { GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); while (true) - if (!Indexer_Parse(completion, diag_pub, working_files, project, vfs, - matcher)) + if (!Indexer_Parse(completion, wfiles, project, vfs, matcher)) indexer_waiter->Wait(index_request); } diff --git a/src/pipeline.hh b/src/pipeline.hh index da9bfc9e..6e311d5c 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -38,9 +38,8 @@ namespace pipeline { void Init(); void LaunchStdin(); void LaunchStdout(); -void Indexer_Main(CompletionManager *complete, - DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, - WorkingFiles *working_files); +void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, + WorkingFiles *wfiles); void MainLoop(); void Index(const std::string &path, const std::vector &args, From c202dd3775b1b563943c7e31726c9b2dcea2bead Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 8 Sep 2018 17:49:52 -0700 Subject: [PATCH 22/66] Make CXXConversion references wider; use getTypedefNameForAnonDecl; improve CXXDestructor CXXConversion spell --- index_tests/constructors/destructor.cc | 2 +- .../inheritance/multiple_base_functions.cc | 6 +-- src/indexer.cc | 42 +++++++++++++++++-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/index_tests/constructors/destructor.cc b/index_tests/constructors/destructor.cc index 3bb394d2..97207f37 100644 --- a/index_tests/constructors/destructor.cc +++ b/index_tests/constructors/destructor.cc @@ -56,7 +56,7 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "4:3-4:4|15041163540773201510|2|1026|-1", + "spell": "4:3-4:7|15041163540773201510|2|1026|-1", "extent": "4:3-4:12|15041163540773201510|2|0|-1", "bases": [], "derived": [], diff --git a/index_tests/inheritance/multiple_base_functions.cc b/index_tests/inheritance/multiple_base_functions.cc index 11719475..76cd27ee 100644 --- a/index_tests/inheritance/multiple_base_functions.cc +++ b/index_tests/inheritance/multiple_base_functions.cc @@ -21,7 +21,7 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "5:11-5:12|15826803741381445676|2|1090|-1", + "spell": "5:11-5:17|15826803741381445676|2|1090|-1", "extent": "5:3-5:23|15826803741381445676|2|0|-1", "bases": [], "derived": [], @@ -36,7 +36,7 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "8:3-8:4|10963370434658308541|2|5186|-1", + "spell": "8:3-8:11|10963370434658308541|2|5186|-1", "extent": "8:3-8:26|10963370434658308541|2|0|-1", "bases": [], "derived": [], @@ -51,7 +51,7 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:11-2:12|11628904180681204356|2|1090|-1", + "spell": "2:11-2:17|11628904180681204356|2|1090|-1", "extent": "2:3-2:23|11628904180681204356|2|0|-1", "bases": [], "derived": [], diff --git a/src/indexer.cc b/src/indexer.cc index 55586691..3d9e2d67 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -675,6 +675,21 @@ public: IndexParam::DeclInfo *info; Usr usr = GetUsr(D, &info); + if (is_def) + switch (OrigD->getKind()) { + case Decl::CXXConversion: // *operator* int => *operator int* + case Decl::CXXDestructor: // *~*A => *~A* + if (Loc.isFileID()) { + SourceRange R = + cast(OrigD)->getNameInfo().getSourceRange(); + if (R.getEnd().isFileID()) + loc = FromTokenRange(SM, Lang, R); + } + break; + default: + break; + } + auto do_def_decl = [&](auto *entity) { if (is_def) { entity->def.spell = GetUse(db, lid, loc, SemDC, role); @@ -704,8 +719,10 @@ public: return true; case SymbolKind::Func: func = &db->ToFunc(usr); - // Span one more column to the left/right if D is CXXConstructor. - if (!is_def && !is_decl && D->getKind() == Decl::CXXConstructor) + // Mark as Role::Implicit to span one more column to the left/right. + if (!is_def && !is_decl && + (D->getKind() == Decl::CXXConstructor || + D->getKind() == Decl::CXXConversion)) role = Role(role | Role::Implicit); do_def_decl(func); if (Spell != Loc) @@ -728,7 +745,7 @@ public: do_def_decl(type); if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Type, Spell); - if (type->def.detailed_name[0] == '\0') + if (type->def.detailed_name[0] == '\0' && info->short_name.size()) SetName(OrigD, info->short_name, info->qualified, type->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); @@ -885,6 +902,25 @@ public: // spec has no Union, use Class type->def.kind = RD->getTagKind() == TTK_Struct ? lsSymbolKind::Struct : lsSymbolKind::Class; + if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) { + if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) { + StringRef Name = TD->getName(); + StringRef Tag; + switch (RD->getTagKind()) { + case TTK_Struct: Tag = "struct "; break; + case TTK_Interface: Tag = "__interface "; break; + case TTK_Union: Tag = "union "; break; + case TTK_Class: Tag = "class "; break; + case TTK_Enum: Tag = "enum "; break; + } + std::string name = ("anon " + Tag + Name).str(); + type->def.detailed_name = Intern(name); + type->def.short_name_size = name.size(); + } else { + // e.g. "struct {}" + SetName(OrigD, "", "", type->def); + } + } if (is_def) { SmallVector, 2> Stack{{RD, 0}}; llvm::DenseSet Seen; From a7c1633b519e3b6ee16f8bca302fea0043333f94 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 9 Sep 2018 23:46:13 -0700 Subject: [PATCH 23/66] Misc --- src/indexer.cc | 2 +- src/message_handler.cc | 4 ++-- src/messages/workspace_didChangeWatchedFiles.cc | 4 ++-- src/pipeline.cc | 12 +++++++++--- src/project.cc | 16 ++++++++++++---- src/project.h | 2 +- src/query.cc | 17 +++++++++++------ 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index 3d9e2d67..a29988c9 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1261,7 +1261,7 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, } std::string buf = wfiles->GetContent(file); std::vector> Bufs; - if (buf.size()) { + if (g_config->index.onChange && buf.size()) { // If there is a completion session, reuse its preamble if exists. bool done_remap = false; std::shared_ptr session = diff --git a/src/message_handler.cc b/src/message_handler.cc index f4d6aae0..ab6d937b 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -160,8 +160,8 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, bool indexing; { std::lock_guard lock(project->mutex_); - indexing = project->absolute_path_to_entry_index_.find(absolute_path) != - project->absolute_path_to_entry_index_.end(); + indexing = project->path_to_entry_index.find(absolute_path) != + project->path_to_entry_index.end(); } if (indexing) LOG_S(INFO) << "\"" << absolute_path << "\" is being indexed."; diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index 5d872859..8ba46408 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -57,8 +57,8 @@ struct Handler_WorkspaceDidChangeWatchedFiles Project::Entry entry; { std::lock_guard lock(project->mutex_); - auto it = project->absolute_path_to_entry_index_.find(path); - if (it == project->absolute_path_to_entry_index_.end()) + auto it = project->path_to_entry_index.find(path); + if (it == project->path_to_entry_index.end()) continue; entry = project->entries[it->second]; } diff --git a/src/pipeline.cc b/src/pipeline.cc index e6df6fd9..31ae2a2a 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -32,6 +32,8 @@ limitations under the License. using namespace llvm; #include +#include +#include #include #ifndef _WIN32 #include @@ -99,6 +101,7 @@ struct InMemoryIndexFile { std::string content; IndexFile index; }; +std::shared_mutex g_index_mutex; std::unordered_map g_index; bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path, @@ -147,6 +150,7 @@ std::string GetCachePath(const std::string &source_file) { std::unique_ptr RawCacheLoad(const std::string &path) { if (g_config->cacheDirectory.empty()) { + std::shared_lock lock(g_index_mutex); auto it = g_index.find(path); if (it == g_index.end()) return nullptr; @@ -189,8 +193,8 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, Project::Entry entry; { std::lock_guard lock(project->mutex_); - auto it = project->absolute_path_to_entry_index_.find(request.path); - if (it != project->absolute_path_to_entry_index_.end()) + auto it = project->path_to_entry_index.find(request.path); + if (it != project->path_to_entry_index.end()) entry = project->entries[it->second]; else { entry.filename = request.path; @@ -307,6 +311,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev << ")"; if (g_config->cacheDirectory.empty()) { + std::lock_guard lock(g_index_mutex); auto it = g_index.insert_or_assign( path, InMemoryIndexFile{curr->file_contents, *curr}); std::string().swap(it.first->second.index.file_contents); @@ -321,7 +326,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (entry.id >= 0) { std::lock_guard lock(project->mutex_); for (auto &dep : curr->dependencies) - project->absolute_path_to_entry_index_[dep.first()] = entry.id; + project->path_to_entry_index[dep.first()] = entry.id; } // Build delta update. @@ -548,6 +553,7 @@ std::optional LastWriteTime(const std::string &path) { std::optional LoadIndexedContent(const std::string &path) { if (g_config->cacheDirectory.empty()) { + std::shared_lock lock(g_index_mutex); auto it = g_index.find(path); if (it == g_index.end()) return {}; diff --git a/src/project.cc b/src/project.cc index 173ec597..3cd4aa52 100644 --- a/src/project.cc +++ b/src/project.cc @@ -377,13 +377,21 @@ void Project::Load(const std::string &root_directory) { EnsureEndsInSlash(path); LOG_S(INFO) << "angle_include_dir: " << path; } + + // Setup project entries. + std::lock_guard lock(mutex_); + path_to_entry_index.reserve(entries.size()); + for (size_t i = 0; i < entries.size(); ++i) { + entries[i].id = i; + path_to_entry_index[entries[i].filename] = i; + } } void Project::SetFlagsForFile(const std::vector &flags, const std::string &path) { std::lock_guard lock(mutex_); - auto it = absolute_path_to_entry_index_.find(path); - if (it != absolute_path_to_entry_index_.end()) { + auto it = path_to_entry_index.find(path); + if (it != path_to_entry_index.end()) { // The entry already exists in the project, just set the flags. this->entries[it->second].args = flags; } else { @@ -400,8 +408,8 @@ Project::Entry Project::FindCompilationEntryForFile(const std::string &filename) { { std::lock_guard lock(mutex_); - auto it = absolute_path_to_entry_index_.find(filename); - if (it != absolute_path_to_entry_index_.end()) + auto it = path_to_entry_index.find(filename); + if (it != path_to_entry_index.end()) return entries[it->second]; } diff --git a/src/project.h b/src/project.h index 3baa545e..b431d1d4 100644 --- a/src/project.h +++ b/src/project.h @@ -43,7 +43,7 @@ struct Project { std::vector entries; std::mutex mutex_; - std::unordered_map absolute_path_to_entry_index_; + std::unordered_map path_to_entry_index; // Loads a project for the given |directory|. // diff --git a/src/query.cc b/src/query.cc index be657184..6ec74143 100644 --- a/src/query.cc +++ b/src/query.cc @@ -227,16 +227,21 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { SymbolKind kind, Use &use, int delta, int k = 1) { use.file_id = use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; + SymbolRef sym{{use.range, usr, kind, use.role}}; if (k & 1) { - int &v = - files[use.file_id] - .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]; + int &v = files[use.file_id].symbol2refcnt[sym]; v += delta; assert(v >= 0); + if (!v) + files[use.file_id].symbol2refcnt.erase(sym); + } + if (k & 2) { + int &v = files[use.file_id].outline2refcnt[sym]; + v += delta; + assert(v >= 0); + if (!v) + files[use.file_id].outline2refcnt.erase(sym); } - if (k & 2) - files[use.file_id] - .outline2refcnt[SymbolRef{{use.range, usr, kind, use.role}}] += delta; }; auto RefDecl = [&](std::unordered_map &lid2fid, Usr usr, SymbolKind kind, DeclRef &dr, int delta) { From c9e6b31dd040fe8ab0f4e60b6636c0c30fe5238b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 10 Sep 2018 22:37:01 -0700 Subject: [PATCH 24/66] Revamp completion and signatureHelp, set completion.detailedLabel: true and add completion.duplicateOptional --- src/clang_complete.cc | 358 +-------------------- src/clang_complete.hh | 36 ++- src/config.h | 28 +- src/message_handler.h | 6 - src/messages/textDocument_completion.cc | 344 +++++++++++++++----- src/messages/textDocument_signatureHelp.cc | 275 +++++++++------- src/pipeline.cc | 7 - src/working_files.cc | 24 +- src/working_files.h | 1 - 9 files changed, 485 insertions(+), 594 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index f6a84820..18b8ef37 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -23,6 +23,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -42,268 +43,6 @@ std::string StripFileType(const std::string &path) { return Ret.str(); } -unsigned GetCompletionPriority(const CodeCompletionString &CCS, - CXCursorKind result_kind, - const std::optional &typedText) { - unsigned priority = CCS.getPriority(); - if (CCS.getAvailability() != CXAvailability_Available || - result_kind == CXCursor_Destructor || - result_kind == CXCursor_ConversionFunction || - (result_kind == CXCursor_CXXMethod && typedText && - StartsWith(*typedText, "operator"))) - priority *= 100; - return priority; -} - -lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { - switch (cursor_kind) { - case CXCursor_UnexposedDecl: - return lsCompletionItemKind::Text; - - case CXCursor_StructDecl: - case CXCursor_UnionDecl: - return lsCompletionItemKind::Struct; - case CXCursor_ClassDecl: - return lsCompletionItemKind::Class; - case CXCursor_EnumDecl: - return lsCompletionItemKind::Enum; - case CXCursor_FieldDecl: - return lsCompletionItemKind::Field; - case CXCursor_EnumConstantDecl: - return lsCompletionItemKind::EnumMember; - case CXCursor_FunctionDecl: - return lsCompletionItemKind::Function; - case CXCursor_VarDecl: - case CXCursor_ParmDecl: - return lsCompletionItemKind::Variable; - case CXCursor_ObjCInterfaceDecl: - return lsCompletionItemKind::Interface; - - case CXCursor_ObjCInstanceMethodDecl: - case CXCursor_CXXMethod: - case CXCursor_ObjCClassMethodDecl: - return lsCompletionItemKind::Method; - - case CXCursor_FunctionTemplate: - return lsCompletionItemKind::Function; - - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: - return lsCompletionItemKind::Constructor; - - case CXCursor_ObjCIvarDecl: - return lsCompletionItemKind::Variable; - - case CXCursor_ClassTemplate: - case CXCursor_ClassTemplatePartialSpecialization: - case CXCursor_UsingDeclaration: - case CXCursor_TypedefDecl: - case CXCursor_TypeAliasDecl: - case CXCursor_TypeAliasTemplateDecl: - case CXCursor_ObjCCategoryDecl: - case CXCursor_ObjCProtocolDecl: - case CXCursor_ObjCImplementationDecl: - case CXCursor_ObjCCategoryImplDecl: - return lsCompletionItemKind::Class; - - case CXCursor_ObjCPropertyDecl: - return lsCompletionItemKind::Property; - - case CXCursor_MacroInstantiation: - case CXCursor_MacroDefinition: - return lsCompletionItemKind::Interface; - - case CXCursor_Namespace: - case CXCursor_NamespaceAlias: - case CXCursor_NamespaceRef: - return lsCompletionItemKind::Module; - - case CXCursor_MemberRef: - case CXCursor_TypeRef: - case CXCursor_ObjCSuperClassRef: - case CXCursor_ObjCProtocolRef: - case CXCursor_ObjCClassRef: - return lsCompletionItemKind::Reference; - - // return lsCompletionItemKind::Unit; - // return lsCompletionItemKind::Value; - // return lsCompletionItemKind::Keyword; - // return lsCompletionItemKind::Snippet; - // return lsCompletionItemKind::Color; - // return lsCompletionItemKind::File; - - case CXCursor_NotImplemented: - case CXCursor_OverloadCandidate: - return lsCompletionItemKind::Text; - - case CXCursor_TemplateTypeParameter: - case CXCursor_TemplateTemplateParameter: - return lsCompletionItemKind::TypeParameter; - - default: - LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind; - return lsCompletionItemKind::Text; - } -} - -void BuildCompletionItemTexts(std::vector &out, - CodeCompletionString &CCS, - bool include_snippets) { - assert(!out.empty()); - auto out_first = out.size() - 1; - - std::string result_type; - - for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) { - const CodeCompletionString::Chunk &Chunk = CCS[i]; - CodeCompletionString::ChunkKind Kind = Chunk.Kind; - std::string text; - switch (Kind) { - case CodeCompletionString::CK_TypedText: - case CodeCompletionString::CK_Text: - case CodeCompletionString::CK_Placeholder: - case CodeCompletionString::CK_Informative: - if (Chunk.Text) - text = Chunk.Text; - for (auto i = out_first; i < out.size(); i++) { - // first TypedText is used for filtering - if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText) - out[i].filterText = text; - if (Kind == CodeCompletionString::CK_Placeholder) - out[i].parameters_.push_back(text); - } - break; - case CodeCompletionString::CK_ResultType: - if (Chunk.Text) - result_type = Chunk.Text; - continue; - case CodeCompletionString::CK_CurrentParameter: - // We have our own parsing logic for active parameter. This doesn't seem - // to be very reliable. - continue; - case CodeCompletionString::CK_Optional: { - // duplicate last element, the recursive call will complete it - out.push_back(out.back()); - BuildCompletionItemTexts(out, *Chunk.Optional, include_snippets); - continue; - } - // clang-format off - case CodeCompletionString::CK_LeftParen: text = '('; break; - case CodeCompletionString::CK_RightParen: text = ')'; break; - case CodeCompletionString::CK_LeftBracket: text = '['; break; - case CodeCompletionString::CK_RightBracket: text = ']'; break; - case CodeCompletionString::CK_LeftBrace: text = '{'; break; - case CodeCompletionString::CK_RightBrace: text = '}'; break; - case CodeCompletionString::CK_LeftAngle: text = '<'; break; - case CodeCompletionString::CK_RightAngle: text = '>'; break; - case CodeCompletionString::CK_Comma: text = ", "; break; - case CodeCompletionString::CK_Colon: text = ':'; break; - case CodeCompletionString::CK_SemiColon: text = ';'; break; - case CodeCompletionString::CK_Equal: text = '='; break; - case CodeCompletionString::CK_HorizontalSpace: text = ' '; break; - case CodeCompletionString::CK_VerticalSpace: text = ' '; break; - // clang-format on - } - - if (Kind != CodeCompletionString::CK_Informative) - for (auto i = out_first; i < out.size(); ++i) { - out[i].label += text; - if (!include_snippets && !out[i].parameters_.empty()) - continue; - - if (Kind == CodeCompletionString::CK_Placeholder) { - out[i].insertText += "${" + - std::to_string(out[i].parameters_.size()) + ":" + - text + "}"; - out[i].insertTextFormat = lsInsertTextFormat::Snippet; - } else { - out[i].insertText += text; - } - } - } - - if (result_type.size()) - for (auto i = out_first; i < out.size(); ++i) { - // ' : ' for variables, - // ' -> ' (trailing return type-like) for functions - out[i].label += (out[i].label == out[i].filterText ? " : " : " -> "); - out[i].label += result_type; - } -} - -// |do_insert|: if |!do_insert|, do not append strings to |insert| after -// a placeholder. -void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item, - bool &do_insert, std::vector *parameters, - bool include_snippets, int &angle_stack) { - for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) { - const CodeCompletionString::Chunk &Chunk = CCS[i]; - CodeCompletionString::ChunkKind Kind = Chunk.Kind; - const char *text = nullptr; - switch (Kind) { - case CodeCompletionString::CK_TypedText: - item.label = Chunk.Text; - [[fallthrough]]; - case CodeCompletionString::CK_Text: - item.detail += Chunk.Text; - if (do_insert) - item.insertText += Chunk.Text; - break; - case CodeCompletionString::CK_Placeholder: { - parameters->push_back(Chunk.Text); - item.detail += Chunk.Text; - // Add parameter declarations as snippets if enabled - if (include_snippets) { - item.insertText += - "${" + std::to_string(parameters->size()) + ":" + Chunk.Text + "}"; - item.insertTextFormat = lsInsertTextFormat::Snippet; - } else - do_insert = false; - break; - } - case CodeCompletionString::CK_Informative: - item.detail += Chunk.Text; - break; - case CodeCompletionString::CK_Optional: { - // Do not add text to insert string if we're in angle brackets. - bool should_insert = do_insert && angle_stack == 0; - BuildDetailString(*Chunk.Optional, item, should_insert, parameters, - include_snippets, angle_stack); - break; - } - case CodeCompletionString::CK_ResultType: - item.detail = Chunk.Text + item.detail + " "; - break; - case CodeCompletionString::CK_CurrentParameter: - // We have our own parsing logic for active parameter. This doesn't seem - // to be very reliable. - break; - // clang-format off - case CodeCompletionString::CK_LeftParen: text = "("; break; - case CodeCompletionString::CK_RightParen: text = ")"; break; - case CodeCompletionString::CK_LeftBracket: text = "["; break; - case CodeCompletionString::CK_RightBracket: text = "]"; break; - case CodeCompletionString::CK_LeftBrace: text = "{"; break; - case CodeCompletionString::CK_RightBrace: text = "}"; break; - case CodeCompletionString::CK_LeftAngle: text = "<"; angle_stack++; break; - case CodeCompletionString::CK_RightAngle: text = ">"; angle_stack--; break; - case CodeCompletionString::CK_Comma: text = ", "; break; - case CodeCompletionString::CK_Colon: text = ":"; break; - case CodeCompletionString::CK_SemiColon: text = ";"; break; - case CodeCompletionString::CK_Equal: text = "="; break; - case CodeCompletionString::CK_HorizontalSpace: - case CodeCompletionString::CK_VerticalSpace: text = " "; break; - // clang-format on - } - if (text) { - item.detail += text; - if (do_insert && include_snippets) - item.insertText += text; - } - } -} - bool LocationInRange(SourceLocation L, CharSourceRange R, const SourceManager &M) { assert(R.isCharRange()); @@ -336,70 +75,6 @@ CharSourceRange DiagnosticRange(const clang::Diagnostic &D, const LangOptions &L } -class CaptureCompletionResults : public CodeCompleteConsumer { - std::shared_ptr Alloc; - CodeCompletionTUInfo CCTUInfo; - -public: - std::vector ls_items; - - CaptureCompletionResults(const CodeCompleteOptions &Opts) - : CodeCompleteConsumer(Opts, false), - Alloc(std::make_shared()), - CCTUInfo(Alloc) {} - - void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, - CodeCompletionResult *Results, - unsigned NumResults) override { - ls_items.reserve(NumResults); - for (unsigned i = 0; i != NumResults; i++) { - auto &R = Results[i]; - if (R.Availability == CXAvailability_NotAccessible || - R.Availability == CXAvailability_NotAvailable) - continue; - CodeCompletionString *CCS = R.CreateCodeCompletionString( - S, Context, getAllocator(), getCodeCompletionTUInfo(), - includeBriefComments()); - lsCompletionItem ls_item; - ls_item.kind = GetCompletionKind(R.CursorKind); - if (const char *brief = CCS->getBriefComment()) - ls_item.documentation = brief; - - // label/detail/filterText/insertText/priority - if (g_config->completion.detailedLabel) { - ls_item.detail = CCS->getParentContextName().str(); - - size_t first_idx = ls_items.size(); - ls_items.push_back(ls_item); - BuildCompletionItemTexts(ls_items, *CCS, - g_config->client.snippetSupport); - - for (size_t j = first_idx; j < ls_items.size(); j++) { - if (g_config->client.snippetSupport && - ls_items[j].insertTextFormat == lsInsertTextFormat::Snippet) - ls_items[j].insertText += "$0"; - ls_items[j].priority_ = GetCompletionPriority( - *CCS, Results[i].CursorKind, ls_items[j].filterText); - } - } else { - bool do_insert = true; - int angle_stack = 0; - BuildDetailString(*CCS, ls_item, do_insert, &ls_item.parameters_, - g_config->client.snippetSupport, angle_stack); - if (g_config->client.snippetSupport && - ls_item.insertTextFormat == lsInsertTextFormat::Snippet) - ls_item.insertText += "$0"; - ls_item.priority_ = - GetCompletionPriority(*CCS, Results[i].CursorKind, ls_item.label); - ls_items.push_back(ls_item); - } - } - } - - CodeCompletionAllocator &getAllocator() override { return *Alloc; } - - CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } -}; class StoreDiags : public DiagnosticConsumer { const LangOptions *LangOpts; @@ -560,6 +235,8 @@ void CompletionMain(CompletionManager *completion_manager) { while (g_config->completion.dropOldRequests && !completion_manager->completion_request_.IsEmpty()) { completion_manager->on_dropped_(request->id); + request->Consumer.reset(); + request->on_complete(nullptr); request = completion_manager->completion_request_.Dequeue(); } @@ -573,15 +250,9 @@ void CompletionMain(CompletionManager *completion_manager) { BuildCompilerInvocation(session->file.args, session->FS); if (!CI) continue; - clang::CodeCompleteOptions CCOpts; - CCOpts.IncludeBriefComments = true; -#if LLVM_VERSION_MAJOR >= 7 - CCOpts.IncludeFixIts = true; -#endif - CCOpts.IncludeCodePatterns = true; auto &FOpts = CI->getFrontendOpts(); - FOpts.CodeCompleteOpts = CCOpts; - FOpts.CodeCompletionAt.FileName = session->file.filename; + FOpts.CodeCompleteOpts = request->CCOpts; + FOpts.CodeCompletionAt.FileName = path; FOpts.CodeCompletionAt.Line = request->position.line + 1; FOpts.CodeCompletionAt.Column = request->position.character + 1; FOpts.SkipFunctionBodies = true; @@ -595,14 +266,13 @@ void CompletionMain(CompletionManager *completion_manager) { if (!Clang) continue; - auto Consumer = new CaptureCompletionResults(CCOpts); - Clang->setCodeCompletionConsumer(Consumer); + Clang->setCodeCompletionConsumer(request->Consumer.release()); if (!Parse(*Clang)) continue; for (auto &Buf : Bufs) Buf.release(); - request->on_complete(Consumer->ls_items, false /*is_cached_result*/); + request->on_complete(&Clang->getCodeCompletionConsumer()); } } @@ -729,9 +399,6 @@ void CompletionManager::CodeComplete( const lsRequestId &id, const lsTextDocumentPositionParams &completion_location, const OnComplete &on_complete) { - completion_request_.PushBack(std::make_unique( - id, completion_location.textDocument, completion_location.position, - on_complete)); } void CompletionManager::DiagnosticsUpdate( @@ -844,14 +511,3 @@ void CompletionManager::FlushAllSessions() { preloaded_sessions_.Clear(); completion_sessions_.Clear(); } - -void CodeCompleteCache::WithLock(std::function action) { - std::lock_guard lock(mutex_); - action(); -} - -bool CodeCompleteCache::IsCacheValid(lsTextDocumentPositionParams position) { - std::lock_guard lock(mutex_); - return cached_path_ == position.textDocument.uri.GetPath() && - cached_completion_position_ == position.position; -} diff --git a/src/clang_complete.hh b/src/clang_complete.hh index 94e9fc36..81fd0020 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -25,6 +25,7 @@ limitations under the License. #include #include +#include #include #include @@ -79,8 +80,9 @@ struct CompletionSession struct CompletionManager { using OnDiagnostic = std::function diagnostics)>; - using OnComplete = std::function &results, bool is_cached_result)>; + // If OptConsumer is nullptr, the request has been cancelled. + using OnComplete = + std::function; using OnDropped = std::function; struct PreloadRequest { @@ -93,13 +95,19 @@ struct CompletionManager { struct CompletionRequest { CompletionRequest(const lsRequestId &id, const lsTextDocumentIdentifier &document, - const lsPosition &position, const OnComplete &on_complete) + const lsPosition &position, + std::unique_ptr Consumer, + clang::CodeCompleteOptions CCOpts, + const OnComplete &on_complete) : id(id), document(document), position(position), + Consumer(std::move(Consumer)), CCOpts(CCOpts), on_complete(on_complete) {} lsRequestId id; lsTextDocumentIdentifier document; lsPosition position; + std::unique_ptr Consumer; + clang::CodeCompleteOptions CCOpts; OnComplete on_complete; }; struct DiagnosticRequest { @@ -176,14 +184,22 @@ struct CompletionManager { // Cached completion information, so we can give fast completion results when // the user erases a character. vscode will resend the completion request if // that happens. -struct CodeCompleteCache { +template +struct CompleteConsumerCache { // NOTE: Make sure to access these variables under |WithLock|. - std::optional cached_path_; - std::optional cached_completion_position_; - std::vector cached_results_; + std::optional path; + std::optional position; + T result; - std::mutex mutex_; + std::mutex mutex; - void WithLock(std::function action); - bool IsCacheValid(lsTextDocumentPositionParams position); + void WithLock(std::function action) { + std::lock_guard lock(mutex); + action(); + } + bool IsCacheValid(const lsTextDocumentPositionParams ¶ms) { + std::lock_guard lock(mutex); + return path == params.textDocument.uri.GetPath() && + position == params.position; + } }; diff --git a/src/config.h b/src/config.h index 310d8dba..19093af1 100644 --- a/src/config.h +++ b/src/config.h @@ -92,16 +92,7 @@ struct Config { // When this option is enabled, the completion item label is very detailed, // it shows the full signature of the candidate. // The detail just contains the completion item parent context. - // Also, in this mode, functions with default arguments, - // generates one more item per default argument - // so that the right function call can be selected. - // That is, you get something like: - // "int foo()" "Foo" - // "void bar()" "Foo" - // "void bar(int i = 0)" "Foo" - // Be wary, this is quickly quite verbose, - // items can end up truncated by the UIs. - bool detailedLabel = false; + bool detailedLabel = true; // On large projects, completion can take a long time. By default if ccls // receives multiple completion requests while completion is still running @@ -109,6 +100,15 @@ struct Config { // completion requests will be serviced. bool dropOldRequests = true; + // Functions with default arguments, generate one more item per default + // argument. That is, you get something like: + // "int foo()" "Foo" + // "void bar()" "Foo" + // "void bar(int i = 0)" "Foo" + // Be wary, this is quickly quite verbose, + // items can end up truncated by the UIs. + bool duplicateOptional = true; + // If true, filter and sort completion response. ccls filters and sorts // completions to try to be nicer to clients that can't handle big numbers // of completion candidates. This behaviour can be disabled by specifying @@ -238,10 +238,10 @@ struct Config { MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, resourceDir); MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); -MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, - detailedLabel, filterAndSort, includeBlacklist, - includeMaxPathSize, includeSuffixWhitelist, - includeWhitelist); +MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, + dropOldRequests, duplicateOptional, filterAndSort, + includeBlacklist, includeMaxPathSize, + includeSuffixWhitelist, includeWhitelist); MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, onOpen, onSave, spellChecking, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) diff --git a/src/message_handler.h b/src/message_handler.h index 3d314222..ac1c8021 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -27,11 +27,9 @@ limitations under the License. #include struct CompletionManager; -struct CodeCompleteCache; struct Config; class DiagnosticsPublisher; struct VFS; -struct ImportManager; struct IncludeComplete; struct MultiQueueWaiter; struct Project; @@ -116,14 +114,10 @@ struct MessageHandler { Project *project = nullptr; DiagnosticsPublisher *diag_pub = nullptr; VFS *vfs = nullptr; - ImportManager *import_manager = nullptr; SemanticHighlightSymbolCache *semantic_cache = nullptr; WorkingFiles *working_files = nullptr; CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; - CodeCompleteCache *global_code_complete_cache = nullptr; - CodeCompleteCache *non_global_code_complete_cache = nullptr; - CodeCompleteCache *signature_cache = nullptr; virtual MethodType GetMethodType() const = 0; virtual void Run(std::unique_ptr message) = 0; diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 78383969..663a4a88 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -16,12 +16,16 @@ limitations under the License. #include "clang_complete.hh" #include "fuzzy_match.h" #include "include_complete.h" +#include "log.hh" #include "message_handler.h" #include "pipeline.hh" #include "working_files.h" using namespace ccls; +#include +#include #include +using namespace clang; using namespace llvm; #include @@ -261,24 +265,245 @@ bool IsOpenParenOrAngle(const std::vector &lines, return false; } -struct Handler_TextDocumentCompletion : MessageHandler { +unsigned GetCompletionPriority(const CodeCompletionString &CCS, + CXCursorKind result_kind, + const std::optional &typedText) { + unsigned priority = CCS.getPriority(); + if (CCS.getAvailability() != CXAvailability_Available || + result_kind == CXCursor_Destructor || + result_kind == CXCursor_ConversionFunction || + (result_kind == CXCursor_CXXMethod && typedText && + StartsWith(*typedText, "operator"))) + priority *= 100; + return priority; +} + +lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { + switch (cursor_kind) { + case CXCursor_UnexposedDecl: + return lsCompletionItemKind::Text; + + case CXCursor_StructDecl: + case CXCursor_UnionDecl: + return lsCompletionItemKind::Struct; + case CXCursor_ClassDecl: + return lsCompletionItemKind::Class; + case CXCursor_EnumDecl: + return lsCompletionItemKind::Enum; + case CXCursor_FieldDecl: + return lsCompletionItemKind::Field; + case CXCursor_EnumConstantDecl: + return lsCompletionItemKind::EnumMember; + case CXCursor_FunctionDecl: + return lsCompletionItemKind::Function; + case CXCursor_VarDecl: + case CXCursor_ParmDecl: + return lsCompletionItemKind::Variable; + case CXCursor_ObjCInterfaceDecl: + return lsCompletionItemKind::Interface; + + case CXCursor_ObjCInstanceMethodDecl: + case CXCursor_CXXMethod: + case CXCursor_ObjCClassMethodDecl: + return lsCompletionItemKind::Method; + + case CXCursor_FunctionTemplate: + return lsCompletionItemKind::Function; + + case CXCursor_Constructor: + case CXCursor_Destructor: + case CXCursor_ConversionFunction: + return lsCompletionItemKind::Constructor; + + case CXCursor_ObjCIvarDecl: + return lsCompletionItemKind::Variable; + + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + case CXCursor_UsingDeclaration: + case CXCursor_TypedefDecl: + case CXCursor_TypeAliasDecl: + case CXCursor_TypeAliasTemplateDecl: + case CXCursor_ObjCCategoryDecl: + case CXCursor_ObjCProtocolDecl: + case CXCursor_ObjCImplementationDecl: + case CXCursor_ObjCCategoryImplDecl: + return lsCompletionItemKind::Class; + + case CXCursor_ObjCPropertyDecl: + return lsCompletionItemKind::Property; + + case CXCursor_MacroInstantiation: + case CXCursor_MacroDefinition: + return lsCompletionItemKind::Interface; + + case CXCursor_Namespace: + case CXCursor_NamespaceAlias: + case CXCursor_NamespaceRef: + return lsCompletionItemKind::Module; + + case CXCursor_MemberRef: + case CXCursor_TypeRef: + case CXCursor_ObjCSuperClassRef: + case CXCursor_ObjCProtocolRef: + case CXCursor_ObjCClassRef: + return lsCompletionItemKind::Reference; + + // return lsCompletionItemKind::Unit; + // return lsCompletionItemKind::Value; + // return lsCompletionItemKind::Keyword; + // return lsCompletionItemKind::Snippet; + // return lsCompletionItemKind::Color; + // return lsCompletionItemKind::File; + + case CXCursor_NotImplemented: + case CXCursor_OverloadCandidate: + return lsCompletionItemKind::Text; + + case CXCursor_TemplateTypeParameter: + case CXCursor_TemplateTemplateParameter: + return lsCompletionItemKind::TypeParameter; + + default: + LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind; + return lsCompletionItemKind::Text; + } +} + +void BuildItem(std::vector &out, + const CodeCompletionString &CCS) { + assert(!out.empty()); + auto first = out.size() - 1; + + std::string result_type; + + for (const auto &Chunk : CCS) { + CodeCompletionString::ChunkKind Kind = Chunk.Kind; + std::string text; + switch (Kind) { + case CodeCompletionString::CK_TypedText: + text = Chunk.Text; + for (auto i = first; i < out.size(); i++) + if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText) + out[i].filterText = text; + break; + case CodeCompletionString::CK_Placeholder: + text = Chunk.Text; + for (auto i = first; i < out.size(); i++) + out[i].parameters_.push_back(text); + break; + case CodeCompletionString::CK_ResultType: + result_type = Chunk.Text; + continue; + case CodeCompletionString::CK_CurrentParameter: + // This should never be present while collecting completion items. + llvm_unreachable("unexpected CK_CurrentParameter"); + continue; + case CodeCompletionString::CK_Optional: { + // Duplicate last element, the recursive call will complete it. + if (g_config->completion.duplicateOptional) { + out.push_back(out.back()); + BuildItem(out, *Chunk.Optional); + } + continue; + } + default: + text = Chunk.Text; + break; + } + + for (auto i = first; i < out.size(); ++i) { + out[i].label += text; + if (!g_config->client.snippetSupport && !out[i].parameters_.empty()) + continue; + + if (Kind == CodeCompletionString::CK_Placeholder) { + out[i].insertText += + "${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}"; + out[i].insertTextFormat = lsInsertTextFormat::Snippet; + } else { + out[i].insertText += text; + } + } + } + + if (result_type.size()) + for (auto i = first; i < out.size(); ++i) { + // ' : ' for variables, + // ' -> ' (trailing return type-like) for functions + out[i].label += (out[i].label == out[i].filterText ? " : " : " -> "); + out[i].label += result_type; + } +} + +class CompletionConsumer : public CodeCompleteConsumer { + std::shared_ptr Alloc; + CodeCompletionTUInfo CCTUInfo; + +public: + bool from_cache; + std::vector ls_items; + + CompletionConsumer(const CodeCompleteOptions &Opts, bool from_cache) + : CodeCompleteConsumer(Opts, false), + Alloc(std::make_shared()), + CCTUInfo(Alloc), from_cache(from_cache) {} + + void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) override { + ls_items.reserve(NumResults); + for (unsigned i = 0; i != NumResults; i++) { + auto &R = Results[i]; + if (R.Availability == CXAvailability_NotAccessible || + R.Availability == CXAvailability_NotAvailable) + continue; + CodeCompletionString *CCS = R.CreateCodeCompletionString( + S, Context, getAllocator(), getCodeCompletionTUInfo(), + includeBriefComments()); + lsCompletionItem ls_item; + ls_item.kind = GetCompletionKind(R.CursorKind); + if (const char *brief = CCS->getBriefComment()) + ls_item.documentation = brief; + ls_item.detail = CCS->getParentContextName().str(); + + size_t first_idx = ls_items.size(); + ls_items.push_back(ls_item); + BuildItem(ls_items, *CCS); + + for (size_t j = first_idx; j < ls_items.size(); j++) { + if (g_config->client.snippetSupport && + ls_items[j].insertTextFormat == lsInsertTextFormat::Snippet) + ls_items[j].insertText += "$0"; + ls_items[j].priority_ = GetCompletionPriority( + *CCS, Results[i].CursorKind, ls_items[j].filterText); + if (!g_config->completion.detailedLabel) { + ls_items[j].detail = ls_items[j].label; + ls_items[j].label = ls_items[j].filterText.value_or(""); + } + } + } + } + + CodeCompletionAllocator &getAllocator() override { return *Alloc; } + CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } +}; + +struct Handler_TextDocumentCompletion + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(std::unique_ptr message) override { - auto request = std::shared_ptr( - static_cast(message.release())); - auto ¶ms = request->params; + void Run(In_TextDocumentComplete *request) override { + static CompleteConsumerCache> cache; - auto write_empty_result = [request]() { - Out_TextDocumentComplete out; - out.id = request->id; - pipeline::WriteStdout(kMethodType, out); - }; + auto ¶ms = request->params; + Out_TextDocumentComplete out; + out.id = request->id; std::string path = params.textDocument.uri.GetPath(); WorkingFile *file = working_files->GetFileByFilename(path); if (!file) { - write_empty_result(); + pipeline::WriteStdout(kMethodType, out); return; } @@ -323,19 +548,15 @@ struct Handler_TextDocumentCompletion : MessageHandler { } if (did_fail_check) { - write_empty_result(); + pipeline::WriteStdout(kMethodType, out); return; } } - bool is_global_completion = false; - std::string existing_completion; + std::string completion_text; lsPosition end_pos = params.position; - if (file) { - params.position = file->FindStableCompletionSource( - request->params.position, &is_global_completion, &existing_completion, - &end_pos); - } + params.position = file->FindStableCompletionSource( + request->params.position, &completion_text, &end_pos); ParseIncludeLineResult result = ParseIncludeLine(buffer_line); bool has_open_paren = IsOpenParenOrAngle(file->buffer_lines, end_pos); @@ -380,69 +601,44 @@ struct Handler_TextDocumentCompletion : MessageHandler { pipeline::WriteStdout(kMethodType, out); } else { - CompletionManager::OnComplete callback = std::bind( - [this, request, params, is_global_completion, existing_completion, - has_open_paren](const std::vector &results, - bool is_cached_result) { + CompletionManager::OnComplete callback = + [completion_text, has_open_paren, id = request->id, + params = request->params](CodeCompleteConsumer *OptConsumer) { + if (!OptConsumer) + return; + auto *Consumer = static_cast(OptConsumer); Out_TextDocumentComplete out; - out.id = request->id; - out.result.items = results; + out.id = id; + out.result.items = Consumer->ls_items; - // Emit completion results. - FilterAndSortCompletionResponse(&out, existing_completion, + FilterAndSortCompletionResponse(&out, completion_text, has_open_paren); pipeline::WriteStdout(kMethodType, out); - - // Cache completion results. - if (!is_cached_result) { + if (!Consumer->from_cache) { std::string path = params.textDocument.uri.GetPath(); - if (is_global_completion) { - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_path_ = path; - global_code_complete_cache->cached_results_ = results; - }); - } else { - non_global_code_complete_cache->WithLock([&]() { - non_global_code_complete_cache->cached_path_ = path; - non_global_code_complete_cache->cached_completion_position_ = - params.position; - non_global_code_complete_cache->cached_results_ = results; - }); - } - } - }, - std::placeholders::_1, std::placeholders::_2); - - bool is_cache_match = false; - global_code_complete_cache->WithLock([&]() { - is_cache_match = is_global_completion && - global_code_complete_cache->cached_path_ == path && - !global_code_complete_cache->cached_results_.empty(); - }); - if (is_cache_match) { - CompletionManager::OnComplete freshen_global = - [this](std::vector results, - bool is_cached_result) { - assert(!is_cached_result); - - // note: path is updated in the normal completion handler. - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_results_ = results; + cache.WithLock([&]() { + cache.path = path; + cache.position = params.position; + cache.result = Consumer->ls_items; }); - }; + } + }; - global_code_complete_cache->WithLock([&]() { - callback(global_code_complete_cache->cached_results_, - true /*is_cached_result*/); - }); - clang_complete->CodeComplete(request->id, params, freshen_global); - } else if (non_global_code_complete_cache->IsCacheValid(params)) { - non_global_code_complete_cache->WithLock([&]() { - callback(non_global_code_complete_cache->cached_results_, - true /*is_cached_result*/); - }); + clang::CodeCompleteOptions CCOpts; + CCOpts.IncludeBriefComments = true; +#if LLVM_VERSION_MAJOR >= 7 + CCOpts.IncludeFixIts = true; +#endif + if (cache.IsCacheValid(params)) { + CompletionConsumer Consumer(CCOpts, true); + cache.WithLock([&]() { Consumer.ls_items = cache.result; }); + callback(&Consumer); } else { - clang_complete->CodeComplete(request->id, params, callback); + clang_complete->completion_request_.PushBack( + std::make_unique( + request->id, params.textDocument, params.position, + std::make_unique(CCOpts, false), CCOpts, + callback)); } } } diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 1a763e21..4fcbd764 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -18,44 +18,29 @@ limitations under the License. #include "pipeline.hh" using namespace ccls; +#include +using namespace clang; + #include namespace { MethodType kMethodType = "textDocument/signatureHelp"; -struct In_TextDocumentSignatureHelp : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentSignatureHelp, id, params); -REGISTER_IN_MESSAGE(In_TextDocumentSignatureHelp); - // Represents a parameter of a callable-signature. A parameter can // have a label and a doc-comment. struct lsParameterInformation { - // The label of this parameter. Will be shown in - // the UI. std::string label; - - // The human-readable doc-comment of this parameter. Will be shown - // in the UI but can be omitted. - std::optional documentation; + // Not available in clang + // std::optional documentation; }; -MAKE_REFLECT_STRUCT(lsParameterInformation, label, documentation); +MAKE_REFLECT_STRUCT(lsParameterInformation, label); // Represents the signature of something callable. A signature // can have a label, like a function-name, a doc-comment, and // a set of parameters. struct lsSignatureInformation { - // The label of this signature. Will be shown in - // the UI. std::string label; - - // The human-readable doc-comment of this signature. Will be shown - // in the UI but can be omitted. std::optional documentation; - - // The parameters of this signature. std::vector parameters; }; MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); @@ -64,30 +49,20 @@ MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); // callable. There can be multiple signature but only one // active and only one active parameter. struct lsSignatureHelp { - // One or more signatures. std::vector signatures; - - // The active signature. If omitted or the value lies outside the - // range of `signatures` the value defaults to zero or is ignored if - // `signatures.length === 0`. Whenever possible implementors should - // make an active decision about the active signature and shouldn't - // rely on a default value. - // In future version of the protocol this property might become - // mandantory to better express this. - std::optional activeSignature; - - // The active parameter of the active signature. If omitted or the value - // lies outside the range of `signatures[activeSignature].parameters` - // defaults to 0 if the active signature has parameters. If - // the active signature has no parameters it is ignored. - // In future version of the protocol this property might become - // mandantory to better express the active parameter if the - // active signature does have any. - std::optional activeParameter; + int activeSignature = 0; + int activeParameter; }; MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature, activeParameter); +struct In_TextDocumentSignatureHelp : public RequestInMessage { + MethodType GetMethodType() const override { return kMethodType; } + lsTextDocumentPositionParams params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentSignatureHelp, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentSignatureHelp); + struct Out_TextDocumentSignatureHelp : public lsOutMessage { lsRequestId id; @@ -95,88 +70,164 @@ struct Out_TextDocumentSignatureHelp }; MAKE_REFLECT_STRUCT(Out_TextDocumentSignatureHelp, jsonrpc, id, result); -struct Handler_TextDocumentSignatureHelp : MessageHandler { +std::string BuildOptional(const CodeCompletionString &CCS, + std::vector &ls_params) { + std::string ret; + for (const auto &Chunk : CCS) { + switch (Chunk.Kind) { + case CodeCompletionString::CK_Optional: + ret += BuildOptional(*Chunk.Optional, ls_params); + break; + case CodeCompletionString::CK_Placeholder: + // A string that acts as a placeholder for, e.g., a function call + // argument. + // Intentional fallthrough here. + case CodeCompletionString::CK_CurrentParameter: { + // A piece of text that describes the parameter that corresponds to + // the code-completion location within a function call, message send, + // macro invocation, etc. + ret += Chunk.Text; + ls_params.push_back(lsParameterInformation{Chunk.Text}); + break; + } + case CodeCompletionString::CK_VerticalSpace: + break; + default: + ret += Chunk.Text; + break; + } + } + return ret; +} + +class SignatureHelpConsumer : public CodeCompleteConsumer { + std::shared_ptr Alloc; + CodeCompletionTUInfo CCTUInfo; +public: + bool from_cache; + lsSignatureHelp ls_sighelp; + SignatureHelpConsumer(const clang::CodeCompleteOptions &CCOpts, + bool from_cache) + : CodeCompleteConsumer(CCOpts, false), + Alloc(std::make_shared()), + CCTUInfo(Alloc), from_cache(from_cache) {} + void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates +#if LLVM_VERSION_MAJOR >= 8 + , + SourceLocation OpenParLoc +#endif + ) override { + ls_sighelp.activeParameter = (int)CurrentArg; + for (unsigned i = 0; i < NumCandidates; i++) { + OverloadCandidate Cand = Candidates[i]; + // We want to avoid showing instantiated signatures, because they may be + // long in some cases (e.g. when 'T' is substituted with 'std::string', we + // would get 'std::basic_string'). + if (auto *Func = Cand.getFunction()) + if (auto *Pattern = Func->getTemplateInstantiationPattern()) + Cand = OverloadCandidate(Pattern); + + const auto *CCS = + Cand.CreateSignatureString(CurrentArg, S, *Alloc, CCTUInfo, true); + + const char *ret_type = nullptr; + lsSignatureInformation &ls_sig = ls_sighelp.signatures.emplace_back(); +#if LLVM_VERSION_MAJOR >= 8 + const RawComment *RC = getCompletionComment(S.getASTContext(), Cand.getFunction()); + ls_sig.documentation = RC ? RC->getBriefText(S.getASTContext()) : ""; +#endif + for (const auto &Chunk : *CCS) + switch (Chunk.Kind) { + case CodeCompletionString::CK_ResultType: + ret_type = Chunk.Text; + break; + case CodeCompletionString::CK_Placeholder: + case CodeCompletionString::CK_CurrentParameter: { + ls_sig.label += Chunk.Text; + ls_sig.parameters.push_back(lsParameterInformation{Chunk.Text}); + break; + } + case CodeCompletionString::CK_Optional: + ls_sig.label += BuildOptional(*Chunk.Optional, ls_sig.parameters); + break; + case CodeCompletionString::CK_VerticalSpace: + break; + default: + ls_sig.label += Chunk.Text; + break; + } + if (ret_type) { + ls_sig.label += " -> "; + ls_sig.label += ret_type; + } + } + std::sort( + ls_sighelp.signatures.begin(), ls_sighelp.signatures.end(), + [](const lsSignatureInformation &l, const lsSignatureInformation &r) { + if (l.parameters.size() != r.parameters.size()) + return l.parameters.size() < r.parameters.size(); + if (l.label.size() != r.label.size()) + return l.label.size() < r.label.size(); + return l.label < r.label; + }); + } + + CodeCompletionAllocator &getAllocator() override { return *Alloc; } + CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } +}; + +struct Handler_TextDocumentSignatureHelp + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(std::unique_ptr message) override { - auto request = static_cast(message.get()); - lsTextDocumentPositionParams ¶ms = request->params; - WorkingFile *file = - working_files->GetFileByFilename(params.textDocument.uri.GetPath()); - std::string search; - int active_param = 0; - if (file) { - lsPosition completion_position; - search = file->FindClosestCallNameInBuffer(params.position, &active_param, - &completion_position); - params.position = completion_position; + void Run(In_TextDocumentSignatureHelp *request) override { + static CompleteConsumerCache cache; + + auto ¶ms = request->params; + std::string path = params.textDocument.uri.GetPath(); + if (WorkingFile *file = working_files->GetFileByFilename(path)) { + std::string completion_text; + lsPosition end_pos = params.position; + params.position = file->FindStableCompletionSource( + request->params.position, &completion_text, &end_pos); } - if (search.empty()) - return; - - CompletionManager::OnComplete callback = std::bind( - [this](InMessage *message, std::string search, int active_param, - const std::vector &results, - bool is_cached_result) { - auto msg = static_cast(message); + CompletionManager::OnComplete callback = + [id = request->id, + params = request->params](CodeCompleteConsumer *OptConsumer) { + if (!OptConsumer) + return; + auto *Consumer = static_cast(OptConsumer); Out_TextDocumentSignatureHelp out; - out.id = msg->id; - - for (auto &result : results) { - if (result.label != search) - continue; - - lsSignatureInformation signature; - signature.label = result.detail; - for (auto ¶meter : result.parameters_) { - lsParameterInformation ls_param; - ls_param.label = parameter; - signature.parameters.push_back(ls_param); - } - out.result.signatures.push_back(signature); - } - - // Prefer the signature with least parameter count but still larger - // than active_param. - out.result.activeSignature = 0; - if (out.result.signatures.size()) { - size_t num_parameters = SIZE_MAX; - for (size_t i = 0; i < out.result.signatures.size(); ++i) { - size_t t = out.result.signatures[i].parameters.size(); - if (active_param < t && t < num_parameters) { - out.result.activeSignature = int(i); - num_parameters = t; - } - } - } - - // Set signature to what we parsed from the working file. - out.result.activeParameter = active_param; - + out.id = id; + out.result = Consumer->ls_sighelp; pipeline::WriteStdout(kMethodType, out); - - if (!is_cached_result) { - signature_cache->WithLock([&]() { - signature_cache->cached_path_ = - msg->params.textDocument.uri.GetPath(); - signature_cache->cached_completion_position_ = - msg->params.position; - signature_cache->cached_results_ = results; + if (!Consumer->from_cache) { + std::string path = params.textDocument.uri.GetPath(); + cache.WithLock([&]() { + cache.path = path; + cache.position = params.position; + cache.result = Consumer->ls_sighelp; }); } + }; - delete message; - }, - message.release(), search, active_param, std::placeholders::_1, - std::placeholders::_2); - - if (signature_cache->IsCacheValid(params)) { - signature_cache->WithLock([&]() { - callback(signature_cache->cached_results_, true /*is_cached_result*/); - }); + CodeCompleteOptions CCOpts; + CCOpts.IncludeGlobals = false; + CCOpts.IncludeMacros = false; + CCOpts.IncludeBriefComments = false; + if (cache.IsCacheValid(params)) { + SignatureHelpConsumer Consumer(CCOpts, true); + cache.WithLock([&]() { Consumer.ls_sighelp = cache.result; }); + callback(&Consumer); } else { - clang_complete->CodeComplete(request->id, params, std::move(callback)); + clang_complete->completion_request_.PushBack( + std::make_unique( + request->id, params.textDocument, params.position, + std::make_unique(CCOpts, false), CCOpts, + callback)); } } }; diff --git a/src/pipeline.cc b/src/pipeline.cc index 31ae2a2a..be30a5f8 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -486,9 +486,6 @@ void MainLoop() { }); IncludeComplete include_complete(&project); - auto global_code_complete_cache = std::make_unique(); - auto non_global_code_complete_cache = std::make_unique(); - auto signature_cache = std::make_unique(); DB db; // Setup shared references. @@ -502,10 +499,6 @@ void MainLoop() { handler->working_files = &working_files; handler->clang_complete = &clang_complete; handler->include_complete = &include_complete; - handler->global_code_complete_cache = global_code_complete_cache.get(); - handler->non_global_code_complete_cache = - non_global_code_complete_cache.get(); - handler->signature_cache = signature_cache.get(); } while (true) { diff --git a/src/working_files.cc b/src/working_files.cc index 74b9f30d..319a887e 100644 --- a/src/working_files.cc +++ b/src/working_files.cc @@ -387,31 +387,17 @@ std::string WorkingFile::FindClosestCallNameInBuffer( return buffer_content.substr(offset, start_offset - offset + 1); } -lsPosition WorkingFile::FindStableCompletionSource( - lsPosition position, bool *is_global_completion, - std::string *existing_completion, lsPosition *replace_end_pos) const { - *is_global_completion = true; - +lsPosition +WorkingFile::FindStableCompletionSource(lsPosition position, + std::string *existing_completion, + lsPosition *replace_end_pos) const { int start_offset = GetOffsetForPosition(position, buffer_content); int offset = start_offset; while (offset > 0) { char c = buffer_content[offset - 1]; - if (!isalnum(c) && c != '_') { - // Global completion is everything except for dot (.), arrow (->), and - // double colon (::) - if (c == '.') - *is_global_completion = false; - if (offset > 2) { - char pc = buffer_content[offset - 2]; - if (pc == ':' && c == ':') - *is_global_completion = false; - else if (pc == '-' && c == '>') - *is_global_completion = false; - } - + if (!isalnum(c) && c != '_') break; - } --offset; } diff --git a/src/working_files.h b/src/working_files.h index dcd8fa84..caa001fd 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -82,7 +82,6 @@ struct WorkingFile { // The out param |existing_completion| is set to any existing completion // content the user has entered. lsPosition FindStableCompletionSource(lsPosition position, - bool *is_global_completion, std::string *existing_completion, lsPosition *replace_end_pos) const; From a45686ae1b2aa8b0fa26e79452e9775ad2cc0f23 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 11 Sep 2018 16:42:04 -0700 Subject: [PATCH 25/66] diagnostics; use custom DenseMapInfo --- src/clang_complete.cc | 19 +++++---- src/clang_complete.hh | 4 -- src/messages/textDocument_didSave.cc | 2 - src/query.cc | 61 ++++++++++++++-------------- src/query.h | 27 ++++++------ src/query_utils.cc | 6 +-- 6 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 18b8ef37..335123c9 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -200,17 +200,15 @@ bool Parse(CompilerInstance &Clang) { return true; } -void CompletionPreloadMain(CompletionManager *completion_manager) { +void CompletionPreloadMain(CompletionManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. - auto request = completion_manager->preload_requests_.Dequeue(); + auto request = manager->preload_requests_.Dequeue(); // If we don't get a session then that means we don't care about the file // anymore - abandon the request. - std::shared_ptr session = - completion_manager->TryGetSession(request.path, - false /*mark_as_completion*/, - false /*create_if_needed*/); + std::shared_ptr session = manager->TryGetSession( + request.path, false /*mark_as_completion*/, false /*create_if_needed*/); if (!session) continue; @@ -222,6 +220,11 @@ void CompletionPreloadMain(CompletionManager *completion_manager) { if (std::unique_ptr CI = BuildCompilerInvocation(args, session->FS)) session->BuildPreamble(*CI); + if (g_config->diagnostics.onSave) { + lsTextDocumentIdentifier document; + document.uri = lsDocumentUri::FromPath(request.path); + manager->diagnostic_request_.PushBack({document}, true); + } } } @@ -416,7 +419,7 @@ void CompletionManager::DiagnosticsUpdate( void CompletionManager::NotifyView(const std::string &path) { // Only reparse the file if we create a new CompletionSession. if (EnsureCompletionOrCreatePreloadSession(path)) - preload_requests_.PushBack(PreloadRequest(path), true); + preload_requests_.PushBack(PreloadRequest{path}, true); } void CompletionManager::NotifySave(const std::string &filename) { @@ -425,7 +428,7 @@ void CompletionManager::NotifySave(const std::string &filename) { // EnsureCompletionOrCreatePreloadSession(filename); - preload_requests_.PushBack(PreloadRequest(filename), true); + preload_requests_.PushBack(PreloadRequest{filename}, true); } void CompletionManager::NotifyClose(const std::string &filename) { diff --git a/src/clang_complete.hh b/src/clang_complete.hh index 81fd0020..c7232692 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -86,10 +86,6 @@ struct CompletionManager { using OnDropped = std::function; struct PreloadRequest { - PreloadRequest(const std::string &path) - : request_time(std::chrono::high_resolution_clock::now()), path(path) {} - - std::chrono::time_point request_time; std::string path; }; struct CompletionRequest { diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 08520a92..0badb21c 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -49,8 +49,6 @@ struct Handler_TextDocumentDidSave Project::Entry entry = project->FindCompilationEntryForFile(path); pipeline::Index(entry.filename, entry.args, IndexMode::Normal); clang_complete->NotifySave(path); - if (g_config->diagnostics.onSave) - clang_complete->DiagnosticsUpdate(params.textDocument); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); diff --git a/src/query.cc b/src/query.cc index 6ec74143..e84040d4 100644 --- a/src/query.cc +++ b/src/query.cc @@ -250,36 +250,37 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { .outline2refcnt[SymbolRef{{dr.extent, usr, kind, dr.role}}] += delta; }; - auto UpdateUses = [&](Usr usr, SymbolKind kind, - llvm::DenseMap &entity_usr, - auto &entities, auto &p, bool hint_implicit) { - auto R = entity_usr.try_emplace({usr}, entity_usr.size()); - if (R.second) - vars.emplace_back().usr = usr; - auto &entity = entities[R.first->second]; - for (Use &use : p.first) { - if (hint_implicit && use.role & Role::Implicit) { - // Make ranges of implicit function calls larger (spanning one more - // column to the left/right). This is hacky but useful. e.g. - // textDocument/definition on the space/semicolon in `A a;` or ` 42;` - // will take you to the constructor. - if (use.range.start.column > 0) - use.range.start.column--; - use.range.end.column++; - } - Ref(prev_lid2file_id, usr, kind, use, -1); - } - RemoveRange(entity.uses, p.first); - for (Use &use : p.second) { - if (hint_implicit && use.role & Role::Implicit) { - if (use.range.start.column > 0) - use.range.start.column--; - use.range.end.column++; - } - Ref(lid2file_id, usr, kind, use, 1); - } - AddRange(entity.uses, p.second); - }; + auto UpdateUses = + [&](Usr usr, SymbolKind kind, + llvm::DenseMap &entity_usr, + auto &entities, auto &p, bool hint_implicit) { + auto R = entity_usr.try_emplace(usr, entity_usr.size()); + if (R.second) + vars.emplace_back().usr = usr; + auto &entity = entities[R.first->second]; + for (Use &use : p.first) { + if (hint_implicit && use.role & Role::Implicit) { + // Make ranges of implicit function calls larger (spanning one more + // column to the left/right). This is hacky but useful. e.g. + // textDocument/definition on the space/semicolon in `A a;` or ` + // 42;` will take you to the constructor. + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; + } + Ref(prev_lid2file_id, usr, kind, use, -1); + } + RemoveRange(entity.uses, p.first); + for (Use &use : p.second) { + if (hint_implicit && use.role & Role::Implicit) { + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; + } + Ref(lid2file_id, usr, kind, use, 1); + } + AddRange(entity.uses, p.second); + }; if (u->files_removed) files[name2file_id[LowerPathIfInsensitive(*u->files_removed)]].def = diff --git a/src/query.h b/src/query.h index 7cf17018..1d4ebf3c 100644 --- a/src/query.h +++ b/src/query.h @@ -147,14 +147,11 @@ struct IndexUpdate { UseUpdate vars_uses; }; -struct WrappedUsr { - Usr usr; -}; -template <> struct llvm::DenseMapInfo { - static inline WrappedUsr getEmptyKey() { return {0}; } - static inline WrappedUsr getTombstoneKey() { return {~0ULL}; } - static unsigned getHashValue(WrappedUsr w) { return w.usr; } - static bool isEqual(WrappedUsr l, WrappedUsr r) { return l.usr == r.usr; } +struct DenseMapInfoForUsr { + static inline Usr getEmptyKey() { return 0; } + static inline Usr getTombstoneKey() { return ~0ULL; } + static unsigned getHashValue(Usr w) { return w; } + static bool isEqual(Usr l, Usr r) { return l == r; } }; using Lid2file_id = std::unordered_map; @@ -164,7 +161,7 @@ using Lid2file_id = std::unordered_map; struct DB { std::vector files; llvm::StringMap name2file_id; - llvm::DenseMap func_usr, type_usr, var_usr; + llvm::DenseMap func_usr, type_usr, var_usr; std::vector funcs; std::vector types; std::vector vars; @@ -184,13 +181,13 @@ struct DB { std::vector> &&us); std::string_view GetSymbolName(SymbolIdx sym, bool qualified); - bool HasFunc(Usr usr) const { return func_usr.count({usr}); } - bool HasType(Usr usr) const { return type_usr.count({usr}); } - bool HasVar(Usr usr) const { return var_usr.count({usr}); } + bool HasFunc(Usr usr) const { return func_usr.count(usr); } + bool HasType(Usr usr) const { return type_usr.count(usr); } + bool HasVar(Usr usr) const { return var_usr.count(usr); } - QueryFunc &Func(Usr usr) { return funcs[func_usr[{usr}]]; } - QueryType &Type(Usr usr) { return types[type_usr[{usr}]]; } - QueryVar &Var(Usr usr) { return vars[var_usr[{usr}]]; } + QueryFunc &Func(Usr usr) { return funcs[func_usr[usr]]; } + QueryType &Type(Usr usr) { return types[type_usr[usr]]; } + QueryVar &Var(Usr usr) { return vars[var_usr[usr]]; } QueryFile &GetFile(SymbolIdx ref) { return files[ref.usr]; } QueryFunc &GetFunc(SymbolIdx ref) { return Func(ref.usr); } diff --git a/src/query_utils.cc b/src/query_utils.cc index af885525..749b9088 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -30,9 +30,9 @@ int ComputeRangeSize(const Range &range) { } template -std::vector GetDeclarations(llvm::DenseMap &entity_usr, - std::vector &entities, - const std::vector &usrs) { +std::vector +GetDeclarations(llvm::DenseMap &entity_usr, + std::vector &entities, const std::vector &usrs) { std::vector ret; ret.reserve(usrs.size()); for (Usr usr : usrs) { From a607dcec248a2404e5122e2f7d692efb5cd60afa Mon Sep 17 00:00:00 2001 From: Riatre Foo Date: Wed, 12 Sep 2018 03:13:54 +0800 Subject: [PATCH 26/66] Normalize paths on Windows 1. Normalize paths in LSP document URIs and project root to forward slash and uppercase drive letters. 2. Normalize paths in compile_commands.json to forward slash and uppercase drive letters. 3. Normalize paths from directory listing to forward slash. (Drive letter should be same as input dir path, which is already uppercase since path of project root dir is normalized) 4. Add llvm::sys::path::convert_to_slash after certain llvm::sys::path and llvm::fs calls. --- src/clang_complete.cc | 2 +- src/clang_utils.cc | 2 +- src/filesystem.cc | 2 +- src/indexer.cc | 2 +- src/lsp.cc | 15 +++++++++++++-- src/platform_win.cc | 11 ++++++++--- src/project.cc | 8 +++++--- 7 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 335123c9..3fa70c32 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -40,7 +40,7 @@ namespace { std::string StripFileType(const std::string &path) { SmallString<128> Ret; sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path)); - return Ret.str(); + return sys::path::convert_to_slash(Ret); } bool LocationInRange(SourceLocation L, CharSourceRange R, diff --git a/src/clang_utils.cc b/src/clang_utils.cc index 6a92b73b..a58237e1 100644 --- a/src/clang_utils.cc +++ b/src/clang_utils.cc @@ -34,7 +34,7 @@ std::string FileName(const FileEntry &file) { if (!StartsWith(ret, g_config->projectRoot)) { SmallString<256> dest; sys::fs::real_path(ret, dest); - ret = dest.str(); + ret = sys::path::convert_to_slash(dest.str()); } return ret; } diff --git a/src/filesystem.cc b/src/filesystem.cc index 74eb836b..613666ad 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -59,7 +59,7 @@ void GetFilesInFolder(std::string folder, bool recursive, bool dir_prefix, if (sys::fs::is_regular_file(Status)) { if (!dir_prefix) path = path.substr(folder.size()); - handler(path); + handler(sys::path::convert_to_slash(path)); } else if (recursive && sys::fs::is_directory(Status) && !seen.count(ID = Status.getUniqueID())) { curr.push_back(path); diff --git a/src/indexer.cc b/src/indexer.cc index a29988c9..4ae432f2 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -567,7 +567,7 @@ public: if (!llvm::sys::path::is_absolute(Path) && !SM.getFileManager().makeAbsolutePath(Path)) return -1; - it->second.second = Path.str(); + it->second.second = llvm::sys::path::convert_to_slash(Path.str()); } return it->second.first; } diff --git a/src/lsp.cc b/src/lsp.cc index afb0b76c..6fac3d6c 100644 --- a/src/lsp.cc +++ b/src/lsp.cc @@ -220,10 +220,15 @@ void lsDocumentUri::SetPath(const std::string &path) { } std::string lsDocumentUri::GetPath() const { - if (raw_uri.compare(0, 8, "file:///")) + if (raw_uri.compare(0, 7, "file://")) { + LOG_S(WARNING) + << "Received potentially bad URI (not starting with file://): " + << raw_uri; return raw_uri; + } std::string ret; #ifdef _WIN32 + // Skipping the initial "/" on Windows size_t i = 8; #else size_t i = 7; @@ -236,8 +241,14 @@ std::string lsDocumentUri::GetPath() const { ret.push_back(from_hex(raw_uri[i + 1]) * 16 + from_hex(raw_uri[i + 2])); i += 2; } else - ret.push_back(raw_uri[i] == '\\' ? '/' : raw_uri[i]); + ret.push_back(raw_uri[i]); } +#ifdef _WIN32 + std::replace(ret.begin(), ret.end(), '\\', '/'); + if (ret.size() > 1 && ret[0] >= 'a' && ret[0] <= 'z' && ret[1] == ':') { + ret[0] = toupper(ret[0]); + } +#endif return ret; } diff --git a/src/platform_win.cc b/src/platform_win.cc index be03055c..3acbe7e2 100644 --- a/src/platform_win.cc +++ b/src/platform_win.cc @@ -35,14 +35,19 @@ std::string NormalizePath(const std::string &path) { TCHAR buffer[MAX_PATH] = TEXT(""); TCHAR **lpp_part = {NULL}; + std::string result; retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part); // fail, return original if (retval == 0) - return path; + result = path; + else + result = buffer; - std::string result = buffer; std::replace(result.begin(), result.end(), '\\', '/'); - // std::transform(result.begin(), result.end(), result.begin(), ::tolower); + // Normalize drive letter. + if (result.size() > 1 && result[0] >= 'a' && result[0] <= 'z' && + result[1] == ':') + result[0] = toupper(result[0]); return result; } diff --git a/src/project.cc b/src/project.cc index 3cd4aa52..64c63308 100644 --- a/src/project.cc +++ b/src/project.cc @@ -172,7 +172,8 @@ struct ProjectProcessor { HeaderSearchOptions &HeaderOpts = CI->getHeaderSearchOpts(); for (auto &E : HeaderOpts.UserEntries) { - std::string path = ResolveIfRelative(entry.directory, E.Path); + std::string path = + NormalizePath(ResolveIfRelative(entry.directory, E.Path)); switch (E.Group) { default: config->angle_dirs.insert(path); @@ -327,8 +328,9 @@ LoadEntriesFromDirectory(ProjectConfig *project, ProjectProcessor proc(project); for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) { Project::Entry entry; - entry.directory = std::move(Cmd.Directory); - entry.filename = ResolveIfRelative(entry.directory, Cmd.Filename); + entry.directory = NormalizePath(Cmd.Directory); + entry.filename = + NormalizePath(ResolveIfRelative(entry.directory, Cmd.Filename)); entry.args = std::move(Cmd.CommandLine); proc.Process(entry); if (Seen.insert(entry.filename).second) From c7a6c5cd12a0184834be2571db28920346cc7ecd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 11 Sep 2018 23:31:06 -0700 Subject: [PATCH 27/66] Make $ccls/reload reset DB and reload cached index files $ccls/reload is renamed from $ccls/freshenIndex This is useful when DB (merged index) diverges from backing IndexFile. Also fix a semantic highlighting bug. --- CMakeLists.txt | 2 +- .../{ccls_freshenIndex.cc => ccls_reload.cc} | 34 ++++++++++++------- src/pipeline.cc | 11 ++++-- src/query.cc | 11 ++++++ src/query.h | 4 ++- 5 files changed, 45 insertions(+), 17 deletions(-) rename src/messages/{ccls_freshenIndex.cc => ccls_reload.cc} (78%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9574aad8..01eead6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,10 +212,10 @@ target_sources(ccls PRIVATE src/messages/ccls_callHierarchy.cc src/messages/ccls_callers.cc src/messages/ccls_fileInfo.cc - src/messages/ccls_freshenIndex.cc src/messages/ccls_inheritanceHierarchy.cc src/messages/ccls_memberHierarchy.cc src/messages/ccls_navigate.cc + src/messages/ccls_reload.cc src/messages/ccls_vars.cc src/messages/exit.cc src/messages/initialize.cc diff --git a/src/messages/ccls_freshenIndex.cc b/src/messages/ccls_reload.cc similarity index 78% rename from src/messages/ccls_freshenIndex.cc rename to src/messages/ccls_reload.cc index a49e0243..6652b049 100644 --- a/src/messages/ccls_freshenIndex.cc +++ b/src/messages/ccls_reload.cc @@ -25,9 +25,9 @@ using namespace ccls; #include namespace { -MethodType kMethodType = "$ccls/freshenIndex"; +MethodType kMethodType = "$ccls/reload"; -struct In_CclsFreshenIndex : public NotificationInMessage { +struct In_CclsReload : public NotificationInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { bool dependencies = true; @@ -36,15 +36,28 @@ struct In_CclsFreshenIndex : public NotificationInMessage { }; Params params; }; -MAKE_REFLECT_STRUCT(In_CclsFreshenIndex::Params, dependencies, whitelist, +MAKE_REFLECT_STRUCT(In_CclsReload::Params, dependencies, whitelist, blacklist); -MAKE_REFLECT_STRUCT(In_CclsFreshenIndex, params); -REGISTER_IN_MESSAGE(In_CclsFreshenIndex); +MAKE_REFLECT_STRUCT(In_CclsReload, params); +REGISTER_IN_MESSAGE(In_CclsReload); -struct Handler_CclsFreshenIndex : BaseMessageHandler { +struct Handler_CclsReload : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsFreshenIndex *request) override { - GroupMatch matcher(request->params.whitelist, request->params.blacklist); + void Run(In_CclsReload *request) override { + const auto ¶ms = request->params; + // Send index requests for every file. + if (params.whitelist.empty() && params.blacklist.empty()) { + { + std::lock_guard lock(vfs->mutex); + vfs->state.clear(); + } + db->clear(); + project->Index(working_files, lsRequestId()); + return; + } + + // TODO + GroupMatch matcher(params.whitelist, params.blacklist); std::queue q; // |need_index| stores every filename ever enqueued. @@ -89,10 +102,7 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler { } } } - - // Send index requests for every file. - project->Index(working_files, lsRequestId()); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsFreshenIndex); +REGISTER_MESSAGE_HANDLER(Handler_CclsReload); } // namespace diff --git a/src/pipeline.cc b/src/pipeline.cc index be30a5f8..4ee4f971 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -248,14 +248,19 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); + std::lock_guard lock(vfs->mutex); + vfs->state[path_to_index].loaded = true; } - for (const auto &dep : dependencies) - if (vfs->Mark(dep.first().str(), 0, 2) && - (prev = RawCacheLoad(dep.first().str()))) { + for (const auto &dep : dependencies) { + std::string path = dep.first().str(); + if (vfs->Mark(path, 0, 2) && (prev = RawCacheLoad(path))) { IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); + std::lock_guard lock(vfs->mutex); + vfs->state[path].loaded = true; } + } return true; } diff --git a/src/query.cc b/src/query.cc index e84040d4..d09f33b1 100644 --- a/src/query.cc +++ b/src/query.cc @@ -148,6 +148,17 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { return r; } +void DB::clear() { + files.clear(); + name2file_id.clear(); + func_usr.clear(); + type_usr.clear(); + var_usr.clear(); + funcs.clear(); + types.clear(); + vars.clear(); +} + template void DB::RemoveUsrs(SymbolKind kind, int file_id, const std::vector> &to_remove) { diff --git a/src/query.h b/src/query.h index 1d4ebf3c..ea7d0bcf 100644 --- a/src/query.h +++ b/src/query.h @@ -45,7 +45,7 @@ struct QueryFile { std::vector includes; // Parts of the file which are disabled. std::vector skipped_ranges; - // Used by |$ccls/freshenIndex|. + // Used by |$ccls/reload|. std::vector dependencies; }; @@ -166,6 +166,8 @@ struct DB { std::vector types; std::vector vars; + void clear(); + template void RemoveUsrs(SymbolKind kind, int file_id, const std::vector> &to_remove); From e2f29d7b1b3d81b01a21f9a1313598f383ce2aeb Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 12 Sep 2018 11:12:00 -0700 Subject: [PATCH 28/66] pipeline improvement for files not having a project entry (e.g. .h) --- src/messages/textDocument_didChange.cc | 6 ++-- src/messages/textDocument_didOpen.cc | 10 +++--- src/messages/textDocument_didSave.cc | 4 +-- src/pipeline.cc | 44 +++++++++++++++----------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc index 5b50714c..7488ff2f 100644 --- a/src/messages/textDocument_didChange.cc +++ b/src/messages/textDocument_didChange.cc @@ -39,10 +39,8 @@ struct Handler_TextDocumentDidChange const auto ¶ms = request->params; std::string path = params.textDocument.uri.GetPath(); working_files->OnChange(params); - if (g_config->index.onChange) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, IndexMode::OnChange); - } + if (g_config->index.onChange) + pipeline::Index(path, {}, IndexMode::OnChange); clang_complete->NotifyView(path); if (g_config->diagnostics.onChange) clang_complete->DiagnosticsUpdate( diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 146c22c0..939ec8bd 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -69,12 +69,10 @@ struct Handler_TextDocumentDidOpen // Submit new index request if it is not a header file. if (SourceFileLanguage(path) != LanguageId::Unknown) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, - params.args.size() ? params.args : entry.args, - IndexMode::Normal); - - clang_complete->FlushSession(entry.filename); + pipeline::Index( + path, params.args.size() ? params.args : std::vector{}, + IndexMode::Normal); + clang_complete->FlushSession(path); } clang_complete->NotifyView(path); diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 0badb21c..87b7e793 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -45,9 +45,7 @@ struct Handler_TextDocumentDidSave void Run(In_TextDocumentDidSave *request) override { const auto ¶ms = request->params; std::string path = params.textDocument.uri.GetPath(); - - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, IndexMode::Normal); + pipeline::Index(path, {}, IndexMode::Normal); clang_complete->NotifySave(path); } }; diff --git a/src/pipeline.cc b/src/pipeline.cc index 4ee4f971..dd52fcbc 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -190,25 +190,23 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, return false; } - Project::Entry entry; - { - std::lock_guard lock(project->mutex_); - auto it = project->path_to_entry_index.find(request.path); - if (it != project->path_to_entry_index.end()) - entry = project->entries[it->second]; - else { - entry.filename = request.path; - entry.args = request.args; - } - } + Project::Entry entry = project->FindCompilationEntryForFile(request.path); + if (request.args.size()) + entry.args = request.args; std::string path_to_index = entry.filename; std::unique_ptr prev; - // Try to load the file from cache. std::optional write_time = LastWriteTime(path_to_index); if (!write_time) return true; int reparse = vfs->Stamp(path_to_index, *write_time); + if (request.path != path_to_index) { + std::optional mtime1 = LastWriteTime(request.path); + if (!mtime1) + return true; + if (vfs->Stamp(request.path, *mtime1)) + reparse = 2; + } if (g_config->index.onChange) reparse = 2; if (!vfs->Mark(path_to_index, g_thread_id, 1) && !reparse) @@ -257,8 +255,14 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); - std::lock_guard lock(vfs->mutex); - vfs->state[path].loaded = true; + { + std::lock_guard lock(vfs->mutex); + vfs->state[path].loaded = true; + } + if (entry.id >= 0) { + std::lock_guard lock(project->mutex_); + project->path_to_entry_index[path] = entry.id; + } } } return true; @@ -268,9 +272,9 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, std::vector> remapped; if (g_config->index.onChange) { - std::string content = wfiles->GetContent(request.path); + std::string content = wfiles->GetContent(path_to_index); if (content.size()) - remapped.emplace_back(request.path, content); + remapped.emplace_back(path_to_index, content); } auto indexes = idx::Index(completion, wfiles, vfs, entry.directory, path_to_index, entry.args, remapped); @@ -289,7 +293,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, for (std::unique_ptr &curr : indexes) { std::string path = curr->path; - bool do_update = path == path_to_index, loaded; + bool do_update = path == path_to_index || path == request.path, loaded; { std::lock_guard lock(vfs->mutex); VFS::State &st = vfs->state[path]; @@ -300,11 +304,13 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, loaded = st.loaded; st.loaded = true; } - if (!do_update) - continue; if (std::string reason; !matcher.IsMatch(path, &reason)) { LOG_IF_S(INFO, loud) << "skip emitting and storing index of " << path << " for " << reason; + do_update = false; + } + if (!do_update) { + vfs->Reset(path); continue; } From 6bca153ee307488e999e79f7715a311709e9f1e8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 12 Sep 2018 13:46:20 -0700 Subject: [PATCH 29/66] Make $ccls/inheritanceHierarchy and textDocument/typeDefinition find declarations if definitions do not exist; spelling ranges of operator= --- index_tests/operators/operator.cc | 2 +- src/indexer.cc | 1 + src/messages/ccls_inheritanceHierarchy.cc | 3 ++ src/messages/textDocument_typeDefinition.cc | 34 +++++++++++++-------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/index_tests/operators/operator.cc b/index_tests/operators/operator.cc index 3a569983..009db1c0 100644 --- a/index_tests/operators/operator.cc +++ b/index_tests/operators/operator.cc @@ -45,7 +45,7 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:8-2:16|15041163540773201510|2|1026|-1", + "spell": "2:8-2:18|15041163540773201510|2|1026|-1", "extent": "2:3-2:27|15041163540773201510|2|0|-1", "bases": [], "derived": [], diff --git a/src/indexer.cc b/src/indexer.cc index 4ae432f2..cc8fc8bc 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -679,6 +679,7 @@ public: switch (OrigD->getKind()) { case Decl::CXXConversion: // *operator* int => *operator int* case Decl::CXXDestructor: // *~*A => *~A* + case Decl::CXXMethod: // *operator*= => *operator=* if (Loc.isFileID()) { SourceRange R = cast(OrigD)->getNameInfo().getSourceRange(); diff --git a/src/messages/ccls_inheritanceHierarchy.cc b/src/messages/ccls_inheritanceHierarchy.cc index bea19515..617198dc 100644 --- a/src/messages/ccls_inheritanceHierarchy.cc +++ b/src/messages/ccls_inheritanceHierarchy.cc @@ -83,6 +83,9 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, if (def->spell) { if (auto loc = GetLsLocation(m->db, m->working_files, *def->spell)) entry->location = *loc; + } else if (entity.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, entity.declarations[0])) + entry->location = *loc; } } else if (!derived) { entry->numChildren = 0; diff --git a/src/messages/textDocument_typeDefinition.cc b/src/messages/textDocument_typeDefinition.cc index ff1383f7..30786850 100644 --- a/src/messages/textDocument_typeDefinition.cc +++ b/src/messages/textDocument_typeDefinition.cc @@ -42,32 +42,40 @@ struct Handler_TextDocumentTypeDefinition QueryFile *file; if (!FindFileOrFail(db, project, request->id, request->params.textDocument.uri.GetPath(), &file, - nullptr)) { + nullptr)) return; - } WorkingFile *working_file = working_files->GetFileByFilename(file->def->path); Out_TextDocumentTypeDefinition out; out.id = request->id; + auto Add = [&](const QueryType &type) { + for (const auto &def : type.def) + if (def.spell) { + if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, + g_config->xref.container)) + out.result.push_back(*ls_loc); + } + if (out.result.empty()) + for (const DeclRef &dr : type.declarations) + if (auto ls_loc = GetLsLocationEx(db, working_files, dr, + g_config->xref.container)) + out.result.push_back(*ls_loc); + }; for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { - Usr usr = sym.usr; switch (sym.kind) { case SymbolKind::Var: { const QueryVar::Def *def = db->GetVar(sym).AnyDef(); - if (!def || !def->type) - continue; - usr = def->type; - [[fallthrough]]; + if (def && def->type) + Add(db->Type(def->type)); + break; } case SymbolKind::Type: { - QueryType &type = db->Type(usr); - for (const auto &def : type.def) - if (def.spell) { - if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, - g_config->xref.container)) - out.result.push_back(*ls_loc); + for (auto &def : db->GetType(sym).def) + if (def.alias_of) { + Add(db->Type(def.alias_of)); + break; } break; } From 196973178143303adfaf13d8393ff3459781f557 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 12 Sep 2018 21:03:35 -0700 Subject: [PATCH 30/66] textDocument/documentSymbol --- src/messages/textDocument_documentSymbol.cc | 2 +- src/messages/workspace_symbol.cc | 3 +-- src/query_utils.cc | 10 +++------- src/query_utils.h | 8 +++----- src/symbol.h | 2 +- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index 53b63960..9991cc93 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -84,7 +84,7 @@ struct Handler_TextDocumentDocumentSymbol for (auto [sym, refcnt] : symbol2refcnt) { if (refcnt <= 0) continue; if (std::optional info = - GetSymbolInfo(db, working_files, sym, false)) { + GetSymbolInfo(db, sym, false)) { if (sym.kind == SymbolKind::Var) { QueryVar &var = db->GetVar(sym); auto *def = var.AnyDef(); diff --git a/src/messages/workspace_symbol.cc b/src/messages/workspace_symbol.cc index 2449e072..c78e9462 100644 --- a/src/messages/workspace_symbol.cc +++ b/src/messages/workspace_symbol.cc @@ -31,8 +31,7 @@ MethodType kMethodType = "workspace/symbol"; bool AddSymbol( DB *db, WorkingFiles *working_files, SymbolIdx sym, bool use_detailed, std::vector> *result) { - std::optional info = - GetSymbolInfo(db, working_files, sym, true); + std::optional info = GetSymbolInfo(db, sym, true); if (!info) return false; diff --git a/src/query_utils.cc b/src/query_utils.cc index 749b9088..4390ae14 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -286,11 +286,8 @@ lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym) { return ret; } -// Returns a symbol. The symbol will have *NOT* have a location assigned. -std::optional GetSymbolInfo(DB *db, - WorkingFiles *working_files, - SymbolIdx sym, - bool detailed_name) { +std::optional GetSymbolInfo(DB *db, SymbolIdx sym, + bool detailed) { switch (sym.kind) { case SymbolKind::Invalid: break; @@ -307,12 +304,11 @@ std::optional GetSymbolInfo(DB *db, default: { lsSymbolInformation info; EachEntityDef(db, sym, [&](const auto &def) { - if (detailed_name) + if (detailed) info.name = def.detailed_name; else info.name = def.Name(true); info.kind = def.kind; - info.containerName = def.detailed_name; return false; }); return info; diff --git a/src/query_utils.h b/src/query_utils.h index 262fbdfa..cd07d963 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -47,11 +47,9 @@ std::optional GetLsLocationEx(DB *db, WorkingFiles *working_files, Use use, bool container); std::vector GetLsLocationExs(DB *db, WorkingFiles *working_files, const std::vector &refs); -// Returns a symbol. The symbol will have *NOT* have a location assigned. -std::optional GetSymbolInfo(DB *db, - WorkingFiles *working_files, - SymbolIdx sym, - bool detailed_name); +// Returns a symbol. The symbol will *NOT* have a location assigned. +std::optional GetSymbolInfo(DB *db, SymbolIdx sym, + bool detailed); std::vector FindSymbolsAtLocation(WorkingFile *working_file, QueryFile *file, diff --git a/src/symbol.h b/src/symbol.h index a4f3c05d..16e4de11 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -76,6 +76,6 @@ struct lsSymbolInformation { std::string_view name; lsSymbolKind kind; lsLocation location; - std::string_view containerName; + std::optional containerName; }; MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName); From a174105abe0c98905dfaa542bf71e1d3c9bfb9ba Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 12 Sep 2018 23:07:47 -0700 Subject: [PATCH 31/66] Better diagnostics --- src/clang_complete.cc | 90 +++++++++++++++++----- src/messages/textDocument_signatureHelp.cc | 2 +- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 3fa70c32..078da29d 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -279,6 +279,34 @@ void CompletionMain(CompletionManager *completion_manager) { } } +llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) { + switch (Lvl) { + case DiagnosticsEngine::Ignored: + return "ignored"; + case DiagnosticsEngine::Note: + return "note"; + case DiagnosticsEngine::Remark: + return "remark"; + case DiagnosticsEngine::Warning: + return "warning"; + case DiagnosticsEngine::Error: + return "error"; + case DiagnosticsEngine::Fatal: + return "fatal error"; + } +} + +void printDiag(llvm::raw_string_ostream &OS, const DiagBase &d) { + if (d.inside_main) + OS << llvm::sys::path::filename(d.file); + else + OS << d.file; + auto pos = d.range.start; + OS << ":" << (pos.line + 1) << ":" << (pos.column + 1) << ":" + << (d.inside_main ? " " : "\n"); + OS << diagLeveltoString(d.level) << ": " << d.message; +} + void DiagnosticMain(CompletionManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. @@ -307,30 +335,56 @@ void DiagnosticMain(CompletionManager *manager) { for (auto &Buf : Bufs) Buf.release(); + auto Fill = [](const DiagBase &d, lsDiagnostic &ret) { + ret.range = lsRange{{d.range.start.line, d.range.start.column}, + {d.range.end.line, d.range.end.column}}; + switch (d.level) { + case DiagnosticsEngine::Ignored: + // llvm_unreachable + case DiagnosticsEngine::Remark: + ret.severity = lsDiagnosticSeverity::Hint; + break; + case DiagnosticsEngine::Note: + ret.severity = lsDiagnosticSeverity::Information; + break; + case DiagnosticsEngine::Warning: + ret.severity = lsDiagnosticSeverity::Warning; + break; + case DiagnosticsEngine::Error: + case DiagnosticsEngine::Fatal: + ret.severity = lsDiagnosticSeverity::Error; + break; + } + ret.code = d.category; + return ret; + }; + std::vector ls_diags; for (auto &d : DC.Take()) { if (!d.inside_main) continue; + std::string buf; + llvm::raw_string_ostream OS(buf); lsDiagnostic &ls_diag = ls_diags.emplace_back(); - ls_diag.range = lsRange{{d.range.start.line, d.range.start.column}, - {d.range.end.line, d.range.end.column}}; - ls_diag.message = d.message; - switch (d.level) { - case DiagnosticsEngine::Ignored: - // llvm_unreachable - case DiagnosticsEngine::Note: - case DiagnosticsEngine::Remark: - ls_diag.severity = lsDiagnosticSeverity::Information; - continue; - case DiagnosticsEngine::Warning: - ls_diag.severity = lsDiagnosticSeverity::Warning; - break; - case DiagnosticsEngine::Error: - case DiagnosticsEngine::Fatal: - ls_diag.severity = lsDiagnosticSeverity::Error; - } - ls_diag.code = d.category; + Fill(d, ls_diag); ls_diag.fixits_ = d.edits; + OS << d.message; + for (auto &n : d.notes) { + OS << "\n\n"; + printDiag(OS, n); + } + OS.flush(); + ls_diag.message = std::move(buf); + for (auto &n : d.notes) { + if (!n.inside_main) + continue; + lsDiagnostic &ls_diag1 = ls_diags.emplace_back(); + Fill(n, ls_diag1); + OS << n.message << "\n\n"; + printDiag(OS, d); + OS.flush(); + ls_diag1.message = std::move(buf); + } } manager->on_diagnostic_(path, ls_diags); } diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 4fcbd764..007003db 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -51,7 +51,7 @@ MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); struct lsSignatureHelp { std::vector signatures; int activeSignature = 0; - int activeParameter; + int activeParameter = 0; }; MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature, activeParameter); From 70deeca8ad89fedd7f07af03a959dfe7f62d668f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 13 Sep 2018 00:18:37 -0700 Subject: [PATCH 32/66] Rename hierarchies to $ccls/{call,inheritance,member} bool flat = false; -> bool hierarchy = false; (set it to true to enable hierarchical view) Delete $ccls/callers (which is what $ccls/call does now) --- CMakeLists.txt | 7 +- src/hierarchy.hh | 39 +++++++++ .../{ccls_callHierarchy.cc => ccls_call.cc} | 48 ++++++----- src/messages/ccls_callers.cc | 62 -------------- ...itanceHierarchy.cc => ccls_inheritance.cc} | 72 +++++++--------- ...ccls_memberHierarchy.cc => ccls_member.cc} | 85 ++++++++----------- src/query_utils.cc | 12 --- src/query_utils.h | 20 ----- 8 files changed, 137 insertions(+), 208 deletions(-) create mode 100644 src/hierarchy.hh rename src/messages/{ccls_callHierarchy.cc => ccls_call.cc} (83%) delete mode 100644 src/messages/ccls_callers.cc rename src/messages/{ccls_inheritanceHierarchy.cc => ccls_inheritance.cc} (72%) rename src/messages/{ccls_memberHierarchy.cc => ccls_member.cc} (78%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 01eead6c..20a4bd91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,11 +209,10 @@ target_sources(ccls PRIVATE ) target_sources(ccls PRIVATE - src/messages/ccls_callHierarchy.cc - src/messages/ccls_callers.cc + src/messages/ccls_call.cc src/messages/ccls_fileInfo.cc - src/messages/ccls_inheritanceHierarchy.cc - src/messages/ccls_memberHierarchy.cc + src/messages/ccls_inheritance.cc + src/messages/ccls_member.cc src/messages/ccls_navigate.cc src/messages/ccls_reload.cc src/messages/ccls_vars.cc diff --git a/src/hierarchy.hh b/src/hierarchy.hh new file mode 100644 index 00000000..c79cbd0d --- /dev/null +++ b/src/hierarchy.hh @@ -0,0 +1,39 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#pragma once + +#include "lsp.h" + +#include +#include + +template +void FlattenHierarchy(const Node &root, Out_LocationList &out) { + std::queue q; + for (auto &entry : root.children) + q.push(&entry); + while (q.size()) { + auto *entry = q.front(); + q.pop(); + if (entry->location.uri.raw_uri.size()) + out.result.push_back({entry->location}); + for (auto &entry1 : entry->children) + q.push(&entry1); + } + std::sort(out.result.begin(), out.result.end()); + out.result.erase(std::unique(out.result.begin(), out.result.end()), + out.result.end()); +} diff --git a/src/messages/ccls_callHierarchy.cc b/src/messages/ccls_call.cc similarity index 83% rename from src/messages/ccls_callHierarchy.cc rename to src/messages/ccls_call.cc index ce593425..98016480 100644 --- a/src/messages/ccls_callHierarchy.cc +++ b/src/messages/ccls_call.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" @@ -22,7 +23,7 @@ using namespace ccls; namespace { -MethodType kMethodType = "$ccls/callHierarchy"; +MethodType kMethodType = "$ccls/call"; enum class CallType : uint8_t { Direct = 0, @@ -36,7 +37,7 @@ bool operator&(CallType lhs, CallType rhs) { return uint8_t(lhs) & uint8_t(rhs); } -struct In_CclsCallHierarchy : public RequestInMessage { +struct In_CclsCall : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { @@ -56,15 +57,16 @@ struct In_CclsCallHierarchy : public RequestInMessage { CallType callType = CallType::All; bool qualified = true; int levels = 1; + bool hierarchy = false; }; Params params; }; -MAKE_REFLECT_STRUCT(In_CclsCallHierarchy::Params, textDocument, position, id, - callee, callType, qualified, levels); -MAKE_REFLECT_STRUCT(In_CclsCallHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsCallHierarchy); +MAKE_REFLECT_STRUCT(In_CclsCall::Params, textDocument, position, id, + callee, callType, qualified, levels, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsCall, id, params); +REGISTER_IN_MESSAGE(In_CclsCall); -struct Out_CclsCallHierarchy : public lsOutMessage { +struct Out_CclsCall : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -79,12 +81,12 @@ struct Out_CclsCallHierarchy : public lsOutMessage { lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsCallHierarchy::Entry, id, name, location, callType, +MAKE_REFLECT_STRUCT(Out_CclsCall::Entry, id, name, location, callType, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCallHierarchy, jsonrpc, id, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCall, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, +bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee, CallType call_type, bool qualified, int levels) { const QueryFunc &func = m->db->Func(entry->usr); const QueryFunc::Def *def = func.AnyDef(); @@ -94,7 +96,7 @@ bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, auto handle = [&](Use use, CallType call_type1) { entry->numChildren++; if (levels > 0) { - Out_CclsCallHierarchy::Entry entry1; + Out_CclsCall::Entry entry1; entry1.id = std::to_string(use.usr); entry1.usr = use.usr; if (auto loc = GetLsLocation(m->db, m->working_files, use)) @@ -160,17 +162,17 @@ bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, return true; } -struct Handler_CclsCallHierarchy : BaseMessageHandler { +struct Handler_CclsCall : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional + std::optional BuildInitial(Usr root_usr, bool callee, CallType call_type, bool qualified, int levels) { const auto *def = db->Func(root_usr).AnyDef(); if (!def) return {}; - Out_CclsCallHierarchy::Entry entry; + Out_CclsCall::Entry entry; entry.id = std::to_string(root_usr); entry.usr = root_usr; entry.callType = CallType::Direct; @@ -183,9 +185,9 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { return entry; } - void Run(In_CclsCallHierarchy *request) override { + void Run(In_CclsCall *request) override { auto ¶ms = request->params; - Out_CclsCallHierarchy out; + Out_CclsCall out; out.id = request->id; if (params.id.size()) { @@ -194,7 +196,7 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { } catch (...) { return; } - Out_CclsCallHierarchy::Entry entry; + Out_CclsCall::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; entry.callType = CallType::Direct; @@ -219,9 +221,17 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { } } - pipeline::WriteStdout(kMethodType, out); + if (params.hierarchy) { + pipeline::WriteStdout(kMethodType, out); + return; + } + Out_LocationList out1; + out1.id = request->id; + if (out.result) + FlattenHierarchy(*out.result, out1); + pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsCallHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsCall); } // namespace diff --git a/src/messages/ccls_callers.cc b/src/messages/ccls_callers.cc deleted file mode 100644 index 7b6c28f9..00000000 --- a/src/messages/ccls_callers.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "$ccls/callers"; - -struct In_CclsCallers : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsCallers, id, params); -REGISTER_IN_MESSAGE(In_CclsCallers); - -struct Handler_CclsCallers : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsCallers *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - WorkingFile *working_file = - working_files->GetFileByFilename(file->def->path); - - Out_LocationList out; - out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - if (sym.kind == SymbolKind::Func) { - QueryFunc &func = db->GetFunc(sym); - std::vector uses = func.uses; - for (Use func_ref : GetUsesForAllBases(db, func)) - uses.push_back(func_ref); - for (Use func_ref : GetUsesForAllDerived(db, func)) - uses.push_back(func_ref); - out.result = GetLsLocationExs(db, working_files, uses); - break; - } - } - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsCallers); -} // namespace diff --git a/src/messages/ccls_inheritanceHierarchy.cc b/src/messages/ccls_inheritance.cc similarity index 72% rename from src/messages/ccls_inheritanceHierarchy.cc rename to src/messages/ccls_inheritance.cc index 617198dc..0ed23585 100644 --- a/src/messages/ccls_inheritanceHierarchy.cc +++ b/src/messages/ccls_inheritance.cc @@ -13,18 +13,18 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" using namespace ccls; -#include #include namespace { -MethodType kMethodType = "$ccls/inheritanceHierarchy"; +MethodType kMethodType = "$ccls/inheritance"; -struct In_CclsInheritanceHierarchy : public RequestInMessage { +struct In_CclsInheritance : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { // If id+kind are specified, expand a node; otherwise textDocument+position @@ -40,17 +40,17 @@ struct In_CclsInheritanceHierarchy : public RequestInMessage { bool derived = false; bool qualified = true; int levels = 1; - bool flat = false; + bool hierarchy = false; } params; }; -MAKE_REFLECT_STRUCT(In_CclsInheritanceHierarchy::Params, textDocument, position, - id, kind, derived, qualified, levels, flat); -MAKE_REFLECT_STRUCT(In_CclsInheritanceHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsInheritanceHierarchy); +MAKE_REFLECT_STRUCT(In_CclsInheritance::Params, textDocument, position, + id, kind, derived, qualified, levels, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsInheritance, id, params); +REGISTER_IN_MESSAGE(In_CclsInheritance); -struct Out_CclsInheritanceHierarchy - : public lsOutMessage { +struct Out_CclsInheritance + : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -66,16 +66,16 @@ struct Out_CclsInheritanceHierarchy lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsInheritanceHierarchy::Entry, id, kind, name, +MAKE_REFLECT_STRUCT(Out_CclsInheritance::Entry, id, kind, name, location, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritanceHierarchy, jsonrpc, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritance, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels); template -bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool ExpandHelper(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels, Q &entity) { const auto *def = entity.AnyDef(); if (def) { @@ -97,7 +97,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, for (auto usr : entity.derived) { if (!seen.insert(usr).second) continue; - Out_CclsInheritanceHierarchy::Entry entry1; + Out_CclsInheritance::Entry entry1; entry1.id = std::to_string(usr); entry1.usr = usr; entry1.kind = entry->kind; @@ -112,7 +112,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, for (auto usr : def->bases) { if (!seen.insert(usr).second) continue; - Out_CclsInheritanceHierarchy::Entry entry1; + Out_CclsInheritance::Entry entry1; entry1.id = std::to_string(usr); entry1.usr = usr; entry1.kind = entry->kind; @@ -126,7 +126,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, return true; } -bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels) { if (entry->kind == SymbolKind::Func) return ExpandHelper(m, entry, derived, qualified, levels, @@ -136,13 +136,13 @@ bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, m->db->Type(entry->usr)); } -struct Handler_CclsInheritanceHierarchy - : BaseMessageHandler { +struct Handler_CclsInheritance + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional + std::optional BuildInitial(SymbolRef sym, bool derived, bool qualified, int levels) { - Out_CclsInheritanceHierarchy::Entry entry; + Out_CclsInheritance::Entry entry; entry.id = std::to_string(sym.usr); entry.usr = sym.usr; entry.kind = sym.kind; @@ -150,18 +150,18 @@ struct Handler_CclsInheritanceHierarchy return entry; } - void Run(In_CclsInheritanceHierarchy *request) override { + void Run(In_CclsInheritance *request) override { auto ¶ms = request->params; - Out_CclsInheritanceHierarchy out; + Out_CclsInheritance out; out.id = request->id; - if (!params.flat && params.id.size()) { + if (params.id.size()) { try { params.usr = std::stoull(params.id); } catch (...) { return; } - Out_CclsInheritanceHierarchy::Entry entry; + Out_CclsInheritance::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; entry.kind = params.kind; @@ -184,31 +184,17 @@ struct Handler_CclsInheritanceHierarchy } } - if (!params.flat) { + if (params.hierarchy) { pipeline::WriteStdout(kMethodType, out); return; } Out_LocationList out1; out1.id = request->id; - if (out.result) { - std::queue q; - for (auto &entry1 : out.result->children) - q.push(&entry1); - while (q.size()) { - auto *entry = q.front(); - q.pop(); - if (entry->location.uri.raw_uri.size()) - out1.result.push_back({entry->location}); - for (auto &entry1 : entry->children) - q.push(&entry1); - } - std::sort(out1.result.begin(), out1.result.end()); - out1.result.erase(std::unique(out1.result.begin(), out1.result.end()), - out1.result.end()); - } + if (out.result) + FlattenHierarchy(*out.result, out1); pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsInheritanceHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsInheritance); } // namespace diff --git a/src/messages/ccls_memberHierarchy.cc b/src/messages/ccls_member.cc similarity index 78% rename from src/messages/ccls_memberHierarchy.cc rename to src/messages/ccls_member.cc index 7de03d9e..d70add57 100644 --- a/src/messages/ccls_memberHierarchy.cc +++ b/src/messages/ccls_member.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" @@ -21,13 +22,12 @@ using namespace ccls; #include using namespace clang; -#include #include namespace { -MethodType kMethodType = "$ccls/memberHierarchy"; +MethodType kMethodType = "$ccls/member"; -struct In_CclsMemberHierarchy : public RequestInMessage { +struct In_CclsMember : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { @@ -42,16 +42,16 @@ struct In_CclsMemberHierarchy : public RequestInMessage { bool qualified = false; int levels = 1; - bool flat = false; + bool hierarchy = false; } params; }; -MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy::Params, textDocument, position, id, - qualified, levels, flat); -MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsMemberHierarchy); +MAKE_REFLECT_STRUCT(In_CclsMember::Params, textDocument, position, id, + qualified, levels, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsMember, id, params); +REGISTER_IN_MESSAGE(In_CclsMember); -struct Out_CclsMemberHierarchy : public lsOutMessage { +struct Out_CclsMember : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -67,21 +67,21 @@ struct Out_CclsMemberHierarchy : public lsOutMessage { lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsMemberHierarchy::Entry, id, name, fieldName, +MAKE_REFLECT_STRUCT(Out_CclsMember::Entry, id, name, fieldName, location, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMemberHierarchy, jsonrpc, id, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMember, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, bool qualified, int levels); // Add a field to |entry| which is a Func/Type. -void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, +void DoField(MessageHandler *m, Out_CclsMember::Entry *entry, const QueryVar &var, int64_t offset, bool qualified, int levels) { const QueryVar::Def *def1 = var.AnyDef(); if (!def1) return; - Out_CclsMemberHierarchy::Entry entry1; + Out_CclsMember::Entry entry1; // With multiple inheritance, the offset is incorrect. if (offset >= 0) { if (offset / 8 < 10) @@ -118,7 +118,7 @@ void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, } // Expand a type node by adding members recursively to it. -bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, bool qualified, int levels) { if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) { entry->name = ClangBuiltinTypeName(int(entry->usr)); @@ -139,15 +139,16 @@ bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, const auto *def = stack.back()->AnyDef(); stack.pop_back(); if (def) { - EachDefinedType(m->db, def->bases, [&](QueryType &type1) { - if (!seen.count(type1.usr)) { + for (Usr usr : def->bases) { + auto &type1 = m->db->Type(usr); + if (type1.def.size()) { seen.insert(type1.usr); stack.push_back(&type1); } - }); + } if (def->alias_of) { const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef(); - Out_CclsMemberHierarchy::Entry entry1; + Out_CclsMember::Entry entry1; entry1.id = std::to_string(def->alias_of); entry1.usr = def->alias_of; if (def1 && def1->spell) { @@ -185,11 +186,11 @@ bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, return true; } -struct Handler_CclsMemberHierarchy - : BaseMessageHandler { +struct Handler_CclsMember + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional + std::optional BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels) { switch (kind) { default: @@ -199,7 +200,7 @@ struct Handler_CclsMemberHierarchy if (!def) return {}; - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; // Not type, |id| is invalid. entry.name = def->Name(qualified); if (def->spell) { @@ -207,9 +208,11 @@ struct Handler_CclsMemberHierarchy GetLsLocation(db, working_files, *def->spell)) entry.location = *loc; } - EachDefinedVar(db, def->vars, [&](QueryVar &var) { - DoField(this, &entry, var, -1, qualified, levels - 1); - }); + for (Usr usr : def->vars) { + auto &var = db->Var(usr); + if (var.def.size()) + DoField(this, &entry, var, -1, qualified, levels - 1); + } return entry; } case SymbolKind::Type: { @@ -217,7 +220,7 @@ struct Handler_CclsMemberHierarchy if (!def) return {}; - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; entry.id = std::to_string(root_usr); entry.usr = root_usr; if (def->spell) { @@ -231,9 +234,9 @@ struct Handler_CclsMemberHierarchy } } - void Run(In_CclsMemberHierarchy *request) override { + void Run(In_CclsMember *request) override { auto ¶ms = request->params; - Out_CclsMemberHierarchy out; + Out_CclsMember out; out.id = request->id; if (params.id.size()) { @@ -242,7 +245,7 @@ struct Handler_CclsMemberHierarchy } catch (...) { return; } - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; // entry.name is empty as it is known by the client. @@ -277,31 +280,17 @@ struct Handler_CclsMemberHierarchy } } - if (!params.flat) { + if (params.hierarchy) { pipeline::WriteStdout(kMethodType, out); return; } Out_LocationList out1; out1.id = request->id; - if (out.result) { - std::queue q; - for (auto &entry1 : out.result->children) - q.push(&entry1); - while (q.size()) { - auto *entry = q.front(); - q.pop(); - if (entry->location.uri.raw_uri.size()) - out1.result.push_back({entry->location}); - for (auto &entry1 : entry->children) - q.push(&entry1); - } - std::sort(out1.result.begin(), out1.result.end()); - out1.result.erase(std::unique(out1.result.begin(), out1.result.end()), - out1.result.end()); - } + if (out.result) + FlattenHierarchy(*out.result, out1); pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsMemberHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsMember); } // namespace diff --git a/src/query_utils.cc b/src/query_utils.cc index 4390ae14..c2e0f0b7 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -167,18 +167,6 @@ std::vector GetUsesForAllDerived(DB *db, QueryFunc &root) { return ret; } -std::optional GetLsPosition(WorkingFile *wfile, - const Position &position) { - if (!wfile || wfile->index_lines.empty()) - return lsPosition{position.line, position.column}; - - int column = position.column; - if (std::optional start = - wfile->GetBufferPosFromIndexPos(position.line, &column, false)) - return lsPosition{*start, column}; - return std::nullopt; -} - std::optional GetLsRange(WorkingFile *wfile, const Range &location) { if (!wfile || wfile->index_lines.empty()) diff --git a/src/query_utils.h b/src/query_utils.h index cd07d963..0ec2501c 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -34,8 +34,6 @@ std::vector GetNonDefDeclarations(DB *db, SymbolIdx sym); std::vector GetUsesForAllBases(DB *db, QueryFunc &root); std::vector GetUsesForAllDerived(DB *db, QueryFunc &root); -std::optional GetLsPosition(WorkingFile *working_file, - const Position &position); std::optional GetLsRange(WorkingFile *working_file, const Range &location); lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path); @@ -105,21 +103,3 @@ void EachDefinedFunc(DB *db, const std::vector &usrs, Fn &&fn) { fn(obj); } } - -template -void EachDefinedType(DB *db, const std::vector &usrs, Fn &&fn) { - for (Usr usr : usrs) { - auto &obj = db->Type(usr); - if (!obj.def.empty()) - fn(obj); - } -} - -template -void EachDefinedVar(DB *db, const std::vector &usrs, Fn &&fn) { - for (Usr usr : usrs) { - auto &obj = db->Var(usr); - if (!obj.def.empty()) - fn(obj); - } -} From 56c6ec43dfd87ed2e44418b8d172307d87327a64 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 16 Sep 2018 16:57:43 -0700 Subject: [PATCH 33/66] Skip informative scope foo:: --- src/messages/textDocument_completion.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 663a4a88..545490da 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -392,6 +392,11 @@ void BuildItem(std::vector &out, for (auto i = first; i < out.size(); i++) out[i].parameters_.push_back(text); break; + case CodeCompletionString::CK_Informative: + if (StringRef(Chunk.Text).endswith("::")) + continue; + text = Chunk.Text; + break; case CodeCompletionString::CK_ResultType: result_type = Chunk.Text; continue; From 34c1ebcefd3cd6c15fe6dabc280d9f148da2b0d6 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 16 Sep 2018 11:29:48 -0700 Subject: [PATCH 34/66] Remove [spell.start, spell.end) -> [spell.start, extent.end) hack --- src/messages/textDocument_definition.cc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 1b616c80..7cff442c 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -43,7 +43,7 @@ std::vector GetNonDefDeclarationTargets(DB *db, SymbolRef sym) { switch (sym.kind) { case SymbolKind::Var: { std::vector ret = GetNonDefDeclarations(db, sym); - // If there is no declaration, jump the its type. + // If there is no declaration, jump to its type. if (ret.empty()) { for (auto &def : db->GetVar(sym).def) if (def.type) { @@ -76,44 +76,45 @@ struct Handler_TextDocumentDefinition out.id = request->id; Maybe range; + SymbolKind kind; Maybe on_def; WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); lsPosition &ls_pos = params.position; for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) { - if (!range) + if (!range) { range = sym.range; - else if (!(*range == sym.range)) + kind = sym.kind; + } else if (!(sym.range == *range && sym.kind == kind)) { break; + } // Found symbol. Return definition. // Special cases which are handled: // - symbol has declaration but no definition (ie, pure virtual) - // - start at spelling but end at extent for better mouse tooltip // - goto declaration while in definition of recursive type std::vector uses; EachEntityDef(db, sym, [&](const auto &def) { - if (def.spell && def.extent) { + if (def.spell) { Use spell = *def.spell; - // If on a definition, clear |uses| to find declarations below. if (spell.file_id == file_id && spell.range.Contains(ls_pos.line, ls_pos.character)) { on_def = spell; uses.clear(); return false; } - // We use spelling start and extent end because this causes vscode - // to highlight the entire definition when previewing / hoving with - // the mouse. - spell.range.end = def.extent->range.end; uses.push_back(spell); } return true; }); + // |uses| is empty if on a declaration/definition, otherwise it includes + // all declarations/definitions. if (uses.empty()) { - // The symbol has no definition or the cursor is on a definition. - uses = GetNonDefDeclarationTargets(db, sym); + for (Use use : GetNonDefDeclarationTargets(db, sym)) + if (!(use.file_id == file_id && + use.range.Contains(ls_pos.line, ls_pos.character))) + uses.push_back(use); // There is no declaration but the cursor is on a definition. if (uses.empty() && on_def) uses.push_back(*on_def); From a18977b9fc384509f6fd4b1b2588c329e39b25bd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 16 Sep 2018 11:07:15 -0700 Subject: [PATCH 35/66] Add clang.pathMappings to reuse cache files with differect source paths --- src/clang_tu.cc | 3 ++ src/config.cc | 13 ++++++++ src/config.h | 19 ++++++++++- src/messages/initialize.cc | 9 ++--- src/pipeline.cc | 7 ++-- src/project.cc | 19 ++++------- src/serializer.cc | 67 +++++++++++++++++++++++++++----------- src/serializers/json.h | 2 ++ 8 files changed, 100 insertions(+), 39 deletions(-) diff --git a/src/clang_tu.cc b/src/clang_tu.cc index d4646705..ecac6ab7 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -16,6 +16,7 @@ limitations under the License. #include "clang_tu.h" #include "clang_utils.h" +#include "config.h" #include using namespace clang; @@ -67,9 +68,11 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, std::unique_ptr BuildCompilerInvocation(const std::vector &args, IntrusiveRefCntPtr VFS) { + std::string save = "-resource-dir=" + g_config->clang.resourceDir; std::vector cargs; for (auto &arg : args) cargs.push_back(arg.c_str()); + cargs.push_back(save.c_str()); IntrusiveRefCntPtr Diags( CompilerInstance::createDiagnostics(new DiagnosticOptions)); std::unique_ptr CI = diff --git a/src/config.cc b/src/config.cc index bd0ecc2b..47dbfd00 100644 --- a/src/config.cc +++ b/src/config.cc @@ -17,3 +17,16 @@ limitations under the License. Config *g_config; thread_local int g_thread_id; + +namespace ccls { +void DoPathMapping(std::string &arg) { + for (const std::string &mapping : g_config->clang.pathMappings) { + auto colon = mapping.find(':'); + if (colon != std::string::npos) { + auto p = arg.find(mapping.substr(0, colon)); + if (p != std::string::npos) + arg.replace(p, colon, mapping.substr(colon + 1)); + } + } +} +} diff --git a/src/config.h b/src/config.h index 19093af1..23b2fdb8 100644 --- a/src/config.h +++ b/src/config.h @@ -61,6 +61,18 @@ struct Config { // Additional arguments to pass to clang. std::vector extraArgs; + // Translate absolute paths in compile_commands.json entries, .ccls options + // and cache files. This allows to reuse cache files built otherwhere if the + // source paths are different. + // + // This is a list of colon-separated strings, e.g. ["/container:/host"] + // + // An entry of "clang -I /container/include /container/a.cc" will be + // translated to "clang -I /host/include /host/a.cc". This is simple string + // replacement, so "clang /prefix/container/a.cc" will become "clang + // /prefix/host/a.cc". + std::vector pathMappings; + // Value to use for clang -resource-dir if not specified. // // This option defaults to clang -print-resource-dir and should not be @@ -235,7 +247,8 @@ struct Config { int maxNum = 2000; } xref; }; -MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, resourceDir); +MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, + resourceDir); MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, @@ -258,3 +271,7 @@ MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, extern Config *g_config; thread_local extern int g_thread_id; + +namespace ccls { +void DoPathMapping(std::string &arg); +} diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index c4516ef1..f93c0494 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -453,6 +453,7 @@ struct Handler_Initialize : BaseMessageHandler { // Ensure there is a resource directory. if (g_config->clang.resourceDir.empty()) g_config->clang.resourceDir = GetDefaultResourceDirectory(); + DoPathMapping(g_config->clang.resourceDir); LOG_S(INFO) << "Using -resource-dir=" << g_config->clang.resourceDir; // Send initialization before starting indexers, so we don't send a @@ -471,10 +472,10 @@ struct Handler_Initialize : BaseMessageHandler { if (g_config->cacheDirectory.size()) { // Create two cache directories for files inside and outside of the // project. - sys::fs::create_directories(g_config->cacheDirectory + - EscapeFileName(g_config->projectRoot)); - sys::fs::create_directories(g_config->cacheDirectory + '@' + - EscapeFileName(g_config->projectRoot)); + auto len = g_config->projectRoot.size(); + std::string escaped = EscapeFileName(g_config->projectRoot.substr(0, len - 1)); + sys::fs::create_directories(g_config->cacheDirectory + escaped); + sys::fs::create_directories(g_config->cacheDirectory + '@' + escaped); } diag_pub->Init(); diff --git a/src/pipeline.cc b/src/pipeline.cc index dd52fcbc..67e5706c 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -136,12 +136,13 @@ std::string AppendSerializationFormat(const std::string &base) { std::string GetCachePath(const std::string &source_file) { std::string cache_file; - size_t len = g_config->projectRoot.size(); + auto len = g_config->projectRoot.size(); if (StartsWith(source_file, g_config->projectRoot)) { - cache_file = EscapeFileName(g_config->projectRoot) + + cache_file = EscapeFileName(g_config->projectRoot.substr(0, len - 1)) + '/' + EscapeFileName(source_file.substr(len)); } else { - cache_file = '@' + EscapeFileName(g_config->projectRoot) + + cache_file = '@' + + EscapeFileName(g_config->projectRoot.substr(0, len - 1)) + '/' + EscapeFileName(source_file); } diff --git a/src/project.cc b/src/project.cc index 64c63308..2d6eed1e 100644 --- a/src/project.cc +++ b/src/project.cc @@ -117,17 +117,6 @@ struct ProjectProcessor { } hash_combine(hash, std::hash{}(arg)); } - for (size_t i = 1; i < args.size(); i++) - // This is most likely the file path we will be passing to clang. The - // path needs to be absolute, otherwise clang_codeCompleteAt is extremely - // slow. See - // https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678. - if (args[i][0] != '-' && EndsWith(args[i], base_name)) { - args[i] = ResolveIfRelative(entry.directory, args[i]); - continue; - } - - args.push_back("-resource-dir=" + g_config->clang.resourceDir); args.push_back("-working-directory=" + entry.directory); if (!command_set.insert(hash).second) { @@ -197,8 +186,10 @@ ReadCompilerArgumentsFromFile(const std::string &path) { if (!MBOrErr) return {}; std::vector args; - for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I) + for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I) { args.push_back(*I); + DoPathMapping(args.back()); + } return args; } @@ -329,9 +320,13 @@ LoadEntriesFromDirectory(ProjectConfig *project, for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) { Project::Entry entry; entry.directory = NormalizePath(Cmd.Directory); + DoPathMapping(entry.directory); entry.filename = NormalizePath(ResolveIfRelative(entry.directory, Cmd.Filename)); + DoPathMapping(entry.filename); entry.args = std::move(Cmd.CommandLine); + for (std::string &arg : entry.args) + DoPathMapping(arg); proc.Process(entry); if (Seen.insert(entry.filename).second) result.push_back(entry); diff --git a/src/serializer.cc b/src/serializer.cc index 41c10d9a..e0f59535 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -159,26 +159,39 @@ void Reflect(Writer &visitor, std::unordered_map &map) { visitor.EndArray(); } -// Used by IndexFile::dependencies. Timestamps are emitted for Binary. -void Reflect(Reader &visitor, StringMap &map) { - visitor.IterArray([&](Reader &entry) { - std::string name; - Reflect(entry, name); - if (visitor.Format() == SerializeFormat::Binary) - Reflect(entry, map[name]); - else - map[name] = 0; - }); -} -void Reflect(Writer &visitor, StringMap &map) { - visitor.StartArray(map.size()); - for (auto &it : map) { - std::string key = it.first(); - Reflect(visitor, key); - if (visitor.Format() == SerializeFormat::Binary) - Reflect(visitor, it.second); +// Used by IndexFile::dependencies. +void Reflect(Reader &vis, StringMap &v) { + std::string name; + if (vis.Format() == SerializeFormat::Json) { + auto &vis1 = static_cast(vis); + for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it) + v[it->name.GetString()] = it->value.GetInt64(); + } else { + vis.IterArray([&](Reader &entry) { + Reflect(entry, name); + Reflect(entry, v[name]); + }); + } +} +void Reflect(Writer &vis, StringMap &v) { + if (vis.Format() == SerializeFormat::Json) { + auto &vis1 = static_cast(vis); + vis.StartObject(); + for (auto &it : v) { + std::string key = it.first(); + vis1.m().Key(key.c_str()); + vis1.m().Int64(it.second); + } + vis.EndObject(); + } else { + vis.StartArray(v.size()); + for (auto &it : v) { + std::string key = it.first(); + Reflect(vis, key); + Reflect(vis, it.second); + } + vis.EndArray(); } - visitor.EndArray(); } // TODO: Move this to indexer.cc @@ -448,6 +461,22 @@ Deserialize(SerializeFormat format, const std::string &path, // Restore non-serialized state. file->path = path; + if (g_config->clang.pathMappings.size()) { + DoPathMapping(file->import_file); + for (std::string &arg : file->args) + DoPathMapping(arg); + for (auto &[_, path] : file->lid2path) + DoPathMapping(path); + for (auto &include : file->includes) + DoPathMapping(include.resolved_path); + StringMap dependencies; + for (auto &it : file->dependencies) { + std::string path = it.first().str(); + DoPathMapping(path); + dependencies[path] = it.second; + } + file->dependencies = std::move(dependencies); + } return file; } } // namespace ccls diff --git a/src/serializers/json.h b/src/serializers/json.h index 131556c2..fb3751bc 100644 --- a/src/serializers/json.h +++ b/src/serializers/json.h @@ -27,6 +27,7 @@ class JsonReader : public Reader { public: JsonReader(rapidjson::GenericValue> *m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } + rapidjson::GenericValue> &m() { return *m_; } bool IsBool() override { return m_->IsBool(); } bool IsNull() override { return m_->IsNull(); } @@ -95,6 +96,7 @@ class JsonWriter : public Writer { public: JsonWriter(rapidjson::Writer *m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } + rapidjson::Writer &m() { return *m_; } void Null() override { m_->Null(); } void Bool(bool x) override { m_->Bool(x); } From 14b73f0d6f69b2be0780ecde9d72266b4abf5cfc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 16 Sep 2018 16:32:06 -0700 Subject: [PATCH 36/66] Add hierarchicalDocumentSymbolSupport --- src/config.h | 5 +- src/indexer.cc | 23 ++-- src/messages/initialize.cc | 12 +- src/messages/textDocument_documentSymbol.cc | 113 ++++++++++++++++++ .../workspace_didChangeWatchedFiles.cc | 22 ++-- 5 files changed, 147 insertions(+), 28 deletions(-) diff --git a/src/config.h b/src/config.h index 23b2fdb8..1b7b7ae5 100644 --- a/src/config.h +++ b/src/config.h @@ -81,6 +81,8 @@ struct Config { } clang; struct ClientCapability { + // TextDocumentClientCapabilities.documentSymbol.hierarchicalDocumentSymbolSupport + bool hierarchicalDocumentSymbolSupport = false; // TextDocumentClientCapabilities.completion.completionItem.snippetSupport bool snippetSupport = false; } client; @@ -249,7 +251,8 @@ struct Config { }; MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, resourceDir); -MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport); +MAKE_REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport, + snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, dropOldRequests, duplicateOptional, filterAndSort, diff --git a/src/indexer.cc b/src/indexer.cc index cc8fc8bc..e4c86d31 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -904,22 +904,23 @@ public: type->def.kind = RD->getTagKind() == TTK_Struct ? lsSymbolKind::Struct : lsSymbolKind::Class; if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) { + StringRef Tag; + switch (RD->getTagKind()) { + case TTK_Struct: Tag = "struct"; break; + case TTK_Interface: Tag = "__interface"; break; + case TTK_Union: Tag = "union"; break; + case TTK_Class: Tag = "class"; break; + case TTK_Enum: Tag = "enum"; break; + } if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) { StringRef Name = TD->getName(); - StringRef Tag; - switch (RD->getTagKind()) { - case TTK_Struct: Tag = "struct "; break; - case TTK_Interface: Tag = "__interface "; break; - case TTK_Union: Tag = "union "; break; - case TTK_Class: Tag = "class "; break; - case TTK_Enum: Tag = "enum "; break; - } - std::string name = ("anon " + Tag + Name).str(); + std::string name = ("anon " + Tag + " " + Name).str(); type->def.detailed_name = Intern(name); type->def.short_name_size = name.size(); } else { - // e.g. "struct {}" - SetName(OrigD, "", "", type->def); + std::string name = ("anon " + Tag).str(); + type->def.detailed_name = Intern(name); + type->def.short_name_size = name.size(); } } if (is_def) { diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index f93c0494..407f7b18 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -270,6 +270,10 @@ struct lsTextDocumentClientCapabilities { } completionItem; } completion; + struct lsDocumentSymbol { + bool hierarchicalDocumentSymbolSupport = false; + } documentSymbol; + struct lsGenericDynamicReg { // Whether foo supports dynamic registration. std::optional dynamicRegistration; @@ -291,6 +295,8 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization, dynamicRegistration, willSave, willSaveWaitUntil, didSave); MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion, dynamicRegistration, completionItem); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsDocumentSymbol, + hierarchicalDocumentSymbolSupport); MAKE_REFLECT_STRUCT( lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem, snippetSupport); @@ -299,8 +305,8 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg, MAKE_REFLECT_STRUCT( lsTextDocumentClientCapabilities::CodeLensRegistrationOptions, dynamicRegistration, resolveProvider); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, synchronization, - completion, rename); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, completion, + documentSymbol, rename, synchronization); struct lsClientCapabilities { // Workspace specific client capabilities. @@ -449,6 +455,8 @@ struct Handler_Initialize : BaseMessageHandler { const auto &capabilities = params.capabilities; g_config->client.snippetSupport = capabilities.textDocument.completion.completionItem.snippetSupport; + g_config->client.hierarchicalDocumentSymbolSupport = + capabilities.textDocument.documentSymbol.hierarchicalDocumentSymbolSupport; // Ensure there is a resource directory. if (g_config->clang.resourceDir.empty()) diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index 9991cc93..f6064d19 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -19,6 +19,8 @@ limitations under the License. using namespace ccls; using namespace clang; +MAKE_HASHABLE(SymbolIdx, t.usr, t.kind); + namespace { MethodType kMethodType = "textDocument/documentSymbol"; @@ -52,6 +54,28 @@ struct Out_TextDocumentDocumentSymbol }; MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result); +struct lsDocumentSymbol { + std::string name; + std::string detail; + lsSymbolKind kind; + lsRange range; + lsRange selectionRange; + std::vector> children; +}; +void Reflect(Writer &vis, std::unique_ptr &v); +MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, detail, kind, range, selectionRange, + children); +void Reflect(Writer &vis, std::unique_ptr &v) { + Reflect(vis, *v); +} + +struct Out_HierarchicalDocumentSymbol + : public lsOutMessage { + lsRequestId id; + std::vector> result; +}; +MAKE_REFLECT_STRUCT(Out_HierarchicalDocumentSymbol, jsonrpc, id, result); + struct Handler_TextDocumentDocumentSymbol : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -63,6 +87,9 @@ struct Handler_TextDocumentDocumentSymbol if (!FindFileOrFail(db, project, request->id, params.textDocument.uri.GetPath(), &file, &file_id)) return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; const auto &symbol2refcnt = params.all ? file->symbol2refcnt : file->outline2refcnt; @@ -78,6 +105,92 @@ struct Handler_TextDocumentDocumentSymbol out.result.push_back(ls_loc->range); std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); + } else if (g_config->client.hierarchicalDocumentSymbolSupport) { + std::unordered_map< + SymbolIdx, std::pair>> + sym2ds; + for (auto [sym, refcnt] : symbol2refcnt) { + if (refcnt <= 0) + continue; + auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind}); + if (!r.second) + continue; + auto &kv = r.first->second; + kv.second = std::make_unique(); + lsDocumentSymbol &ds = *kv.second; + WithEntity(db, sym, [&](const auto &entity) { + auto *def = entity.AnyDef(); + if (!def) + return; + ds.name = def->Name(false); + ds.detail = def->Name(true); + for (auto &def : entity.def) + if (def.file_id == file_id) { + if (!def.spell || !def.extent) + break; + ds.kind = def.kind; + if (auto ls_range = GetLsRange(wfile, def.extent->range)) + ds.range = *ls_range; + else + break; + if (auto ls_range = GetLsRange(wfile, def.spell->range)) + ds.selectionRange = *ls_range; + else + break; + kv.first = static_cast(&def); + } + }); + if (kv.first && sym.kind == SymbolKind::Var) + if (static_cast(kv.first)->is_local()) + kv.first = nullptr; + if (!kv.first) { + kv.second.reset(); + continue; + } + } + for (auto &[sym, def_ds] : sym2ds) { + if (!def_ds.second) + continue; + lsDocumentSymbol &ds = *def_ds.second; + switch (sym.kind) { + case SymbolKind::Func: { + auto &def = *static_cast(def_ds.first); + for (Usr usr1 : def.vars) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + break; + } + case SymbolKind::Type: { + auto &def = *static_cast(def_ds.first); + for (Usr usr1 : def.funcs) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Func}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + for (Usr usr1 : def.types) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Type}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + for (auto [usr1, _] : def.vars) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + break; + } + default: + break; + } + } + Out_HierarchicalDocumentSymbol out; + out.id = request->id; + for (auto &[sym, def_ds] : sym2ds) + if (def_ds.second) + out.result.push_back(std::move(def_ds.second)); + pipeline::WriteStdout(kMethodType, out); } else { Out_TextDocumentDocumentSymbol out; out.id = request->id; diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index 8ba46408..fd5806d1 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -54,28 +54,22 @@ struct Handler_WorkspaceDidChangeWatchedFiles void Run(In_WorkspaceDidChangeWatchedFiles *request) override { for (lsFileEvent &event : request->params.changes) { std::string path = event.uri.GetPath(); - Project::Entry entry; - { - std::lock_guard lock(project->mutex_); - auto it = project->path_to_entry_index.find(path); - if (it == project->path_to_entry_index.end()) - continue; - entry = project->entries[it->second]; - } - IndexMode mode = - working_files->GetFileByFilename(entry.filename) != nullptr - ? IndexMode::Normal - : IndexMode::NonInteractive; + IndexMode mode = working_files->GetFileByFilename(path) + ? IndexMode::Normal + : IndexMode::NonInteractive; switch (event.type) { case lsFileChangeType::Created: case lsFileChangeType::Changed: { - pipeline::Index(path, entry.args, mode); + pipeline::Index(path, {}, mode); if (mode == IndexMode::Normal) clang_complete->NotifySave(path); + else + clang_complete->FlushSession(path); break; } case lsFileChangeType::Deleted: - pipeline::Index(path, entry.args, mode); + pipeline::Index(path, {}, mode); + clang_complete->FlushSession(path); break; } } From 763106c3d41a8c198e24f8567ac989492b4eb6d2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 17 Sep 2018 18:03:59 -0700 Subject: [PATCH 37/66] Simplify pipeline and fix race --- src/config.cc | 1 - src/config.h | 1 - src/file_consumer.cc | 36 ++----- src/file_consumer.h | 8 +- src/indexer.cc | 4 +- src/match.cc | 17 +--- src/messages/ccls_reload.cc | 11 --- src/messages/initialize.cc | 1 - src/pipeline.cc | 189 +++++++++++++++++------------------- src/pipeline.hh | 1 + src/project.cc | 4 +- src/project.h | 2 - 12 files changed, 106 insertions(+), 169 deletions(-) diff --git a/src/config.cc b/src/config.cc index 47dbfd00..0d4b9039 100644 --- a/src/config.cc +++ b/src/config.cc @@ -16,7 +16,6 @@ limitations under the License. #include "config.h" Config *g_config; -thread_local int g_thread_id; namespace ccls { void DoPathMapping(std::string &arg) { diff --git a/src/config.h b/src/config.h index 1b7b7ae5..816c024c 100644 --- a/src/config.h +++ b/src/config.h @@ -273,7 +273,6 @@ MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, index, largeFileSize, workspaceSymbol, xref); extern Config *g_config; -thread_local extern int g_thread_id; namespace ccls { void DoPathMapping(std::string &arg); diff --git a/src/file_consumer.cc b/src/file_consumer.cc index 3542b263..7f8cca71 100644 --- a/src/file_consumer.cc +++ b/src/file_consumer.cc @@ -69,43 +69,21 @@ VFS::State VFS::Get(const std::string &file) { auto it = state.find(file); if (it != state.end()) return it->second; - return {0, 0, 0}; + return {0, 0}; } -bool VFS::Mark(const std::string &file, int owner, int stage) { - std::lock_guard lock(mutex); - State &st = state[file]; - if (st.stage < stage) { - st.owner = owner; - st.stage = stage; - return true; - } else - return false; -} - -bool VFS::Stamp(const std::string &file, int64_t ts) { +bool VFS::Stamp(const std::string &file, int64_t ts, int64_t offset) { std::lock_guard lock(mutex); State &st = state[file]; if (st.timestamp < ts) { - st.timestamp = ts; + st.timestamp = ts + offset; return true; } else return false; } -void VFS::ResetLocked(const std::string &file) { - State &st = state[file]; - if (st.owner == 0 || st.owner == g_thread_id) - st.stage = 0; -} - -void VFS::Reset(const std::string &file) { - std::lock_guard lock(mutex); - ResetLocked(file); -} - FileConsumer::FileConsumer(VFS *vfs, const std::string &parse_file) - : vfs_(vfs), parse_file_(parse_file), thread_id_(g_thread_id) {} + : vfs_(vfs), parse_file_(parse_file) {} IndexFile *FileConsumer::TryConsumeFile( const clang::FileEntry &File, @@ -116,9 +94,9 @@ IndexFile *FileConsumer::TryConsumeFile( return it->second.get(); std::string file_name = FileName(File); - // We did not take the file from global. Cache that we failed so we don't try - // again and return nullptr. - if (!vfs_->Mark(file_name, thread_id_, 2)) { + int64_t tim = File.getModificationTime(); + assert(tim); + if (!vfs_->Stamp(file_name, tim, 0)) { local_[UniqueID] = nullptr; return nullptr; } diff --git a/src/file_consumer.h b/src/file_consumer.h index d2c75894..ab2bebcc 100644 --- a/src/file_consumer.h +++ b/src/file_consumer.h @@ -43,18 +43,13 @@ struct FileContents { struct VFS { struct State { int64_t timestamp; - int owner; - int stage; bool loaded = false; }; mutable std::unordered_map state; mutable std::mutex mutex; State Get(const std::string &file); - bool Mark(const std::string &file, int owner, int stage); - bool Stamp(const std::string &file, int64_t ts); - void ResetLocked(const std::string &file); - void Reset(const std::string &file); + bool Stamp(const std::string &file, int64_t ts, int64_t offset); }; namespace std { @@ -95,5 +90,4 @@ private: local_; VFS *vfs_; std::string parse_file_; - int thread_id_; }; diff --git a/src/indexer.cc b/src/indexer.cc index e4c86d31..592d35f0 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1263,9 +1263,10 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, } std::string buf = wfiles->GetContent(file); std::vector> Bufs; - if (g_config->index.onChange && buf.size()) { + if (buf.size()) { // If there is a completion session, reuse its preamble if exists. bool done_remap = false; +#if 0 std::shared_ptr session = completion->TryGetSession(file, false, false); if (session) @@ -1278,6 +1279,7 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, done_remap = true; } } +#endif for (auto &[filename, content] : remapped) { if (filename == file && done_remap) continue; diff --git a/src/match.cc b/src/match.cc index 3ddb0c37..b86dfd90 100644 --- a/src/match.cc +++ b/src/match.cc @@ -19,18 +19,7 @@ limitations under the License. #include "pipeline.hh" using namespace ccls; -// static std::optional Matcher::Create(const std::string &search) { - /* - std::string real_search; - real_search.reserve(search.size() * 3 + 2); - for (auto c : search) { - real_search += ".*"; - real_search += c; - } - real_search += ".*"; - */ - try { Matcher m; m.regex_string = search; @@ -73,18 +62,16 @@ GroupMatch::GroupMatch(const std::vector &whitelist, bool GroupMatch::IsMatch(const std::string &value, std::string *match_failure_reason) const { - for (const Matcher &m : whitelist) { + for (const Matcher &m : whitelist) if (m.IsMatch(value)) return true; - } - for (const Matcher &m : blacklist) { + for (const Matcher &m : blacklist) if (m.IsMatch(value)) { if (match_failure_reason) *match_failure_reason = "blacklist \"" + m.regex_string + "\""; return false; } - } return true; } diff --git a/src/messages/ccls_reload.cc b/src/messages/ccls_reload.cc index 6652b049..bc67cc26 100644 --- a/src/messages/ccls_reload.cc +++ b/src/messages/ccls_reload.cc @@ -82,17 +82,6 @@ struct Handler_CclsReload : BaseMessageHandler { q.pop(); need_index.insert(file->def->path); - std::optional write_time = - pipeline::LastWriteTime(file->def->path); - if (!write_time) - continue; - { - std::lock_guard lock(vfs->mutex); - VFS::State &st = vfs->state[file->def->path]; - if (st.timestamp < write_time) - st.stage = 0; - } - if (request->params.dependencies) for (const std::string &path : graph[file->def->path]) { auto it = path_to_file.find(path); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 407f7b18..07a5e90d 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -502,7 +502,6 @@ struct Handler_Initialize : BaseMessageHandler { LOG_S(INFO) << "start " << g_config->index.threads << " indexers"; for (int i = 0; i < g_config->index.threads; i++) { std::thread([=]() { - g_thread_id = i + 1; std::string name = "indexer" + std::to_string(i); set_thread_name(name.c_str()); pipeline::Indexer_Main(clang_complete, vfs, project, working_files); diff --git a/src/pipeline.cc b/src/pipeline.cc index 67e5706c..3b8fb3c5 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -26,7 +26,6 @@ limitations under the License. #include "project.h" #include "query_utils.h" -#include #include #include using namespace llvm; @@ -75,6 +74,9 @@ void DiagnosticsPublisher::Publish(WorkingFiles *working_files, } namespace ccls::pipeline { + +int64_t loaded_ts = 0, tick = 0; + namespace { struct Index_Request { @@ -82,6 +84,7 @@ struct Index_Request { std::vector args; IndexMode mode; lsRequestId id; + int64_t ts = tick++; }; struct Stdout_Request { @@ -172,6 +175,8 @@ std::unique_ptr RawCacheLoad(const std::string &path) { bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, Project *project, VFS *vfs, const GroupMatch &matcher) { + const int N_MUTEXES = 256; + static std::mutex mutexes[N_MUTEXES]; std::optional opt_request = index_request->TryPopFront(); if (!opt_request) return false; @@ -186,8 +191,8 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, return false; } - if (std::string reason; !matcher.IsMatch(request.path, &reason)) { - LOG_IF_S(INFO, loud) << "skip " << request.path << " for " << reason; + if (!matcher.IsMatch(request.path)) { + LOG_IF_S(INFO, loud) << "skip " << request.path; return false; } @@ -200,74 +205,75 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, std::optional write_time = LastWriteTime(path_to_index); if (!write_time) return true; - int reparse = vfs->Stamp(path_to_index, *write_time); + int reparse = vfs->Stamp(path_to_index, *write_time, -1); if (request.path != path_to_index) { std::optional mtime1 = LastWriteTime(request.path); if (!mtime1) return true; - if (vfs->Stamp(request.path, *mtime1)) - reparse = 2; + if (vfs->Stamp(request.path, *mtime1, -1)) + reparse = 1; } if (g_config->index.onChange) reparse = 2; - if (!vfs->Mark(path_to_index, g_thread_id, 1) && !reparse) + if (!reparse) return true; - prev = RawCacheLoad(path_to_index); - if (!prev) - reparse = 2; - else { - if (CacheInvalid(vfs, prev.get(), path_to_index, entry.args, std::nullopt)) - reparse = 2; - int reparseForDep = g_config->index.reparseForDependency; - if (reparseForDep > 1 || (reparseForDep == 1 && !Project::loaded)) - for (const auto &dep : prev->dependencies) { - if (auto write_time1 = LastWriteTime(dep.first().str())) { - if (dep.second < *write_time1) { - reparse = 2; - std::lock_guard lock(vfs->mutex); - vfs->state[dep.first().str()].stage = 0; - } - } else - reparse = 2; + if (reparse < 2) do { + std::unique_lock lock( + mutexes[std::hash()(path_to_index) % N_MUTEXES]); + prev = RawCacheLoad(path_to_index); + if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, + std::nullopt)) + break; + bool update = false; + for (const auto &dep : prev->dependencies) + if (auto mtime1 = LastWriteTime(dep.first.val().str())) { + if (dep.second < *mtime1) + update = true; + } else { + update = true; } - } + int forDep = g_config->index.reparseForDependency; + if (update && (forDep > 1 || (forDep == 1 && request.ts < loaded_ts))) + break; - // Grab the ownership - if (reparse) { - std::lock_guard lock(vfs->mutex); - vfs->state[path_to_index].owner = g_thread_id; - vfs->state[path_to_index].stage = 0; - } - - if (reparse < 2) { - LOG_S(INFO) << "load cache for " << path_to_index; - auto dependencies = prev->dependencies; - if (reparse) { - IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); - std::lock_guard lock(vfs->mutex); - vfs->state[path_to_index].loaded = true; - } - for (const auto &dep : dependencies) { - std::string path = dep.first().str(); - if (vfs->Mark(path, 0, 2) && (prev = RawCacheLoad(path))) { + if (reparse < 2) { + LOG_S(INFO) << "load cache for " << path_to_index; + auto dependencies = prev->dependencies; + if (reparse) { IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); + std::lock_guard lock1(vfs->mutex); + vfs->state[path_to_index].loaded = true; + } + lock.unlock(); + for (const auto &dep : dependencies) { + std::string path = dep.first.val().str(); + std::lock_guard lock1( + mutexes[std::hash()(path) % N_MUTEXES]); + prev = RawCacheLoad(path); + if (!prev) + continue; { - std::lock_guard lock(vfs->mutex); - vfs->state[path].loaded = true; + std::lock_guard lock2(vfs->mutex); + VFS::State &st = vfs->state[path]; + if (st.loaded) + continue; + st.loaded = true; + st.timestamp = prev->mtime; } + IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); if (entry.id >= 0) { - std::lock_guard lock(project->mutex_); + std::lock_guard lock2(project->mutex_); project->path_to_entry_index[path] = entry.id; } } + return true; } - return true; - } + } while (0); LOG_IF_S(INFO, loud) << "parse " << path_to_index; @@ -288,64 +294,52 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, out.error.message = "Failed to index " + path_to_index; pipeline::WriteStdout(kMethodType_Unknown, out); } - vfs->Reset(path_to_index); return true; } for (std::unique_ptr &curr : indexes) { std::string path = curr->path; - bool do_update = path == path_to_index || path == request.path, loaded; - { - std::lock_guard lock(vfs->mutex); - VFS::State &st = vfs->state[path]; - if (st.timestamp < curr->mtime) { - st.timestamp = curr->mtime; - do_update = true; - } - loaded = st.loaded; - st.loaded = true; - } - if (std::string reason; !matcher.IsMatch(path, &reason)) { - LOG_IF_S(INFO, loud) << "skip emitting and storing index of " << path << " for " - << reason; - do_update = false; - } - if (!do_update) { - vfs->Reset(path); + if (!matcher.IsMatch(path)) { + LOG_IF_S(INFO, loud) << "skip index for " << path; continue; } - prev.reset(); - if (loaded) - prev = RawCacheLoad(path); - - // Store current index. LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev << ")"; - if (g_config->cacheDirectory.empty()) { - std::lock_guard lock(g_index_mutex); - auto it = g_index.insert_or_assign( - path, InMemoryIndexFile{curr->file_contents, *curr}); - std::string().swap(it.first->second.index.file_contents); - } else { - std::string cache_path = GetCachePath(path); - WriteToFile(cache_path, curr->file_contents); - WriteToFile(AppendSerializationFormat(cache_path), - Serialize(g_config->cacheFormat, *curr)); + { + std::lock_guard lock(mutexes[std::hash()(path) % N_MUTEXES]); + bool loaded; + { + std::lock_guard lock1(vfs->mutex); + loaded = vfs->state[path].loaded; + } + if (loaded) + prev = RawCacheLoad(path); + else + prev.reset(); + if (g_config->cacheDirectory.empty()) { + std::lock_guard lock(g_index_mutex); + auto it = g_index.insert_or_assign( + path, InMemoryIndexFile{curr->file_contents, *curr}); + std::string().swap(it.first->second.index.file_contents); + } else { + std::string cache_path = GetCachePath(path); + WriteToFile(cache_path, curr->file_contents); + WriteToFile(AppendSerializationFormat(cache_path), + Serialize(g_config->cacheFormat, *curr)); + } + on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()), + request.mode != IndexMode::NonInteractive); + { + std::lock_guard lock1(vfs->mutex); + vfs->state[path].loaded = true; + } + if (entry.id >= 0) { + std::lock_guard lock(project->mutex_); + for (auto &dep : curr->dependencies) + project->path_to_entry_index[dep.first()] = entry.id; + } } - - vfs->Reset(path); - if (entry.id >= 0) { - std::lock_guard lock(project->mutex_); - for (auto &dep : curr->dependencies) - project->path_to_entry_index[dep.first()] = entry.id; - } - - // Build delta update. - IndexUpdate update = IndexUpdate::CreateDelta(prev.get(), curr.get()); - - on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); } return true; @@ -376,7 +370,6 @@ void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, WorkingFiles *working_files, IndexUpdate *update) { if (update->refresh) { - Project::loaded = true; LOG_S(INFO) << "loaded project. Refresh semantic highlight for all working file."; std::lock_guard lock(working_files->files_mutex); diff --git a/src/pipeline.hh b/src/pipeline.hh index 6e311d5c..946236e1 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -35,6 +35,7 @@ enum class IndexMode { }; namespace pipeline { +extern int64_t loaded_ts, tick; void Init(); void LaunchStdin(); void LaunchStdout(); diff --git a/src/project.cc b/src/project.cc index 2d6eed1e..fcbce38f 100644 --- a/src/project.cc +++ b/src/project.cc @@ -351,10 +351,7 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { } // namespace -bool Project::loaded = false; - void Project::Load(const std::string &root_directory) { - Project::loaded = false; ProjectConfig project; project.extra_flags = g_config->clang.extraArgs; project.project_dir = root_directory; @@ -470,6 +467,7 @@ void Project::Index(WorkingFiles *wfiles, lsRequestId id) { interactive ? IndexMode::Normal : IndexMode::NonInteractive, id); }); + pipeline::loaded_ts = pipeline::tick; // Dummy request to indicate that project is loaded and // trigger refreshing semantic highlight for all working files. pipeline::Index("", {}, IndexMode::NonInteractive); diff --git a/src/project.h b/src/project.h index b431d1d4..10c0b3c3 100644 --- a/src/project.h +++ b/src/project.h @@ -72,6 +72,4 @@ struct Project { ForAllFilteredFiles(std::function action); void Index(WorkingFiles *wfiles, lsRequestId id); - - static bool loaded; }; From 525b6da1accfb0e6a7d69fc8016f12ab85a4eebd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 19 Sep 2018 00:51:15 -0700 Subject: [PATCH 38/66] intern strings in dependencies and IndexInclude::resolved_path --- src/indexer.cc | 5 +++-- src/indexer.h | 7 ++++--- src/pipeline.cc | 2 +- src/query.cc | 2 +- src/query.h | 2 +- src/serializer.cc | 30 +++++++++++++++++------------- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index 592d35f0..1f28475c 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1104,7 +1104,7 @@ public: if (IndexFile *db = param.ConsumeFile(*FE)) { std::string file_name = FileName(*File); if (file_name.size()) - db->includes.push_back({spell.start.line, std::move(file_name)}); + db->includes.push_back({spell.start.line, Intern(file_name)}); } } void MacroDefined(const Token &Tok, const MacroDirective *MD) override { @@ -1368,7 +1368,8 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, // dependency set. for (auto &[_, path] : param.SeenUniqueID) if (path != entry->path && path != entry->import_file) - entry->dependencies[path] = param.file2mtime[path]; + entry->dependencies[llvm::CachedHashStringRef(Intern(path))] = + param.file2mtime[path]; } return result; diff --git a/src/indexer.h b/src/indexer.h index ab20ba30..7235f373 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -27,7 +27,8 @@ limitations under the License. #include "utils.h" #include -#include +#include +#include #include #include @@ -232,7 +233,7 @@ struct IndexInclude { // information - a line is good enough for clicking. int line = 0; // Absolute path to the index. - std::string resolved_path; + const char *resolved_path; }; struct IndexFile { @@ -266,7 +267,7 @@ struct IndexFile { std::vector skipped_ranges; std::vector includes; - llvm::StringMap dependencies; + llvm::DenseMap dependencies; std::unordered_map usr2func; std::unordered_map usr2type; std::unordered_map usr2var; diff --git a/src/pipeline.cc b/src/pipeline.cc index 3b8fb3c5..f651f271 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -337,7 +337,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (entry.id >= 0) { std::lock_guard lock(project->mutex_); for (auto &dep : curr->dependencies) - project->path_to_entry_index[dep.first()] = entry.id; + project->path_to_entry_index[dep.first.val().str()] = entry.id; } } } diff --git a/src/query.cc b/src/query.cc index d09f33b1..f052c42c 100644 --- a/src/query.cc +++ b/src/query.cc @@ -62,7 +62,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile &indexed) { def.skipped_ranges = std::move(indexed.skipped_ranges); def.dependencies.reserve(indexed.dependencies.size()); for (auto &dep : indexed.dependencies) - def.dependencies.push_back(dep.first()); + def.dependencies.push_back(dep.first.val().data()); // llvm 8 -> data() def.language = indexed.language; return {std::move(def), std::move(indexed.file_contents)}; } diff --git a/src/query.h b/src/query.h index ea7d0bcf..4dfe62bb 100644 --- a/src/query.h +++ b/src/query.h @@ -46,7 +46,7 @@ struct QueryFile { // Parts of the file which are disabled. std::vector skipped_ranges; // Used by |$ccls/reload|. - std::vector dependencies; + std::vector dependencies; }; using DefUpdate = std::pair; diff --git a/src/serializer.cc b/src/serializer.cc index e0f59535..d523b118 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -27,6 +27,7 @@ limitations under the License. #include #include +using namespace ccls; using namespace llvm; bool gTestOutputMode = false; @@ -127,7 +128,7 @@ void Reflect(Writer &visitor, std::string_view &data) { void Reflect(Reader &vis, const char *&v) { const char *str = vis.GetString(); - v = ccls::Intern(str); + v = Intern(str); } void Reflect(Writer &vis, const char *&v) { vis.String(v); } @@ -160,33 +161,33 @@ void Reflect(Writer &visitor, std::unordered_map &map) { } // Used by IndexFile::dependencies. -void Reflect(Reader &vis, StringMap &v) { +void Reflect(Reader &vis, DenseMap &v) { std::string name; if (vis.Format() == SerializeFormat::Json) { auto &vis1 = static_cast(vis); for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it) - v[it->name.GetString()] = it->value.GetInt64(); + v[CachedHashStringRef(Intern(it->name.GetString()))] = + it->value.GetInt64(); } else { vis.IterArray([&](Reader &entry) { Reflect(entry, name); - Reflect(entry, v[name]); + Reflect(entry, v[CachedHashStringRef(Intern(name))]); }); } } -void Reflect(Writer &vis, StringMap &v) { +void Reflect(Writer &vis, DenseMap &v) { if (vis.Format() == SerializeFormat::Json) { auto &vis1 = static_cast(vis); vis.StartObject(); for (auto &it : v) { - std::string key = it.first(); - vis1.m().Key(key.c_str()); + vis1.m().Key(it.first.val().data()); // llvm 8 -> data() vis1.m().Int64(it.second); } vis.EndObject(); } else { vis.StartArray(v.size()); for (auto &it : v) { - std::string key = it.first(); + std::string key = it.first.val().str(); Reflect(vis, key); Reflect(vis, it.second); } @@ -467,13 +468,16 @@ Deserialize(SerializeFormat format, const std::string &path, DoPathMapping(arg); for (auto &[_, path] : file->lid2path) DoPathMapping(path); - for (auto &include : file->includes) - DoPathMapping(include.resolved_path); - StringMap dependencies; + for (auto &include : file->includes) { + std::string p(include.resolved_path); + DoPathMapping(p); + include.resolved_path = Intern(p); + } + decltype(file->dependencies) dependencies; for (auto &it : file->dependencies) { - std::string path = it.first().str(); + std::string path = it.first.val().str(); DoPathMapping(path); - dependencies[path] = it.second; + dependencies[CachedHashStringRef(Intern(path))] = it.second; } file->dependencies = std::move(dependencies); } From 08645d64c190dc11341f28b3d35f5c3eacdac22f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 19 Sep 2018 09:31:45 -0700 Subject: [PATCH 39/66] intern args --- index_tests/types/anonymous_struct.cc | 4 +- src/clang_tu.cc | 9 ++-- src/clang_tu.h | 2 +- src/indexer.cc | 2 +- src/indexer.h | 4 +- src/messages/textDocument_didOpen.cc | 11 +++-- src/pipeline.cc | 17 +++---- src/pipeline.hh | 2 +- src/project.cc | 68 +++++++++++++-------------- src/project.h | 6 +-- src/query.h | 2 +- src/serializer.cc | 9 +++- src/test.cc | 11 +++-- 13 files changed, 76 insertions(+), 71 deletions(-) diff --git a/index_tests/types/anonymous_struct.cc b/index_tests/types/anonymous_struct.cc index b3dbecc3..9d88a8bf 100644 --- a/index_tests/types/anonymous_struct.cc +++ b/index_tests/types/anonymous_struct.cc @@ -26,9 +26,9 @@ OUTPUT: "uses": [] }, { "usr": 1428566502523368801, - "detailed_name": "struct {}", + "detailed_name": "anon struct", "qual_name_offset": 0, - "short_name": "", + "short_name": "anon struct", "kind": 23, "declarations": [], "spell": "2:3-2:9|17937907487590875128|2|1026|-1", diff --git a/src/clang_tu.cc b/src/clang_tu.cc index ecac6ab7..53645489 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -66,17 +66,14 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, } std::unique_ptr -BuildCompilerInvocation(const std::vector &args, +BuildCompilerInvocation(std::vector args, IntrusiveRefCntPtr VFS) { std::string save = "-resource-dir=" + g_config->clang.resourceDir; - std::vector cargs; - for (auto &arg : args) - cargs.push_back(arg.c_str()); - cargs.push_back(save.c_str()); + args.push_back(save.c_str()); IntrusiveRefCntPtr Diags( CompilerInstance::createDiagnostics(new DiagnosticOptions)); std::unique_ptr CI = - createInvocationFromCommandLine(cargs, Diags, VFS); + createInvocationFromCommandLine(args, Diags, VFS); if (CI) { CI->getDiagnosticOpts().IgnoreWarnings = true; CI->getFrontendOpts().DisableFree = false; diff --git a/src/clang_tu.h b/src/clang_tu.h index ec4b5770..1edcd5ee 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.h @@ -36,5 +36,5 @@ Range FromTokenRange(const clang::SourceManager &SM, llvm::sys::fs::UniqueID *UniqueID = nullptr); std::unique_ptr -BuildCompilerInvocation(const std::vector &args, +BuildCompilerInvocation(std::vector args, llvm::IntrusiveRefCntPtr VFS); diff --git a/src/indexer.cc b/src/indexer.cc index 1f28475c..a6b70ca1 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1236,7 +1236,7 @@ void Init() { std::vector> Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &file, - const std::vector &args, + const std::vector &args, const std::vector> &remapped) { if (!g_config->index.enabled) return {}; diff --git a/src/indexer.h b/src/indexer.h index 7235f373..17306552 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -247,7 +247,7 @@ struct IndexFile { llvm::sys::fs::UniqueID UniqueID; std::string path; - std::vector args; + std::vector args; // This is unfortunately time_t as used by clang::FileEntry int64_t mtime = 0; LanguageId language = LanguageId::C; @@ -293,6 +293,6 @@ void Init(); std::vector> Index(CompletionManager *complete, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &file, - const std::vector &args, + const std::vector &args, const std::vector> &remapped); } diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 939ec8bd..4e76e8e9 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -64,14 +64,15 @@ struct Handler_TextDocumentDidOpen } include_complete->AddFile(working_file->filename); - if (params.args.size()) - project->SetFlagsForFile(params.args, path); + std::vector args; + for (const std::string &arg : params.args) + args.push_back(Intern(arg)); + if (args.size()) + project->SetArgsForFile(args, path); // Submit new index request if it is not a header file. if (SourceFileLanguage(path) != LanguageId::Unknown) { - pipeline::Index( - path, params.args.size() ? params.args : std::vector{}, - IndexMode::Normal); + pipeline::Index(path, args, IndexMode::Normal); clang_complete->FlushSession(path); } diff --git a/src/pipeline.cc b/src/pipeline.cc index f651f271..0b5a0f6f 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -81,7 +81,7 @@ namespace { struct Index_Request { std::string path; - std::vector args; + std::vector args; IndexMode mode; lsRequestId id; int64_t ts = tick++; @@ -108,7 +108,7 @@ std::shared_mutex g_index_mutex; std::unordered_map g_index; bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path, - const std::vector &args, + const std::vector &args, const std::optional &from) { { std::lock_guard lock(vfs->mutex); @@ -119,13 +119,14 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path, } } - if (prev->args != args) { + bool changed = prev->args.size() != args.size(); + for (size_t i = 0; !changed && i < args.size(); i++) + if (strcmp(prev->args[i], args[i])) + changed = true; + if (changed) LOG_S(INFO) << "args changed for " << path << (from ? " (via " + *from + ")" : std::string()); - return true; - } - - return false; + return changed; }; std::string AppendSerializationFormat(const std::string &base) { @@ -537,7 +538,7 @@ void MainLoop() { } } -void Index(const std::string &path, const std::vector &args, +void Index(const std::string &path, const std::vector &args, IndexMode mode, lsRequestId id) { index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } diff --git a/src/pipeline.hh b/src/pipeline.hh index 946236e1..0cbabffc 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -43,7 +43,7 @@ void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, WorkingFiles *wfiles); void MainLoop(); -void Index(const std::string &path, const std::vector &args, +void Index(const std::string &path, const std::vector &args, IndexMode mode, lsRequestId id = {}); std::optional LastWriteTime(const std::string &path); diff --git a/src/project.cc b/src/project.cc index fcbce38f..98f84083 100644 --- a/src/project.cc +++ b/src/project.cc @@ -55,7 +55,6 @@ enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand }; struct ProjectConfig { std::unordered_set quote_dirs; std::unordered_set angle_dirs; - std::vector extra_flags; std::string project_dir; ProjectMode mode = ProjectMode::CompileCommandsJson; }; @@ -85,17 +84,17 @@ struct ProjectProcessor { const std::string base_name = sys::path::filename(entry.filename); // Expand %c %cpp %clang - std::vector args; - args.reserve(entry.args.size() + config->extra_flags.size() + 3); + std::vector args; + args.reserve(entry.args.size() + g_config->clang.extraArgs.size() + 1); const LanguageId lang = SourceFileLanguage(entry.filename); - for (const std::string &arg : entry.args) { - if (arg.compare(0, 3, "%c ") == 0) { + for (const char *arg : entry.args) { + if (strncmp(arg, "%c ", 3) == 0) { if (lang == LanguageId::C) - args.push_back(arg.substr(3)); - } else if (arg.compare(0, 5, "%cpp ") == 0) { + args.push_back(arg + 3); + } else if (strncmp(arg, "%cpp ", 5) == 0) { if (lang == LanguageId::Cpp) - args.push_back(arg.substr(5)); - } else if (arg == "%clang") { + args.push_back(arg + 5); + } else if (strcmp(arg, "%clang") == 0) { args.push_back(lang == LanguageId::Cpp ? "clang++" : "clang"); } else if (!llvm::is_contained(g_config->clang.excludeArgs, arg)) { args.push_back(arg); @@ -103,8 +102,8 @@ struct ProjectProcessor { } if (args.empty()) return; - args.insert(args.end(), config->extra_flags.begin(), - config->extra_flags.end()); + for (const std::string &arg : g_config->clang.extraArgs) + args.push_back(Intern(arg)); size_t hash = std::hash{}(entry.directory); for (auto &arg : args) { @@ -117,7 +116,7 @@ struct ProjectProcessor { } hash_combine(hash, std::hash{}(arg)); } - args.push_back("-working-directory=" + entry.directory); + args.push_back(Intern("-working-directory=" + entry.directory)); if (!command_set.insert(hash).second) { entry.args = std::move(args); @@ -141,13 +140,9 @@ struct ProjectProcessor { } Driver.setCheckInputsExist(false); - std::vector cargs; - cargs.reserve(args.size() + 1); - for (auto &arg : args) - cargs.push_back(arg.c_str()); - cargs.push_back("-fsyntax-only"); + args.push_back("-fsyntax-only"); - std::unique_ptr C(Driver.BuildCompilation(cargs)); + std::unique_ptr C(Driver.BuildCompilation(args)); const driver::JobList &Jobs = C->getJobs(); if (Jobs.size() != 1) return; @@ -180,15 +175,16 @@ struct ProjectProcessor { } }; -std::vector +std::vector ReadCompilerArgumentsFromFile(const std::string &path) { auto MBOrErr = MemoryBuffer::getFile(path); if (!MBOrErr) return {}; - std::vector args; + std::vector args; for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I) { - args.push_back(*I); - DoPathMapping(args.back()); + std::string line = *I; + DoPathMapping(line); + args.push_back(Intern(line)); } return args; } @@ -198,12 +194,12 @@ std::vector LoadFromDirectoryListing(ProjectConfig *config) { config->mode = ProjectMode::DotCcls; SmallString<256> Path; sys::path::append(Path, config->project_dir, ".ccls"); - LOG_IF_S(WARNING, !sys::fs::exists(Path) && config->extra_flags.empty()) + LOG_IF_S(WARNING, !sys::fs::exists(Path) && g_config->clang.extraArgs.empty()) << "ccls has no clang arguments. Use either " "compile_commands.json or .ccls, See ccls README for " "more information."; - std::unordered_map> folder_args; + std::unordered_map> folder_args; std::vector files; GetFilesInFolder(config->project_dir, true /*recursive*/, @@ -246,7 +242,7 @@ std::vector LoadFromDirectoryListing(ProjectConfig *config) { e.args = GetCompilerArgumentForFile(file); if (e.args.empty()) e.args.push_back("%clang"); // Add a Dummy. - e.args.push_back(e.filename); + e.args.push_back(Intern(e.filename)); proc.Process(e); result.push_back(e); } @@ -324,9 +320,12 @@ LoadEntriesFromDirectory(ProjectConfig *project, entry.filename = NormalizePath(ResolveIfRelative(entry.directory, Cmd.Filename)); DoPathMapping(entry.filename); - entry.args = std::move(Cmd.CommandLine); - for (std::string &arg : entry.args) + std::vector args = std::move(Cmd.CommandLine); + entry.args.reserve(args.size()); + for (std::string &arg : args) { DoPathMapping(arg); + entry.args.push_back(Intern(arg)); + } proc.Process(entry); if (Seen.insert(entry.filename).second) result.push_back(entry); @@ -353,7 +352,6 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { void Project::Load(const std::string &root_directory) { ProjectConfig project; - project.extra_flags = g_config->clang.extraArgs; project.project_dir = root_directory; entries = LoadEntriesFromDirectory(&project, g_config->compilationDatabaseDirectory); @@ -381,19 +379,19 @@ void Project::Load(const std::string &root_directory) { } } -void Project::SetFlagsForFile(const std::vector &flags, - const std::string &path) { +void Project::SetArgsForFile(const std::vector &args, + const std::string &path) { std::lock_guard lock(mutex_); auto it = path_to_entry_index.find(path); if (it != path_to_entry_index.end()) { // The entry already exists in the project, just set the flags. - this->entries[it->second].args = flags; + this->entries[it->second].args = args; } else { // Entry wasn't found, so we create a new one. Entry entry; entry.is_inferred = false; entry.filename = path; - entry.args = flags; + entry.args = args; this->entries.emplace_back(entry); } } @@ -424,7 +422,7 @@ Project::FindCompilationEntryForFile(const std::string &filename) { result.filename = filename; if (!best_entry) { result.args.push_back("%clang"); - result.args.push_back(filename); + result.args.push_back(Intern(filename)); } else { result.args = best_entry->args; @@ -432,11 +430,11 @@ Project::FindCompilationEntryForFile(const std::string &filename) { // that path to the new filename. std::string best_entry_base_name = sys::path::filename(best_entry->filename); - for (std::string &arg : result.args) { + for (const char *&arg : result.args) { try { if (arg == best_entry->filename || sys::path::filename(arg) == best_entry_base_name) - arg = filename; + arg = Intern(filename); } catch (...) { } } diff --git a/src/project.h b/src/project.h index 10c0b3c3..e5582a40 100644 --- a/src/project.h +++ b/src/project.h @@ -30,7 +30,7 @@ struct Project { struct Entry { std::string directory; std::string filename; - std::vector args; + std::vector args; // If true, this entry is inferred and was not read from disk. bool is_inferred = false; int id = -1; @@ -64,8 +64,8 @@ struct Project { // If the client has overridden the flags, or specified them for a file // that is not in the compilation_database.json make sure those changes // are permanent. - void SetFlagsForFile(const std::vector &flags, - const std::string &path); + void SetArgsForFile(const std::vector &args, + const std::string &path); // Run |action| on every file in the project. void diff --git a/src/query.h b/src/query.h index 4dfe62bb..3cc50fd6 100644 --- a/src/query.h +++ b/src/query.h @@ -39,7 +39,7 @@ template <> struct DenseMapInfo { struct QueryFile { struct Def { std::string path; - std::vector args; + std::vector args; LanguageId language; // Includes in the file. std::vector includes; diff --git a/src/serializer.cc b/src/serializer.cc index d523b118..8faf8ebd 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -464,8 +464,13 @@ Deserialize(SerializeFormat format, const std::string &path, file->path = path; if (g_config->clang.pathMappings.size()) { DoPathMapping(file->import_file); - for (std::string &arg : file->args) - DoPathMapping(arg); + std::vector args; + for (const char *arg : file->args) { + std::string s(arg); + DoPathMapping(s); + args.push_back(Intern(s)); + } + file->args = std::move(args); for (auto &[_, path] : file->lid2path) DoPathMapping(path); for (auto &include : file->includes) { diff --git a/src/test.cc b/src/test.cc index 19d52a9e..52bd3506 100644 --- a/src/test.cc +++ b/src/test.cc @@ -259,6 +259,9 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { bool update_all = false; // FIXME: show diagnostics in STL/headers when running tests. At the moment // this can be done by constructing ClangIndex index(1, 1); + CompletionManager completion( + nullptr, nullptr, [&](std::string, std::vector) {}, + [](lsRequestId id) {}); GetFilesInFolder( "index_tests", true /*recursive*/, true /*add_folder_to_path*/, [&](const std::string &path) { @@ -302,11 +305,11 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { // Run test. g_config = new Config; VFS vfs; - CompletionManager completion( - nullptr, nullptr, [&](std::string, std::vector) {}, - [](lsRequestId id) {}); WorkingFiles wfiles; - auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, flags, {}); + std::vector cargs; + for (auto &arg : flags) + cargs.push_back(arg.c_str()); + auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}); for (const auto &entry : all_expected_output) { const std::string &expected_path = entry.first; From f515b4b4660bf9ee9c3b09212b10e73c5977ab3b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 19 Sep 2018 13:05:52 -0700 Subject: [PATCH 40/66] Improve VarDef::type for textDocument/typeDefinition --- index_tests/foobar.cc | 42 +------ index_tests/lambdas/lambda.cc | 4 +- ...ace_template_type_usage_folded_into_one.cc | 40 +------ index_tests/templates/specialization.cc | 71 ++---------- ...mplate_class_type_usage_folded_into_one.cc | 40 +------ .../template_type_usage_folded_into_one.cc | 40 +------ .../usage/type_usage_as_template_parameter.cc | 42 +------ ...ype_usage_as_template_parameter_complex.cc | 14 +-- ...type_usage_as_template_parameter_simple.cc | 21 +--- src/indexer.cc | 103 ++++++++---------- 10 files changed, 78 insertions(+), 339 deletions(-) diff --git a/index_tests/foobar.cc b/index_tests/foobar.cc index e92f23cf..4b9d2f65 100644 --- a/index_tests/foobar.cc +++ b/index_tests/foobar.cc @@ -31,23 +31,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["9:5-9:6|0|1|4|-1"] - }, { - "usr": 7074603899792463171, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2|-1", - "extent": "6:3-6:18|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo {}", @@ -63,25 +46,8 @@ OUTPUT: "types": [13938528237873543349], "funcs": [], "vars": [], - "instances": [], - "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] - }, { - "usr": 11976530632376795217, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "5:8-5:11|0|1|2|-1", - "extent": "4:1-7:2|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], "instances": [12028309045033782423], - "uses": [] + "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] }, { "usr": 13892793056005362145, "detailed_name": "enum B {}", @@ -114,7 +80,7 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [16721564935990383768], "uses": ["9:9-9:14|0|1|4|-1"] }], "usr2var": [{ @@ -125,7 +91,7 @@ OUTPUT: "declarations": [], "spell": "10:8-10:9|0|1|2|-1", "extent": "10:1-10:9|0|1|0|-1", - "type": 11976530632376795217, + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 @@ -137,7 +103,7 @@ OUTPUT: "declarations": [], "spell": "9:15-9:16|0|1|2|-1", "extent": "9:1-9:16|0|1|0|-1", - "type": 7074603899792463171, + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/lambdas/lambda.cc b/index_tests/lambdas/lambda.cc index 2f5371f9..b4e58a30 100644 --- a/index_tests/lambdas/lambda.cc +++ b/index_tests/lambdas/lambda.cc @@ -65,10 +65,8 @@ OUTPUT: "detailed_name": "", "qual_name_offset": 0, "short_name": "", - "kind": 26, + "kind": 0, "declarations": [], - "spell": "4:22-4:23|4259594751088586730|3|2|-1", - "extent": "4:22-4:23|4259594751088586730|3|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc index c7ce4fae..b3144b08 100644 --- a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc @@ -13,40 +13,6 @@ OUTPUT: "skipped_ranges": [], "usr2func": [], "usr2type": [{ - "usr": 3948666349864691553, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2|-1", - "extent": "2:3-3:15|11072669167287398027|2|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [3182917058194750998], - "uses": [] - }, { - "usr": 8224244241460152567, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2|-1", - "extent": "2:3-3:15|11072669167287398027|2|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [15768138241775955040], - "uses": [] - }, { "usr": 11072669167287398027, "detailed_name": "namespace ns {}", "qual_name_offset": 10, @@ -82,7 +48,7 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [15768138241775955040, 3182917058194750998], "uses": ["5:3-5:6|11072669167287398027|2|4|-1", "6:3-6:6|11072669167287398027|2|4|-1"] }], "usr2var": [{ @@ -93,7 +59,7 @@ OUTPUT: "declarations": [], "spell": "6:13-6:14|11072669167287398027|2|1026|-1", "extent": "6:3-6:14|11072669167287398027|2|0|-1", - "type": 3948666349864691553, + "type": 14042997404480181958, "uses": [], "kind": 13, "storage": 0 @@ -105,7 +71,7 @@ OUTPUT: "declarations": [], "spell": "5:12-5:13|11072669167287398027|2|1026|-1", "extent": "5:3-5:13|11072669167287398027|2|0|-1", - "type": 8224244241460152567, + "type": 14042997404480181958, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/specialization.cc b/index_tests/templates/specialization.cc index d597a78c..52cfe543 100644 --- a/index_tests/templates/specialization.cc +++ b/index_tests/templates/specialization.cc @@ -132,7 +132,7 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [2933643612409209903], "uses": ["7:1-7:9|0|1|4|-1"] }, { "usr": 1663022413889915338, @@ -151,23 +151,6 @@ OUTPUT: "vars": [], "instances": [15931696253641284761], "uses": ["26:7-26:13|0|1|4|-1", "33:1-33:7|0|1|4|-1"] - }, { - "usr": 3231449734830406187, - "detailed_name": "function", - "qual_name_offset": 0, - "short_name": "function", - "kind": 26, - "declarations": [], - "spell": "5:7-5:15|0|1|2|-1", - "extent": "4:1-5:30|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [2933643612409209903], - "uses": [] }, { "usr": 5760043510674081814, "detailed_name": "struct Z1 {}", @@ -200,7 +183,7 @@ OUTPUT: "types": [], "funcs": [18107614608385228556], "vars": [], - "instances": [], + "instances": [5792869548777559988], "uses": ["21:16-21:22|0|1|4|-1", "30:1-30:7|0|1|4|-1", "32:1-32:7|0|1|4|-1"] }, { "usr": 9201299975592934124, @@ -236,40 +219,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["26:14-26:16|0|1|4|-1", "33:8-33:10|0|1|4|-1"] - }, { - "usr": 11153492883079050853, - "detailed_name": "vector", - "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, - "declarations": [], - "spell": "17:7-17:13|0|1|2|-1", - "extent": "16:1-17:20|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [86949563628772958], - "uses": [] - }, { - "usr": 13322943937025195708, - "detailed_name": "vector", - "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, - "declarations": [], - "spell": "12:7-12:13|0|1|2|-1", - "extent": "11:1-14:2|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [5792869548777559988], - "uses": [] }, { "usr": 14111105212951082474, "detailed_name": "T", @@ -304,13 +253,11 @@ OUTPUT: "uses": [] }, { "usr": 15440970074034693939, - "detailed_name": "vector", + "detailed_name": "", "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, + "short_name": "", + "kind": 0, "declarations": [], - "spell": "21:16-21:22|0|1|2|-1", - "extent": "21:1-21:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -349,7 +296,7 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [86949563628772958], "uses": ["31:1-31:7|0|1|4|-1"] }], "usr2var": [{ @@ -360,7 +307,7 @@ OUTPUT: "declarations": [], "spell": "31:14-31:17|0|1|2|-1", "extent": "31:1-31:17|0|1|0|-1", - "type": 11153492883079050853, + "type": 16155717907537731864, "uses": [], "kind": 13, "storage": 0 @@ -372,7 +319,7 @@ OUTPUT: "declarations": [], "spell": "7:21-7:22|0|1|2|-1", "extent": "7:1-7:22|0|1|0|-1", - "type": 3231449734830406187, + "type": 218068462278884837, "uses": [], "kind": 13, "storage": 0 @@ -409,7 +356,7 @@ OUTPUT: "declarations": [], "spell": "30:14-30:16|0|1|2|-1", "extent": "30:1-30:16|0|1|0|-1", - "type": 13322943937025195708, + "type": 7440942986741176606, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/template_class_type_usage_folded_into_one.cc b/index_tests/templates/template_class_type_usage_folded_into_one.cc index e1b1b829..09bc2e7c 100644 --- a/index_tests/templates/template_class_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_type_usage_folded_into_one.cc @@ -50,23 +50,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["9:5-9:6|0|1|4|-1"] - }, { - "usr": 7074603899792463171, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2|-1", - "extent": "6:3-6:18|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo {}", @@ -116,25 +99,8 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [16721564935990383768, 12028309045033782423], "uses": ["9:9-9:14|0|1|4|-1", "10:9-10:14|0|1|4|-1"] - }, { - "usr": 15961308565836244174, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2|-1", - "extent": "6:3-6:18|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12028309045033782423], - "uses": [] }], "usr2var": [{ "usr": 12028309045033782423, @@ -144,7 +110,7 @@ OUTPUT: "declarations": [], "spell": "10:15-10:16|0|1|2|-1", "extent": "10:1-10:16|0|1|0|-1", - "type": 15961308565836244174, + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 @@ -156,7 +122,7 @@ OUTPUT: "declarations": [], "spell": "9:15-9:16|0|1|2|-1", "extent": "9:1-9:16|0|1|0|-1", - "type": 7074603899792463171, + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/template_type_usage_folded_into_one.cc b/index_tests/templates/template_type_usage_folded_into_one.cc index bb9745e8..fb719179 100644 --- a/index_tests/templates/template_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_type_usage_folded_into_one.cc @@ -11,23 +11,6 @@ OUTPUT: "skipped_ranges": [], "usr2func": [], "usr2type": [{ - "usr": 5123806965838456033, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "2:7-2:10|0|1|2|-1", - "extent": "1:1-2:13|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] - }, { "usr": 10528472276654770367, "detailed_name": "class Foo {}", "qual_name_offset": 6, @@ -42,25 +25,8 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [16721564935990383768, 12028309045033782423], "uses": ["4:1-4:4|0|1|4|-1", "5:1-5:4|0|1|4|-1"] - }, { - "usr": 14134940367505932005, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "2:7-2:10|0|1|2|-1", - "extent": "1:1-2:13|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12028309045033782423], - "uses": [] }], "usr2var": [{ "usr": 12028309045033782423, @@ -70,7 +36,7 @@ OUTPUT: "declarations": [], "spell": "5:11-5:12|0|1|2|-1", "extent": "5:1-5:12|0|1|0|-1", - "type": 14134940367505932005, + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 @@ -82,7 +48,7 @@ OUTPUT: "declarations": [], "spell": "4:10-4:11|0|1|2|-1", "extent": "4:1-4:11|0|1|0|-1", - "type": 5123806965838456033, + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/usage/type_usage_as_template_parameter.cc b/index_tests/usage/type_usage_as_template_parameter.cc index 5c4dc824..169d5ad4 100644 --- a/index_tests/usage/type_usage_as_template_parameter.cc +++ b/index_tests/usage/type_usage_as_template_parameter.cc @@ -46,25 +46,8 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [12857919739649552168, 18075066956054788088, 3364438781074774169], "uses": ["6:8-6:18|0|1|4|-1", "7:8-7:18|0|1|4|-1", "9:1-9:11|0|1|4|-1", "10:3-10:13|16359708726068806331|3|4|-1"] - }, { - "usr": 4186953406371619898, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2|-1", - "extent": "1:1-2:20|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [18075066956054788088, 3364438781074774169], - "uses": [] }, { "usr": 4750332761459066907, "detailed_name": "struct S {}", @@ -82,23 +65,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["7:19-7:20|0|1|4|-1", "9:12-9:13|0|1|4|-1", "10:14-10:15|16359708726068806331|3|4|-1"] - }, { - "usr": 16848604152578034754, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2|-1", - "extent": "1:1-2:20|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12857919739649552168], - "uses": [] }], "usr2var": [{ "usr": 3364438781074774169, @@ -108,7 +74,7 @@ OUTPUT: "declarations": [], "spell": "10:18-10:23|16359708726068806331|3|2|-1", "extent": "10:3-10:23|16359708726068806331|3|0|-1", - "type": 4186953406371619898, + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 0 @@ -120,7 +86,7 @@ OUTPUT: "declarations": [], "spell": "6:25-6:27|0|1|2|-1", "extent": "6:1-6:27|0|1|0|-1", - "type": 16848604152578034754, + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 @@ -132,7 +98,7 @@ OUTPUT: "declarations": [], "spell": "7:22-7:24|0|1|2|-1", "extent": "7:1-7:24|0|1|0|-1", - "type": 4186953406371619898, + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 diff --git a/index_tests/usage/type_usage_as_template_parameter_complex.cc b/index_tests/usage/type_usage_as_template_parameter_complex.cc index 0b4e20e0..a49ccb84 100644 --- a/index_tests/usage/type_usage_as_template_parameter_complex.cc +++ b/index_tests/usage/type_usage_as_template_parameter_complex.cc @@ -202,7 +202,7 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], + "instances": [2933643612409209903, 500112618220246], "uses": [] }, { "usr": 15041163540773201510, @@ -223,20 +223,18 @@ OUTPUT: "uses": ["79:21-79:24|0|1|4|-1"] }, { "usr": 18153735331422331128, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, + "detailed_name": "template<> class unique_ptr, S2>", + "qual_name_offset": 17, "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2|-1", - "extent": "1:1-2:17|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [2933643612409209903, 500112618220246], + "instances": [], "uses": ["15:8-15:18|0|1|4|-1", "33:1-33:11|0|1|4|-1", "54:3-54:13|18320186404467436976|3|4|-1"] }], "usr2var": [{ @@ -247,7 +245,7 @@ OUTPUT: "declarations": [], "spell": "54:39-54:44|18320186404467436976|3|2|-1", "extent": "54:3-54:44|18320186404467436976|3|0|-1", - "type": 18153735331422331128, + "type": 14209198335088845323, "uses": [], "kind": 13, "storage": 0 @@ -257,7 +255,7 @@ OUTPUT: "qual_name_offset": 42, "short_name": "f", "declarations": ["15:43-15:44|15:1-15:44|0|1|1|-1"], - "type": 18153735331422331128, + "type": 14209198335088845323, "uses": [], "kind": 13, "storage": 1 diff --git a/index_tests/usage/type_usage_as_template_parameter_simple.cc b/index_tests/usage/type_usage_as_template_parameter_simple.cc index 1893c26e..9f7c8da2 100644 --- a/index_tests/usage/type_usage_as_template_parameter_simple.cc +++ b/index_tests/usage/type_usage_as_template_parameter_simple.cc @@ -26,25 +26,8 @@ OUTPUT: "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["6:8-6:18|0|1|4|-1"] - }, { - "usr": 4186953406371619898, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2|-1", - "extent": "1:1-2:20|0|1|0|-1", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], "instances": [3398408600781120939], - "uses": [] + "uses": ["6:8-6:18|0|1|4|-1"] }, { "usr": 4750332761459066907, "detailed_name": "struct S", @@ -69,7 +52,7 @@ OUTPUT: "declarations": [], "spell": "6:22-6:25|0|1|2|-1", "extent": "6:1-6:25|0|1|0|-1", - "type": 4186953406371619898, + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 diff --git a/src/indexer.cc b/src/indexer.cc index a6b70ca1..27607db5 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -283,41 +283,6 @@ try_again: return D; } -const Decl *GetSpecialized(const Decl *D) { - if (!D) - return D; - Decl *Template = nullptr; - if (const CXXRecordDecl *CXXRecord = dyn_cast(D)) { - if (const ClassTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast(CXXRecord)) - Template = PartialSpec->getSpecializedTemplate(); - else if (const ClassTemplateSpecializationDecl *ClassSpec = - dyn_cast(CXXRecord)) { - llvm::PointerUnion - Result = ClassSpec->getSpecializedTemplateOrPartial(); - if (Result.is()) - Template = Result.get(); - else - Template = Result.get(); - - } else - Template = CXXRecord->getInstantiatedFromMemberClass(); - } else if (const FunctionDecl *Function = dyn_cast(D)) { - Template = Function->getPrimaryTemplate(); - if (!Template) - Template = Function->getInstantiatedFromMemberFunction(); - } else if (const VarDecl *Var = dyn_cast(D)) { - if (Var->isStaticDataMember()) - Template = Var->getInstantiatedFromStaticDataMember(); - } else if (const RedeclarableTemplateDecl *Tmpl = - dyn_cast(D)) - Template = Tmpl->getInstantiatedFromMemberTemplate(); - else - return nullptr; - return Template; -} - bool ValidateRecord(const RecordDecl *RD) { for (const auto *I : RD->fields()) { QualType FQT = I->getType(); @@ -778,33 +743,51 @@ public: var->def.type = usr1; db->ToType(usr1).instances.push_back(usr); } else { - for (const Decl *D1 = GetTypeDecl(T); D1; D1 = GetSpecialized(D1)) { + for (const Decl *D1 = GetTypeDecl(T); D1; ) { + if (auto *R1 = dyn_cast(D1)) { + if (auto *S1 = dyn_cast(D1)) { + if (!S1->getTypeAsWritten()) { + llvm::PointerUnion + Result = S1->getSpecializedTemplateOrPartial(); + if (Result.is()) + D1 = Result.get(); + else + D1 = Result.get(); + continue; + } + } else if (auto *D2 = R1->getInstantiatedFromMemberClass()) { + D1 = D2; + continue; + } + } else if (auto *TP1 = dyn_cast(D1)) { + // e.g. TemplateTypeParmDecl is not handled by + // handleDeclOccurence. + SourceRange R1 = D1->getSourceRange(); + if (SM.getFileID(R1.getBegin()) == LocFID) { + IndexParam::DeclInfo *info1; + Usr usr1 = GetUsr(D1, &info1); + IndexType &type1 = db->ToType(usr1); + SourceLocation L1 = D1->getLocation(); + type1.def.spell = + GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, + Role::Definition); + type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), + LexDC, Role::None); + type1.def.detailed_name = Intern(info1->short_name); + type1.def.short_name_size = int16_t(info1->short_name.size()); + type1.def.kind = lsSymbolKind::TypeParameter; + var->def.type = usr1; + type1.instances.push_back(usr); + break; + } + } + IndexParam::DeclInfo *info1; Usr usr1 = GetUsr(D1, &info1); - auto it = db->usr2type.find(usr1); - if (it != db->usr2type.end()) { - var->def.type = usr1; - it->second.instances.push_back(usr); - break; - } - // e.g. TemplateTypeParmDecl is not handled by - // handleDeclOccurence. - SourceRange R1 = D1->getSourceRange(); - if (SM.getFileID(R1.getBegin()) == LocFID) { - IndexType &type1 = db->ToType(usr1); - SourceLocation L1 = D1->getLocation(); - type1.def.spell = - GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, - Role::Definition); - type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), - LexDC, Role::None); - type1.def.detailed_name = Intern(info1->short_name); - type1.def.short_name_size = int16_t(info1->short_name.size()); - type1.def.kind = lsSymbolKind::TypeParameter; - var->def.type = usr1; - type1.instances.push_back(usr); - break; - } + var->def.type = usr1; + db->ToType(usr1).instances.push_back(usr); + break; } } } From f9bd84a97583a4299b4a8768dcb37fa1c71ff0ca Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 20 Sep 2018 00:31:23 -0700 Subject: [PATCH 41/66] Clean up FileConsumer and improve pipeline --- src/file_consumer.cc | 88 ++++++++++---------------------------------- src/file_consumer.h | 39 +++++++------------- src/indexer.cc | 35 ++++++++++-------- src/pipeline.cc | 27 ++++++-------- src/pipeline.hh | 1 - src/utils.cc | 12 +++++- src/utils.h | 1 + 7 files changed, 76 insertions(+), 127 deletions(-) diff --git a/src/file_consumer.cc b/src/file_consumer.cc index 7f8cca71..1859e023 100644 --- a/src/file_consumer.cc +++ b/src/file_consumer.cc @@ -21,62 +21,17 @@ limitations under the License. #include "platform.h" #include "utils.h" -namespace { - -std::optional -GetFileContents(const std::string &path, - std::unordered_map *file_contents) { - auto it = file_contents->find(path); - if (it == file_contents->end()) { - std::optional content = ReadContent(path); - if (content) - (*file_contents)[path] = FileContents(path, *content); - return content; - } - return it->second.content; +bool VFS::Loaded(const std::string &path) { + std::lock_guard lock(mutex); + return state[path].loaded; } -} // namespace - -FileContents::FileContents(const std::string &path, const std::string &content) - : path(path), content(content) { - line_offsets_.push_back(0); - for (size_t i = 0; i < content.size(); i++) { - if (content[i] == '\n') - line_offsets_.push_back(i + 1); - } -} - -std::optional FileContents::ToOffset(Position p) const { - if (0 <= p.line && size_t(p.line) < line_offsets_.size()) { - int ret = line_offsets_[p.line] + p.column; - if (size_t(ret) < content.size()) - return ret; - } - return std::nullopt; -} - -std::optional FileContents::ContentsInRange(Range range) const { - std::optional start_offset = ToOffset(range.start), - end_offset = ToOffset(range.end); - if (start_offset && end_offset && *start_offset < *end_offset) - return content.substr(*start_offset, *end_offset - *start_offset); - return std::nullopt; -} - -VFS::State VFS::Get(const std::string &file) { +bool VFS::Stamp(const std::string &path, int64_t ts, int step) { std::lock_guard lock(mutex); - auto it = state.find(file); - if (it != state.end()) - return it->second; - return {0, 0}; -} - -bool VFS::Stamp(const std::string &file, int64_t ts, int64_t offset) { - std::lock_guard lock(mutex); - State &st = state[file]; - if (st.timestamp < ts) { - st.timestamp = ts + offset; + State &st = state[path]; + if (st.timestamp < ts || (st.timestamp == ts && st.step < step)) { + st.timestamp = ts; + st.step = step; return true; } else return false; @@ -87,29 +42,26 @@ FileConsumer::FileConsumer(VFS *vfs, const std::string &parse_file) IndexFile *FileConsumer::TryConsumeFile( const clang::FileEntry &File, - std::unordered_map *file_contents_map) { + const std::unordered_map + &UID2File) { auto UniqueID = File.getUniqueID(); - auto it = local_.find(UniqueID); - if (it != local_.end()) - return it->second.get(); + { + auto it = local_.find(UniqueID); + if (it != local_.end()) + return it->second.get(); + } - std::string file_name = FileName(File); - int64_t tim = File.getModificationTime(); - assert(tim); - if (!vfs_->Stamp(file_name, tim, 0)) { + auto it = UID2File.find(UniqueID); + assert(it != UID2File.end()); + assert(it->second.mtime); + if (!vfs_->Stamp(it->second.path, it->second.mtime, 1)) { local_[UniqueID] = nullptr; return nullptr; } - // Read the file contents, if we fail then we cannot index the file. - std::optional contents = - GetFileContents(file_name, file_contents_map); - if (!contents) - return nullptr; - // Build IndexFile instance. local_[UniqueID] = - std::make_unique(UniqueID, file_name, *contents); + std::make_unique(UniqueID, it->second.path, it->second.content); return local_[UniqueID].get(); } diff --git a/src/file_consumer.h b/src/file_consumer.h index ab2bebcc..4722ec8b 100644 --- a/src/file_consumer.h +++ b/src/file_consumer.h @@ -27,29 +27,17 @@ limitations under the License. struct IndexFile; -struct FileContents { - FileContents() = default; - FileContents(const std::string &path, const std::string &content); - - std::optional ToOffset(Position p) const; - std::optional ContentsInRange(Range range) const; - - std::string path; - std::string content; - // {0, 1 + position of first newline, 1 + position of second newline, ...} - std::vector line_offsets_; -}; - struct VFS { struct State { int64_t timestamp; - bool loaded = false; + int step; + bool loaded; }; mutable std::unordered_map state; mutable std::mutex mutex; - State Get(const std::string &file); - bool Stamp(const std::string &file, int64_t ts, int64_t offset); + bool Loaded(const std::string &path); + bool Stamp(const std::string &path, int64_t ts, int step); }; namespace std { @@ -70,17 +58,18 @@ template <> struct hash { // The indexer does this because header files do not have their own translation // units but we still want to index them. struct FileConsumer { + struct File { + std::string path; + int64_t mtime; + std::string content; + }; + FileConsumer(VFS *vfs, const std::string &parse_file); - // Returns IndexFile for the file or nullptr. |is_first_ownership| is set - // to true iff the function just took ownership over the file. Otherwise it - // is set to false. - // - // note: file_contents is passed as a parameter instead of as a member - // variable since it is large and we do not want to copy it. - IndexFile * - TryConsumeFile(const clang::FileEntry &file, - std::unordered_map *file_contents); + // Returns IndexFile or nullptr for the file or nullptr. + IndexFile *TryConsumeFile( + const clang::FileEntry &file, + const std::unordered_map &); // Returns and passes ownership of all local state. std::vector> TakeLocalState(); diff --git a/src/indexer.cc b/src/indexer.cc index 27607db5..686768c2 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -49,10 +49,8 @@ constexpr int kInitializerMaxLines = 3; GroupMatch *multiVersionMatcher; struct IndexParam { - std::unordered_map SeenUniqueID; + std::unordered_map UID2File; std::unordered_map UID2multi; - std::unordered_map file_contents; - std::unordered_map file2mtime; struct DeclInfo { Usr usr; std::string short_name; @@ -68,17 +66,22 @@ struct IndexParam { void SeenFile(const FileEntry &File) { // If this is the first time we have seen the file (ignoring if we are // generating an index for it): - auto [it, inserted] = SeenUniqueID.try_emplace(File.getUniqueID()); + auto [it, inserted] = UID2File.try_emplace(File.getUniqueID()); if (inserted) { - std::string file_name = FileName(File); - it->second = file_name; - file2mtime[file_name] = File.getModificationTime(); + std::string path = FileName(File); + it->second.path = path; + it->second.mtime = File.getModificationTime(); + if (!it->second.mtime) + if (auto tim = LastWriteTime(path)) + it->second.mtime = *tim; + if (std::optional content = ReadContent(path)) + it->second.content = *content; } } IndexFile *ConsumeFile(const FileEntry &FE) { SeenFile(FE); - return file_consumer->TryConsumeFile(FE, &file_contents); + return file_consumer->TryConsumeFile(FE, UID2File); } bool UseMultiVersion(const FileEntry &FE) { @@ -1344,15 +1347,15 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, for (auto &it : entry->usr2var) Uniquify(it.second.uses); - // Update file contents and modification time. - entry->mtime = param.file2mtime[entry->path]; - - // Update dependencies for the file. Do not include the file in its own - // dependency set. - for (auto &[_, path] : param.SeenUniqueID) - if (path != entry->path && path != entry->import_file) + // Update dependencies for the file. + for (auto &[_, file] : param.UID2File) { + const std::string &path = file.path; + if (path == entry->path) + entry->mtime = file.mtime; + else if (path != entry->import_file) entry->dependencies[llvm::CachedHashStringRef(Intern(path))] = - param.file2mtime[path]; + file.mtime; + } } return result; diff --git a/src/pipeline.cc b/src/pipeline.cc index 0b5a0f6f..c748b96b 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -206,16 +206,21 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, std::optional write_time = LastWriteTime(path_to_index); if (!write_time) return true; - int reparse = vfs->Stamp(path_to_index, *write_time, -1); + int reparse = vfs->Stamp(path_to_index, *write_time, 0); if (request.path != path_to_index) { std::optional mtime1 = LastWriteTime(request.path); if (!mtime1) return true; - if (vfs->Stamp(request.path, *mtime1, -1)) + if (vfs->Stamp(request.path, *mtime1, 0)) reparse = 1; } - if (g_config->index.onChange) + if (g_config->index.onChange) { reparse = 2; + std::lock_guard lock(vfs->mutex); + vfs->state[path_to_index].step = 0; + if (request.path != path_to_index) + vfs->state[request.path].step = 0; + } if (!reparse) return true; @@ -242,6 +247,8 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, LOG_S(INFO) << "load cache for " << path_to_index; auto dependencies = prev->dependencies; if (reparse) { + if (vfs->Loaded(path_to_index)) + return true; IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), request.mode != IndexMode::NonInteractive); @@ -309,12 +316,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, << ")"; { std::lock_guard lock(mutexes[std::hash()(path) % N_MUTEXES]); - bool loaded; - { - std::lock_guard lock1(vfs->mutex); - loaded = vfs->state[path].loaded; - } - if (loaded) + if (vfs->Loaded(path)) prev = RawCacheLoad(path); else prev.reset(); @@ -543,13 +545,6 @@ void Index(const std::string &path, const std::vector &args, index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } -std::optional LastWriteTime(const std::string &path) { - sys::fs::file_status Status; - if (sys::fs::status(path, Status)) - return {}; - return sys::toTimeT(Status.getLastModificationTime()); -} - std::optional LoadIndexedContent(const std::string &path) { if (g_config->cacheDirectory.empty()) { std::shared_lock lock(g_index_mutex); diff --git a/src/pipeline.hh b/src/pipeline.hh index 0cbabffc..285dfb80 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -46,7 +46,6 @@ void MainLoop(); void Index(const std::string &path, const std::vector &args, IndexMode mode, lsRequestId id = {}); -std::optional LastWriteTime(const std::string &path); std::optional LoadIndexedContent(const std::string& path); void WriteStdout(MethodType method, lsBaseOutMessage &response); } // namespace pipeline diff --git a/src/utils.cc b/src/utils.cc index df5b98c8..f9e3dcda 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -20,7 +20,10 @@ limitations under the License. #include -#include "llvm/ADT/StringRef.h" +#include +#include +#include +using namespace llvm; #include #include @@ -124,6 +127,13 @@ std::string EscapeFileName(std::string path) { return path; } +std::optional LastWriteTime(const std::string &path) { + sys::fs::file_status Status; + if (sys::fs::status(path, Status)) + return {}; + return sys::toTimeT(Status.getLastModificationTime()); +} + std::optional ReadContent(const std::string &filename) { char buf[4096]; std::string ret; diff --git a/src/utils.h b/src/utils.h index 40352e1a..113a2147 100644 --- a/src/utils.h +++ b/src/utils.h @@ -73,6 +73,7 @@ void EnsureEndsInSlash(std::string &path); // e.g. foo/bar.c => foo_bar.c std::string EscapeFileName(std::string path); +std::optional LastWriteTime(const std::string &path); std::optional ReadContent(const std::string &filename); void WriteToFile(const std::string &filename, const std::string &content); From 41756297ef35ffdcb2774aea596243c5b85281c5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 20 Sep 2018 17:20:09 -0700 Subject: [PATCH 42/66] Simplify semantic highlighting --- src/config.h | 2 +- src/message_handler.cc | 83 +++++++--------------------- src/message_handler.h | 37 +++---------- src/messages/initialize.cc | 2 +- src/messages/textDocument_didOpen.cc | 2 +- src/pipeline.cc | 13 +++-- src/test.cc | 13 ++++- src/utils.cc | 10 ---- src/utils.h | 3 - 9 files changed, 47 insertions(+), 118 deletions(-) diff --git a/src/config.h b/src/config.h index 816c024c..f9194c08 100644 --- a/src/config.h +++ b/src/config.h @@ -146,7 +146,7 @@ struct Config { // auto-completion. An example value is { ".h", ".hpp" } // // This is significantly faster than using a regex. - std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh"}; + std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh", ".inc"}; std::vector includeWhitelist; } completion; diff --git a/src/message_handler.cc b/src/message_handler.cc index ab6d937b..aa2924a3 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -16,6 +16,7 @@ limitations under the License. #include "message_handler.h" #include "log.hh" +#include "match.h" #include "pipeline.hh" #include "project.h" #include "query_utils.h" @@ -59,74 +60,34 @@ struct ScanLineEvent { }; } // namespace -SemanticHighlightSymbolCache::Entry::Entry( - SemanticHighlightSymbolCache *all_caches, const std::string &path) - : all_caches_(all_caches), path(path) {} - -std::optional SemanticHighlightSymbolCache::Entry::TryGetStableId( - SymbolKind kind, const std::string &detailed_name) { - TNameToId *map = GetMapForSymbol_(kind); - auto it = map->find(detailed_name); - if (it != map->end()) - return it->second; - - return std::nullopt; -} - -int SemanticHighlightSymbolCache::Entry::GetStableId( - SymbolKind kind, const std::string &detailed_name) { - std::optional id = TryGetStableId(kind, detailed_name); - if (id) - return *id; - - // Create a new id. First try to find a key in another map. - all_caches_->cache_.IterateValues([&](const std::shared_ptr &entry) { - std::optional other_id = entry->TryGetStableId(kind, detailed_name); - if (other_id) { - id = other_id; - return false; - } - return true; - }); - - // Create a new id. - TNameToId *map = GetMapForSymbol_(kind); - if (!id) - id = all_caches_->next_stable_id_++; - return (*map)[detailed_name] = *id; -} - -SemanticHighlightSymbolCache::Entry::TNameToId * -SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) { +int SemanticHighlight::GetStableId(SymbolKind kind, Usr usr) { + decltype(func2id) *map; switch (kind) { - case SymbolKind::Type: - return &detailed_type_name_to_stable_id; case SymbolKind::Func: - return &detailed_func_name_to_stable_id; + map = &func2id; + break; + case SymbolKind::Type: + map = &type2id; + break; case SymbolKind::Var: - return &detailed_var_name_to_stable_id; + map = &var2id; + break; case SymbolKind::File: case SymbolKind::Invalid: - break; + llvm_unreachable(""); } - assert(false); - return nullptr; + + auto it = map->try_emplace(usr, next_id); + if (it.second) + next_id++; + return it.first->second; } -SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() - : cache_(kCacheSize) {} - -void SemanticHighlightSymbolCache::Init() { +void SemanticHighlight::Init() { match_ = std::make_unique(g_config->highlight.whitelist, g_config->highlight.blacklist); } -std::shared_ptr -SemanticHighlightSymbolCache::GetCacheForFile(const std::string &path) { - return cache_.Get( - path, [&, this]() { return std::make_shared(this, path); }); -} - MessageHandler::MessageHandler() { // Dynamically allocate |message_handlers|, otherwise there will be static // initialization order races. @@ -196,15 +157,12 @@ void EmitSkippedRanges(WorkingFile *working_file, pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out); } -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, +void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, WorkingFile *wfile, QueryFile *file) { assert(file->def); if (wfile->buffer_content.size() > g_config->largeFileSize || - !semantic_cache->match_->IsMatch(file->def->path)) + !highlight->match_->IsMatch(file->def->path)) return; - auto semantic_cache_for_file = - semantic_cache->GetCacheForFile(file->def->path); // Group symbols together. std::unordered_map @@ -300,8 +258,7 @@ void EmitSemanticHighlighting(DB *db, it->second.lsRanges.push_back(*loc); } else { Out_CclsPublishSemanticHighlighting::Symbol symbol; - symbol.stableId = semantic_cache_for_file->GetStableId( - sym.kind, std::string(detailed_name)); + symbol.stableId = highlight->GetStableId(sym.kind, sym.usr); symbol.parentKind = parent_kind; symbol.kind = kind; symbol.storage = storage; diff --git a/src/message_handler.h b/src/message_handler.h index ac1c8021..b7110295 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -17,7 +17,6 @@ limitations under the License. #include "lru_cache.h" #include "lsp.h" -#include "match.h" #include "method.h" #include "query.h" @@ -29,6 +28,7 @@ limitations under the License. struct CompletionManager; struct Config; class DiagnosticsPublisher; +struct GroupMatch; struct VFS; struct IncludeComplete; struct MultiQueueWaiter; @@ -39,35 +39,13 @@ struct WorkingFiles; // Caches symbols for a single file for semantic highlighting to provide // relatively stable ids. Only supports xxx files at a time. -struct SemanticHighlightSymbolCache { - struct Entry { - SemanticHighlightSymbolCache *all_caches_ = nullptr; - - // The path this cache belongs to. - std::string path; - // Detailed symbol name to stable id. - using TNameToId = std::unordered_map; - TNameToId detailed_type_name_to_stable_id; - TNameToId detailed_func_name_to_stable_id; - TNameToId detailed_var_name_to_stable_id; - - Entry(SemanticHighlightSymbolCache *all_caches, const std::string &path); - - std::optional TryGetStableId(SymbolKind kind, - const std::string &detailed_name); - int GetStableId(SymbolKind kind, const std::string &detailed_name); - - TNameToId *GetMapForSymbol_(SymbolKind kind); - }; - - constexpr static int kCacheSize = 10; - LruCache cache_; - uint32_t next_stable_id_ = 0; +struct SemanticHighlight { + llvm::DenseMap func2id, type2id, var2id; + uint32_t next_id = 0; std::unique_ptr match_; - SemanticHighlightSymbolCache(); void Init(); - std::shared_ptr GetCacheForFile(const std::string &path); + int GetStableId(SymbolKind kind, Usr usr); }; struct Out_CclsPublishSemanticHighlighting @@ -114,7 +92,7 @@ struct MessageHandler { Project *project = nullptr; DiagnosticsPublisher *diag_pub = nullptr; VFS *vfs = nullptr; - SemanticHighlightSymbolCache *semantic_cache = nullptr; + SemanticHighlight *highlight = nullptr; WorkingFiles *working_files = nullptr; CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; @@ -144,6 +122,5 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, void EmitSkippedRanges(WorkingFile *working_file, const std::vector &skipped_ranges); -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, +void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, WorkingFile *working_file, QueryFile *file); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 07a5e90d..2e5e5213 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -488,7 +488,7 @@ struct Handler_Initialize : BaseMessageHandler { diag_pub->Init(); idx::Init(); - semantic_cache->Init(); + highlight->Init(); // Open up / load the project. project->Load(project_path); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 4e76e8e9..4911a338 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -60,7 +60,7 @@ struct Handler_TextDocumentDidOpen FindFileOrFail(db, project, std::nullopt, path, &file); if (file && file->def) { EmitSkippedRanges(working_file, file->def->skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, working_file, file); + EmitSemanticHighlighting(db, highlight, working_file, file); } include_complete->AddFile(working_file->filename); diff --git a/src/pipeline.cc b/src/pipeline.cc index c748b96b..99b4784c 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -20,6 +20,7 @@ limitations under the License. #include "include_complete.h" #include "log.hh" #include "lsp.h" +#include "match.h" #include "message_handler.h" #include "pipeline.hh" #include "platform.h" @@ -370,7 +371,7 @@ void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, indexer_waiter->Wait(index_request); } -void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, +void Main_OnIndexed(DB *db, SemanticHighlight *highlight, WorkingFiles *working_files, IndexUpdate *update) { if (update->refresh) { LOG_S(INFO) @@ -381,7 +382,7 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, if (db->name2file_id.find(filename) == db->name2file_id.end()) continue; QueryFile *file = &db->files[db->name2file_id[filename]]; - EmitSemanticHighlighting(db, semantic_cache, f.get(), file); + EmitSemanticHighlighting(db, highlight, f.get(), file); } return; } @@ -401,7 +402,7 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, wfile->SetIndexContent(g_config->index.onChange ? wfile->buffer_content : def_u.second); EmitSkippedRanges(wfile, def_u.first.skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, wfile, + EmitSemanticHighlighting(db, highlight, wfile, &db->files[update->file_id]); } } @@ -472,7 +473,7 @@ void LaunchStdout() { void MainLoop() { Project project; - SemanticHighlightSymbolCache semantic_cache; + SemanticHighlight highlight; WorkingFiles working_files; VFS vfs; DiagnosticsPublisher diag_pub; @@ -503,7 +504,7 @@ void MainLoop() { handler->project = &project; handler->diag_pub = &diag_pub; handler->vfs = &vfs; - handler->semantic_cache = &semantic_cache; + handler->highlight = &highlight; handler->working_files = &working_files; handler->clang_complete = &clang_complete; handler->include_complete = &include_complete; @@ -530,7 +531,7 @@ void MainLoop() { if (!update) break; did_work = true; - Main_OnIndexed(&db, &semantic_cache, &working_files, &*update); + Main_OnIndexed(&db, &highlight, &working_files, &*update); } if (!did_work) { diff --git a/src/test.cc b/src/test.cc index 52bd3506..6c595200 100644 --- a/src/test.cc +++ b/src/test.cc @@ -23,6 +23,8 @@ limitations under the License. #include "utils.h" #include +#include +using namespace llvm; #include #include @@ -80,6 +82,12 @@ struct TextReplacer { } }; +void TrimInPlace(std::string &s) { + auto f = [](char c) { return !isspace(c); }; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); + s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); +} + void ParseTestExpectation( const std::string &filename, const std::vector &lines_with_endings, TextReplacer *replacer, @@ -89,7 +97,7 @@ void ParseTestExpectation( { bool in_output = false; for (std::string line : lines_with_endings) { - TrimInPlace(line); + line = StringRef(line).trim().str(); if (StartsWith(line, "EXTRA_FLAGS:")) { assert(!in_output && "multiple EXTRA_FLAGS sections"); @@ -125,8 +133,7 @@ void ParseTestExpectation( // one token assume it is a filename. std::vector tokens = SplitString(line_with_ending, " "); if (tokens.size() > 1) { - active_output_filename = tokens[1]; - TrimInPlace(active_output_filename); + active_output_filename = StringRef(tokens[1]).trim().str(); } else { active_output_filename = filename; } diff --git a/src/utils.cc b/src/utils.cc index f9e3dcda..6d3e06af 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -33,16 +33,6 @@ using namespace llvm; #include #include -void TrimInPlace(std::string &s) { - auto f = [](char c) { return !isspace(c); }; - s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); - s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); -} -std::string Trim(std::string s) { - TrimInPlace(s); - return s; -} - uint64_t HashUsr(std::string_view s) { union { uint64_t ret; diff --git a/src/utils.h b/src/utils.h index 113a2147..d34187bc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -28,9 +28,6 @@ namespace llvm { class StringRef; } -void TrimInPlace(std::string &s); -std::string Trim(std::string s); - uint64_t HashUsr(std::string_view s); uint64_t HashUsr(llvm::StringRef s); From 4d76108d6b4e7a048ca6baee567fe1659ac40c08 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 20 Sep 2018 18:04:55 -0700 Subject: [PATCH 43/66] Delete file_consumer.* --- CMakeLists.txt | 1 - src/file_consumer.cc | 75 --------------------------------- src/file_consumer.h | 82 ------------------------------------- src/indexer.cc | 33 +++++++++++---- src/indexer.h | 12 +++++- src/messages/ccls_reload.cc | 5 +-- src/pipeline.cc | 21 ++++++++++ src/pipeline.hh | 15 +++++++ src/test.cc | 1 + 9 files changed, 73 insertions(+), 172 deletions(-) delete mode 100644 src/file_consumer.cc delete mode 100644 src/file_consumer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 20a4bd91..3985e129 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,7 +183,6 @@ target_sources(ccls PRIVATE src/clang_tu.cc src/clang_utils.cc src/config.cc - src/file_consumer.cc src/filesystem.cc src/fuzzy_match.cc src/main.cc diff --git a/src/file_consumer.cc b/src/file_consumer.cc deleted file mode 100644 index 1859e023..00000000 --- a/src/file_consumer.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "file_consumer.h" - -#include "clang_utils.h" -#include "indexer.h" -#include "log.hh" -#include "platform.h" -#include "utils.h" - -bool VFS::Loaded(const std::string &path) { - std::lock_guard lock(mutex); - return state[path].loaded; -} - -bool VFS::Stamp(const std::string &path, int64_t ts, int step) { - std::lock_guard lock(mutex); - State &st = state[path]; - if (st.timestamp < ts || (st.timestamp == ts && st.step < step)) { - st.timestamp = ts; - st.step = step; - return true; - } else - return false; -} - -FileConsumer::FileConsumer(VFS *vfs, const std::string &parse_file) - : vfs_(vfs), parse_file_(parse_file) {} - -IndexFile *FileConsumer::TryConsumeFile( - const clang::FileEntry &File, - const std::unordered_map - &UID2File) { - auto UniqueID = File.getUniqueID(); - { - auto it = local_.find(UniqueID); - if (it != local_.end()) - return it->second.get(); - } - - auto it = UID2File.find(UniqueID); - assert(it != UID2File.end()); - assert(it->second.mtime); - if (!vfs_->Stamp(it->second.path, it->second.mtime, 1)) { - local_[UniqueID] = nullptr; - return nullptr; - } - - // Build IndexFile instance. - local_[UniqueID] = - std::make_unique(UniqueID, it->second.path, it->second.content); - return local_[UniqueID].get(); -} - -std::vector> FileConsumer::TakeLocalState() { - std::vector> result; - for (auto &entry : local_) { - if (entry.second) - result.push_back(std::move(entry.second)); - } - return result; -} diff --git a/src/file_consumer.h b/src/file_consumer.h deleted file mode 100644 index 4722ec8b..00000000 --- a/src/file_consumer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include "position.h" -#include "serializer.h" -#include "utils.h" - -#include - -#include -#include -#include - -struct IndexFile; - -struct VFS { - struct State { - int64_t timestamp; - int step; - bool loaded; - }; - mutable std::unordered_map state; - mutable std::mutex mutex; - - bool Loaded(const std::string &path); - bool Stamp(const std::string &path, int64_t ts, int step); -}; - -namespace std { -template <> struct hash { - std::size_t operator()(llvm::sys::fs::UniqueID ID) const { - size_t ret = ID.getDevice(); - hash_combine(ret, ID.getFile()); - return ret; - } -}; -} // namespace std - -// FileConsumer is used by the indexer. When it encouters a file, it tries to -// take ownership over it. If the indexer has ownership over a file, it will -// produce an index, otherwise, it will emit nothing for that declarations -// and references coming from that file. -// -// The indexer does this because header files do not have their own translation -// units but we still want to index them. -struct FileConsumer { - struct File { - std::string path; - int64_t mtime; - std::string content; - }; - - FileConsumer(VFS *vfs, const std::string &parse_file); - - // Returns IndexFile or nullptr for the file or nullptr. - IndexFile *TryConsumeFile( - const clang::FileEntry &file, - const std::unordered_map &); - - // Returns and passes ownership of all local state. - std::vector> TakeLocalState(); - -private: - std::unordered_map> - local_; - VFS *vfs_; - std::string parse_file_; -}; diff --git a/src/indexer.cc b/src/indexer.cc index 686768c2..080511b7 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -19,6 +19,7 @@ limitations under the License. #include "clang_tu.h" #include "log.hh" #include "match.h" +#include "pipeline.hh" #include "platform.h" #include "serializer.h" using namespace ccls; @@ -48,8 +49,15 @@ constexpr int kInitializerMaxLines = 3; GroupMatch *multiVersionMatcher; +struct File { + std::string path; + int64_t mtime; + std::string content; + std::unique_ptr db; +}; + struct IndexParam { - std::unordered_map UID2File; + std::unordered_map UID2File; std::unordered_map UID2multi; struct DeclInfo { Usr usr; @@ -58,10 +66,9 @@ struct IndexParam { }; std::unordered_map Decl2Info; + VFS &vfs; ASTContext *Ctx; - FileConsumer *file_consumer = nullptr; - - IndexParam(FileConsumer *file_consumer) : file_consumer(file_consumer) {} + IndexParam(VFS &vfs) : vfs(vfs) {} void SeenFile(const FileEntry &File) { // If this is the first time we have seen the file (ignoring if we are @@ -76,12 +83,17 @@ struct IndexParam { it->second.mtime = *tim; if (std::optional content = ReadContent(path)) it->second.content = *content; + + if (!vfs.Stamp(path, it->second.mtime, 1)) + return; + it->second.db = std::make_unique(File.getUniqueID(), path, + it->second.content); } } IndexFile *ConsumeFile(const FileEntry &FE) { SeenFile(FE); - return file_consumer->TryConsumeFile(FE, UID2File); + return UID2File[FE.getUniqueID()].db.get(); } bool UseMultiVersion(const FileEntry &FE) { @@ -1287,8 +1299,7 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, if (!Clang->hasTarget()) return {}; - FileConsumer file_consumer(vfs, file); - IndexParam param(&file_consumer); + IndexParam param(*vfs); auto DataConsumer = std::make_shared(param); index::IndexingOptions IndexOpts; @@ -1325,8 +1336,11 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, for (auto &Buf : Bufs) Buf.release(); - auto result = param.file_consumer->TakeLocalState(); - for (std::unique_ptr &entry : result) { + std::vector> result; + for (auto &it : param.UID2File) { + if (!it.second.db) + continue; + std::unique_ptr &entry = it.second.db; entry->import_file = file; entry->args = args; for (auto &[_, it] : entry->uid2lid_and_path) @@ -1356,6 +1370,7 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, entry->dependencies[llvm::CachedHashStringRef(Intern(path))] = file.mtime; } + result.push_back(std::move(entry)); } return result; diff --git a/src/indexer.h b/src/indexer.h index 17306552..2dbe6d6f 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -16,7 +16,6 @@ limitations under the License. #pragma once #include "clang_utils.h" -#include "file_consumer.h" #include "language.h" #include "lsp.h" #include "lsp_diagnostic.h" @@ -236,6 +235,16 @@ struct IndexInclude { const char *resolved_path; }; +namespace std { +template <> struct hash { + std::size_t operator()(llvm::sys::fs::UniqueID ID) const { + size_t ret = ID.getDevice(); + hash_combine(ret, ID.getFile()); + return ret; + } +}; +} // namespace std + struct IndexFile { // For both JSON and MessagePack cache files. static const int kMajorVersion; @@ -287,6 +296,7 @@ struct IndexFile { struct CompletionManager; struct WorkingFiles; +struct VFS; namespace ccls::idx { void Init(); diff --git a/src/messages/ccls_reload.cc b/src/messages/ccls_reload.cc index bc67cc26..0368d486 100644 --- a/src/messages/ccls_reload.cc +++ b/src/messages/ccls_reload.cc @@ -47,10 +47,7 @@ struct Handler_CclsReload : BaseMessageHandler { const auto ¶ms = request->params; // Send index requests for every file. if (params.whitelist.empty() && params.blacklist.empty()) { - { - std::lock_guard lock(vfs->mutex); - vfs->state.clear(); - } + vfs->Clear(); db->clear(); project->Index(working_files, lsRequestId()); return; diff --git a/src/pipeline.cc b/src/pipeline.cc index 99b4784c..99ca5a1b 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -74,6 +74,27 @@ void DiagnosticsPublisher::Publish(WorkingFiles *working_files, } } +void VFS::Clear() { + std::lock_guard lock(mutex); + state.clear(); +} + +bool VFS::Loaded(const std::string &path) { + std::lock_guard lock(mutex); + return state[path].loaded; +} + +bool VFS::Stamp(const std::string &path, int64_t ts, int step) { + std::lock_guard lock(mutex); + State &st = state[path]; + if (st.timestamp < ts || (st.timestamp == ts && st.step < step)) { + st.timestamp = ts; + st.step = step; + return true; + } else + return false; +} + namespace ccls::pipeline { int64_t loaded_ts = 0, tick = 0; diff --git a/src/pipeline.hh b/src/pipeline.hh index 285dfb80..1fb3bac3 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -4,6 +4,7 @@ #include "method.h" #include "query.h" +#include #include #include #include @@ -27,6 +28,20 @@ class DiagnosticsPublisher { std::vector diagnostics); }; +struct VFS { + struct State { + int64_t timestamp; + int step; + bool loaded; + }; + std::unordered_map state; + std::mutex mutex; + + void Clear(); + bool Loaded(const std::string &path); + bool Stamp(const std::string &path, int64_t ts, int step); +}; + namespace ccls { enum class IndexMode { NonInteractive, diff --git a/src/test.cc b/src/test.cc index 6c595200..69cf8536 100644 --- a/src/test.cc +++ b/src/test.cc @@ -18,6 +18,7 @@ limitations under the License. #include "clang_complete.hh" #include "filesystem.hh" #include "indexer.h" +#include "pipeline.hh" #include "platform.h" #include "serializer.h" #include "utils.h" From 1a519163da8fcba302d0223b3a20468c538db352 Mon Sep 17 00:00:00 2001 From: Riatre Foo Date: Sat, 22 Sep 2018 23:57:36 +0800 Subject: [PATCH 44/66] Remove chunks with CK_Information kind from insertText. (#78) Without this ccls inserts "size() const" in the following scenario: std::string text; text.si| <-- Trigger completion here and pick "size" --- src/messages/textDocument_completion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 545490da..e4bc36dc 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -426,7 +426,7 @@ void BuildItem(std::vector &out, out[i].insertText += "${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}"; out[i].insertTextFormat = lsInsertTextFormat::Snippet; - } else { + } else if (Kind != CodeCompletionString::CK_Informative) { out[i].insertText += text; } } From 28d33324b13a548465144dfd49755220a18c9811 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 22 Sep 2018 01:37:00 -0700 Subject: [PATCH 45/66] Publish diagnostics of inferred files and change diagnostics.{onChange,onOpen,onSave} from bool to debounce time --- src/clang_complete.cc | 258 +++++++++--------- src/clang_complete.hh | 31 +-- src/config.h | 26 +- src/message_handler.h | 2 - src/messages/ccls_reload.cc | 2 + src/messages/initialize.cc | 1 - src/messages/textDocument_didChange.cc | 5 +- src/messages/textDocument_didClose.cc | 2 +- src/messages/textDocument_didOpen.cc | 6 +- .../workspace_didChangeWatchedFiles.cc | 4 +- src/pipeline.cc | 43 +-- src/pipeline.hh | 12 - src/project.cc | 9 - src/utils.cc | 9 + src/utils.h | 3 + 15 files changed, 185 insertions(+), 228 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 078da29d..ab90d6b8 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -18,6 +18,7 @@ limitations under the License. #include "clang_utils.h" #include "filesystem.hh" #include "log.hh" +#include "match.h" #include "platform.h" #include @@ -32,7 +33,10 @@ using namespace clang; using namespace llvm; #include +#include +#include #include +namespace chrono = std::chrono; namespace ccls { namespace { @@ -80,22 +84,34 @@ class StoreDiags : public DiagnosticConsumer { const LangOptions *LangOpts; std::optional last; std::vector output; + std::string path; + std::unordered_map FID2concerned; void Flush() { if (!last) return; - bool mentions = last->inside_main || last->edits.size(); + bool mentions = last->concerned || last->edits.size(); if (!mentions) for (auto &N : last->notes) - if (N.inside_main) + if (N.concerned) mentions = true; if (mentions) output.push_back(std::move(*last)); last.reset(); } public: + StoreDiags(std::string path) : path(path) {} std::vector Take() { return std::move(output); } + bool IsConcerned(const SourceManager &SM, SourceLocation L) { + FileID FID = SM.getFileID(L); + auto it = FID2concerned.try_emplace(FID.getHashValue()); + if (it.second) { + const FileEntry *FE = SM.getFileEntryForID(FID); + it.first->second = FE && FileName(*FE) == path; + } + return it.first->second; + } void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override { LangOpts = &Opts; } @@ -108,24 +124,25 @@ public: SourceLocation L = Info.getLocation(); if (!L.isValid()) return; const SourceManager &SM = Info.getSourceManager(); - bool inside_main = SM.isInMainFile(L); + StringRef Filename = SM.getFilename(Info.getLocation()); + bool concerned = IsConcerned(SM, Info.getLocation()); auto fillDiagBase = [&](DiagBase &d) { llvm::SmallString<64> Message; Info.FormatDiagnostic(Message); d.range = FromCharSourceRange(SM, *LangOpts, DiagnosticRange(Info, *LangOpts)); d.message = Message.str(); - d.inside_main = inside_main; - d.file = SM.getFilename(Info.getLocation()); + d.concerned = concerned; + d.file = Filename; d.level = Level; d.category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); }; auto addFix = [&](bool SyntheticMessage) -> bool { - if (!inside_main) + if (!concerned) return false; for (const FixItHint &FixIt : Info.getFixItHints()) { - if (!SM.isInMainFile(FixIt.RemoveRange.getBegin())) + if (!IsConcerned(SM, FixIt.RemoveRange.getBegin())) return false; lsTextEdit edit; edit.newText = FixIt.CodeToInsert; @@ -158,9 +175,10 @@ std::unique_ptr BuildCompilerInstance( CompletionSession &session, std::unique_ptr CI, DiagnosticConsumer &DC, const WorkingFiles::Snapshot &snapshot, std::vector> &Bufs) { + std::string main = ResolveIfRelative(session.file.directory, CI->getFrontendOpts().Inputs[0].getFile()); for (auto &file : snapshot.files) { Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); - if (file.filename == session.file.filename) { + if (file.filename == main) if (auto Preamble = session.GetPreamble()) { #if LLVM_VERSION_MAJOR >= 7 Preamble->Preamble.OverridePreamble(*CI, session.FS, @@ -169,14 +187,10 @@ std::unique_ptr BuildCompilerInstance( Preamble->Preamble.AddImplicitPreamble(*CI, session.FS, Bufs.back().get()); #endif - } else { - CI->getPreprocessorOpts().addRemappedFile( - CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get()); + continue; } - } else { - CI->getPreprocessorOpts().addRemappedFile(file.filename, - Bufs.back().get()); - } + CI->getPreprocessorOpts().addRemappedFile(file.filename, + Bufs.back().get()); } auto Clang = std::make_unique(session.PCH); @@ -202,52 +216,53 @@ bool Parse(CompilerInstance &Clang) { void CompletionPreloadMain(CompletionManager *manager) { while (true) { - // Fetching the completion request blocks until we have a request. auto request = manager->preload_requests_.Dequeue(); - // If we don't get a session then that means we don't care about the file - // anymore - abandon the request. - std::shared_ptr session = manager->TryGetSession( - request.path, false /*mark_as_completion*/, false /*create_if_needed*/); + bool is_open = false; + std::shared_ptr session = + manager->TryGetSession(request.path, true, &is_open); if (!session) continue; - const auto &args = session->file.args; - WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( - {StripFileType(session->file.filename)}); - - LOG_S(INFO) << "create completion session for " << session->file.filename; - if (std::unique_ptr CI = - BuildCompilerInvocation(args, session->FS)) - session->BuildPreamble(*CI); - if (g_config->diagnostics.onSave) { + // For inferred session, don't build preamble because changes in a.h will + // invalidate it. + if (!session->inferred) { + const auto &args = session->file.args; + WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( + {StripFileType(session->file.filename)}); + if (std::unique_ptr CI = + BuildCompilerInvocation(args, session->FS)) + session->BuildPreamble(*CI, request.path); + } + int debounce = + is_open ? g_config->diagnostics.onOpen : g_config->diagnostics.onSave; + if (debounce >= 0) { lsTextDocumentIdentifier document; document.uri = lsDocumentUri::FromPath(request.path); - manager->diagnostic_request_.PushBack({document}, true); + manager->DiagnosticsUpdate(request.path, debounce); } } } -void CompletionMain(CompletionManager *completion_manager) { +void CompletionMain(CompletionManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. std::unique_ptr request = - completion_manager->completion_request_.Dequeue(); + manager->completion_request_.Dequeue(); // Drop older requests if we're not buffering. while (g_config->completion.dropOldRequests && - !completion_manager->completion_request_.IsEmpty()) { - completion_manager->on_dropped_(request->id); + !manager->completion_request_.IsEmpty()) { + manager->on_dropped_(request->id); request->Consumer.reset(); request->on_complete(nullptr); - request = completion_manager->completion_request_.Dequeue(); + request = manager->completion_request_.Dequeue(); } std::string path = request->document.uri.GetPath(); std::shared_ptr session = - completion_manager->TryGetSession(path, true /*mark_as_completion*/, - true /*create_if_needed*/); + manager->TryGetSession(path, false); std::unique_ptr CI = BuildCompilerInvocation(session->file.args, session->FS); @@ -263,7 +278,7 @@ void CompletionMain(CompletionManager *completion_manager) { DiagnosticConsumer DC; WorkingFiles::Snapshot snapshot = - completion_manager->working_files_->AsSnapshot({StripFileType(path)}); + manager->working_files_->AsSnapshot({StripFileType(path)}); std::vector> Bufs; auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs); if (!Clang) @@ -297,25 +312,31 @@ llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) { } void printDiag(llvm::raw_string_ostream &OS, const DiagBase &d) { - if (d.inside_main) + if (d.concerned) OS << llvm::sys::path::filename(d.file); else OS << d.file; auto pos = d.range.start; OS << ":" << (pos.line + 1) << ":" << (pos.column + 1) << ":" - << (d.inside_main ? " " : "\n"); + << (d.concerned ? " " : "\n"); OS << diagLeveltoString(d.level) << ": " << d.message; } void DiagnosticMain(CompletionManager *manager) { while (true) { - // Fetching the completion request blocks until we have a request. CompletionManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); - std::string path = request.document.uri.GetPath(); + const std::string &path = request.path; + int64_t wait = request.wait_until - + chrono::duration_cast( + chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + if (wait > 0) + std::this_thread::sleep_for(chrono::duration( + std::min(wait, request.debounce))); - std::shared_ptr session = manager->TryGetSession( - path, true /*mark_as_completion*/, true /*create_if_needed*/); + std::shared_ptr session = + manager->TryGetSession(path, false); std::unique_ptr CI = BuildCompilerInvocation(session->file.args, session->FS); @@ -323,7 +344,7 @@ void DiagnosticMain(CompletionManager *manager) { continue; CI->getDiagnosticOpts().IgnoreWarnings = false; CI->getLangOpts()->SpellChecking = g_config->diagnostics.spellChecking; - StoreDiags DC; + StoreDiags DC(path); WorkingFiles::Snapshot snapshot = manager->working_files_->AsSnapshot({StripFileType(path)}); std::vector> Bufs; @@ -359,9 +380,12 @@ void DiagnosticMain(CompletionManager *manager) { return ret; }; + std::vector diags = DC.Take(); + if (std::shared_ptr preamble = session->GetPreamble()) + diags.insert(diags.end(), preamble->diags.begin(), preamble->diags.end()); std::vector ls_diags; - for (auto &d : DC.Take()) { - if (!d.inside_main) + for (auto &d : diags) { + if (!d.concerned) continue; std::string buf; llvm::raw_string_ostream OS(buf); @@ -376,7 +400,7 @@ void DiagnosticMain(CompletionManager *manager) { OS.flush(); ls_diag.message = std::move(buf); for (auto &n : d.notes) { - if (!n.inside_main) + if (!n.concerned) continue; lsDiagnostic &ls_diag1 = ls_diags.emplace_back(); Fill(n, ls_diag1); @@ -386,6 +410,12 @@ void DiagnosticMain(CompletionManager *manager) { ls_diag1.message = std::move(buf); } } + + { + std::lock_guard lock(session->wfiles->files_mutex); + if (WorkingFile *wfile = session->wfiles->GetFileByFilenameNoLock(path)) + wfile->diagnostics_ = ls_diags; + } manager->on_diagnostic_(path, ls_diags); } } @@ -397,9 +427,10 @@ std::shared_ptr CompletionSession::GetPreamble() { return preamble; } -void CompletionSession::BuildPreamble(CompilerInvocation &CI) { +void CompletionSession::BuildPreamble(CompilerInvocation &CI, + const std::string &main) { std::shared_ptr OldP = GetPreamble(); - std::string content = wfiles->GetContent(file.filename); + std::string content = wfiles->GetContent(main); std::unique_ptr Buf = llvm::MemoryBuffer::getMemBuffer(content); auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0); @@ -412,7 +443,7 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) { CI.getPreprocessorOpts().WriteCommentListToPCH = false; #endif - StoreDiags DC; + StoreDiags DC(main); IntrusiveRefCntPtr DE = CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), &DC, false); PreambleCallbacks PP; @@ -432,8 +463,8 @@ CompletionManager::CompletionManager(Project *project, OnDropped on_dropped) : project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_dropped_(on_dropped), - preloaded_sessions_(kMaxPreloadedSessions), - completion_sessions_(kMaxCompletionSessions), + preloads(kMaxPreloadedSessions), + sessions(kMaxCompletionSessions), PCH(std::make_shared()) { std::thread([&]() { set_thread_name("comp"); @@ -452,22 +483,28 @@ CompletionManager::CompletionManager(Project *project, .detach(); } -void CompletionManager::CodeComplete( - const lsRequestId &id, - const lsTextDocumentPositionParams &completion_location, - const OnComplete &on_complete) { -} - -void CompletionManager::DiagnosticsUpdate( - const lsTextDocumentIdentifier &document) { - bool has = false; - diagnostic_request_.Iterate([&](const DiagnosticRequest &request) { - if (request.document.uri == document.uri) - has = true; - }); - if (!has) - diagnostic_request_.PushBack(DiagnosticRequest{document}, - true /*priority*/); +void CompletionManager::DiagnosticsUpdate(const std::string &path, + int debounce) { + static GroupMatch match(g_config->diagnostics.whitelist, + g_config->diagnostics.blacklist); + if (!match.IsMatch(path)) + return; + int64_t now = chrono::duration_cast( + chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + bool flag = false; + { + std::lock_guard lock(diag_mutex); + int64_t &next = next_diag[path]; + auto &d = g_config->diagnostics; + if (next <= now || + now - next > std::max(d.onChange, std::max(d.onChange, d.onSave))) { + next = now + debounce; + flag = true; + } + } + if (flag) + diagnostic_request_.PushBack({path, now + debounce, debounce}, false); } void CompletionManager::NotifyView(const std::string &path) { @@ -477,94 +514,67 @@ void CompletionManager::NotifyView(const std::string &path) { } void CompletionManager::NotifySave(const std::string &filename) { - // - // On save, always reparse. - // - EnsureCompletionOrCreatePreloadSession(filename); preload_requests_.PushBack(PreloadRequest{filename}, true); } -void CompletionManager::NotifyClose(const std::string &filename) { - // - // On close, we clear any existing CompletionSession instance. - // - +void CompletionManager::OnClose(const std::string &filename) { std::lock_guard lock(sessions_lock_); - - // Take and drop. It's okay if we don't actually drop the file, it'll - // eventually get pushed out of the caches as the user opens other files. - auto preloaded_ptr = preloaded_sessions_.TryTake(filename); - LOG_IF_S(INFO, !!preloaded_ptr) - << "Dropped preloaded-based code completion session for " << filename; - auto completion_ptr = completion_sessions_.TryTake(filename); - LOG_IF_S(INFO, !!completion_ptr) - << "Dropped completion-based code completion session for " << filename; - - // We should never have both a preloaded and completion session. - assert((preloaded_ptr && completion_ptr) == false); + preloads.TryTake(filename); + sessions.TryTake(filename); } bool CompletionManager::EnsureCompletionOrCreatePreloadSession( const std::string &path) { std::lock_guard lock(sessions_lock_); - - // Check for an existing CompletionSession. - if (preloaded_sessions_.TryGet(path) || - completion_sessions_.TryGet(path)) { + if (preloads.TryGet(path) || sessions.TryGet(path)) return false; - } // No CompletionSession, create new one. auto session = std::make_shared( project_->FindCompilationEntryForFile(path), working_files_, PCH); - preloaded_sessions_.Insert(session->file.filename, session); + if (session->file.filename != path) { + session->inferred = true; + session->file.filename = path; + } + preloads.Insert(path, session); + LOG_S(INFO) << "create preload session for " << path; return true; } std::shared_ptr -CompletionManager::TryGetSession(const std::string &path, - bool mark_as_completion, - bool create_if_needed) { +CompletionManager::TryGetSession(const std::string &path, bool preload, + bool *is_open) { std::lock_guard lock(sessions_lock_); + std::shared_ptr session = preloads.TryGet(path); - // Try to find a preloaded session. - std::shared_ptr preloaded = - preloaded_sessions_.TryGet(path); - - if (preloaded) { - // If this request is for a completion, we should move it to - // |completion_sessions|. - if (mark_as_completion) { - preloaded_sessions_.TryTake(path); - completion_sessions_.Insert(path, preloaded); + if (session) { + if (!preload) { + preloads.TryTake(path); + sessions.Insert(path, session); + if (is_open) + *is_open = true; } - return preloaded; + return session; } - // Try to find a completion session. If none create one. - std::shared_ptr session = - completion_sessions_.TryGet(path); - if (!session && create_if_needed) { + session = sessions.TryGet(path); + if (!session && !preload) { session = std::make_shared( project_->FindCompilationEntryForFile(path), working_files_, PCH); - completion_sessions_.Insert(path, session); + sessions.Insert(path, session); + LOG_S(INFO) << "create session for " << path; + if (is_open) + *is_open = true; } return session; } -void CompletionManager::FlushSession(const std::string &path) { - std::lock_guard lock(sessions_lock_); - - preloaded_sessions_.TryTake(path); - completion_sessions_.TryTake(path); -} - void CompletionManager::FlushAllSessions() { LOG_S(INFO) << "flush all clang complete sessions"; std::lock_guard lock(sessions_lock_); - preloaded_sessions_.Clear(); - completion_sessions_.Clear(); + preloads.Clear(); + sessions.Clear(); } diff --git a/src/clang_complete.hh b/src/clang_complete.hh index c7232692..45d16dcd 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -39,7 +39,7 @@ struct DiagBase { std::string file; clang::DiagnosticsEngine::Level level = clang::DiagnosticsEngine::Note; unsigned category; - bool inside_main = false; + bool concerned = false; }; struct Note : DiagBase {}; struct Diag : DiagBase { @@ -58,10 +58,10 @@ struct CompletionSession : public std::enable_shared_from_this { std::mutex mutex; std::shared_ptr preamble; - std::vector diags; Project::Entry file; WorkingFiles *wfiles; + bool inferred = false; // TODO share llvm::IntrusiveRefCntPtr FS = @@ -73,7 +73,7 @@ struct CompletionSession : file(file), wfiles(wfiles), PCH(PCH) {} std::shared_ptr GetPreamble(); - void BuildPreamble(clang::CompilerInvocation &CI); + void BuildPreamble(clang::CompilerInvocation &CI, const std::string &main); }; } @@ -107,19 +107,16 @@ struct CompletionManager { OnComplete on_complete; }; struct DiagnosticRequest { - lsTextDocumentIdentifier document; + std::string path; + int64_t wait_until; + int64_t debounce; }; CompletionManager(Project *project, WorkingFiles *working_files, OnDiagnostic on_diagnostic, OnDropped on_dropped); - // Start a code completion at the given location. |on_complete| will run when - // completion results are available. |on_complete| may run on any thread. - void CodeComplete(const lsRequestId &request_id, - const lsTextDocumentPositionParams &completion_location, - const OnComplete &on_complete); // Request a diagnostics update. - void DiagnosticsUpdate(const lsTextDocumentIdentifier &document); + void DiagnosticsUpdate(const std::string &path, int debounce); // Notify the completion manager that |filename| has been viewed and we // should begin preloading completion data. @@ -129,7 +126,7 @@ struct CompletionManager { void NotifySave(const std::string &path); // Notify the completion manager that |filename| has been closed. Any existing // completion session will be dropped. - void NotifyClose(const std::string &path); + void OnClose(const std::string &path); // Ensures there is a completion or preloaded session. Returns true if a new // session was created. @@ -137,11 +134,8 @@ struct CompletionManager { // Tries to find an edit session for |filename|. This will move the session // from view to edit. std::shared_ptr - TryGetSession(const std::string &path, bool mark_as_completion, - bool create_if_needed); + TryGetSession(const std::string &path, bool preload, bool *is_open = nullptr); - // Flushes all saved sessions with the supplied filename - void FlushSession(const std::string &path); // Flushes all saved sessions void FlushAllSessions(void); @@ -159,14 +153,17 @@ struct CompletionManager { // CompletionSession instances which are preloaded, ie, files which the user // has viewed but not requested code completion for. - LruSessionCache preloaded_sessions_; + LruSessionCache preloads; // CompletionSession instances which the user has actually performed // completion on. This is more rare so these instances tend to stay alive // much longer than the ones in |preloaded_sessions_|. - LruSessionCache completion_sessions_; + LruSessionCache sessions; // Mutex which protects |view_sessions_| and |edit_sessions_|. std::mutex sessions_lock_; + std::mutex diag_mutex; + std::unordered_map next_diag; + // Request a code completion at the given location. ThreadedQueue> completion_request_; ThreadedQueue diagnostic_request_; diff --git a/src/config.h b/src/config.h index f9194c08..b8a4d05b 100644 --- a/src/config.h +++ b/src/config.h @@ -156,20 +156,18 @@ struct Config { // blacklisted files. std::vector blacklist; - // How often should ccls publish diagnostics in completion? - // -1: never - // 0: as often as possible - // xxx: at most every xxx milliseconds - int frequencyMs = 0; + // Time to wait before computing diagnostics for textDocument/didChange. + // -1: disable diagnostics on change + // 0: immediately + // positive (e.g. 500): wait for 500 milliseconds. didChange requests in + // this period of time will only cause one computation. + int onChange = 1000; - // If true, diagnostics will be reported for textDocument/didChange. - bool onChange = true; + // Time to wait before computing diagnostics for textDocument/didOpen. + int onOpen = 0; - // If true, diagnostics will be reported for textDocument/didOpen. - bool onOpen = true; - - // If true, diagnostics will be reported for textDocument/didSave. - bool onSave = true; + // Time to wait before computing diagnostics for textDocument/didSave. + int onSave = 0; bool spellChecking = true; @@ -258,8 +256,8 @@ MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, dropOldRequests, duplicateOptional, filterAndSort, includeBlacklist, includeMaxPathSize, includeSuffixWhitelist, includeWhitelist); -MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onChange, - onOpen, onSave, spellChecking, whitelist) +MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, + spellChecking, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, diff --git a/src/message_handler.h b/src/message_handler.h index b7110295..1d790432 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -27,7 +27,6 @@ limitations under the License. struct CompletionManager; struct Config; -class DiagnosticsPublisher; struct GroupMatch; struct VFS; struct IncludeComplete; @@ -90,7 +89,6 @@ struct MessageHandler { DB *db = nullptr; MultiQueueWaiter *waiter = nullptr; Project *project = nullptr; - DiagnosticsPublisher *diag_pub = nullptr; VFS *vfs = nullptr; SemanticHighlight *highlight = nullptr; WorkingFiles *working_files = nullptr; diff --git a/src/messages/ccls_reload.cc b/src/messages/ccls_reload.cc index 0368d486..6a450655 100644 --- a/src/messages/ccls_reload.cc +++ b/src/messages/ccls_reload.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_complete.hh" #include "match.h" #include "message_handler.h" #include "pipeline.hh" @@ -50,6 +51,7 @@ struct Handler_CclsReload : BaseMessageHandler { vfs->Clear(); db->clear(); project->Index(working_files, lsRequestId()); + clang_complete->FlushAllSessions(); return; } diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 2e5e5213..bce54fb9 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -486,7 +486,6 @@ struct Handler_Initialize : BaseMessageHandler { sys::fs::create_directories(g_config->cacheDirectory + '@' + escaped); } - diag_pub->Init(); idx::Init(); highlight->Init(); diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc index 7488ff2f..76bdef49 100644 --- a/src/messages/textDocument_didChange.cc +++ b/src/messages/textDocument_didChange.cc @@ -42,9 +42,8 @@ struct Handler_TextDocumentDidChange if (g_config->index.onChange) pipeline::Index(path, {}, IndexMode::OnChange); clang_complete->NotifyView(path); - if (g_config->diagnostics.onChange) - clang_complete->DiagnosticsUpdate( - params.textDocument.AsTextDocumentIdentifier()); + if (g_config->diagnostics.onChange >= 0) + clang_complete->DiagnosticsUpdate(path, g_config->diagnostics.onChange); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); diff --git a/src/messages/textDocument_didClose.cc b/src/messages/textDocument_didClose.cc index 8e3f504f..c905f154 100644 --- a/src/messages/textDocument_didClose.cc +++ b/src/messages/textDocument_didClose.cc @@ -47,7 +47,7 @@ struct Handler_TextDocumentDidClose // Remove internal state. working_files->OnClose(request->params.textDocument); - clang_complete->NotifyClose(path); + clang_complete->OnClose(path); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 4911a338..27eb8f41 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -71,14 +71,10 @@ struct Handler_TextDocumentDidOpen project->SetArgsForFile(args, path); // Submit new index request if it is not a header file. - if (SourceFileLanguage(path) != LanguageId::Unknown) { + if (SourceFileLanguage(path) != LanguageId::Unknown) pipeline::Index(path, args, IndexMode::Normal); - clang_complete->FlushSession(path); - } clang_complete->NotifyView(path); - if (g_config->diagnostics.onOpen) - clang_complete->DiagnosticsUpdate({params.textDocument.uri}); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index fd5806d1..d338cfc8 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -64,12 +64,12 @@ struct Handler_WorkspaceDidChangeWatchedFiles if (mode == IndexMode::Normal) clang_complete->NotifySave(path); else - clang_complete->FlushSession(path); + clang_complete->OnClose(path); break; } case lsFileChangeType::Deleted: pipeline::Index(path, {}, mode); - clang_complete->FlushSession(path); + clang_complete->OnClose(path); break; } } diff --git a/src/pipeline.cc b/src/pipeline.cc index 99ca5a1b..631ecd7b 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -39,41 +39,6 @@ using namespace llvm; #include #endif -void DiagnosticsPublisher::Init() { - frequencyMs_ = g_config->diagnostics.frequencyMs; - match_ = std::make_unique(g_config->diagnostics.whitelist, - g_config->diagnostics.blacklist); -} - -void DiagnosticsPublisher::Publish(WorkingFiles *working_files, - std::string path, - std::vector diagnostics) { - bool good = true; - // Cache diagnostics so we can show fixits. - working_files->DoActionOnFile(path, [&](WorkingFile *working_file) { - if (working_file) { - good = working_file->diagnostics_.empty(); - working_file->diagnostics_ = diagnostics; - } - }); - - int64_t now = - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); - if (frequencyMs_ >= 0 && - (nextPublish_ <= now || (!good && diagnostics.empty())) && - match_->IsMatch(path)) { - nextPublish_ = now + frequencyMs_; - - Out_TextDocumentPublishDiagnostics out; - out.params.uri = lsDocumentUri::FromPath(path); - out.params.diagnostics = diagnostics; - ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, - out); - } -} - void VFS::Clear() { std::lock_guard lock(mutex); state.clear(); @@ -497,12 +462,15 @@ void MainLoop() { SemanticHighlight highlight; WorkingFiles working_files; VFS vfs; - DiagnosticsPublisher diag_pub; CompletionManager clang_complete( &project, &working_files, [&](std::string path, std::vector diagnostics) { - diag_pub.Publish(&working_files, path, diagnostics); + Out_TextDocumentPublishDiagnostics out; + out.params.uri = lsDocumentUri::FromPath(path); + out.params.diagnostics = diagnostics; + ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, + out); }, [](lsRequestId id) { if (id.Valid()) { @@ -523,7 +491,6 @@ void MainLoop() { handler->db = &db; handler->waiter = indexer_waiter; handler->project = &project; - handler->diag_pub = &diag_pub; handler->vfs = &vfs; handler->highlight = &highlight; handler->working_files = &working_files; diff --git a/src/pipeline.hh b/src/pipeline.hh index 1fb3bac3..920053c8 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -16,18 +16,6 @@ struct Project; struct WorkingFiles; struct lsBaseOutMessage; -class DiagnosticsPublisher { - std::unique_ptr match_; - int64_t nextPublish_ = 0; - int frequencyMs_; - - public: - void Init(); - void Publish(WorkingFiles* working_files, - std::string path, - std::vector diagnostics); -}; - struct VFS { struct State { int64_t timestamp; diff --git a/src/project.cc b/src/project.cc index 98f84083..f4beb6c0 100644 --- a/src/project.cc +++ b/src/project.cc @@ -66,15 +66,6 @@ enum OptionClass { Separate, }; -std::string ResolveIfRelative(const std::string &directory, - const std::string &path) { - if (sys::path::is_absolute(path)) - return path; - SmallString<256> Ret; - sys::path::append(Ret, directory, path); - return NormalizePath(Ret.str()); -} - struct ProjectProcessor { ProjectConfig *config; std::unordered_set command_set; diff --git a/src/utils.cc b/src/utils.cc index 6d3e06af..6a2f9e50 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -117,6 +117,15 @@ std::string EscapeFileName(std::string path) { return path; } +std::string ResolveIfRelative(const std::string &directory, + const std::string &path) { + if (sys::path::is_absolute(path)) + return path; + SmallString<256> Ret; + sys::path::append(Ret, directory, path); + return NormalizePath(Ret.str()); +} + std::optional LastWriteTime(const std::string &path) { sys::fs::file_status Status; if (sys::fs::status(path, Status)) diff --git a/src/utils.h b/src/utils.h index d34187bc..7b4087ce 100644 --- a/src/utils.h +++ b/src/utils.h @@ -70,6 +70,9 @@ void EnsureEndsInSlash(std::string &path); // e.g. foo/bar.c => foo_bar.c std::string EscapeFileName(std::string path); +std::string ResolveIfRelative(const std::string &directory, + const std::string &path); + std::optional LastWriteTime(const std::string &path); std::optional ReadContent(const std::string &filename); void WriteToFile(const std::string &filename, const std::string &content); From 6ea399559deaad8beef05a34af8653f8cda8a85d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 22 Sep 2018 18:00:50 -0700 Subject: [PATCH 46/66] Fix spurious "Failed to index" errors --- src/indexer.cc | 6 ++++-- src/indexer.h | 5 +++-- src/pipeline.cc | 5 +++-- src/test.cc | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index 080511b7..45af8e7e 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1235,15 +1235,18 @@ std::vector> Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, - const std::vector> &remapped) { + const std::vector> &remapped, bool &ok) { + ok = true; if (!g_config->index.enabled) return {}; auto PCH = std::make_shared(); llvm::IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); std::shared_ptr CI = BuildCompilerInvocation(args, FS); + // e.g. .s if (!CI) return {}; + ok = false; // -fparse-all-comments enables documentation in the indexer and in // code completion. if (g_config->index.comments > 1) @@ -1313,7 +1316,6 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, std::unique_ptr Action = createIndexingAction( DataConsumer, IndexOpts, std::make_unique(param)); - bool ok = false; { llvm::CrashRecoveryContext CRC; auto parse = [&]() { diff --git a/src/indexer.h b/src/indexer.h index 2dbe6d6f..553ee640 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -304,5 +304,6 @@ std::vector> Index(CompletionManager *complete, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, - const std::vector> &remapped); -} + const std::vector> &remapped, + bool &ok); +} // namespace ccls::idx diff --git a/src/pipeline.cc b/src/pipeline.cc index 631ecd7b..9864a09b 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -278,10 +278,11 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (content.size()) remapped.emplace_back(path_to_index, content); } + bool ok; auto indexes = idx::Index(completion, wfiles, vfs, entry.directory, - path_to_index, entry.args, remapped); + path_to_index, entry.args, remapped, ok); - if (indexes.empty()) { + if (!ok) { if (g_config->index.enabled && request.id.Valid()) { Out_Error out; out.id = request.id; diff --git a/src/test.cc b/src/test.cc index 69cf8536..57af162c 100644 --- a/src/test.cc +++ b/src/test.cc @@ -317,7 +317,8 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { std::vector cargs; for (auto &arg : flags) cargs.push_back(arg.c_str()); - auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}); + bool ok; + auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}, ok); for (const auto &entry : all_expected_output) { const std::string &expected_path = entry.first; From 7eb58bb5e13d7c5f99e2bae5d197bed3d868de7c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 22 Sep 2018 22:05:24 -0700 Subject: [PATCH 47/66] Misc --- src/indexer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/indexer.cc b/src/indexer.cc index 45af8e7e..069f4e41 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -660,6 +660,7 @@ public: case Decl::CXXConversion: // *operator* int => *operator int* case Decl::CXXDestructor: // *~*A => *~A* case Decl::CXXMethod: // *operator*= => *operator=* + case Decl::Function: // operator delete if (Loc.isFileID()) { SourceRange R = cast(OrigD)->getNameInfo().getSourceRange(); From 22daed7001db3331d795617d0356a5b78bcf6e21 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 22 Sep 2018 22:55:17 -0700 Subject: [PATCH 48/66] Add kind to $ccls/member and iterate all QueryType::def kind:2 => member functions kind:3 => nested classes / namespace members --- README.md | 6 +- src/messages/ccls_member.cc | 155 ++++++++++++++++++++++++------------ 2 files changed, 106 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 1f85d442..e3349def 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,14 @@ ccls, which originates from [cquery](https://github.com/cquery-project/cquery), * code completion (with both signature help and snippets) * [definition](src/messages/textDocument_definition.cc)/[references](src/messages/textDcument_references.cc), and other cross references - * hierarchies: [call (caller/callee) hierarchy](src/messages/ccls_callHierarchy.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritanceHierarchy.cc), [member hierarchy](src/messages/ccls_memberHierarchy.cc) - * [symbol rename](src/messages/text_documentRename.cc) + * cross reference extensions: `$ccls/call` `$ccls/inheritance` `$ccls/member` `$ccls/vars` ... + * hierarchies: [call (caller/callee) hierarchy](src/messages/ccls_call.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritance.cc), [member hierarchy](src/messages/ccls_member.cc) + * [symbol rename](src/messages/textDocument_rename.cc) * [document symbols](src/messages/textDocument_documentSymbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) * [hover information](src/messages/textDocument_hover.cc) * diagnostics and code actions (clang FixIts) * semantic highlighting and preprocessor skipped regions + * semantic navigation: `$ccls/navigate` It has a global view of the code base and support a lot of cross reference features, see [wiki/FAQ](../../wiki/FAQ). It starts indexing the whole project (including subprojects if exist) parallelly when you open the first file, while the main thread can serve requests before the indexing is complete. diff --git a/src/messages/ccls_member.cc b/src/messages/ccls_member.cc index d70add57..e95c7065 100644 --- a/src/messages/ccls_member.cc +++ b/src/messages/ccls_member.cc @@ -20,6 +20,7 @@ limitations under the License. using namespace ccls; #include +#include using namespace clang; #include @@ -42,12 +43,15 @@ struct In_CclsMember : public RequestInMessage { bool qualified = false; int levels = 1; + // If SymbolKind::Func and the point is at a type, list member functions + // instead of member variables. + SymbolKind kind = SymbolKind::Var; bool hierarchy = false; } params; }; MAKE_REFLECT_STRUCT(In_CclsMember::Params, textDocument, position, id, - qualified, levels, hierarchy); + qualified, levels, kind, hierarchy); MAKE_REFLECT_STRUCT(In_CclsMember, id, params); REGISTER_IN_MESSAGE(In_CclsMember); @@ -73,7 +77,7 @@ MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMember, jsonrpc, id, result); bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, - bool qualified, int levels); + bool qualified, int levels, SymbolKind memberKind); // Add a field to |entry| which is a Func/Type. void DoField(MessageHandler *m, Out_CclsMember::Entry *entry, @@ -108,7 +112,7 @@ void DoField(MessageHandler *m, Out_CclsMember::Entry *entry, if (def1->type) { entry1.id = std::to_string(def1->type); entry1.usr = def1->type; - if (Expand(m, &entry1, qualified, levels)) + if (Expand(m, &entry1, qualified, levels, SymbolKind::Var)) entry->children.push_back(std::move(entry1)); } else { entry1.id = "0"; @@ -119,13 +123,13 @@ void DoField(MessageHandler *m, Out_CclsMember::Entry *entry, // Expand a type node by adding members recursively to it. bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, - bool qualified, int levels) { + bool qualified, int levels, SymbolKind memberKind) { if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) { entry->name = ClangBuiltinTypeName(int(entry->usr)); return true; } - const QueryType &type = m->db->Type(entry->usr); - const QueryType::Def *def = type.AnyDef(); + const QueryType *type = &m->db->Type(entry->usr); + const QueryType::Def *def = type->AnyDef(); // builtin types have no declaration and empty |qualified|. if (!def) return false; @@ -133,51 +137,96 @@ bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, std::unordered_set seen; if (levels > 0) { std::vector stack; - seen.insert(type.usr); - stack.push_back(&type); + seen.insert(type->usr); + stack.push_back(type); while (stack.size()) { - const auto *def = stack.back()->AnyDef(); + type = stack.back(); stack.pop_back(); - if (def) { - for (Usr usr : def->bases) { - auto &type1 = m->db->Type(usr); - if (type1.def.size()) { - seen.insert(type1.usr); - stack.push_back(&type1); - } + const auto *def = type->AnyDef(); + if (!def) continue; + for (Usr usr : def->bases) { + auto &type1 = m->db->Type(usr); + if (type1.def.size()) { + seen.insert(type1.usr); + stack.push_back(&type1); } - if (def->alias_of) { - const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef(); - Out_CclsMember::Entry entry1; - entry1.id = std::to_string(def->alias_of); - entry1.usr = def->alias_of; - if (def1 && def1->spell) { - // The declaration of target type. - if (std::optional loc = + } + if (def->alias_of) { + const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef(); + Out_CclsMember::Entry entry1; + entry1.id = std::to_string(def->alias_of); + entry1.usr = def->alias_of; + if (def1 && def1->spell) { + // The declaration of target type. + if (std::optional loc = + GetLsLocation(m->db, m->working_files, *def1->spell)) + entry1.location = *loc; + } else if (def->spell) { + // Builtin types have no declaration but the typedef declaration + // itself is useful. + if (std::optional loc = + GetLsLocation(m->db, m->working_files, *def->spell)) + entry1.location = *loc; + } + if (def1 && qualified) + entry1.fieldName = def1->detailed_name; + if (Expand(m, &entry1, qualified, levels - 1, memberKind)) { + // For builtin types |name| is set. + if (entry1.fieldName.empty()) + entry1.fieldName = std::string(entry1.name); + entry->children.push_back(std::move(entry1)); + } + } else if (memberKind == SymbolKind::Func) { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (Usr usr : def.funcs) + if (seen1.insert(usr).second) { + QueryFunc &func1 = m->db->Func(usr); + if (const QueryFunc::Def *def1 = func1.AnyDef()) { + Out_CclsMember::Entry entry1; + entry1.fieldName = def1->Name(false); + if (def1->spell) { + if (auto loc = + GetLsLocation(m->db, m->working_files, *def1->spell)) + entry1.location = *loc; + } else if (func1.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, + func1.declarations[0])) + entry1.location = *loc; + } + entry->children.push_back(std::move(entry1)); + } + } + } else if (memberKind == SymbolKind::Type) { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (Usr usr : def.types) + if (seen1.insert(usr).second) { + QueryType &type1 = m->db->Type(usr); + if (const QueryType::Def *def1 = type1.AnyDef()) { + Out_CclsMember::Entry entry1; + entry1.fieldName = def1->Name(false); + if (def1->spell) { + if (auto loc = GetLsLocation(m->db, m->working_files, *def1->spell)) - entry1.location = *loc; - } else if (def->spell) { - // Builtin types have no declaration but the typedef declaration - // itself is useful. - if (std::optional loc = - GetLsLocation(m->db, m->working_files, *def->spell)) - entry1.location = *loc; - } - if (def1 && qualified) - entry1.fieldName = def1->detailed_name; - if (Expand(m, &entry1, qualified, levels - 1)) { - // For builtin types |name| is set. - if (entry1.fieldName.empty()) - entry1.fieldName = std::string(entry1.name); - entry->children.push_back(std::move(entry1)); - } - } else { - for (auto it : def->vars) { - QueryVar &var = m->db->Var(it.first); - if (!var.def.empty()) - DoField(m, entry, var, it.second, qualified, levels - 1); - } - } + entry1.location = *loc; + } else if (type1.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, + type1.declarations[0])) + entry1.location = *loc; + } + entry->children.push_back(std::move(entry1)); + } + } + } else { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (auto it : def.vars) + if (seen1.insert(it.first).second) { + QueryVar &var = m->db->Var(it.first); + if (!var.def.empty()) + DoField(m, entry, var, it.second, qualified, levels - 1); + } } } entry->numChildren = int(entry->children.size()); @@ -191,7 +240,7 @@ struct Handler_CclsMember MethodType GetMethodType() const override { return kMethodType; } std::optional - BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels) { + BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels, SymbolKind memberKind) { switch (kind) { default: return {}; @@ -228,7 +277,7 @@ struct Handler_CclsMember GetLsLocation(db, working_files, *def->spell)) entry.location = *loc; } - Expand(this, &entry, qualified, levels); + Expand(this, &entry, qualified, levels, memberKind); return entry; } } @@ -250,7 +299,7 @@ struct Handler_CclsMember entry.usr = params.usr; // entry.name is empty as it is known by the client. if (db->HasType(entry.usr) && - Expand(this, &entry, params.qualified, params.levels)) + Expand(this, &entry, params.qualified, params.levels, params.kind)) out.result = std::move(entry); } else { QueryFile *file; @@ -263,14 +312,14 @@ struct Handler_CclsMember switch (sym.kind) { case SymbolKind::Func: case SymbolKind::Type: - out.result = - BuildInitial(sym.kind, sym.usr, params.qualified, params.levels); + out.result = BuildInitial(sym.kind, sym.usr, params.qualified, + params.levels, params.kind); break; case SymbolKind::Var: { const QueryVar::Def *def = db->GetVar(sym).AnyDef(); if (def && def->type) out.result = BuildInitial(SymbolKind::Type, def->type, - params.qualified, params.levels); + params.qualified, params.levels, params.kind); break; } default: From e320ce42ab40bea65de350b8114ef25c5f7d4f64 Mon Sep 17 00:00:00 2001 From: Riatre Foo Date: Sun, 23 Sep 2018 06:10:03 +0800 Subject: [PATCH 49/66] Include macros in completion result --- src/messages/textDocument_completion.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index e4bc36dc..474d1df8 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -634,6 +634,7 @@ struct Handler_TextDocumentCompletion #if LLVM_VERSION_MAJOR >= 7 CCOpts.IncludeFixIts = true; #endif + CCOpts.IncludeMacros = true; if (cache.IsCacheValid(params)) { CompletionConsumer Consumer(CCOpts, true); cache.WithLock([&]() { Consumer.ls_items = cache.result; }); From 71e9835b8c29f567d1f4e49545e390ec72bf65f4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 10:20:05 -0700 Subject: [PATCH 50/66] documentSymbol: ignore TypeParameter Reported by Riatre --- src/messages/textDocument_documentSymbol.cc | 27 ++++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index f6064d19..bda4a270 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -76,6 +76,14 @@ struct Out_HierarchicalDocumentSymbol }; MAKE_REFLECT_STRUCT(Out_HierarchicalDocumentSymbol, jsonrpc, id, result); +bool IgnoreType(const QueryType::Def *def) { + return !def || def->kind == lsSymbolKind::TypeParameter; +} + +bool IgnoreVar(const QueryVar::Def *def) { + return !def || def->is_local(); +} + struct Handler_TextDocumentDocumentSymbol : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -140,9 +148,11 @@ struct Handler_TextDocumentDocumentSymbol kv.first = static_cast(&def); } }); - if (kv.first && sym.kind == SymbolKind::Var) - if (static_cast(kv.first)->is_local()) - kv.first = nullptr; + if (kv.first && ((sym.kind == SymbolKind::Type && + IgnoreType((const QueryType::Def *)kv.first)) || + (sym.kind == SymbolKind::Var && + IgnoreVar((const QueryVar::Def *)kv.first)))) + kv.first = nullptr; if (!kv.first) { kv.second.reset(); continue; @@ -198,12 +208,11 @@ struct Handler_TextDocumentDocumentSymbol if (refcnt <= 0) continue; if (std::optional info = GetSymbolInfo(db, sym, false)) { - if (sym.kind == SymbolKind::Var) { - QueryVar &var = db->GetVar(sym); - auto *def = var.AnyDef(); - if (!def || !def->spell || def->is_local()) - continue; - } + if ((sym.kind == SymbolKind::Type && + IgnoreType(db->GetType(sym).AnyDef())) || + (sym.kind == SymbolKind::Var && + IgnoreVar(db->GetVar(sym).AnyDef()))) + continue; if (std::optional location = GetLsLocation( db, working_files, Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) { From 32f7d148ca70c15382651df0adc6cb23a78fe89f Mon Sep 17 00:00:00 2001 From: Riatre Foo Date: Fri, 14 Sep 2018 05:01:37 +0800 Subject: [PATCH 51/66] Allow force disabling snippet via client.snippetSupport --- src/config.h | 4 ++-- src/messages/initialize.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config.h b/src/config.h index b8a4d05b..04d10c06 100644 --- a/src/config.h +++ b/src/config.h @@ -82,9 +82,9 @@ struct Config { struct ClientCapability { // TextDocumentClientCapabilities.documentSymbol.hierarchicalDocumentSymbolSupport - bool hierarchicalDocumentSymbolSupport = false; + bool hierarchicalDocumentSymbolSupport = true; // TextDocumentClientCapabilities.completion.completionItem.snippetSupport - bool snippetSupport = false; + bool snippetSupport = true; } client; struct CodeLens { diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index bce54fb9..cb795148 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -453,9 +453,9 @@ struct Handler_Initialize : BaseMessageHandler { // Client capabilities const auto &capabilities = params.capabilities; - g_config->client.snippetSupport = + g_config->client.snippetSupport &= capabilities.textDocument.completion.completionItem.snippetSupport; - g_config->client.hierarchicalDocumentSymbolSupport = + g_config->client.hierarchicalDocumentSymbolSupport &= capabilities.textDocument.documentSymbol.hierarchicalDocumentSymbolSupport; // Ensure there is a resource directory. From 854225bd3090e041bb5e00a5e8da2ba81b90c516 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 12:10:40 -0700 Subject: [PATCH 52/66] Misc Move using below #include to make preamble happy textDocument/references: if no references, first line or last line => list where this file is included malloc_trim() only if files have been indexed in last cycle Intern: use CachedHashStringRef --- src/clang_complete.cc | 4 ++- src/indexer.cc | 10 +++---- src/indexer.h | 1 - src/main.cc | 7 +++-- src/message_handler.h | 1 - src/messages/ccls_call.cc | 3 +- src/messages/ccls_member.cc | 5 ++-- src/messages/ccls_reload.cc | 7 ++--- src/messages/initialize.cc | 6 ++-- src/messages/textDocument_completion.cc | 12 +++----- src/messages/textDocument_definition.cc | 5 ++-- src/messages/textDocument_didClose.cc | 3 +- src/messages/textDocument_didOpen.cc | 3 +- src/messages/textDocument_didSave.cc | 3 +- src/messages/textDocument_references.cc | 15 ++++++---- src/messages/textDocument_signatureHelp.cc | 5 ++-- src/messages/workspace_symbol.cc | 3 +- src/pipeline.cc | 10 +++++-- src/platform_posix.cc | 2 +- src/project.cc | 12 ++++---- src/serializer.cc | 33 +++++++++++++--------- src/serializer.h | 8 +++++- 22 files changed, 87 insertions(+), 71 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index ab90d6b8..ee6386ed 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -175,7 +175,9 @@ std::unique_ptr BuildCompilerInstance( CompletionSession &session, std::unique_ptr CI, DiagnosticConsumer &DC, const WorkingFiles::Snapshot &snapshot, std::vector> &Bufs) { - std::string main = ResolveIfRelative(session.file.directory, CI->getFrontendOpts().Inputs[0].getFile()); + std::string main = ResolveIfRelative( + session.file.directory, + sys::path::convert_to_slash(CI->getFrontendOpts().Inputs[0].getFile())); for (auto &file : snapshot.files) { Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); if (file.filename == main) diff --git a/src/indexer.cc b/src/indexer.cc index 069f4e41..11fb859d 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -22,7 +22,6 @@ limitations under the License. #include "pipeline.hh" #include "platform.h" #include "serializer.h" -using namespace ccls; #include #include @@ -33,16 +32,15 @@ using namespace ccls; #include #include #include -#include -using namespace clang; -using llvm::Timer; #include #include -#include #include #include +using namespace ccls; +using namespace clang; + namespace { constexpr int kInitializerMaxLines = 3; @@ -509,7 +507,7 @@ public: def.short_name_offset = Str.size() + qualified.size() - short_name.size(); def.short_name_size = short_name.size(); Str += StringRef(qualified.data(), qualified.size()); - def.detailed_name = Intern(Str.str()); + def.detailed_name = Intern(Str); } else { SetName(D, short_name, qualified, def); } diff --git a/src/indexer.h b/src/indexer.h index 553ee640..f74e2f8c 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -30,7 +30,6 @@ limitations under the License. #include #include -#include #include #include #include diff --git a/src/main.cc b/src/main.cc index 55880343..4d2fb679 100644 --- a/src/main.cc +++ b/src/main.cc @@ -20,15 +20,12 @@ limitations under the License. #include "serializers/json.h" #include "test.h" #include "working_files.h" -using namespace ccls; #include #include #include #include #include -using namespace llvm; -using namespace llvm::cl; #include @@ -38,6 +35,10 @@ using namespace llvm::cl; #include #include +using namespace ccls; +using namespace llvm; +using namespace llvm::cl; + std::string g_init_options; namespace { diff --git a/src/message_handler.h b/src/message_handler.h index 1d790432..2e420dc3 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -87,7 +87,6 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting, jsonrpc, method, struct MessageHandler { DB *db = nullptr; - MultiQueueWaiter *waiter = nullptr; Project *project = nullptr; VFS *vfs = nullptr; SemanticHighlight *highlight = nullptr; diff --git a/src/messages/ccls_call.cc b/src/messages/ccls_call.cc index 98016480..0ec68f8b 100644 --- a/src/messages/ccls_call.cc +++ b/src/messages/ccls_call.cc @@ -17,10 +17,11 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include +using namespace ccls; + namespace { MethodType kMethodType = "$ccls/call"; diff --git a/src/messages/ccls_member.cc b/src/messages/ccls_member.cc index e95c7065..f17699e9 100644 --- a/src/messages/ccls_member.cc +++ b/src/messages/ccls_member.cc @@ -17,14 +17,15 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include #include -using namespace clang; #include +using namespace ccls; +using namespace clang; + namespace { MethodType kMethodType = "$ccls/member"; diff --git a/src/messages/ccls_reload.cc b/src/messages/ccls_reload.cc index 6a450655..67b97c25 100644 --- a/src/messages/ccls_reload.cc +++ b/src/messages/ccls_reload.cc @@ -17,14 +17,14 @@ limitations under the License. #include "match.h" #include "message_handler.h" #include "pipeline.hh" -#include "platform.h" #include "project.h" #include "working_files.h" -using namespace ccls; #include #include +using namespace ccls; + namespace { MethodType kMethodType = "$ccls/reload"; @@ -34,8 +34,7 @@ struct In_CclsReload : public NotificationInMessage { bool dependencies = true; std::vector whitelist; std::vector blacklist; - }; - Params params; + } params; }; MAKE_REFLECT_STRUCT(In_CclsReload::Params, dependencies, whitelist, blacklist); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index cb795148..d8039aee 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -23,16 +23,16 @@ limitations under the License. #include "project.h" #include "serializers/json.h" #include "working_files.h" -using namespace ccls; #include #include -using namespace llvm; -#include #include #include +using namespace ccls; +using namespace llvm; + // TODO Cleanup global variables extern std::string g_init_options; diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 474d1df8..411e4763 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -20,16 +20,16 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "working_files.h" -using namespace ccls; #include #include -#include -using namespace clang; -using namespace llvm; #include +using namespace ccls; +using namespace clang; +using namespace llvm; + namespace { MethodType kMethodType = "textDocument/completion"; @@ -179,10 +179,6 @@ void FilterAndSortCompletionResponse( const std::string &complete_text, bool has_open_paren) { if (!g_config->completion.filterAndSort) return; - - static Timer timer("FilterAndSortCompletionResponse", ""); - TimeRegion region(timer); - auto &items = complete_response->result.items; auto finalize = [&]() { diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 7cff442c..df28502d 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -16,11 +16,12 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; -#include #include #include +#include + +using namespace ccls; namespace { MethodType kMethodType = "textDocument/definition"; diff --git a/src/messages/textDocument_didClose.cc b/src/messages/textDocument_didClose.cc index c905f154..a7344e5d 100644 --- a/src/messages/textDocument_didClose.cc +++ b/src/messages/textDocument_didClose.cc @@ -26,8 +26,7 @@ struct In_TextDocumentDidClose : public NotificationInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { lsTextDocumentIdentifier textDocument; - }; - Params params; + } params; }; MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument); MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 27eb8f41..ec1b925a 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -24,7 +24,6 @@ using namespace ccls; namespace { MethodType kMethodType = "textDocument/didOpen"; -// Open, view, change, close file struct In_TextDocumentDidOpen : public NotificationInMessage { MethodType GetMethodType() const override { return kMethodType; } @@ -49,7 +48,7 @@ struct Handler_TextDocumentDidOpen // NOTE: This function blocks code lens. If it starts taking a long time // we will need to find a way to unblock the code lens request. const auto ¶ms = request->params; - std::string path = params.textDocument.uri.GetPath(); + const std::string &path = params.textDocument.uri.GetPath(); WorkingFile *working_file = working_files->OnOpen(params.textDocument); if (std::optional cached_file_contents = diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc index 87b7e793..f00ecc11 100644 --- a/src/messages/textDocument_didSave.cc +++ b/src/messages/textDocument_didSave.cc @@ -16,7 +16,6 @@ limitations under the License. #include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" -#include "project.h" using namespace ccls; namespace { @@ -44,7 +43,7 @@ struct Handler_TextDocumentDidSave void Run(In_TextDocumentDidSave *request) override { const auto ¶ms = request->params; - std::string path = params.textDocument.uri.GetPath(); + const std::string &path = params.textDocument.uri.GetPath(); pipeline::Index(path, {}, IndexMode::Normal); clang_complete->NotifySave(path); } diff --git a/src/messages/textDocument_references.cc b/src/messages/textDocument_references.cc index 0c73a405..f09adfc8 100644 --- a/src/messages/textDocument_references.cc +++ b/src/messages/textDocument_references.cc @@ -16,10 +16,11 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include +using namespace ccls; + namespace { MethodType kMethodType = "textDocument/references"; @@ -66,13 +67,17 @@ struct Handler_TextDocumentReferences if (!FindFileOrFail(db, project, request->id, params.textDocument.uri.GetPath(), &file)) return; - - WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); - Out_TextDocumentReferences out; out.id = request->id; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!file) { + pipeline::WriteStdout(kMethodType, out); + return; + } + bool container = g_config->xref.container; std::unordered_set seen_uses; + int line = params.position.line; for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position)) { // Found symbol. Return references. @@ -127,7 +132,7 @@ struct Handler_TextDocumentReferences // = 0, // use the current filename. std::string path; - if (params.position.line == 0) + if (line == 0 || line >= (int)wfile->buffer_lines.size() - 1) path = file->def->path; for (const IndexInclude &include : file->def->includes) if (include.line == params.position.line) { diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 007003db..1635cb35 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -16,12 +16,11 @@ limitations under the License. #include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" -using namespace ccls; #include -using namespace clang; -#include +using namespace ccls; +using namespace clang; namespace { MethodType kMethodType = "textDocument/signatureHelp"; diff --git a/src/messages/workspace_symbol.cc b/src/messages/workspace_symbol.cc index c78e9462..4758b38e 100644 --- a/src/messages/workspace_symbol.cc +++ b/src/messages/workspace_symbol.cc @@ -17,13 +17,14 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include #include #include #include +using namespace ccls; + namespace { MethodType kMethodType = "workspace/symbol"; diff --git a/src/pipeline.cc b/src/pipeline.cc index 9864a09b..4810c87c 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -490,7 +490,6 @@ void MainLoop() { // Setup shared references. for (MessageHandler *handler : *MessageHandler::message_handlers) { handler->db = &db; - handler->waiter = indexer_waiter; handler->project = &project; handler->vfs = &vfs; handler->highlight = &highlight; @@ -499,6 +498,7 @@ void MainLoop() { handler->include_complete = &include_complete; } + bool last_indexed = false; while (true) { std::vector> messages = on_request->DequeueAll(); bool did_work = messages.size(); @@ -515,18 +515,22 @@ void MainLoop() { LOG_S(ERROR) << "No handler for " << message->GetMethodType(); } - for (int i = 80; i--;) { + bool indexed = false; + for (int i = 20; i--;) { std::optional update = on_indexed->TryPopFront(); if (!update) break; did_work = true; + indexed = true; Main_OnIndexed(&db, &highlight, &working_files, &*update); } if (!did_work) { - FreeUnusedMemory(); + if (last_indexed) + FreeUnusedMemory(); main_waiter->Wait(on_indexed, on_request); } + last_indexed = indexed; } } diff --git a/src/platform_posix.cc b/src/platform_posix.cc index 4f48896c..1d2d59a9 100644 --- a/src/platform_posix.cc +++ b/src/platform_posix.cc @@ -113,7 +113,7 @@ std::string NormalizePath(const std::string &path) { void FreeUnusedMemory() { #ifdef __GLIBC__ - malloc_trim(0); + malloc_trim(4 * 1024 * 1024); #endif } diff --git a/src/project.cc b/src/project.cc index f4beb6c0..534d08fa 100644 --- a/src/project.cc +++ b/src/project.cc @@ -25,18 +25,14 @@ limitations under the License. #include "serializers/json.h" #include "utils.h" #include "working_files.h" -using namespace ccls; #include #include #include #include -#include #include #include #include -using namespace clang; -using namespace llvm; #include @@ -44,10 +40,14 @@ using namespace llvm; #include #endif -#include +#include #include #include +using namespace ccls; +using namespace clang; +using namespace llvm; + namespace { enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand }; @@ -399,7 +399,7 @@ Project::FindCompilationEntryForFile(const std::string &filename) { // We couldn't find the file. Try to infer it. // TODO: Cache inferred file in a separate array (using a lock or similar) Entry *best_entry = nullptr; - int best_score = std::numeric_limits::min(); + int best_score = INT_MIN; for (Entry &entry : entries) { int score = ComputeGuessScore(filename, entry.filename); if (score > best_score) { diff --git a/src/serializer.cc b/src/serializer.cc index 8faf8ebd..68c80493 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -166,12 +166,11 @@ void Reflect(Reader &vis, DenseMap &v) { if (vis.Format() == SerializeFormat::Json) { auto &vis1 = static_cast(vis); for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it) - v[CachedHashStringRef(Intern(it->name.GetString()))] = - it->value.GetInt64(); + v[InternH(it->name.GetString())] = it->value.GetInt64(); } else { vis.IterArray([&](Reader &entry) { Reflect(entry, name); - Reflect(entry, v[CachedHashStringRef(Intern(name))]); + Reflect(entry, v[InternH(name)]); }); } } @@ -356,18 +355,26 @@ void Reflect(Writer &visitor, SerializeFormat &value) { namespace ccls { static BumpPtrAllocator Alloc; -static DenseSet Strings; +static DenseSet Strings; static std::mutex AllocMutex; -const char *Intern(const std::string &str) { - if (str.empty()) - return ""; - StringRef Str(str.data(), str.size() + 1); +CachedHashStringRef InternH(StringRef S) { + if (S.empty()) + S = ""; + CachedHashString HS(S); std::lock_guard lock(AllocMutex); - auto R = Strings.insert(Str); - if (R.second) - *R.first = Str.copy(Alloc); - return R.first->data(); + auto R = Strings.insert(HS); + if (R.second) { + char *P = Alloc.Allocate(S.size() + 1); + memcpy(P, S.data(), S.size()); + P[S.size()] = '\0'; + *R.first = CachedHashStringRef(StringRef(P, S.size()), HS.hash()); + } + return *R.first; +} + +const char *Intern(StringRef S) { + return InternH(S).val().data(); } std::string Serialize(SerializeFormat format, IndexFile &file) { @@ -482,7 +489,7 @@ Deserialize(SerializeFormat format, const std::string &path, for (auto &it : file->dependencies) { std::string path = it.first.val().str(); DoPathMapping(path); - dependencies[CachedHashStringRef(Intern(path))] = it.second; + dependencies[InternH(path)] = it.second; } file->dependencies = std::move(dependencies); } diff --git a/src/serializer.h b/src/serializer.h index 7e248715..5e05a475 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -30,6 +30,11 @@ limitations under the License. #include #include +namespace llvm { +class CachedHashStringRef; +class StringRef; +} + enum class SerializeFormat { Binary, Json }; struct JsonNull {}; @@ -320,7 +325,8 @@ template void ReflectMember(Writer &vis, const char *name, T &v) { // API namespace ccls { -const char *Intern(const std::string &str); +const char *Intern(llvm::StringRef str); +llvm::CachedHashStringRef InternH(llvm::StringRef str); std::string Serialize(SerializeFormat format, IndexFile &file); std::unique_ptr Deserialize(SerializeFormat format, const std::string &path, From 8f40c0c2442572e4960b267fbaa63a068c81037d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 13:31:06 -0700 Subject: [PATCH 53/66] Remove clang_utils.* --- CMakeLists.txt | 1 - src/clang_complete.cc | 5 +- src/clang_complete.hh | 2 +- src/clang_tu.cc | 171 ++++++++++++++++++++++++++++- src/{clang_tu.h => clang_tu.hh} | 6 +- src/clang_utils.cc | 187 -------------------------------- src/clang_utils.h | 25 ----- src/indexer.cc | 12 +- src/indexer.h | 2 +- src/messages/ccls_member.cc | 1 + src/project.cc | 1 - 11 files changed, 183 insertions(+), 230 deletions(-) rename src/{clang_tu.h => clang_tu.hh} (92%) delete mode 100644 src/clang_utils.cc delete mode 100644 src/clang_utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3985e129..6b447d76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,7 +181,6 @@ target_sources(ccls PRIVATE third_party/siphash.cc) target_sources(ccls PRIVATE src/clang_complete.cc src/clang_tu.cc - src/clang_utils.cc src/config.cc src/filesystem.cc src/fuzzy_match.cc diff --git a/src/clang_complete.cc b/src/clang_complete.cc index ee6386ed..d5efae38 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -15,13 +15,12 @@ limitations under the License. #include "clang_complete.hh" -#include "clang_utils.h" +#include "clang_tu.hh" #include "filesystem.hh" #include "log.hh" #include "match.h" #include "platform.h" -#include #include #include #include @@ -108,7 +107,7 @@ public: auto it = FID2concerned.try_emplace(FID.getHashValue()); if (it.second) { const FileEntry *FE = SM.getFileEntryForID(FID); - it.first->second = FE && FileName(*FE) == path; + it.first->second = FE && PathFromFileEntry(*FE) == path; } return it.first->second; } diff --git a/src/clang_complete.hh b/src/clang_complete.hh index 45d16dcd..7020ab4d 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -15,7 +15,7 @@ limitations under the License. #pragma once -#include "clang_tu.h" +#include "clang_tu.hh" #include "lru_cache.h" #include "lsp_completion.h" #include "lsp_diagnostic.h" diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 53645489..f147b4c2 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -13,16 +13,32 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_tu.h" +#include "clang_tu.hh" -#include "clang_utils.h" #include "config.h" +#include "platform.h" +#include #include +#include + +#include + using namespace clang; -#include -#include +std::string PathFromFileEntry(const FileEntry &file) { + StringRef Name = file.tryGetRealPathName(); + if (Name.empty()) + Name = file.getName(); + std::string ret = NormalizePath(Name); + // Resolve /usr/include/c++/7.3.0 symlink. + if (!StartsWith(ret, g_config->projectRoot)) { + SmallString<256> dest; + llvm::sys::fs::real_path(ret, dest); + ret = llvm::sys::path::convert_to_slash(dest.str()); + } + return ret; +} Range FromCharSourceRange(const SourceManager &SM, const LangOptions &LangOpts, CharSourceRange R, @@ -81,3 +97,150 @@ BuildCompilerInvocation(std::vector args, } return CI; } + +// clang::BuiltinType::getName without PrintingPolicy +const char *ClangBuiltinTypeName(int kind) { + switch (BuiltinType::Kind(kind)) { + case BuiltinType::Void: + return "void"; + case BuiltinType::Bool: + return "bool"; + case BuiltinType::Char_S: + return "char"; + case BuiltinType::Char_U: + return "char"; + case BuiltinType::SChar: + return "signed char"; + case BuiltinType::Short: + return "short"; + case BuiltinType::Int: + return "int"; + case BuiltinType::Long: + return "long"; + case BuiltinType::LongLong: + return "long long"; + case BuiltinType::Int128: + return "__int128"; + case BuiltinType::UChar: + return "unsigned char"; + case BuiltinType::UShort: + return "unsigned short"; + case BuiltinType::UInt: + return "unsigned int"; + case BuiltinType::ULong: + return "unsigned long"; + case BuiltinType::ULongLong: + return "unsigned long long"; + case BuiltinType::UInt128: + return "unsigned __int128"; + case BuiltinType::Half: + return "__fp16"; + case BuiltinType::Float: + return "float"; + case BuiltinType::Double: + return "double"; + case BuiltinType::LongDouble: + return "long double"; +#if LLVM_VERSION_MAJOR >= 7 + case BuiltinType::ShortAccum: + return "short _Accum"; + case BuiltinType::Accum: + return "_Accum"; + case BuiltinType::LongAccum: + return "long _Accum"; + case BuiltinType::UShortAccum: + return "unsigned short _Accum"; + case BuiltinType::UAccum: + return "unsigned _Accum"; + case BuiltinType::ULongAccum: + return "unsigned long _Accum"; + case BuiltinType::BuiltinType::ShortFract: + return "short _Fract"; + case BuiltinType::BuiltinType::Fract: + return "_Fract"; + case BuiltinType::BuiltinType::LongFract: + return "long _Fract"; + case BuiltinType::BuiltinType::UShortFract: + return "unsigned short _Fract"; + case BuiltinType::BuiltinType::UFract: + return "unsigned _Fract"; + case BuiltinType::BuiltinType::ULongFract: + return "unsigned long _Fract"; + case BuiltinType::BuiltinType::SatShortAccum: + return "_Sat short _Accum"; + case BuiltinType::BuiltinType::SatAccum: + return "_Sat _Accum"; + case BuiltinType::BuiltinType::SatLongAccum: + return "_Sat long _Accum"; + case BuiltinType::BuiltinType::SatUShortAccum: + return "_Sat unsigned short _Accum"; + case BuiltinType::BuiltinType::SatUAccum: + return "_Sat unsigned _Accum"; + case BuiltinType::BuiltinType::SatULongAccum: + return "_Sat unsigned long _Accum"; + case BuiltinType::BuiltinType::SatShortFract: + return "_Sat short _Fract"; + case BuiltinType::BuiltinType::SatFract: + return "_Sat _Fract"; + case BuiltinType::BuiltinType::SatLongFract: + return "_Sat long _Fract"; + case BuiltinType::BuiltinType::SatUShortFract: + return "_Sat unsigned short _Fract"; + case BuiltinType::BuiltinType::SatUFract: + return "_Sat unsigned _Fract"; + case BuiltinType::BuiltinType::SatULongFract: + return "_Sat unsigned long _Fract"; +#endif + case BuiltinType::Float16: + return "_Float16"; + case BuiltinType::Float128: + return "__float128"; + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + return "wchar_t"; +#if LLVM_VERSION_MAJOR >= 7 + case BuiltinType::Char8: + return "char8_t"; +#endif + case BuiltinType::Char16: + return "char16_t"; + case BuiltinType::Char32: + return "char32_t"; + case BuiltinType::NullPtr: + return "nullptr_t"; + case BuiltinType::Overload: + return ""; + case BuiltinType::BoundMember: + return ""; + case BuiltinType::PseudoObject: + return ""; + case BuiltinType::Dependent: + return ""; + case BuiltinType::UnknownAny: + return ""; + case BuiltinType::ARCUnbridgedCast: + return ""; + case BuiltinType::BuiltinFn: + return ""; + case BuiltinType::ObjCId: + return "id"; + case BuiltinType::ObjCClass: + return "Class"; + case BuiltinType::ObjCSel: + return "SEL"; + case BuiltinType::OCLSampler: + return "sampler_t"; + case BuiltinType::OCLEvent: + return "event_t"; + case BuiltinType::OCLClkEvent: + return "clk_event_t"; + case BuiltinType::OCLQueue: + return "queue_t"; + case BuiltinType::OCLReserveID: + return "reserve_id_t"; + case BuiltinType::OMPArraySection: + return ""; + default: + return ""; + } +} diff --git a/src/clang_tu.h b/src/clang_tu.hh similarity index 92% rename from src/clang_tu.h rename to src/clang_tu.hh index 1edcd5ee..96325466 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.hh @@ -14,13 +14,15 @@ limitations under the License. ==============================================================================*/ #pragma once + #include "position.h" #include +#include #include #include -#include +std::string PathFromFileEntry(const clang::FileEntry &file); Range FromCharSourceRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, @@ -38,3 +40,5 @@ Range FromTokenRange(const clang::SourceManager &SM, std::unique_ptr BuildCompilerInvocation(std::vector args, llvm::IntrusiveRefCntPtr VFS); + +const char *ClangBuiltinTypeName(int); diff --git a/src/clang_utils.cc b/src/clang_utils.cc deleted file mode 100644 index a58237e1..00000000 --- a/src/clang_utils.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_utils.h" - -#include "config.h" -#include "filesystem.hh" -#include "platform.h" -#include "utils.h" - -#include -#include -using namespace clang; -using namespace llvm; - -std::string FileName(const FileEntry &file) { - StringRef Name = file.tryGetRealPathName(); - if (Name.empty()) - Name = file.getName(); - std::string ret = NormalizePath(Name); - // Resolve /usr/include/c++/7.3.0 symlink. - if (!StartsWith(ret, g_config->projectRoot)) { - SmallString<256> dest; - sys::fs::real_path(ret, dest); - ret = sys::path::convert_to_slash(dest.str()); - } - return ret; -} - -// clang::BuiltinType::getName without PrintingPolicy -const char *ClangBuiltinTypeName(int kind) { - switch (BuiltinType::Kind(kind)) { - case BuiltinType::Void: - return "void"; - case BuiltinType::Bool: - return "bool"; - case BuiltinType::Char_S: - return "char"; - case BuiltinType::Char_U: - return "char"; - case BuiltinType::SChar: - return "signed char"; - case BuiltinType::Short: - return "short"; - case BuiltinType::Int: - return "int"; - case BuiltinType::Long: - return "long"; - case BuiltinType::LongLong: - return "long long"; - case BuiltinType::Int128: - return "__int128"; - case BuiltinType::UChar: - return "unsigned char"; - case BuiltinType::UShort: - return "unsigned short"; - case BuiltinType::UInt: - return "unsigned int"; - case BuiltinType::ULong: - return "unsigned long"; - case BuiltinType::ULongLong: - return "unsigned long long"; - case BuiltinType::UInt128: - return "unsigned __int128"; - case BuiltinType::Half: - return "__fp16"; - case BuiltinType::Float: - return "float"; - case BuiltinType::Double: - return "double"; - case BuiltinType::LongDouble: - return "long double"; -#if LLVM_VERSION_MAJOR >= 7 - case BuiltinType::ShortAccum: - return "short _Accum"; - case BuiltinType::Accum: - return "_Accum"; - case BuiltinType::LongAccum: - return "long _Accum"; - case BuiltinType::UShortAccum: - return "unsigned short _Accum"; - case BuiltinType::UAccum: - return "unsigned _Accum"; - case BuiltinType::ULongAccum: - return "unsigned long _Accum"; - case BuiltinType::BuiltinType::ShortFract: - return "short _Fract"; - case BuiltinType::BuiltinType::Fract: - return "_Fract"; - case BuiltinType::BuiltinType::LongFract: - return "long _Fract"; - case BuiltinType::BuiltinType::UShortFract: - return "unsigned short _Fract"; - case BuiltinType::BuiltinType::UFract: - return "unsigned _Fract"; - case BuiltinType::BuiltinType::ULongFract: - return "unsigned long _Fract"; - case BuiltinType::BuiltinType::SatShortAccum: - return "_Sat short _Accum"; - case BuiltinType::BuiltinType::SatAccum: - return "_Sat _Accum"; - case BuiltinType::BuiltinType::SatLongAccum: - return "_Sat long _Accum"; - case BuiltinType::BuiltinType::SatUShortAccum: - return "_Sat unsigned short _Accum"; - case BuiltinType::BuiltinType::SatUAccum: - return "_Sat unsigned _Accum"; - case BuiltinType::BuiltinType::SatULongAccum: - return "_Sat unsigned long _Accum"; - case BuiltinType::BuiltinType::SatShortFract: - return "_Sat short _Fract"; - case BuiltinType::BuiltinType::SatFract: - return "_Sat _Fract"; - case BuiltinType::BuiltinType::SatLongFract: - return "_Sat long _Fract"; - case BuiltinType::BuiltinType::SatUShortFract: - return "_Sat unsigned short _Fract"; - case BuiltinType::BuiltinType::SatUFract: - return "_Sat unsigned _Fract"; - case BuiltinType::BuiltinType::SatULongFract: - return "_Sat unsigned long _Fract"; -#endif - case BuiltinType::Float16: - return "_Float16"; - case BuiltinType::Float128: - return "__float128"; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - return "wchar_t"; -#if LLVM_VERSION_MAJOR >= 7 - case BuiltinType::Char8: - return "char8_t"; -#endif - case BuiltinType::Char16: - return "char16_t"; - case BuiltinType::Char32: - return "char32_t"; - case BuiltinType::NullPtr: - return "nullptr_t"; - case BuiltinType::Overload: - return ""; - case BuiltinType::BoundMember: - return ""; - case BuiltinType::PseudoObject: - return ""; - case BuiltinType::Dependent: - return ""; - case BuiltinType::UnknownAny: - return ""; - case BuiltinType::ARCUnbridgedCast: - return ""; - case BuiltinType::BuiltinFn: - return ""; - case BuiltinType::ObjCId: - return "id"; - case BuiltinType::ObjCClass: - return "Class"; - case BuiltinType::ObjCSel: - return "SEL"; - case BuiltinType::OCLSampler: - return "sampler_t"; - case BuiltinType::OCLEvent: - return "event_t"; - case BuiltinType::OCLClkEvent: - return "clk_event_t"; - case BuiltinType::OCLQueue: - return "queue_t"; - case BuiltinType::OCLReserveID: - return "reserve_id_t"; - case BuiltinType::OMPArraySection: - return ""; - default: - return ""; - } -} diff --git a/src/clang_utils.h b/src/clang_utils.h deleted file mode 100644 index 769412a9..00000000 --- a/src/clang_utils.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include - -#include - -// Returns the absolute path to |file|. -std::string FileName(const clang::FileEntry &file); - -const char *ClangBuiltinTypeName(int); diff --git a/src/indexer.cc b/src/indexer.cc index 11fb859d..6383c375 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -16,7 +16,7 @@ limitations under the License. #include "indexer.h" #include "clang_complete.hh" -#include "clang_tu.h" +#include "clang_tu.hh" #include "log.hh" #include "match.h" #include "pipeline.hh" @@ -73,7 +73,7 @@ struct IndexParam { // generating an index for it): auto [it, inserted] = UID2File.try_emplace(File.getUniqueID()); if (inserted) { - std::string path = FileName(File); + std::string path = PathFromFileEntry(File); it->second.path = path; it->second.mtime = File.getModificationTime(); if (!it->second.mtime) @@ -97,7 +97,7 @@ struct IndexParam { bool UseMultiVersion(const FileEntry &FE) { auto it = UID2multi.try_emplace(FE.getUniqueID()); if (it.second) - it.first->second = multiVersionMatcher->IsMatch(FileName(FE)); + it.first->second = multiVersionMatcher->IsMatch(PathFromFileEntry(FE)); return it.first->second; } }; @@ -1099,9 +1099,9 @@ public: if (!FE) return; if (IndexFile *db = param.ConsumeFile(*FE)) { - std::string file_name = FileName(*File); - if (file_name.size()) - db->includes.push_back({spell.start.line, Intern(file_name)}); + std::string path = PathFromFileEntry(*File); + if (path.size()) + db->includes.push_back({spell.start.line, Intern(path)}); } } void MacroDefined(const Token &Tok, const MacroDirective *MD) override { diff --git a/src/indexer.h b/src/indexer.h index f74e2f8c..0e6f4e71 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -15,7 +15,6 @@ limitations under the License. #pragma once -#include "clang_utils.h" #include "language.h" #include "lsp.h" #include "lsp_diagnostic.h" @@ -25,6 +24,7 @@ limitations under the License. #include "symbol.h" #include "utils.h" +#include #include #include #include diff --git a/src/messages/ccls_member.cc b/src/messages/ccls_member.cc index f17699e9..47241aad 100644 --- a/src/messages/ccls_member.cc +++ b/src/messages/ccls_member.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_tu.hh" #include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" diff --git a/src/project.cc b/src/project.cc index 534d08fa..c2c44b0c 100644 --- a/src/project.cc +++ b/src/project.cc @@ -15,7 +15,6 @@ limitations under the License. #include "project.h" -#include "clang_utils.h" #include "filesystem.hh" #include "language.h" #include "log.hh" From ce68028caf9d358304863bab10ffd876bc7e5b04 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 16:15:10 -0700 Subject: [PATCH 54/66] Add GetAdjustedDecl to adjust Decl's that are missed by clangIndex --- index_tests/multi_file/impl.cc | 4 +- index_tests/multi_file/static.cc | 4 +- .../outline/static_function_in_type.cc | 4 +- .../func_specialized_template_param.cc | 17 +- .../templates/specialized_func_definition.cc | 4 +- ...ype_usage_as_template_parameter_complex.cc | 32 +--- .../type_usage_typedef_and_using_template.cc | 38 +---- src/indexer.cc | 154 +++++++++--------- 8 files changed, 95 insertions(+), 162 deletions(-) diff --git a/index_tests/multi_file/impl.cc b/index_tests/multi_file/impl.cc index 1ef51a20..dc754b8c 100644 --- a/index_tests/multi_file/impl.cc +++ b/index_tests/multi_file/impl.cc @@ -215,8 +215,8 @@ OUTPUT: impl.cc "callees": ["4:3-4:7|11650481237659640387|3|16420"] }, { "usr": 11650481237659640387, - "detailed_name": "template<> void Foo1()", - "qual_name_offset": 16, + "detailed_name": "void Foo1()", + "qual_name_offset": 5, "short_name": "Foo1", "kind": 12, "storage": 0, diff --git a/index_tests/multi_file/static.cc b/index_tests/multi_file/static.cc index 7f8d6c72..50096fb2 100644 --- a/index_tests/multi_file/static.cc +++ b/index_tests/multi_file/static.cc @@ -50,8 +50,8 @@ OUTPUT: static.cc "skipped_ranges": [], "usr2func": [{ "usr": 14576076421851654759, - "detailed_name": "void Buffer::CreateSharedBuffer()", - "qual_name_offset": 5, + "detailed_name": "static void Buffer::CreateSharedBuffer()", + "qual_name_offset": 12, "short_name": "CreateSharedBuffer", "kind": 254, "storage": 0, diff --git a/index_tests/outline/static_function_in_type.cc b/index_tests/outline/static_function_in_type.cc index 7bf971e6..c29aae07 100644 --- a/index_tests/outline/static_function_in_type.cc +++ b/index_tests/outline/static_function_in_type.cc @@ -84,8 +84,8 @@ OUTPUT: static_function_in_type.cc "skipped_ranges": [], "usr2func": [{ "usr": 17019747379608639279, - "detailed_name": "void Foo::Register(ns::Manager *m)", - "qual_name_offset": 5, + "detailed_name": "static void ns::Foo::Register(ns::Manager *)", + "qual_name_offset": 12, "short_name": "Register", "kind": 254, "storage": 0, diff --git a/index_tests/templates/func_specialized_template_param.cc b/index_tests/templates/func_specialized_template_param.cc index 32222811..af88d365 100644 --- a/index_tests/templates/func_specialized_template_param.cc +++ b/index_tests/templates/func_specialized_template_param.cc @@ -29,21 +29,6 @@ OUTPUT: "callees": [] }], "usr2type": [{ - "usr": 2100211316767379401, - "detailed_name": "template<> class Template", - "qual_name_offset": 17, - "short_name": "Template", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["5:12-5:20|15041163540773201510|2|4|-1", "8:15-8:23|0|1|4|-1"] - }, { "usr": 15041163540773201510, "detailed_name": "struct Foo {}", "qual_name_offset": 7, @@ -76,7 +61,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": [] + "uses": ["5:12-5:20|15041163540773201510|2|4|-1", "8:15-8:23|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/templates/specialized_func_definition.cc b/index_tests/templates/specialized_func_definition.cc index 17dfb783..1397ba80 100644 --- a/index_tests/templates/specialized_func_definition.cc +++ b/index_tests/templates/specialized_func_definition.cc @@ -24,8 +24,8 @@ OUTPUT: "skipped_ranges": [], "usr2func": [{ "usr": 6995843774014807426, - "detailed_name": "template <> void Template::Foo()", - "qual_name_offset": 31, + "detailed_name": "void Template::Foo()", + "qual_name_offset": 5, "short_name": "Foo", "kind": 6, "storage": 0, diff --git a/index_tests/usage/type_usage_as_template_parameter_complex.cc b/index_tests/usage/type_usage_as_template_parameter_complex.cc index a49ccb84..3ed6d40d 100644 --- a/index_tests/usage/type_usage_as_template_parameter_complex.cc +++ b/index_tests/usage/type_usage_as_template_parameter_complex.cc @@ -159,21 +159,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["15:30-15:32|0|1|4|-1", "33:23-33:25|0|1|4|-1", "33:63-33:65|0|1|4|-1", "54:25-54:27|18320186404467436976|3|4|-1", "65:14-65:16|15041163540773201510|2|4|-1", "79:12-79:14|0|1|4|-1"] - }, { - "usr": 7147635971744144194, - "detailed_name": "template<> class unique_ptr", - "qual_name_offset": 17, - "short_name": "unique_ptr", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["15:19-15:29|0|1|4|-1", "33:12-33:22|0|1|4|-1", "33:52-33:62|0|1|4|-1", "54:14-54:24|18320186404467436976|3|4|-1", "65:3-65:13|15041163540773201510|2|4|-1", "79:1-79:11|0|1|4|-1"] }, { "usr": 12728490517004312484, "detailed_name": "struct S2", @@ -203,7 +188,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [2933643612409209903, 500112618220246], - "uses": [] + "uses": ["15:8-15:18|0|1|4|-1", "15:19-15:29|0|1|4|-1", "33:1-33:11|0|1|4|-1", "33:12-33:22|0|1|4|-1", "33:52-33:62|0|1|4|-1", "54:3-54:13|18320186404467436976|3|4|-1", "54:14-54:24|18320186404467436976|3|4|-1", "65:3-65:13|15041163540773201510|2|4|-1", "79:1-79:11|0|1|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "class Foo {}", @@ -221,21 +206,6 @@ OUTPUT: "vars": [], "instances": [], "uses": ["79:21-79:24|0|1|4|-1"] - }, { - "usr": 18153735331422331128, - "detailed_name": "template<> class unique_ptr, S2>", - "qual_name_offset": 17, - "short_name": "unique_ptr", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["15:8-15:18|0|1|4|-1", "33:1-33:11|0|1|4|-1", "54:3-54:13|18320186404467436976|3|4|-1"] }], "usr2var": [{ "usr": 500112618220246, diff --git a/index_tests/usage/type_usage_typedef_and_using_template.cc b/index_tests/usage/type_usage_typedef_and_using_template.cc index e7043557..3c742067 100644 --- a/index_tests/usage/type_usage_typedef_and_using_template.cc +++ b/index_tests/usage/type_usage_typedef_and_using_template.cc @@ -19,7 +19,7 @@ OUTPUT: "declarations": [], "spell": "4:7-4:11|0|1|2|-1", "extent": "4:1-4:22|0|1|0|-1", - "alias_of": 5123806965838456033, + "alias_of": 10528472276654770367, "bases": [], "derived": [], "types": [], @@ -27,27 +27,12 @@ OUTPUT: "vars": [], "instances": [], "uses": ["5:13-5:17|0|1|4|-1"] - }, { - "usr": 5123806965838456033, - "detailed_name": "template<> struct Foo", - "qual_name_offset": 18, - "short_name": "Foo", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["4:14-4:17|0|1|4|-1"] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo", "qual_name_offset": 7, "short_name": "Foo", - "kind": 23, + "kind": 5, "declarations": ["2:8-2:11|2:1-2:11|0|1|1|-1"], "alias_of": 0, "bases": [], @@ -56,22 +41,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": [] - }, { - "usr": 14491685842684954828, - "detailed_name": "template<> struct Foo>", - "qual_name_offset": 18, - "short_name": "Foo", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["5:9-5:12|0|1|4|-1"] + "uses": ["4:14-4:17|0|1|4|-1", "5:9-5:12|0|1|4|-1"] }, { "usr": 15933698173231330933, "detailed_name": "typedef Foo Foo2", @@ -81,7 +51,7 @@ OUTPUT: "declarations": [], "spell": "5:19-5:23|0|1|2|-1", "extent": "5:1-5:23|0|1|0|-1", - "alias_of": 14491685842684954828, + "alias_of": 10528472276654770367, "bases": [], "derived": [], "types": [], diff --git a/src/indexer.cc b/src/indexer.cc index 6383c375..14c1905a 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -296,6 +296,35 @@ try_again: return D; } +const Decl *GetAdjustedDecl(const Decl *D) { + while (D) { + if (auto *R = dyn_cast(D)) { + if (auto *S = dyn_cast(R)) { + if (!S->getTypeAsWritten()) { + llvm::PointerUnion + Result = S->getSpecializedTemplateOrPartial(); + if (Result.is()) + D = Result.get(); + else + D = Result.get(); + continue; + } + } else if (auto *D1 = R->getInstantiatedFromMemberClass()) { + D = D1; + continue; + } + } else if (auto *ED = dyn_cast(D)) { + if (auto *D1 = ED->getInstantiatedFromMemberEnum()) { + D = D1; + continue; + } + } + break; + } + return D; +} + bool ValidateRecord(const RecordDecl *RD) { for (const auto *I : RD->fields()) { QualType FQT = I->getType(); @@ -636,11 +665,12 @@ public: return true; } + // spell, extent, comments use OrigD while most others use adjusted |D|. const Decl *OrigD = ASTNode.OrigD; const DeclContext *SemDC = OrigD->getDeclContext(); const DeclContext *LexDC = ASTNode.ContainerDC; Role role = static_cast(Roles); - db->language = LanguageId((int)db->language | (int)GetDeclLanguage(OrigD)); + db->language = LanguageId((int)db->language | (int)GetDeclLanguage(D)); bool is_decl = Roles & uint32_t(index::SymbolRole::Declaration); bool is_def = Roles & uint32_t(index::SymbolRole::Definition); @@ -650,11 +680,9 @@ public: IndexType *type = nullptr; IndexVar *var = nullptr; SymbolKind kind = GetSymbolKind(D); - IndexParam::DeclInfo *info; - Usr usr = GetUsr(D, &info); if (is_def) - switch (OrigD->getKind()) { + switch (D->getKind()) { case Decl::CXXConversion: // *operator* int => *operator int* case Decl::CXXDestructor: // *~*A => *~A* case Decl::CXXMethod: // *operator*= => *operator=* @@ -669,6 +697,15 @@ public: default: break; } + else { + // e.g. typedef Foo gg; => Foo has an unadjusted `D` + const Decl *D1 = GetAdjustedDecl(D); + if (D1 && D1 != D) + D = D1; + } + + IndexParam::DeclInfo *info; + Usr usr = GetUsr(D, &info); auto do_def_decl = [&](auto *entity) { if (is_def) { @@ -708,7 +745,7 @@ public: if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Func, Spell); if (func->def.detailed_name[0] == '\0') - SetName(OrigD, info->short_name, info->qualified, func->def); + SetName(D, info->short_name, info->qualified, func->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); if (GetSymbolKind(DC) == SymbolKind::Type) @@ -726,7 +763,7 @@ public: if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Type, Spell); if (type->def.detailed_name[0] == '\0' && info->short_name.size()) - SetName(OrigD, info->short_name, info->qualified, type->def); + SetName(D, info->short_name, info->qualified, type->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); if (GetSymbolKind(DC) == SymbolKind::Type) @@ -739,7 +776,7 @@ public: if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Var, Spell); if (var->def.detailed_name[0] == '\0') - SetVarName(OrigD, info->short_name, info->qualified, var->def); + SetVarName(D, info->short_name, info->qualified, var->def); QualType T; if (auto *VD = dyn_cast(D)) T = VD->getType(); @@ -756,63 +793,44 @@ public: Usr usr1 = static_cast(BT->getKind()); var->def.type = usr1; db->ToType(usr1).instances.push_back(usr); - } else { - for (const Decl *D1 = GetTypeDecl(T); D1; ) { - if (auto *R1 = dyn_cast(D1)) { - if (auto *S1 = dyn_cast(D1)) { - if (!S1->getTypeAsWritten()) { - llvm::PointerUnion - Result = S1->getSpecializedTemplateOrPartial(); - if (Result.is()) - D1 = Result.get(); - else - D1 = Result.get(); - continue; - } - } else if (auto *D2 = R1->getInstantiatedFromMemberClass()) { - D1 = D2; - continue; - } - } else if (auto *TP1 = dyn_cast(D1)) { - // e.g. TemplateTypeParmDecl is not handled by - // handleDeclOccurence. - SourceRange R1 = D1->getSourceRange(); - if (SM.getFileID(R1.getBegin()) == LocFID) { - IndexParam::DeclInfo *info1; - Usr usr1 = GetUsr(D1, &info1); - IndexType &type1 = db->ToType(usr1); - SourceLocation L1 = D1->getLocation(); - type1.def.spell = - GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, - Role::Definition); - type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), - LexDC, Role::None); - type1.def.detailed_name = Intern(info1->short_name); - type1.def.short_name_size = int16_t(info1->short_name.size()); - type1.def.kind = lsSymbolKind::TypeParameter; - var->def.type = usr1; - type1.instances.push_back(usr); - break; - } + } else if (const Decl *D1 = GetAdjustedDecl(GetTypeDecl(T))) { + if (isa(D1)) { + // e.g. TemplateTypeParmDecl is not handled by + // handleDeclOccurence. + SourceRange R1 = D1->getSourceRange(); + if (SM.getFileID(R1.getBegin()) == LocFID) { + IndexParam::DeclInfo *info1; + Usr usr1 = GetUsr(D1, &info1); + IndexType &type1 = db->ToType(usr1); + SourceLocation L1 = D1->getLocation(); + type1.def.spell = + GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, + Role::Definition); + type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), + LexDC, Role::None); + type1.def.detailed_name = Intern(info1->short_name); + type1.def.short_name_size = int16_t(info1->short_name.size()); + type1.def.kind = lsSymbolKind::TypeParameter; + var->def.type = usr1; + type1.instances.push_back(usr); + break; } - - IndexParam::DeclInfo *info1; - Usr usr1 = GetUsr(D1, &info1); - var->def.type = usr1; - db->ToType(usr1).instances.push_back(usr); - break; } + + IndexParam::DeclInfo *info1; + Usr usr1 = GetUsr(D1, &info1); + var->def.type = usr1; + db->ToType(usr1).instances.push_back(usr); } } } else if (!var->def.spell && var->declarations.empty()) { // e.g. lambda parameter - SourceLocation L = OrigD->getLocation(); + SourceLocation L = D->getLocation(); if (SM.getFileID(L) == LocFID) { var->def.spell = GetUse(db, lid, FromTokenRange(SM, Lang, {L, L}), SemDC, Role::Definition); var->def.extent = - GetUse(db, lid, FromTokenRange(SM, Lang, OrigD->getSourceRange()), + GetUse(db, lid, FromTokenRange(SM, Lang, D->getSourceRange()), LexDC, Role::None); } } @@ -822,8 +840,8 @@ public: switch (D->getKind()) { case Decl::Namespace: type->def.kind = lsSymbolKind::Namespace; - if (OrigD->isFirstDecl()) { - auto *ND = cast(OrigD); + if (D->isFirstDecl()) { + auto *ND = cast(D); auto *ND1 = cast(ND->getParent()); if (isa(ND1)) { Usr usr1 = GetUsr(ND1); @@ -874,29 +892,19 @@ public: break; case Decl::CXXRecord: if (is_def) { - auto *RD = dyn_cast(OrigD); - if (RD && RD->hasDefinition()) { - for (const CXXBaseSpecifier &Base : RD->bases()) { - QualType T = Base.getType(); - const NamedDecl *BaseD = nullptr; - if (auto *TDT = T->getAs()) { - BaseD = TDT->getDecl(); - } else if (auto *TST = T->getAs()) { - BaseD = TST->getTemplateName().getAsTemplateDecl(); - } else if (auto *RT = T->getAs()) { - BaseD = RT->getDecl(); - } - if (BaseD) { + auto *RD = dyn_cast(D); + if (RD && RD->hasDefinition()) + for (const CXXBaseSpecifier &Base : RD->bases()) + if (const Decl *BaseD = + GetAdjustedDecl(GetTypeDecl(Base.getType()))) { Usr usr1 = GetUsr(BaseD); type->def.bases.push_back(usr1); db->ToType(usr1).derived.push_back(usr); } - } - } } [[fallthrough]]; case Decl::Record: - if (auto *RD = dyn_cast(OrigD)) { + if (auto *RD = dyn_cast(D)) { // spec has no Union, use Class type->def.kind = RD->getTagKind() == TTK_Struct ? lsSymbolKind::Struct : lsSymbolKind::Class; @@ -979,7 +987,7 @@ public: if (auto *TD = dyn_cast(D)) { bool specialization = false; QualType T = TD->getUnderlyingType(); - if (const Decl *D1 = GetTypeDecl(T, &specialization)) { + if (const Decl *D1 = GetAdjustedDecl(GetTypeDecl(T, &specialization))) { Usr usr1 = GetUsr(D1); IndexType &type1 = db->ToType(usr1); type->def.alias_of = usr1; From eb644bb78ee38cbb2ec5032090743cf77a292760 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 18:45:41 -0700 Subject: [PATCH 55/66] Add index.initial{Blacklist,Whitelist} index.{blacklist,whitelist}: disable indexes thoroughly index.initial{Blacklist,Whitelist}: disable initial loading. will still be indexed after opening --- src/config.h | 9 ++++++++- src/project.cc | 31 ++++++++++++++----------------- src/project.h | 4 ---- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/config.h b/src/config.h index 04d10c06..2219a8a1 100644 --- a/src/config.h +++ b/src/config.h @@ -204,6 +204,12 @@ struct Config { // If false, the indexer will be disabled. bool enabled = true; + // By default, all project entries will be indexed on initialization. Use + // these two options to exclude some. They can still be indexed after you + // open them. + std::vector initialBlacklist; + std::vector initialWhitelist; + // If not 0, a file will be indexed in each tranlation unit that includes it. int multiVersion = 0; @@ -259,7 +265,8 @@ MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, spellChecking, whitelist) MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) -MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, multiVersion, +MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, + initialBlacklist, initialWhitelist, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, reparseForDependency, threads, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); diff --git a/src/project.cc b/src/project.cc index c2c44b0c..70802538 100644 --- a/src/project.cc +++ b/src/project.cc @@ -433,28 +433,25 @@ Project::FindCompilationEntryForFile(const std::string &filename) { return result; } -void Project::ForAllFilteredFiles( - std::function action) { - GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); +void Project::Index(WorkingFiles *wfiles, lsRequestId id) { + auto &gi = g_config->index; + GroupMatch match(gi.whitelist, gi.blacklist), + match_i(gi.initialWhitelist, gi.initialBlacklist); for (int i = 0; i < entries.size(); ++i) { const Project::Entry &entry = entries[i]; - std::string failure_reason; - if (matcher.IsMatch(entry.filename, &failure_reason)) - action(i, entries[i]); - else { - LOG_V(1) << "[" << i + 1 << "/" << entries.size() << "]: Failed " - << failure_reason << "; skipping " << entry.filename; + std::string reason; + if (match.IsMatch(entry.filename, &reason) && + match_i.IsMatch(entry.filename, &reason)) { + bool interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; + pipeline::Index( + entry.filename, entry.args, + interactive ? IndexMode::Normal : IndexMode::NonInteractive, id); + } else { + LOG_V(1) << "[" << i << "/" << entries.size() << "]: " << reason + << "; skip " << entry.filename; } } -} -void Project::Index(WorkingFiles *wfiles, lsRequestId id) { - ForAllFilteredFiles([&](int i, const Project::Entry &entry) { - bool interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; - pipeline::Index(entry.filename, entry.args, - interactive ? IndexMode::Normal : IndexMode::NonInteractive, - id); - }); pipeline::loaded_ts = pipeline::tick; // Dummy request to indicate that project is loaded and // trigger refreshing semantic highlight for all working files. diff --git a/src/project.h b/src/project.h index e5582a40..125b2af0 100644 --- a/src/project.h +++ b/src/project.h @@ -67,9 +67,5 @@ struct Project { void SetArgsForFile(const std::vector &args, const std::string &path); - // Run |action| on every file in the project. - void - ForAllFilteredFiles(std::function action); - void Index(WorkingFiles *wfiles, lsRequestId id); }; From 0eb9428a321791a6eea2c078f9a52bb7f8fd7cc3 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Sep 2018 23:02:19 -0700 Subject: [PATCH 56/66] Add index.trackDependency and improve pipeline --- src/config.h | 10 +++---- src/pipeline.cc | 72 ++++++++++++++++++++++++++++--------------------- src/pipeline.hh | 4 ++- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/src/config.h b/src/config.h index 2219a8a1..4ff79a92 100644 --- a/src/config.h +++ b/src/config.h @@ -222,13 +222,13 @@ struct Config { // May be too slow for big projects, so it is off by default. bool onChange = false; + // Number of indexer threads. If 0, 80% of cores are used. + int threads = 0; + // Whether to reparse a file if write times of its dependencies have // changed. The file will always be reparsed if its own write time changes. // 0: no, 1: only after initial load of project, 2: yes - int reparseForDependency = 2; - - // Number of indexer threads. If 0, 80% of cores are used. - int threads = 0; + int trackDependency = 2; std::vector whitelist; } index; @@ -268,7 +268,7 @@ MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, initialBlacklist, initialWhitelist, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, - reparseForDependency, threads, whitelist); + threads, trackDependency, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, diff --git a/src/pipeline.cc b/src/pipeline.cc index 4810c87c..4fd30320 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -62,7 +62,8 @@ bool VFS::Stamp(const std::string &path, int64_t ts, int step) { namespace ccls::pipeline { -int64_t loaded_ts = 0, tick = 0; +std::atomic loaded_ts = ATOMIC_VAR_INIT(0); +int64_t tick = 0; namespace { @@ -199,7 +200,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (!mtime1) return true; if (vfs->Stamp(request.path, *mtime1, 0)) - reparse = 1; + reparse = 2; } if (g_config->index.onChange) { reparse = 2; @@ -208,45 +209,55 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (request.path != path_to_index) vfs->state[request.path].step = 0; } - if (!reparse) + bool track = g_config->index.trackDependency > 1 || + (g_config->index.trackDependency == 1 && request.ts < loaded_ts); + if (!reparse && !track) return true; - if (reparse < 2) do { - std::unique_lock lock( + if (reparse < 2) + do { + std::unique_lock lock( mutexes[std::hash()(path_to_index) % N_MUTEXES]); - prev = RawCacheLoad(path_to_index); - if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, - std::nullopt)) - break; - bool update = false; - for (const auto &dep : prev->dependencies) - if (auto mtime1 = LastWriteTime(dep.first.val().str())) { - if (dep.second < *mtime1) - update = true; - } else { - update = true; - } - int forDep = g_config->index.reparseForDependency; - if (update && (forDep > 1 || (forDep == 1 && request.ts < loaded_ts))) - break; + prev = RawCacheLoad(path_to_index); + if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, + std::nullopt)) + break; + if (track) + for (const auto &dep : prev->dependencies) { + if (auto mtime1 = LastWriteTime(dep.first.val().str())) { + if (dep.second < *mtime1) { + reparse = 2; + break; + } + } else { + reparse = 2; + break; + } + } + if (reparse == 0) + return true; + if (reparse == 2) + break; - if (reparse < 2) { + if (vfs->Loaded(path_to_index)) + return true; LOG_S(INFO) << "load cache for " << path_to_index; auto dependencies = prev->dependencies; - if (reparse) { - if (vfs->Loaded(path_to_index)) - return true; - IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); + { std::lock_guard lock1(vfs->mutex); vfs->state[path_to_index].loaded = true; } lock.unlock(); + for (const auto &dep : dependencies) { std::string path = dep.first.val().str(); + if (!vfs->Stamp(path, dep.second, 1)) + continue; std::lock_guard lock1( - mutexes[std::hash()(path) % N_MUTEXES]); + mutexes[std::hash()(path) % N_MUTEXES]); prev = RawCacheLoad(path); if (!prev) continue; @@ -260,15 +271,14 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, } IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + request.mode != IndexMode::NonInteractive); if (entry.id >= 0) { std::lock_guard lock2(project->mutex_); project->path_to_entry_index[path] = entry.id; } } return true; - } - } while (0); + } while (0); LOG_IF_S(INFO, loud) << "parse " << path_to_index; diff --git a/src/pipeline.hh b/src/pipeline.hh index 920053c8..a232d513 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -4,6 +4,7 @@ #include "method.h" #include "query.h" +#include #include #include #include @@ -38,7 +39,8 @@ enum class IndexMode { }; namespace pipeline { -extern int64_t loaded_ts, tick; +extern std::atomic loaded_ts; +extern int64_t tick; void Init(); void LaunchStdin(); void LaunchStdout(); From 41fcc0272c8c93fcbe52f24ef587e633a9dcc7e1 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 24 Sep 2018 10:56:29 -0700 Subject: [PATCH 57/66] Simplify semantic highlighting; improve hover of auto && --- src/indexer.cc | 3 +- src/message_handler.cc | 51 ++++++++-------------------- src/message_handler.h | 16 ++------- src/messages/initialize.cc | 1 - src/messages/textDocument_didOpen.cc | 2 +- src/pipeline.cc | 23 ++++++------- 6 files changed, 31 insertions(+), 65 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index 14c1905a..9299b4aa 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -524,7 +524,8 @@ public: binding = true; } auto BT = GetBaseType(T, false); - if (!BT.isNull() && (binding || BT->getAs())) { + if (!BT.isNull() && + (binding || BT.getUnqualifiedType()->getAs())) { SmallString<256> Str; llvm::raw_svector_ostream OS(Str); PrintingPolicy PP = GetDefaultPolicy(); diff --git a/src/message_handler.cc b/src/message_handler.cc index aa2924a3..e1721976 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -60,34 +60,6 @@ struct ScanLineEvent { }; } // namespace -int SemanticHighlight::GetStableId(SymbolKind kind, Usr usr) { - decltype(func2id) *map; - switch (kind) { - case SymbolKind::Func: - map = &func2id; - break; - case SymbolKind::Type: - map = &type2id; - break; - case SymbolKind::Var: - map = &var2id; - break; - case SymbolKind::File: - case SymbolKind::Invalid: - llvm_unreachable(""); - } - - auto it = map->try_emplace(usr, next_id); - if (it.second) - next_id++; - return it.first->second; -} - -void SemanticHighlight::Init() { - match_ = std::make_unique(g_config->highlight.whitelist, - g_config->highlight.blacklist); -} - MessageHandler::MessageHandler() { // Dynamically allocate |message_handlers|, otherwise there will be static // initialization order races. @@ -157,11 +129,12 @@ void EmitSkippedRanges(WorkingFile *working_file, pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out); } -void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, - WorkingFile *wfile, QueryFile *file) { +void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { + static GroupMatch match(g_config->highlight.whitelist, + g_config->highlight.blacklist); assert(file->def); if (wfile->buffer_content.size() > g_config->largeFileSize || - !highlight->match_->IsMatch(file->def->path)) + !match.IsMatch(file->def->path)) return; // Group symbols together. @@ -174,10 +147,12 @@ void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, lsSymbolKind parent_kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown; uint8_t storage = SC_None; + int idx; // This switch statement also filters out symbols that are not highlighted. switch (sym.kind) { case SymbolKind::Func: { - const QueryFunc &func = db->GetFunc(sym); + idx = db->func_usr[sym.usr]; + const QueryFunc &func = db->funcs[idx]; const QueryFunc::Def *def = func.AnyDef(); if (!def) continue; // applies to for loop @@ -218,8 +193,10 @@ void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, sym.range.end.column = start_col + concise_name.size(); break; } - case SymbolKind::Type: - for (auto &def : db->GetType(sym).def) { + case SymbolKind::Type: { + idx = db->type_usr[sym.usr]; + const QueryType &type = db->types[idx]; + for (auto &def : type.def) { kind = def.kind; detailed_name = def.detailed_name; if (def.spell) { @@ -228,8 +205,10 @@ void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, } } break; + } case SymbolKind::Var: { - const QueryVar &var = db->GetVar(sym); + idx = db->var_usr[sym.usr]; + const QueryVar &var = db->vars[idx]; for (auto &def : var.def) { kind = def.kind; storage = def.storage; @@ -258,7 +237,7 @@ void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, it->second.lsRanges.push_back(*loc); } else { Out_CclsPublishSemanticHighlighting::Symbol symbol; - symbol.stableId = highlight->GetStableId(sym.kind, sym.usr); + symbol.stableId = idx; symbol.parentKind = parent_kind; symbol.kind = kind; symbol.storage = storage; diff --git a/src/message_handler.h b/src/message_handler.h index 2e420dc3..38074f64 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -36,17 +36,6 @@ struct DB; struct WorkingFile; struct WorkingFiles; -// Caches symbols for a single file for semantic highlighting to provide -// relatively stable ids. Only supports xxx files at a time. -struct SemanticHighlight { - llvm::DenseMap func2id, type2id, var2id; - uint32_t next_id = 0; - std::unique_ptr match_; - - void Init(); - int GetStableId(SymbolKind kind, Usr usr); -}; - struct Out_CclsPublishSemanticHighlighting : public lsOutMessage { struct Symbol { @@ -89,7 +78,6 @@ struct MessageHandler { DB *db = nullptr; Project *project = nullptr; VFS *vfs = nullptr; - SemanticHighlight *highlight = nullptr; WorkingFiles *working_files = nullptr; CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; @@ -119,5 +107,5 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, void EmitSkippedRanges(WorkingFile *working_file, const std::vector &skipped_ranges); -void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, - WorkingFile *working_file, QueryFile *file); +void EmitSemanticHighlighting(DB *db, WorkingFile *working_file, + QueryFile *file); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index d8039aee..18205038 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -487,7 +487,6 @@ struct Handler_Initialize : BaseMessageHandler { } idx::Init(); - highlight->Init(); // Open up / load the project. project->Load(project_path); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index ec1b925a..4c9acd8a 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -59,7 +59,7 @@ struct Handler_TextDocumentDidOpen FindFileOrFail(db, project, std::nullopt, path, &file); if (file && file->def) { EmitSkippedRanges(working_file, file->def->skipped_ranges); - EmitSemanticHighlighting(db, highlight, working_file, file); + EmitSemanticHighlighting(db, working_file, file); } include_complete->AddFile(working_file->filename); diff --git a/src/pipeline.cc b/src/pipeline.cc index 4fd30320..59101324 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -368,8 +368,7 @@ void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, indexer_waiter->Wait(index_request); } -void Main_OnIndexed(DB *db, SemanticHighlight *highlight, - WorkingFiles *working_files, IndexUpdate *update) { +void Main_OnIndexed(DB *db, WorkingFiles *working_files, IndexUpdate *update) { if (update->refresh) { LOG_S(INFO) << "loaded project. Refresh semantic highlight for all working file."; @@ -379,7 +378,7 @@ void Main_OnIndexed(DB *db, SemanticHighlight *highlight, if (db->name2file_id.find(filename) == db->name2file_id.end()) continue; QueryFile *file = &db->files[db->name2file_id[filename]]; - EmitSemanticHighlighting(db, highlight, f.get(), file); + EmitSemanticHighlighting(db, f.get(), file); } return; } @@ -399,8 +398,7 @@ void Main_OnIndexed(DB *db, SemanticHighlight *highlight, wfile->SetIndexContent(g_config->index.onChange ? wfile->buffer_content : def_u.second); EmitSkippedRanges(wfile, def_u.first.skipped_ranges); - EmitSemanticHighlighting(db, highlight, wfile, - &db->files[update->file_id]); + EmitSemanticHighlighting(db, wfile, &db->files[update->file_id]); } } } @@ -470,7 +468,6 @@ void LaunchStdout() { void MainLoop() { Project project; - SemanticHighlight highlight; WorkingFiles working_files; VFS vfs; @@ -502,13 +499,12 @@ void MainLoop() { handler->db = &db; handler->project = &project; handler->vfs = &vfs; - handler->highlight = &highlight; handler->working_files = &working_files; handler->clang_complete = &clang_complete; handler->include_complete = &include_complete; } - bool last_indexed = false; + bool has_indexed = false; while (true) { std::vector> messages = on_request->DequeueAll(); bool did_work = messages.size(); @@ -532,15 +528,18 @@ void MainLoop() { break; did_work = true; indexed = true; - Main_OnIndexed(&db, &highlight, &working_files, &*update); + Main_OnIndexed(&db, &working_files, &*update); } - if (!did_work) { - if (last_indexed) + if (did_work) + has_indexed |= indexed; + else { + if (has_indexed) { FreeUnusedMemory(); + has_indexed = false; + } main_waiter->Wait(on_indexed, on_request); } - last_indexed = indexed; } } From d6ad864f11e36752c47de6169f8fee4f5eef33ac Mon Sep 17 00:00:00 2001 From: Amos Bird Date: Thu, 27 Sep 2018 08:47:03 +0800 Subject: [PATCH 58/66] Update threaded_queue.h (#82) https://en.cppreference.com/w/cpp/language/fold --- src/threaded_queue.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/threaded_queue.h b/src/threaded_queue.h index c14307a3..d72f06d7 100644 --- a/src/threaded_queue.h +++ b/src/threaded_queue.h @@ -48,8 +48,7 @@ private: } template void unlock_impl(std::index_sequence) { - (void)std::initializer_list{ - (std::get(tuple_)->mutex_.unlock(), 0)...}; + (std::get(tuple_)->mutex_.unlock(), ...); } std::tuple tuple_; From 05109b6fa460ecf7f596fdf4a641c18433d2f5fd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 27 Sep 2018 22:16:42 -0700 Subject: [PATCH 59/66] Merge textDocument_did{Change,Close,Open,Save}.cc --- CMakeLists.txt | 5 +- src/messages/textDocument_did.cc | 165 +++++++++++++++++++++++++ src/messages/textDocument_didChange.cc | 50 -------- src/messages/textDocument_didClose.cc | 53 -------- src/messages/textDocument_didOpen.cc | 80 ------------ src/messages/textDocument_didSave.cc | 52 -------- 6 files changed, 166 insertions(+), 239 deletions(-) create mode 100644 src/messages/textDocument_did.cc delete mode 100644 src/messages/textDocument_didChange.cc delete mode 100644 src/messages/textDocument_didClose.cc delete mode 100644 src/messages/textDocument_didOpen.cc delete mode 100644 src/messages/textDocument_didSave.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b447d76..fca0ff41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,10 +221,7 @@ target_sources(ccls PRIVATE src/messages/textDocument_codeLens.cc src/messages/textDocument_completion.cc src/messages/textDocument_definition.cc - src/messages/textDocument_didChange.cc - src/messages/textDocument_didClose.cc - src/messages/textDocument_didOpen.cc - src/messages/textDocument_didSave.cc + src/messages/textDocument_did.cc src/messages/textDocument_documentHighlight.cc src/messages/textDocument_documentSymbol.cc src/messages/textDocument_hover.cc diff --git a/src/messages/textDocument_did.cc b/src/messages/textDocument_did.cc new file mode 100644 index 00000000..5a069ee2 --- /dev/null +++ b/src/messages/textDocument_did.cc @@ -0,0 +1,165 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "clang_complete.hh" +#include "include_complete.h" +#include "message_handler.h" +#include "pipeline.hh" +#include "project.h" +#include "working_files.h" +using namespace ccls; + +namespace { +MethodType didChange = "textDocument/didChange"; +MethodType didClose = "textDocument/didClose"; +MethodType didOpen = "textDocument/didOpen"; +MethodType didSave = "textDocument/didSave"; + +struct In_TextDocumentDidChange : public NotificationInMessage { + MethodType GetMethodType() const override { return didChange; } + lsTextDocumentDidChangeParams params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidChange, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidChange); + +struct Handler_TextDocumentDidChange + : BaseMessageHandler { + MethodType GetMethodType() const override { return didChange; } + + void Run(In_TextDocumentDidChange *request) override { + const auto ¶ms = request->params; + std::string path = params.textDocument.uri.GetPath(); + working_files->OnChange(params); + if (g_config->index.onChange) + pipeline::Index(path, {}, IndexMode::OnChange); + clang_complete->NotifyView(path); + if (g_config->diagnostics.onChange >= 0) + clang_complete->DiagnosticsUpdate(path, g_config->diagnostics.onChange); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); + +struct In_TextDocumentDidClose : public NotificationInMessage { + MethodType GetMethodType() const override { return didClose; } + struct Params { + lsTextDocumentIdentifier textDocument; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument); +MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidClose); + +struct Handler_TextDocumentDidClose + : BaseMessageHandler { + MethodType GetMethodType() const override { return didClose; } + + void Run(In_TextDocumentDidClose *request) override { + std::string path = request->params.textDocument.uri.GetPath(); + + // Clear any diagnostics for the file. + Out_TextDocumentPublishDiagnostics out; + out.params.uri = request->params.textDocument.uri; + pipeline::WriteStdout(didClose, out); + + // Remove internal state. + working_files->OnClose(request->params.textDocument); + clang_complete->OnClose(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose); + +struct In_TextDocumentDidOpen : public NotificationInMessage { + MethodType GetMethodType() const override { return didOpen; } + + struct Params { + lsTextDocumentItem textDocument; + + // ccls extension + // If specified (e.g. ["clang++", "-DM", "a.cc"]), it overrides the project + // entry (e.g. loaded from compile_commands.json or .ccls). + std::vector args; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen::Params, textDocument, args); +MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidOpen); + +struct Handler_TextDocumentDidOpen + : BaseMessageHandler { + MethodType GetMethodType() const override { return didOpen; } + + void Run(In_TextDocumentDidOpen *request) override { + // NOTE: This function blocks code lens. If it starts taking a long time + // we will need to find a way to unblock the code lens request. + const auto ¶ms = request->params; + const std::string &path = params.textDocument.uri.GetPath(); + + WorkingFile *working_file = working_files->OnOpen(params.textDocument); + if (std::optional cached_file_contents = + pipeline::LoadIndexedContent(path)) + working_file->SetIndexContent(*cached_file_contents); + + QueryFile *file = nullptr; + FindFileOrFail(db, project, std::nullopt, path, &file); + if (file && file->def) { + EmitSkippedRanges(working_file, file->def->skipped_ranges); + EmitSemanticHighlighting(db, working_file, file); + } + + include_complete->AddFile(working_file->filename); + std::vector args; + for (const std::string &arg : params.args) + args.push_back(Intern(arg)); + if (args.size()) + project->SetArgsForFile(args, path); + + // Submit new index request if it is not a header file. + if (SourceFileLanguage(path) != LanguageId::Unknown) + pipeline::Index(path, args, IndexMode::Normal); + + clang_complete->NotifyView(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); + +struct In_TextDocumentDidSave : public NotificationInMessage { + MethodType GetMethodType() const override { return didSave; } + + struct Params { + // The document that was saved. + lsTextDocumentIdentifier textDocument; + + // Optional the content when saved. Depends on the includeText value + // when the save notifcation was requested. + // std::string text; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidSave::Params, textDocument); +MAKE_REFLECT_STRUCT(In_TextDocumentDidSave, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidSave); + +struct Handler_TextDocumentDidSave + : BaseMessageHandler { + MethodType GetMethodType() const override { return didSave; } + + void Run(In_TextDocumentDidSave *request) override { + const auto ¶ms = request->params; + const std::string &path = params.textDocument.uri.GetPath(); + pipeline::Index(path, {}, IndexMode::Normal); + clang_complete->NotifySave(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); +} // namespace diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc deleted file mode 100644 index 76bdef49..00000000 --- a/src/messages/textDocument_didChange.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.hh" -#include "message_handler.h" -#include "pipeline.hh" -#include "project.h" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didChange"; - -struct In_TextDocumentDidChange : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentDidChangeParams params; -}; - -MAKE_REFLECT_STRUCT(In_TextDocumentDidChange, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidChange); - -struct Handler_TextDocumentDidChange - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidChange *request) override { - const auto ¶ms = request->params; - std::string path = params.textDocument.uri.GetPath(); - working_files->OnChange(params); - if (g_config->index.onChange) - pipeline::Index(path, {}, IndexMode::OnChange); - clang_complete->NotifyView(path); - if (g_config->diagnostics.onChange >= 0) - clang_complete->DiagnosticsUpdate(path, g_config->diagnostics.onChange); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); -} // namespace diff --git a/src/messages/textDocument_didClose.cc b/src/messages/textDocument_didClose.cc deleted file mode 100644 index a7344e5d..00000000 --- a/src/messages/textDocument_didClose.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.hh" -#include "message_handler.h" -#include "pipeline.hh" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didClose"; - -struct In_TextDocumentDidClose : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - struct Params { - lsTextDocumentIdentifier textDocument; - } params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument); -MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidClose); - -struct Handler_TextDocumentDidClose - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidClose *request) override { - std::string path = request->params.textDocument.uri.GetPath(); - - // Clear any diagnostics for the file. - Out_TextDocumentPublishDiagnostics out; - out.params.uri = request->params.textDocument.uri; - pipeline::WriteStdout(kMethodType, out); - - // Remove internal state. - working_files->OnClose(request->params.textDocument); - clang_complete->OnClose(path); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose); -} // namespace diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc deleted file mode 100644 index 4c9acd8a..00000000 --- a/src/messages/textDocument_didOpen.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.hh" -#include "include_complete.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "project.h" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didOpen"; - -struct In_TextDocumentDidOpen : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - struct Params { - lsTextDocumentItem textDocument; - - // ccls extension - // If specified (e.g. ["clang++", "-DM", "a.cc"]), it overrides the project - // entry (e.g. loaded from compile_commands.json or .ccls). - std::vector args; - } params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen::Params, textDocument, args); -MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidOpen); - -struct Handler_TextDocumentDidOpen - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidOpen *request) override { - // NOTE: This function blocks code lens. If it starts taking a long time - // we will need to find a way to unblock the code lens request. - const auto ¶ms = request->params; - const std::string &path = params.textDocument.uri.GetPath(); - - WorkingFile *working_file = working_files->OnOpen(params.textDocument); - if (std::optional cached_file_contents = - pipeline::LoadIndexedContent(path)) - working_file->SetIndexContent(*cached_file_contents); - - QueryFile *file = nullptr; - FindFileOrFail(db, project, std::nullopt, path, &file); - if (file && file->def) { - EmitSkippedRanges(working_file, file->def->skipped_ranges); - EmitSemanticHighlighting(db, working_file, file); - } - - include_complete->AddFile(working_file->filename); - std::vector args; - for (const std::string &arg : params.args) - args.push_back(Intern(arg)); - if (args.size()) - project->SetArgsForFile(args, path); - - // Submit new index request if it is not a header file. - if (SourceFileLanguage(path) != LanguageId::Unknown) - pipeline::Index(path, args, IndexMode::Normal); - - clang_complete->NotifyView(path); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); -} // namespace diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc deleted file mode 100644 index f00ecc11..00000000 --- a/src/messages/textDocument_didSave.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.hh" -#include "message_handler.h" -#include "pipeline.hh" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didSave"; - -struct In_TextDocumentDidSave : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - struct Params { - // The document that was saved. - lsTextDocumentIdentifier textDocument; - - // Optional the content when saved. Depends on the includeText value - // when the save notifcation was requested. - // std::string text; - } params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidSave::Params, textDocument); -MAKE_REFLECT_STRUCT(In_TextDocumentDidSave, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidSave); - -struct Handler_TextDocumentDidSave - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidSave *request) override { - const auto ¶ms = request->params; - const std::string &path = params.textDocument.uri.GetPath(); - pipeline::Index(path, {}, IndexMode::Normal); - clang_complete->NotifySave(path); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); -} // namespace From a127ca9b0246210195a857cc790311c29d472d32 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 27 Sep 2018 22:19:26 -0700 Subject: [PATCH 60/66] Support textDocument/{formatting,onTypeFormatting,rangeFormatting} --- CMakeLists.txt | 1 + README.md | 3 +- cmake/FindClang.cmake | 10 ++ src/messages/initialize.cc | 11 +- src/messages/textDocument_formatting.cc | 204 ++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 7 deletions(-) create mode 100644 src/messages/textDocument_formatting.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index fca0ff41..384c008f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,7 @@ target_sources(ccls PRIVATE src/messages/textDocument_completion.cc src/messages/textDocument_definition.cc src/messages/textDocument_did.cc + src/messages/textDocument_formatting.cc src/messages/textDocument_documentHighlight.cc src/messages/textDocument_documentSymbol.cc src/messages/textDocument_hover.cc diff --git a/README.md b/README.md index e3349def..2a0c70fa 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ ccls, which originates from [cquery](https://github.com/cquery-project/cquery), * code completion (with both signature help and snippets) * [definition](src/messages/textDocument_definition.cc)/[references](src/messages/textDcument_references.cc), and other cross references * cross reference extensions: `$ccls/call` `$ccls/inheritance` `$ccls/member` `$ccls/vars` ... + * formatting * hierarchies: [call (caller/callee) hierarchy](src/messages/ccls_call.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritance.cc), [member hierarchy](src/messages/ccls_member.cc) * [symbol rename](src/messages/textDocument_rename.cc) * [document symbols](src/messages/textDocument_documentSymbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) @@ -22,7 +23,7 @@ Saving files will incrementally update the index. Compared with cquery, it makes use of C++17 features, has less third-party dependencies and slimmed-down code base. It leverages Clang C++ API as [clangd](https://clang.llvm.org/extra/clangd.html) does, which provides better support for code completion and diagnostics. -Refactoring and formatting are non-goals as they can be provided by clang-format, clang-include-fixer and other Clang based tools. +Refactoring is a non-goal as it can be provided by clang-include-fixer and other Clang based tools. The comparison with cquery as noted on 2018-07-15: diff --git a/cmake/FindClang.cmake b/cmake/FindClang.cmake index e4286d51..e56e25dd 100644 --- a/cmake/FindClang.cmake +++ b/cmake/FindClang.cmake @@ -69,7 +69,17 @@ set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR) _Clang_find_library(Clang_LIBRARY clangIndex) +_Clang_find_add_library(clangFormat) _Clang_find_add_library(clangTooling) + +# TODO Remove after dropping clang 6 +_Clang_find_library(clangToolingInclusions_LIBRARY clangToolingInclusions) +if (clangToolingInclusions_LIBRARY) + list(APPEND _Clang_LIBRARIES ${clangToolingInclusions_LIBRARY}) +endif() + +_Clang_find_add_library(clangToolingCore) +_Clang_find_add_library(clangRewrite) _Clang_find_add_library(clangFrontend) _Clang_find_add_library(clangParse) _Clang_find_add_library(clangSerialization) diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 18205038..7d9ea978 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -66,7 +66,7 @@ MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters); // Format document on type options struct lsDocumentOnTypeFormattingOptions { // A character on which formatting should be triggered, like `}`. - std::string firstTriggerCharacter; + std::string firstTriggerCharacter = "}"; // More trigger characters. std::vector moreTriggerCharacter; @@ -77,7 +77,7 @@ MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter, // Document link options struct lsDocumentLinkOptions { // Document links have a resolve provider as well. - bool resolveProvider = true; + bool resolveProvider = false; }; MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, resolveProvider); @@ -170,12 +170,11 @@ struct lsServerCapabilities { // The server provides code lens. lsCodeLensOptions codeLensProvider; // The server provides document formatting. - bool documentFormattingProvider = false; + bool documentFormattingProvider = true; // The server provides document range formatting. - bool documentRangeFormattingProvider = false; + bool documentRangeFormattingProvider = true; // The server provides document formatting on typing. - std::optional - documentOnTypeFormattingProvider; + lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider; // The server provides rename support. bool renameProvider = true; // The server provides document link support. diff --git a/src/messages/textDocument_formatting.cc b/src/messages/textDocument_formatting.cc new file mode 100644 index 00000000..1676a9b5 --- /dev/null +++ b/src/messages/textDocument_formatting.cc @@ -0,0 +1,204 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "working_files.h" + +#include +#include + +using namespace ccls; +using namespace clang; + +namespace { +const MethodType formatting = "textDocument/formatting", + onTypeFormatting = "textDocument/onTypeFormatting", + rangeFormatting = "textDocument/rangeFormatting"; + +struct lsFormattingOptions { + // Size of a tab in spaces. + int tabSize; + // Prefer spaces over tabs. + bool insertSpaces; +}; +MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces); + +struct Out_TextDocumentFormatting + : public lsOutMessage { + lsRequestId id; + std::vector result; +}; +MAKE_REFLECT_STRUCT(Out_TextDocumentFormatting, jsonrpc, id, result); + +llvm::Expected +FormatCode(std::string_view code, std::string_view file, tooling::Range Range) { + StringRef Code(code.data(), code.size()), File(file.data(), file.size()); + auto Style = format::getStyle("file", File, "LLVM", Code, nullptr); + if (!Style) + return Style.takeError(); + tooling::Replacements IncludeReplaces = + format::sortIncludes(*Style, Code, {Range}, File); + auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces); + if (!Changed) + return Changed.takeError(); + return IncludeReplaces.merge(format::reformat( + *Style, *Changed, + tooling::calculateRangesAfterReplacements(IncludeReplaces, {Range}), + File)); +} + +std::vector +ReplacementsToEdits(std::string_view code, const tooling::Replacements &Repls) { + std::vector ret; + int i = 0, line = 0, col = 0; + auto move = [&](int p) { + for (; i < p; i++) + if (code[i] == '\n') + line++, col = 0; + else { + if ((uint8_t)code[i] >= 128) { + while (128 <= (uint8_t)code[++i] && (uint8_t)code[i] < 192) + ; + i--; + } + col++; + } + }; + for (const auto &R : Repls) { + move(R.getOffset()); + int l = line, c = col; + move(R.getOffset() + R.getLength()); + ret.push_back({{{l, c}, {line, col}}, R.getReplacementText().str()}); + } + return ret; +} + +void Format(WorkingFile *wfile, tooling::Range range, lsRequestId id) { + std::string_view code = wfile->buffer_content; + auto ReplsOrErr = + FormatCode(code, wfile->filename, range); + if (ReplsOrErr) { + Out_TextDocumentFormatting out; + out.id = id; + out.result = ReplacementsToEdits(code, *ReplsOrErr); + pipeline::WriteStdout(formatting, out); + } else { + Out_Error err; + err.id = id; + err.error.code = lsErrorCodes::UnknownErrorCode; + err.error.message = llvm::toString(ReplsOrErr.takeError()); + pipeline::WriteStdout(kMethodType_Unknown, err); + } +} + +struct In_TextDocumentFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return formatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentFormatting::Params, textDocument, options); +MAKE_REFLECT_STRUCT(In_TextDocumentFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentFormatting); + +struct Handler_TextDocumentFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return formatting; } + void Run(In_TextDocumentFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + Format(wfile, {0, (unsigned)wfile->buffer_content.size()}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentFormatting); + +struct In_TextDocumentOnTypeFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return onTypeFormatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsPosition position; + std::string ch; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentOnTypeFormatting::Params, textDocument, + position, ch, options); +MAKE_REFLECT_STRUCT(In_TextDocumentOnTypeFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentOnTypeFormatting); + +struct Handler_TextDocumentOnTypeFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return onTypeFormatting; } + void Run(In_TextDocumentOnTypeFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + std::string_view code = wfile->buffer_content; + int pos = GetOffsetForPosition(params.position, code); + auto lbrace = code.find_last_of('{', pos); + if (lbrace == std::string::npos) + lbrace = pos; + Format(wfile, {(unsigned)lbrace, unsigned(pos - lbrace)}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentOnTypeFormatting); + +struct In_TextDocumentRangeFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return rangeFormatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsRange range; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentRangeFormatting::Params, textDocument, range, + options); +MAKE_REFLECT_STRUCT(In_TextDocumentRangeFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentRangeFormatting); + +struct Handler_TextDocumentRangeFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return rangeFormatting; } + + void Run(In_TextDocumentRangeFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + std::string_view code = wfile->buffer_content; + int begin = GetOffsetForPosition(params.range.start, code), + end = GetOffsetForPosition(params.range.end, code); + Format(wfile, {(unsigned)begin, unsigned(end - begin)}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRangeFormatting); +} // namespace From d4871207ed44c8e5edf0961ae7736c24075486ba Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 28 Sep 2018 13:41:50 -0700 Subject: [PATCH 61/66] Construct SourceManager with UserFilesAreVolatile Prettify pipeline --- src/clang_complete.cc | 6 ++++++ src/pipeline.cc | 16 +++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index d5efae38..6a785470 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -202,6 +202,12 @@ std::unique_ptr BuildCompilerInstance( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); if (!Clang->hasTarget()) return nullptr; + // 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. + Clang->createFileManager(); + Clang->setSourceManager(new SourceManager(Clang->getDiagnostics(), + Clang->getFileManager(), true)); return Clang; } diff --git a/src/pipeline.cc b/src/pipeline.cc index 59101324..ed01feeb 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -162,10 +162,14 @@ std::unique_ptr RawCacheLoad(const std::string &path) { IndexFile::kMajorVersion); } -bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, - Project *project, VFS *vfs, const GroupMatch &matcher) { +std::mutex &GetFileMutex(const std::string &path) { const int N_MUTEXES = 256; static std::mutex mutexes[N_MUTEXES]; + return mutexes[std::hash()(path) % N_MUTEXES]; +} + +bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, + Project *project, VFS *vfs, const GroupMatch &matcher) { std::optional opt_request = index_request->TryPopFront(); if (!opt_request) return false; @@ -216,8 +220,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (reparse < 2) do { - std::unique_lock lock( - mutexes[std::hash()(path_to_index) % N_MUTEXES]); + std::unique_lock lock(GetFileMutex(path_to_index)); prev = RawCacheLoad(path_to_index); if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, std::nullopt)) @@ -256,8 +259,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, std::string path = dep.first.val().str(); if (!vfs->Stamp(path, dep.second, 1)) continue; - std::lock_guard lock1( - mutexes[std::hash()(path) % N_MUTEXES]); + std::lock_guard lock1(GetFileMutex(path)); prev = RawCacheLoad(path); if (!prev) continue; @@ -313,7 +315,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev << ")"; { - std::lock_guard lock(mutexes[std::hash()(path) % N_MUTEXES]); + std::lock_guard lock(GetFileMutex(path)); if (vfs->Loaded(path)) prev = RawCacheLoad(path); else From da704521b550606ad0cf3c8dcff8ad2efb54d02e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 29 Sep 2018 01:10:56 -0700 Subject: [PATCH 62/66] Revamp codeLens & codeAction b.ref: references of bases d.ref: references of derived when b.ref > 0, don't display 0 ref or x bases --- src/lsp.h | 39 +-- src/lsp_code_action.h | 36 --- src/messages/initialize.cc | 12 +- src/messages/textDocument_codeAction.cc | 27 +- src/messages/textDocument_codeLens.cc | 348 ++++++++++++----------- src/messages/workspace_executeCommand.cc | 58 ---- 6 files changed, 199 insertions(+), 321 deletions(-) delete mode 100644 src/lsp_code_action.h delete mode 100644 src/messages/workspace_executeCommand.cc diff --git a/src/lsp.h b/src/lsp.h index ef4ada8c..6e4c5d22 100644 --- a/src/lsp.h +++ b/src/lsp.h @@ -91,6 +91,8 @@ struct lsResponseError { void Write(Writer &visitor); }; +constexpr std::string_view ccls_xref("ccls.xref"); + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -205,43 +207,6 @@ struct lsLocationEx : lsLocation { }; MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, parentKind, role); -template struct lsCommand { - // Title of the command (ie, 'save') - std::string title; - // Actual command identifier. - std::string command; - // Arguments to run the command with. - // **NOTE** This must be serialized as an array. Use - // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY. - T arguments; -}; -template -void Reflect(TVisitor &visitor, lsCommand &value) { - REFLECT_MEMBER_START(); - REFLECT_MEMBER(title); - REFLECT_MEMBER(command); - REFLECT_MEMBER(arguments); - REFLECT_MEMBER_END(); -} - -template struct lsCodeLens { - // The range in which this code lens is valid. Should only span a single line. - lsRange range; - // The command this code lens represents. - std::optional> command; - // A data entry field that is preserved on a code lens item between - // a code lens and a code lens resolve request. - TData data; -}; -template -void Reflect(TVisitor &visitor, lsCodeLens &value) { - REFLECT_MEMBER_START(); - REFLECT_MEMBER(range); - REFLECT_MEMBER(command); - REFLECT_MEMBER(data); - REFLECT_MEMBER_END(); -} - struct lsTextDocumentIdentifier { lsDocumentUri uri; }; diff --git a/src/lsp_code_action.h b/src/lsp_code_action.h deleted file mode 100644 index 15ed6be4..00000000 --- a/src/lsp_code_action.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include "lsp.h" - -// codeAction -struct CommandArgs { - lsDocumentUri textDocumentUri; - std::vector edits; -}; -MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits); - -// codeLens -struct lsCodeLensUserData {}; -MAKE_REFLECT_EMPTY_STRUCT(lsCodeLensUserData); - -struct lsCodeLensCommandArguments { - lsDocumentUri uri; - lsPosition position; - std::vector locations; -}; -MAKE_REFLECT_STRUCT(lsCodeLensCommandArguments, uri, position, locations) diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 7d9ea978..443bf6a6 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -81,13 +81,6 @@ struct lsDocumentLinkOptions { }; MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, resolveProvider); -// Execute command options. -struct lsExecuteCommandOptions { - // The commands to be executed on the server - std::vector commands; -}; -MAKE_REFLECT_STRUCT(lsExecuteCommandOptions, commands); - // Save options. struct lsSaveOptions { // The client is supposed to include the content on save. @@ -180,8 +173,11 @@ struct lsServerCapabilities { // The server provides document link support. lsDocumentLinkOptions documentLinkProvider; // The server provides execute command support. - lsExecuteCommandOptions executeCommandProvider; + struct ExecuteCommandOptions { + std::vector commands{std::string(ccls_xref)}; + } executeCommandProvider; }; +MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands); MAKE_REFLECT_STRUCT(lsServerCapabilities, textDocumentSync, hoverProvider, completionProvider, signatureHelpProvider, definitionProvider, implementationProvider, diff --git a/src/messages/textDocument_codeAction.cc b/src/messages/textDocument_codeAction.cc index 9ee4e5e1..ac5564b3 100644 --- a/src/messages/textDocument_codeAction.cc +++ b/src/messages/textDocument_codeAction.cc @@ -18,12 +18,6 @@ limitations under the License. #include "working_files.h" using namespace ccls; -struct CommandArgs { - lsDocumentUri textDocumentUri; - std::vector edits; -}; -MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits); - namespace { MethodType kMethodType = "textDocument/codeAction"; @@ -53,10 +47,17 @@ MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction::lsCodeActionParams, textDocument, MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction, id, params); REGISTER_IN_MESSAGE(In_TextDocumentCodeAction); +struct lsCodeAction { + std::string title; + const char *kind = "quickfix"; + lsWorkspaceEdit edit; +}; +MAKE_REFLECT_STRUCT(lsCodeAction, title, kind, edit); + struct Out_TextDocumentCodeAction : public lsOutMessage { lsRequestId id; - std::vector> result; + std::vector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentCodeAction, jsonrpc, id, result); @@ -76,12 +77,12 @@ struct Handler_TextDocumentCodeAction working_files->DoAction([&]() { diagnostics = wfile->diagnostics_; }); for (lsDiagnostic &diag : diagnostics) if (diag.fixits_.size()) { - lsCommand command; - command.title = "FixIt: " + diag.message; - command.command = "ccls._applyFixIt"; - command.arguments.textDocumentUri = params.textDocument.uri; - command.arguments.edits = diag.fixits_; - out.result.push_back(command); + lsCodeAction &cmd = out.result.emplace_back(); + cmd.title = "FixIt: " + diag.message; + auto &edit = cmd.edit.documentChanges.emplace_back(); + edit.textDocument.uri = params.textDocument.uri; + edit.textDocument.version = wfile->version; + edit.edits = diag.fixits_; } pipeline::WriteStdout(kMethodType, out); } diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index ccf235fd..da64859e 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -13,21 +13,64 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.hh" -#include "lsp_code_action.h" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; +#include "serializers/json.h" + +#include #include -namespace { -MethodType kMethodType = "textDocument/codeLens"; +using namespace ccls; + +namespace { +const MethodType codeLens = "textDocument/codeLens", + executeCommand = "workspace/executeCommand"; + +struct lsCommand { + std::string title; + std::string command; + std::vector arguments; +}; +MAKE_REFLECT_STRUCT(lsCommand, title, command, arguments); + +struct lsCodeLens { + lsRange range; + std::optional command; +}; +MAKE_REFLECT_STRUCT(lsCodeLens, range, command); + +struct Cmd_xref { + Usr usr; + SymbolKind kind; + std::string field; +}; +MAKE_REFLECT_STRUCT(Cmd_xref, usr, kind, field); + +struct Out_xref : public lsOutMessage { + lsRequestId id; + std::vector result; +}; +MAKE_REFLECT_STRUCT(Out_xref, jsonrpc, id, result); + +template +std::string ToString(T &v) { + rapidjson::StringBuffer output; + rapidjson::Writer writer(output); + JsonWriter json_writer(&writer); + Reflect(json_writer, v); + return output.GetString(); +} + +struct CommonCodeLensParams { + std::vector *result; + DB *db; + WorkingFile *wfile; +}; -using TCodeLens = lsCodeLens; struct In_TextDocumentCodeLens : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } + MethodType GetMethodType() const override { return codeLens; } struct Params { lsTextDocumentIdentifier textDocument; } params; @@ -39,179 +82,85 @@ REGISTER_IN_MESSAGE(In_TextDocumentCodeLens); struct Out_TextDocumentCodeLens : public lsOutMessage { lsRequestId id; - std::vector> - result; + std::vector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentCodeLens, jsonrpc, id, result); -struct CommonCodeLensParams { - std::vector *result; - DB *db; - WorkingFiles *working_files; - WorkingFile *working_file; -}; - -Use OffsetStartColumn(Use use, int16_t offset) { - use.range.start.column += offset; - return use; -} - -void AddCodeLens(const char *singular, const char *plural, - CommonCodeLensParams *common, Use use, - const std::vector &uses, bool force_display) { - TCodeLens code_lens; - std::optional range = GetLsRange(common->working_file, use.range); - if (!range) - return; - if (use.file_id < 0) - return; - code_lens.range = *range; - code_lens.command = lsCommand(); - code_lens.command->command = "ccls.showReferences"; - code_lens.command->arguments.uri = GetLsDocumentUri(common->db, use.file_id); - code_lens.command->arguments.position = code_lens.range.start; - - // Add unique uses. - std::vector unique_uses; - for (Use use1 : uses) { - if (auto ls_loc = GetLsLocation(common->db, common->working_files, use1)) - unique_uses.push_back(*ls_loc); - } - code_lens.command->arguments.locations.assign(unique_uses.begin(), - unique_uses.end()); - - // User visible label - size_t num_usages = unique_uses.size(); - code_lens.command->title = std::to_string(num_usages) + " "; - if (num_usages == 1) - code_lens.command->title += singular; - else - code_lens.command->title += plural; - - if (force_display || unique_uses.size() > 0) - common->result->push_back(code_lens); -} - struct Handler_TextDocumentCodeLens : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } + MethodType GetMethodType() const override { return codeLens; } void Run(In_TextDocumentCodeLens *request) override { auto ¶ms = request->params; Out_TextDocumentCodeLens out; out.id = request->id; - std::string path = params.textDocument.uri.GetPath(); - clang_complete->NotifyView(path); QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, project, request->id, path, &file)) return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); - CommonCodeLensParams common; - common.result = &out.result; - common.db = db; - common.working_files = working_files; - common.working_file = working_files->GetFileByFilename(file->def->path); + auto Add = [&](const char *singular, Cmd_xref show, Use use, int num, + bool force_display = false) { + if (!num && !force_display) + return; + std::optional range = GetLsRange(wfile, use.range); + if (!range) + return; + lsCodeLens &code_lens = out.result.emplace_back(); + code_lens.range = *range; + code_lens.command = lsCommand(); + code_lens.command->command = std::string(ccls_xref); + bool plural = num > 1 && singular[strlen(singular) - 1] != 'd'; + code_lens.command->title = + llvm::formatv("{0} {1}{2}", num, singular, plural ? "s" : "").str(); + code_lens.command->arguments.push_back(ToString(show)); + }; + + auto ToSpell = [&](Use use) { + Maybe def = GetDefinitionSpell(db, use); + if (def && def->file_id == use.file_id && + def->range.start.line == use.range.start.line) + return *def; + return use; + }; std::unordered_set seen; for (auto [sym, refcnt] : file->outline2refcnt) { if (refcnt <= 0 || !seen.insert(sym.range).second) continue; - // NOTE: We OffsetColumn so that the code lens always show up in a - // predictable order. Otherwise, the client may randomize it. - Use use{{sym.range, sym.usr, sym.kind, sym.role}, file->id}; - + Use use = ToSpell({{sym.range, sym.usr, sym.kind, sym.role}, file->id}); switch (sym.kind) { - case SymbolKind::Type: { - QueryType &type = db->GetType(sym); - const QueryType::Def *def = type.AnyDef(); - if (!def || def->kind == lsSymbolKind::Namespace) - continue; - AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0), - type.uses, true /*force_display*/); - AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1), - GetTypeDeclarations(db, type.derived), - false /*force_display*/); - AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2), - GetVarDeclarations(db, type.instances, true), - false /*force_display*/); - break; - } case SymbolKind::Func: { QueryFunc &func = db->GetFunc(sym); const QueryFunc::Def *def = func.AnyDef(); if (!def) continue; - - int16_t offset = 0; - - // For functions, the outline will report a location that is using the - // extent since that is better for outline. This tries to convert the - // extent location to the spelling location. - auto try_ensure_spelling = [&](Use use) { - Maybe def = GetDefinitionSpell(db, use); - if (!def || def->range.start.line != use.range.start.line) { - return use; - } - return *def; - }; - - std::vector base_callers = GetUsesForAllBases(db, func); - std::vector derived_callers = GetUsesForAllDerived(db, func); - if (base_callers.empty() && derived_callers.empty()) { - Use loc = try_ensure_spelling(use); - AddCodeLens("call", "calls", &common, - OffsetStartColumn(loc, offset++), func.uses, - true /*force_display*/); - } else { - Use loc = try_ensure_spelling(use); - AddCodeLens("direct call", "direct calls", &common, - OffsetStartColumn(loc, offset++), func.uses, - false /*force_display*/); - if (!base_callers.empty()) - AddCodeLens("base call", "base calls", &common, - OffsetStartColumn(loc, offset++), base_callers, - false /*force_display*/); - if (!derived_callers.empty()) - AddCodeLens("derived call", "derived calls", &common, - OffsetStartColumn(loc, offset++), derived_callers, - false /*force_display*/); - } - - AddCodeLens( - "derived", "derived", &common, OffsetStartColumn(use, offset++), - GetFuncDeclarations(db, func.derived), false /*force_display*/); - - // "Base" - if (def->bases.size() == 1) { - Maybe base_loc = GetDefinitionSpell( - db, SymbolIdx{def->bases[0], SymbolKind::Func}); - if (base_loc) { - std::optional ls_base = - GetLsLocation(db, working_files, *base_loc); - if (ls_base) { - std::optional range = - GetLsRange(common.working_file, sym.range); - if (range) { - TCodeLens code_lens; - code_lens.range = *range; - code_lens.range.start.character += offset++; - code_lens.command = lsCommand(); - code_lens.command->title = "Base"; - code_lens.command->command = "ccls.goto"; - code_lens.command->arguments.uri = ls_base->uri; - code_lens.command->arguments.position = ls_base->range.start; - out.result.push_back(code_lens); - } - } - } - } else { - AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1), - GetTypeDeclarations(db, def->bases), - false /*force_display*/); - } - + std::vector base_uses = GetUsesForAllBases(db, func); + std::vector derived_uses = GetUsesForAllDerived(db, func); + Add("ref", {sym.usr, SymbolKind::Func, "uses"}, use, func.uses.size(), + base_uses.empty()); + if (base_uses.size()) + Add("b.ref", {sym.usr, SymbolKind::Func, "bases uses"}, use, + base_uses.size()); + if (derived_uses.size()) + Add("d.ref", {sym.usr, SymbolKind::Func, "derived uses"}, use, + derived_uses.size()); + if (base_uses.empty()) + Add("base", {sym.usr, SymbolKind::Func, "bases"}, use, + def->bases.size()); + Add("derived", {sym.usr, SymbolKind::Func, "derived"}, use, + func.derived.size()); + break; + } + case SymbolKind::Type: { + QueryType &type = db->GetType(sym); + Add("ref", {sym.usr, SymbolKind::Type, "uses"}, use, type.uses.size(), + true); + Add("derived", {sym.usr, SymbolKind::Type, "derived"}, use, + type.derived.size()); + Add("var", {sym.usr, SymbolKind::Type, "instances"}, use, + type.instances.size()); break; } case SymbolKind::Var: { @@ -219,27 +168,88 @@ struct Handler_TextDocumentCodeLens const QueryVar::Def *def = var.AnyDef(); if (!def || (def->is_local() && !g_config->codeLens.localVariables)) continue; - - bool force_display = true; - // Do not show 0 refs on macro with no uses, as it is most likely - // a header guard. - if (def->kind == lsSymbolKind::Macro) - force_display = false; - - AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0), var.uses, - force_display); + Add("ref", {sym.usr, SymbolKind::Var, "uses"}, use, var.uses.size(), + def->kind != lsSymbolKind::Macro); break; } case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + case SymbolKind::Invalid: + llvm_unreachable(""); }; } - pipeline::WriteStdout(kMethodType, out); + pipeline::WriteStdout(codeLens, out); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeLens); + +struct In_WorkspaceExecuteCommand : public RequestInMessage { + MethodType GetMethodType() const override { return executeCommand; } + lsCommand params; +}; +MAKE_REFLECT_STRUCT(In_WorkspaceExecuteCommand, id, params); +REGISTER_IN_MESSAGE(In_WorkspaceExecuteCommand); + +struct Handler_WorkspaceExecuteCommand + : BaseMessageHandler { + MethodType GetMethodType() const override { return executeCommand; } + void Run(In_WorkspaceExecuteCommand *request) override { + const auto ¶ms = request->params; + if (params.arguments.empty()) + return; + rapidjson::Document reader; + reader.Parse(params.arguments[0].c_str()); + JsonReader json_reader{&reader}; + if (params.command == ccls_xref) { + Cmd_xref cmd; + Reflect(json_reader, cmd); + Out_xref out; + out.id = request->id; + auto Map = [&](auto &&uses) { + for (auto &use : uses) + if (auto loc = GetLsLocation(db, working_files, use)) + out.result.push_back(std::move(*loc)); + }; + switch (cmd.kind) { + case SymbolKind::Func: { + QueryFunc &func = db->Func(cmd.usr); + if (cmd.field == "bases") { + if (auto *def = func.AnyDef()) + Map(GetFuncDeclarations(db, def->bases)); + } else if (cmd.field == "bases uses") { + Map(GetUsesForAllBases(db, func)); + } else if (cmd.field == "derived") { + Map(GetFuncDeclarations(db, func.derived)); + } else if (cmd.field == "derived uses") { + Map(GetUsesForAllDerived(db, func)); + } else if (cmd.field == "uses") { + Map(func.uses); + } + break; + } + case SymbolKind::Type: { + QueryType &type = db->Type(cmd.usr); + if (cmd.field == "derived") { + Map(GetTypeDeclarations(db, type.derived)); + } else if (cmd.field == "instances") { + Map(GetVarDeclarations(db, type.instances, 7)); + } else if (cmd.field == "uses") { + Map(type.uses); + } + break; + } + case SymbolKind::Var: { + QueryVar &var = db->Var(cmd.usr); + if (cmd.field == "uses") + Map(var.uses); + break; + } + default: + break; + } + pipeline::WriteStdout(executeCommand, out); + } + } +}; +REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand); } // namespace diff --git a/src/messages/workspace_executeCommand.cc b/src/messages/workspace_executeCommand.cc deleted file mode 100644 index a7fc764d..00000000 --- a/src/messages/workspace_executeCommand.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "lsp_code_action.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "workspace/executeCommand"; - -struct In_WorkspaceExecuteCommand : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsCommand params; -}; -MAKE_REFLECT_STRUCT(In_WorkspaceExecuteCommand, id, params); -REGISTER_IN_MESSAGE(In_WorkspaceExecuteCommand); - -struct Out_WorkspaceExecuteCommand - : public lsOutMessage { - lsRequestId id; - std::variant, CommandArgs> result; -}; -MAKE_REFLECT_STRUCT(Out_WorkspaceExecuteCommand, jsonrpc, id, result); - -struct Handler_WorkspaceExecuteCommand - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_WorkspaceExecuteCommand *request) override { - const auto ¶ms = request->params; - Out_WorkspaceExecuteCommand out; - out.id = request->id; - if (params.command == "ccls._applyFixIt") { - } else if (params.command == "ccls._autoImplement") { - } else if (params.command == "ccls._insertInclude") { - } else if (params.command == "ccls.showReferences") { - out.result = params.arguments.locations; - } - - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand); - -} // namespace From 79373ba48681b31085d412b2d8d8646be605110d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 29 Sep 2018 20:26:55 -0700 Subject: [PATCH 63/66] Rename some initialization options * Delete index.enabled which can be achieved with index.blacklist: ['.'] * Move completion.include* to completion.include.* * move largeFileSize to highlight.largeFileSize --- src/config.h | 65 ++++++++++++++++++++--------------------- src/include_complete.cc | 20 ++++++------- src/indexer.cc | 3 -- src/message_handler.cc | 2 +- src/pipeline.cc | 2 +- 5 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/config.h b/src/config.h index 4ff79a92..8889f94b 100644 --- a/src/config.h +++ b/src/config.h @@ -130,25 +130,27 @@ struct Config { // that implement their own filtering and sorting logic. bool filterAndSort = true; - // Regex patterns to match include completion candidates against. They - // receive the absolute file path. - // - // For example, to hide all files in a /CACHE/ folder, use ".*/CACHE/.*" - std::vector includeBlacklist; + struct Include { + // Regex patterns to match include completion candidates against. They + // receive the absolute file path. + // + // For example, to hide all files in a /CACHE/ folder, use ".*/CACHE/.*" + std::vector blacklist; - // Maximum path length to show in completion results. Paths longer than this - // will be elided with ".." put at the front. Set to 0 or a negative number - // to disable eliding. - int includeMaxPathSize = 30; + // Maximum path length to show in completion results. Paths longer than + // this will be elided with ".." put at the front. Set to 0 or a negative + // number to disable eliding. + int maxPathSize = 30; - // Whitelist that file paths will be tested against. If a file path does not - // end in one of these values, it will not be considered for - // auto-completion. An example value is { ".h", ".hpp" } - // - // This is significantly faster than using a regex. - std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh", ".inc"}; + // Whitelist that file paths will be tested against. If a file path does + // not end in one of these values, it will not be considered for + // auto-completion. An example value is { ".h", ".hpp" } + // + // This is significantly faster than using a regex. + std::vector suffixWhitelist = {".h", ".hpp", ".hh", ".inc"}; - std::vector includeWhitelist; + std::vector whitelist; + } include; } completion; struct Diagnostics { @@ -176,6 +178,9 @@ struct Config { // Semantic highlighting struct Highlight { + // Disable semantic highlighting for files larger than the size. + int64_t largeFileSize = 2 * 1024 * 1024; + // true: LSP line/character; false: position bool lsRanges = false; @@ -201,9 +206,6 @@ struct Config { // - https://github.com/autozimu/LanguageClient-neovim/issues/224 int comments = 2; - // If false, the indexer will be disabled. - bool enabled = true; - // By default, all project entries will be indexed on initialization. Use // these two options to exclude some. They can still be indexed after you // open them. @@ -227,15 +229,12 @@ struct Config { // Whether to reparse a file if write times of its dependencies have // changed. The file will always be reparsed if its own write time changes. - // 0: no, 1: only after initial load of project, 2: yes + // 0: no, 1: only during initial load of project, 2: yes int trackDependency = 2; std::vector whitelist; } index; - // Disable semantic highlighting for files larger than the size. - int64_t largeFileSize = 2 * 1024 * 1024; - struct WorkspaceSymbol { int caseSensitivity = 1; // Maximum workspace search results. @@ -258,24 +257,24 @@ MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, MAKE_REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport, snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); +MAKE_REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize, + suffixWhitelist, whitelist); MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, - dropOldRequests, duplicateOptional, filterAndSort, - includeBlacklist, includeMaxPathSize, - includeSuffixWhitelist, includeWhitelist); + dropOldRequests, duplicateOptional, filterAndSort, include); MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, spellChecking, whitelist) -MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) -MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, - initialBlacklist, initialWhitelist, multiVersion, - multiVersionBlacklist, multiVersionWhitelist, onChange, - threads, trackDependency, whitelist); +MAKE_REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, + whitelist) +MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist, + initialWhitelist, multiVersion, multiVersionBlacklist, + multiVersionWhitelist, onChange, threads, trackDependency, + whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, compilationDatabaseDirectory, cacheDirectory, cacheFormat, - clang, client, codeLens, completion, diagnostics, highlight, - index, largeFileSize, workspaceSymbol, xref); + index, workspaceSymbol, xref); extern Config *g_config; diff --git a/src/include_complete.cc b/src/include_complete.cc index 779b04b0..e634e189 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -35,13 +35,11 @@ struct CompletionCandidate { }; std::string ElideLongPath(const std::string &path) { - if (g_config->completion.includeMaxPathSize <= 0) + if (g_config->completion.include.maxPathSize <= 0 || + (int)path.size() <= g_config->completion.include.maxPathSize) return path; - if ((int)path.size() <= g_config->completion.includeMaxPathSize) - return path; - - size_t start = path.size() - g_config->completion.includeMaxPathSize; + size_t start = path.size() - g_config->completion.include.maxPathSize; return ".." + path.substr(start + 2); } @@ -113,11 +111,11 @@ void IncludeComplete::Rescan() { absolute_path_to_completion_item.clear(); inserted_paths.clear(); - if (!match_ && (g_config->completion.includeWhitelist.size() || - g_config->completion.includeBlacklist.size())) + if (!match_ && (g_config->completion.include.whitelist.size() || + g_config->completion.include.blacklist.size())) match_ = - std::make_unique(g_config->completion.includeWhitelist, - g_config->completion.includeBlacklist); + std::make_unique(g_config->completion.include.whitelist, + g_config->completion.include.blacklist); is_scanning = true; std::thread([this]() { @@ -156,7 +154,7 @@ void IncludeComplete::InsertCompletionItem(const std::string &absolute_path, } void IncludeComplete::AddFile(const std::string &absolute_path) { - if (!EndsWithAny(absolute_path, g_config->completion.includeSuffixWhitelist)) + if (!EndsWithAny(absolute_path, g_config->completion.include.suffixWhitelist)) return; if (match_ && !match_->IsMatch(absolute_path)) return; @@ -186,7 +184,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory, directory, true /*recursive*/, false /*add_folder_to_path*/, [&](const std::string &path) { if (!include_cpp && - !EndsWithAny(path, g_config->completion.includeSuffixWhitelist)) + !EndsWithAny(path, g_config->completion.include.suffixWhitelist)) return; if (match_ && !match_->IsMatch(directory + path)) return; diff --git a/src/indexer.cc b/src/indexer.cc index 9299b4aa..ccc5b64f 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1245,9 +1245,6 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, const std::vector &args, const std::vector> &remapped, bool &ok) { ok = true; - if (!g_config->index.enabled) - return {}; - auto PCH = std::make_shared(); llvm::IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); std::shared_ptr CI = BuildCompilerInvocation(args, FS); diff --git a/src/message_handler.cc b/src/message_handler.cc index e1721976..98ef5dde 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -133,7 +133,7 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { static GroupMatch match(g_config->highlight.whitelist, g_config->highlight.blacklist); assert(file->def); - if (wfile->buffer_content.size() > g_config->largeFileSize || + if (wfile->buffer_content.size() > g_config->highlight.largeFileSize || !match.IsMatch(file->def->path)) return; diff --git a/src/pipeline.cc b/src/pipeline.cc index ed01feeb..f4e5cc1f 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -295,7 +295,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, path_to_index, entry.args, remapped, ok); if (!ok) { - if (g_config->index.enabled && request.id.Valid()) { + if (request.id.Valid()) { Out_Error out; out.id = request.id; out.error.code = lsErrorCodes::InternalError; From 84984c6c2720df8454b4c0bfec296db792253792 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 30 Sep 2018 22:54:48 -0700 Subject: [PATCH 64/66] Use non-inferred entries and build preamble for .h; index on didOpen if no pending requests; documentHighlight --- src/clang_complete.cc | 21 +++--- src/indexer.h | 1 - src/messages/textDocument_definition.cc | 13 +--- src/messages/textDocument_did.cc | 6 +- .../textDocument_documentHighlight.cc | 69 ++++++++++++------- src/pipeline.cc | 9 ++- src/pipeline.hh | 2 +- src/project.cc | 21 +++--- src/project.h | 2 +- src/query_utils.cc | 11 ++- src/query_utils.h | 3 +- src/symbol.h | 26 ------- src/utils.h | 1 - 13 files changed, 92 insertions(+), 93 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 6a785470..b66a01f8 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -231,16 +231,13 @@ void CompletionPreloadMain(CompletionManager *manager) { if (!session) continue; - // For inferred session, don't build preamble because changes in a.h will - // invalidate it. - if (!session->inferred) { - const auto &args = session->file.args; - WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot( - {StripFileType(session->file.filename)}); - if (std::unique_ptr CI = - BuildCompilerInvocation(args, session->FS)) - session->BuildPreamble(*CI, request.path); - } + const auto &args = session->file.args; + WorkingFiles::Snapshot snapshot = + session->wfiles->AsSnapshot({StripFileType(session->file.filename)}); + if (std::unique_ptr CI = + BuildCompilerInvocation(args, session->FS)) + session->BuildPreamble(*CI, request.path); + int debounce = is_open ? g_config->diagnostics.onOpen : g_config->diagnostics.onSave; if (debounce >= 0) { @@ -539,7 +536,7 @@ bool CompletionManager::EnsureCompletionOrCreatePreloadSession( // No CompletionSession, create new one. auto session = std::make_shared( - project_->FindCompilationEntryForFile(path), working_files_, PCH); + project_->FindEntry(path, false), working_files_, PCH); if (session->file.filename != path) { session->inferred = true; session->file.filename = path; @@ -568,7 +565,7 @@ CompletionManager::TryGetSession(const std::string &path, bool preload, session = sessions.TryGet(path); if (!session && !preload) { session = std::make_shared( - project_->FindCompilationEntryForFile(path), working_files_, PCH); + project_->FindEntry(path, false), working_files_, PCH); sessions.Insert(path, session); LOG_S(INFO) << "create session for " << path; if (is_open) diff --git a/src/indexer.h b/src/indexer.h index 0e6f4e71..2a911067 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -29,7 +29,6 @@ limitations under the License. #include #include -#include #include #include #include diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index df28502d..2718abd7 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -76,21 +76,11 @@ struct Handler_TextDocumentDefinition Out_TextDocumentDefinition out; out.id = request->id; - Maybe range; - SymbolKind kind; Maybe on_def; WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); lsPosition &ls_pos = params.position; - for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) { - if (!range) { - range = sym.range; - kind = sym.kind; - } else if (!(sym.range == *range && sym.kind == kind)) { - break; - } - // Found symbol. Return definition. - + for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos, true)) { // Special cases which are handled: // - symbol has declaration but no definition (ie, pure virtual) // - goto declaration while in definition of recursive type @@ -129,6 +119,7 @@ struct Handler_TextDocumentDefinition out.result.erase(std::unique(out.result.begin(), out.result.end()), out.result.end()); } else { + Maybe range; // Check #include for (const IndexInclude &include : file->def->includes) { if (include.line == ls_pos.line) { diff --git a/src/messages/textDocument_did.cc b/src/messages/textDocument_did.cc index 5a069ee2..30bf2acd 100644 --- a/src/messages/textDocument_did.cc +++ b/src/messages/textDocument_did.cc @@ -125,8 +125,10 @@ struct Handler_TextDocumentDidOpen if (args.size()) project->SetArgsForFile(args, path); - // Submit new index request if it is not a header file. - if (SourceFileLanguage(path) != LanguageId::Unknown) + // Submit new index request if it is not a header file or there is no + // pending index request. + if (SourceFileLanguage(path) != LanguageId::Unknown || + !pipeline::pending_index_requests) pipeline::Index(path, args, IndexMode::Normal); clang_complete->NotifyView(path); diff --git a/src/messages/textDocument_documentHighlight.cc b/src/messages/textDocument_documentHighlight.cc index 871f617b..e3d6e35d 100644 --- a/src/messages/textDocument_documentHighlight.cc +++ b/src/messages/textDocument_documentHighlight.cc @@ -17,11 +17,28 @@ limitations under the License. #include "pipeline.hh" #include "query_utils.h" #include "symbol.h" + +#include using namespace ccls; namespace { MethodType kMethodType = "textDocument/documentHighlight"; +struct lsDocumentHighlight { + enum Kind { Text = 1, Read = 2, Write = 3 }; + + lsRange range; + int kind = 1; + + // ccls extension + Role role = Role::None; + + bool operator<(const lsDocumentHighlight &o) const { + return !(range == o.range) ? range < o.range : kind < o.kind; + } +}; +MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role); + struct In_TextDocumentDocumentHighlight : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } lsTextDocumentPositionParams params; @@ -44,39 +61,41 @@ struct Handler_TextDocumentDocumentHighlight QueryFile *file; if (!FindFileOrFail(db, project, request->id, request->params.textDocument.uri.GetPath(), &file, - &file_id)) { + &file_id)) return; - } - WorkingFile *working_file = working_files->GetFileByFilename(file->def->path); Out_TextDocumentDocumentHighlight out; out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - // Found symbol. Return references to highlight. - EachOccurrence(db, sym, true, [&](Use use) { - if (use.file_id != file_id) - return; - if (std::optional ls_loc = - GetLsLocation(db, working_files, use)) { - lsDocumentHighlight highlight; - highlight.range = ls_loc->range; - if (use.role & Role::Write) - highlight.kind = lsDocumentHighlightKind::Write; - else if (use.role & Role::Read) - highlight.kind = lsDocumentHighlightKind::Read; - else - highlight.kind = lsDocumentHighlightKind::Text; - highlight.role = use.role; - out.result.push_back(highlight); - } - }); - break; + std::vector syms = FindSymbolsAtLocation( + working_file, file, request->params.position, true); + for (auto [sym, refcnt] : file->symbol2refcnt) { + if (refcnt <= 0) + continue; + Usr usr = sym.usr; + SymbolKind kind = sym.kind; + if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) { + return usr == sym1.usr && kind == sym1.kind; + })) + continue; + if (auto ls_loc = + GetLsLocation(db, working_files, + Use{{sym.range, usr, kind, sym.role}, file_id})) { + lsDocumentHighlight highlight; + highlight.range = ls_loc->range; + if (sym.role & Role::Write) + highlight.kind = lsDocumentHighlight::Write; + else if (sym.role & Role::Read) + highlight.kind = lsDocumentHighlight::Read; + else + highlight.kind = lsDocumentHighlight::Text; + highlight.role = sym.role; + out.result.push_back(highlight); + } } - + std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); } }; diff --git a/src/pipeline.cc b/src/pipeline.cc index f4e5cc1f..c61469c0 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -62,7 +62,8 @@ bool VFS::Stamp(const std::string &path, int64_t ts, int step) { namespace ccls::pipeline { -std::atomic loaded_ts = ATOMIC_VAR_INIT(0); +std::atomic loaded_ts = ATOMIC_VAR_INIT(0), + pending_index_requests = ATOMIC_VAR_INIT(0); int64_t tick = 0; namespace { @@ -175,6 +176,9 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, return false; auto &request = *opt_request; bool loud = request.mode != IndexMode::OnChange; + struct RAII { + ~RAII() { pending_index_requests--; } + } raii; // Dummy one to trigger refresh semantic highlight. if (request.path.empty()) { @@ -189,7 +193,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, return false; } - Project::Entry entry = project->FindCompilationEntryForFile(request.path); + Project::Entry entry = project->FindEntry(request.path, true); if (request.args.size()) entry.args = request.args; std::string path_to_index = entry.filename; @@ -547,6 +551,7 @@ void MainLoop() { void Index(const std::string &path, const std::vector &args, IndexMode mode, lsRequestId id) { + pending_index_requests++; index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } diff --git a/src/pipeline.hh b/src/pipeline.hh index a232d513..b4cc514b 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -39,7 +39,7 @@ enum class IndexMode { }; namespace pipeline { -extern std::atomic loaded_ts; +extern std::atomic loaded_ts, pending_index_requests; extern int64_t tick; void Init(); void LaunchStdin(); diff --git a/src/project.cc b/src/project.cc index 70802538..ca1a0f38 100644 --- a/src/project.cc +++ b/src/project.cc @@ -386,13 +386,16 @@ void Project::SetArgsForFile(const std::vector &args, } } -Project::Entry -Project::FindCompilationEntryForFile(const std::string &filename) { +Project::Entry Project::FindEntry(const std::string &path, + bool can_be_inferred) { { std::lock_guard lock(mutex_); - auto it = path_to_entry_index.find(filename); - if (it != path_to_entry_index.end()) - return entries[it->second]; + auto it = path_to_entry_index.find(path); + if (it != path_to_entry_index.end()) { + Project::Entry &entry = entries[it->second]; + if (can_be_inferred || entry.filename == path) + return entry; + } } // We couldn't find the file. Try to infer it. @@ -400,7 +403,7 @@ Project::FindCompilationEntryForFile(const std::string &filename) { Entry *best_entry = nullptr; int best_score = INT_MIN; for (Entry &entry : entries) { - int score = ComputeGuessScore(filename, entry.filename); + int score = ComputeGuessScore(path, entry.filename); if (score > best_score) { best_score = score; best_entry = &entry; @@ -409,10 +412,10 @@ Project::FindCompilationEntryForFile(const std::string &filename) { Project::Entry result; result.is_inferred = true; - result.filename = filename; + result.filename = path; if (!best_entry) { result.args.push_back("%clang"); - result.args.push_back(Intern(filename)); + result.args.push_back(Intern(path)); } else { result.args = best_entry->args; @@ -424,7 +427,7 @@ Project::FindCompilationEntryForFile(const std::string &filename) { try { if (arg == best_entry->filename || sys::path::filename(arg) == best_entry_base_name) - arg = Intern(filename); + arg = Intern(path); } catch (...) { } } diff --git a/src/project.h b/src/project.h index 125b2af0..59a89855 100644 --- a/src/project.h +++ b/src/project.h @@ -59,7 +59,7 @@ struct Project { // Lookup the CompilationEntry for |filename|. If no entry was found this // will infer one based on existing project structure. - Entry FindCompilationEntryForFile(const std::string &filename); + Entry FindEntry(const std::string &path, bool can_be_inferred); // If the client has overridden the flags, or specified them for a file // that is not in the compilation_database.json make sure those changes diff --git a/src/query_utils.cc b/src/query_utils.cc index c2e0f0b7..27ce5f71 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -308,7 +308,8 @@ std::optional GetSymbolInfo(DB *db, SymbolIdx sym, std::vector FindSymbolsAtLocation(WorkingFile *wfile, QueryFile *file, - lsPosition &ls_pos) { + lsPosition &ls_pos, + bool smallest) { std::vector symbols; // If multiVersion > 0, index may not exist and thus index_lines is empty. if (wfile && wfile->index_lines.size()) { @@ -353,6 +354,14 @@ std::vector FindSymbolsAtLocation(WorkingFile *wfile, return t > 0; return a.usr < b.usr; }); + if (symbols.size() && smallest) { + SymbolRef sym = symbols[0]; + for (size_t i = 1; i < symbols.size(); i++) + if (!(sym.range == symbols[i].range && sym.kind == symbols[i].kind)) { + symbols.resize(i); + break; + } + } return symbols; } diff --git a/src/query_utils.h b/src/query_utils.h index 0ec2501c..642a6ba1 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -51,7 +51,8 @@ std::optional GetSymbolInfo(DB *db, SymbolIdx sym, std::vector FindSymbolsAtLocation(WorkingFile *working_file, QueryFile *file, - lsPosition &ls_pos); + lsPosition &ls_pos, + bool smallest = false); template void WithEntity(DB *db, SymbolIdx sym, Fn &&fn) { switch (sym.kind) { diff --git a/src/symbol.h b/src/symbol.h index 16e4de11..beec82b8 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -46,32 +46,6 @@ inline Role operator|(Role lhs, Role rhs) { return Role(uint16_t(lhs) | uint16_t(rhs)); } -// A document highlight kind. -enum class lsDocumentHighlightKind { - // A textual occurrence. - Text = 1, - // Read-access of a symbol, like reading a variable. - Read = 2, - // Write-access of a symbol, like writing to a variable. - Write = 3 -}; -MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind); - -// A document highlight is a range inside a text document which deserves -// special attention. Usually a document highlight is visualized by changing -// the background color of its range. -struct lsDocumentHighlight { - // The range this highlight applies to. - lsRange range; - - // The highlight kind, default is DocumentHighlightKind.Text. - lsDocumentHighlightKind kind = lsDocumentHighlightKind::Text; - - // ccls extension - Role role = Role::None; -}; -MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role); - struct lsSymbolInformation { std::string_view name; lsSymbolKind kind; diff --git a/src/utils.h b/src/utils.h index 7b4087ce..2e556074 100644 --- a/src/utils.h +++ b/src/utils.h @@ -18,7 +18,6 @@ limitations under the License. #include #include -#include #include #include #include From f2227cbaa21866e238708e56563fdd48919ed5ff Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 1 Oct 2018 00:39:44 -0700 Subject: [PATCH 65/66] Clean --- src/main.cc | 2 +- src/message_handler.h | 1 - src/project.cc | 20 +++++++++++--------- src/utils.h | 21 --------------------- 4 files changed, 12 insertions(+), 32 deletions(-) diff --git a/src/main.cc b/src/main.cc index 4d2fb679..66e76f86 100644 --- a/src/main.cc +++ b/src/main.cc @@ -102,7 +102,7 @@ int main(int argc, char **argv) { if (!opt_init.empty()) { // We check syntax error here but override client-side // initializationOptions in messages/initialize.cc - g_init_options = opt_init; + g_init_options = opt_init.getValue(); rapidjson::Document reader; rapidjson::ParseResult ok = reader.Parse(g_init_options.c_str()); if (!ok) { diff --git a/src/message_handler.h b/src/message_handler.h index 38074f64..33bbb6f3 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -15,7 +15,6 @@ limitations under the License. #pragma once -#include "lru_cache.h" #include "lsp.h" #include "method.h" #include "query.h" diff --git a/src/project.cc b/src/project.cc index ca1a0f38..1278e1e4 100644 --- a/src/project.cc +++ b/src/project.cc @@ -191,24 +191,26 @@ std::vector LoadFromDirectoryListing(ProjectConfig *config) { std::unordered_map> folder_args; std::vector files; + const std::string &project_dir = config->project_dir; - GetFilesInFolder(config->project_dir, true /*recursive*/, + GetFilesInFolder(project_dir, true /*recursive*/, true /*add_folder_to_path*/, [&folder_args, &files](const std::string &path) { if (SourceFileLanguage(path) != LanguageId::Unknown) { files.push_back(path); } else if (sys::path::filename(path) == ".ccls") { - LOG_S(INFO) << "Using .ccls arguments from " << path; - folder_args.emplace(sys::path::parent_path(path), - ReadCompilerArgumentsFromFile(path)); + std::vector args = ReadCompilerArgumentsFromFile(path); + folder_args.emplace(sys::path::parent_path(path), args); + std::string l; + for (size_t i = 0; i < args.size(); i++) { + if (i) + l += ' '; + l += args[i]; + } + LOG_S(INFO) << "use " << path << ": " << l; } }); - const std::string &project_dir = config->project_dir; - const auto &project_dir_args = folder_args[project_dir]; - LOG_IF_S(INFO, !project_dir_args.empty()) - << "Using .ccls arguments " << StringJoin(project_dir_args); - auto GetCompilerArgumentForFile = [&project_dir, &folder_args](std::string cur) { while (!(cur = sys::path::parent_path(cur)).empty()) { diff --git a/src/utils.h b/src/utils.h index 2e556074..85e74c1d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -19,7 +19,6 @@ limitations under the License. #include #include -#include #include #include @@ -42,26 +41,6 @@ std::vector SplitString(const std::string &str, std::string LowerPathIfInsensitive(const std::string &path); -template -std::string StringJoinMap(const TValues &values, const TMap &map, - const std::string &sep = ", ") { - std::string result; - bool first = true; - for (auto &entry : values) { - if (!first) - result += sep; - first = false; - result += map(entry); - } - return result; -} - -template -std::string StringJoin(const TValues &values, const std::string &sep = ", ") { - return StringJoinMap(values, [](const std::string &entry) { return entry; }, - sep); -} - // Ensures that |path| ends in a slash. void EnsureEndsInSlash(std::string &path); From da07cb2da41376be488849a106271aa477c8a3e0 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 1 Oct 2018 00:57:24 -0700 Subject: [PATCH 66/66] Add $ccls/info --- CMakeLists.txt | 2 +- src/messages/ccls_fileInfo.cc | 66 --------------------- src/messages/ccls_info.cc | 106 ++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 67 deletions(-) delete mode 100644 src/messages/ccls_fileInfo.cc create mode 100644 src/messages/ccls_info.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 384c008f..47af70f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,7 +208,7 @@ target_sources(ccls PRIVATE target_sources(ccls PRIVATE src/messages/ccls_call.cc - src/messages/ccls_fileInfo.cc + src/messages/ccls_info.cc src/messages/ccls_inheritance.cc src/messages/ccls_member.cc src/messages/ccls_navigate.cc diff --git a/src/messages/ccls_fileInfo.cc b/src/messages/ccls_fileInfo.cc deleted file mode 100644 index 5e4f546a..00000000 --- a/src/messages/ccls_fileInfo.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges, - dependencies); - -namespace { -MethodType kMethodType = "$ccls/fileInfo"; - -struct lsDocumentSymbolParams { - lsTextDocumentIdentifier textDocument; -}; -MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument); - -struct In_CclsFileInfo : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsDocumentSymbolParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsFileInfo, id, params); -REGISTER_IN_MESSAGE(In_CclsFileInfo); - -struct Out_CclsFileInfo : public lsOutMessage { - lsRequestId id; - QueryFile::Def result; -}; -MAKE_REFLECT_STRUCT(Out_CclsFileInfo, jsonrpc, id, result); - -struct Handler_CclsFileInfo : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsFileInfo *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - Out_CclsFileInfo out; - out.id = request->id; - // Expose some fields of |QueryFile::Def|. - out.result.path = file->def->path; - out.result.args = file->def->args; - out.result.language = file->def->language; - out.result.includes = file->def->includes; - out.result.skipped_ranges = file->def->skipped_ranges; - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsFileInfo); -} // namespace diff --git a/src/messages/ccls_info.cc b/src/messages/ccls_info.cc new file mode 100644 index 00000000..3efcae50 --- /dev/null +++ b/src/messages/ccls_info.cc @@ -0,0 +1,106 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "project.h" +#include "query_utils.h" +using namespace ccls; + +MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges, + dependencies); + +namespace { +MethodType cclsInfo = "$ccls/info", fileInfo = "$ccls/fileInfo"; + +struct In_cclsInfo : public RequestInMessage { + MethodType GetMethodType() const override { return cclsInfo; } +}; +MAKE_REFLECT_STRUCT(In_cclsInfo, id); +REGISTER_IN_MESSAGE(In_cclsInfo); + +struct Out_cclsInfo : public lsOutMessage { + lsRequestId id; + struct Result { + struct DB { + int files, funcs, types, vars; + } db; + struct Pipeline { + int pendingIndexRequests; + } pipeline; + struct Project { + int entries; + } project; + } result; +}; +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::DB, files, funcs, types, vars); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::Pipeline, pendingIndexRequests); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::Project, entries); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result, db, pipeline, project); +MAKE_REFLECT_STRUCT(Out_cclsInfo, jsonrpc, id, result); + +struct Handler_cclsInfo : BaseMessageHandler { + MethodType GetMethodType() const override { return cclsInfo; } + void Run(In_cclsInfo *request) override { + Out_cclsInfo out; + out.id = request->id; + out.result.db.files = db->files.size(); + out.result.db.funcs = db->funcs.size(); + out.result.db.types = db->types.size(); + out.result.db.vars = db->vars.size(); + out.result.pipeline.pendingIndexRequests = pipeline::pending_index_requests; + out.result.project.entries = project->entries.size(); + pipeline::WriteStdout(cclsInfo, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_cclsInfo); + +struct In_cclsFileInfo : public RequestInMessage { + MethodType GetMethodType() const override { return fileInfo; } + struct Params { + lsTextDocumentIdentifier textDocument; + } params; +}; +MAKE_REFLECT_STRUCT(In_cclsFileInfo::Params, textDocument); +MAKE_REFLECT_STRUCT(In_cclsFileInfo, id, params); +REGISTER_IN_MESSAGE(In_cclsFileInfo); + +struct Out_cclsFileInfo : public lsOutMessage { + lsRequestId id; + QueryFile::Def result; +}; +MAKE_REFLECT_STRUCT(Out_cclsFileInfo, jsonrpc, id, result); + +struct Handler_cclsFileInfo : BaseMessageHandler { + MethodType GetMethodType() const override { return fileInfo; } + void Run(In_cclsFileInfo *request) override { + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + request->params.textDocument.uri.GetPath(), &file)) + return; + + Out_cclsFileInfo out; + out.id = request->id; + // Expose some fields of |QueryFile::Def|. + out.result.path = file->def->path; + out.result.args = file->def->args; + out.result.language = file->def->language; + out.result.includes = file->def->includes; + out.result.skipped_ranges = file->def->skipped_ranges; + pipeline::WriteStdout(fileInfo, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_cclsFileInfo); +} // namespace