diff --git a/src/indexer.cc b/src/indexer.cc index a9db95dd..643d86e0 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -65,9 +65,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 4234cb53..ae413292 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -197,7 +197,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 b7cbddd1..3893833d 100644 --- a/src/messages/ccls_fileInfo.cc +++ b/src/messages/ccls_fileInfo.cc @@ -6,8 +6,8 @@ #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 e4d75299..1713a6d1 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -104,7 +104,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 a19a7189..f29a035f 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -105,12 +105,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 5e081d6d..4b4c5d7e 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -53,20 +53,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) { @@ -82,6 +82,7 @@ struct Handler_TextDocumentDocumentSymbol out.result.push_back(*info); } } + } pipeline::WriteStdout(kMethodType, out); } } diff --git a/src/query.cc b/src/query.cc index 010806dd..cc9b9346 100644 --- a/src/query.cc +++ b/src/query.cc @@ -17,34 +17,13 @@ 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) { @@ -78,79 +57,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)}; } @@ -182,7 +88,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); @@ -200,7 +106,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); @@ -220,7 +126,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); } @@ -235,11 +141,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; @@ -253,7 +160,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; @@ -267,7 +174,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; @@ -292,43 +199,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); }; @@ -347,36 +279,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 } @@ -402,9 +370,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(); @@ -421,8 +397,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(); @@ -439,8 +423,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 cfa87485..93b2b0e0 100644 --- a/src/query.h +++ b/src/query.h @@ -10,6 +10,21 @@ #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; @@ -17,10 +32,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|. @@ -31,7 +42,8 @@ struct QueryFile { int id = -1; std::optional def; - std::unordered_map symbol2refcnt; + llvm::DenseMap symbol2refcnt; + llvm::DenseMap outline2refcnt; }; template struct QueryEntity { @@ -98,7 +110,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; @@ -106,7 +118,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; @@ -115,7 +127,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; @@ -143,8 +155,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 195de920..b054af04 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -147,29 +147,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; @@ -303,12 +302,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 { @@ -317,9 +317,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);