From 6ec032c2a0fc733713b3a605673431dff2f5e3ad Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 4 Oct 2018 16:13:30 -0700 Subject: [PATCH] Redesign SymbolRef, Ref, Use Remove lsLocationEx --- src/config.h | 4 +- src/indexer.cc | 289 ++++++++---------- src/indexer.h | 75 ++--- src/lsp.h | 11 +- src/message_handler.cc | 21 +- src/messages/ccls_call.cc | 38 ++- src/messages/ccls_navigate.cc | 2 +- src/messages/ccls_vars.cc | 2 +- src/messages/textDocument_codeLens.cc | 12 +- src/messages/textDocument_definition.cc | 21 +- .../textDocument_documentHighlight.cc | 6 +- src/messages/textDocument_documentSymbol.cc | 12 +- src/messages/textDocument_implementation.cc | 8 +- src/messages/textDocument_references.cc | 24 +- src/messages/textDocument_typeDefinition.cc | 15 +- src/query.cc | 18 +- src/query.h | 4 +- src/query_utils.cc | 34 +-- src/query_utils.h | 11 +- src/serializer.cc | 62 ++-- 20 files changed, 292 insertions(+), 377 deletions(-) diff --git a/src/config.h b/src/config.h index 32d9fff6..abb31dee 100644 --- a/src/config.h +++ b/src/config.h @@ -249,8 +249,6 @@ struct Config { } workspaceSymbol; struct Xref { - // If true, |Location[]| response will include lexical container. - bool container = false; // Maximum number of definition/reference/... results. int maxNum = 2000; } xref; @@ -274,7 +272,7 @@ MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist, multiVersionWhitelist, onChange, threads, trackDependency, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); -MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); +MAKE_REFLECT_STRUCT(Config::Xref, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, compilationDatabaseDirectory, cacheDirectory, cacheFormat, clang, client, codeLens, completion, diagnostics, highlight, diff --git a/src/indexer.cc b/src/indexer.cc index 530a2767..2ebbdd34 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -117,50 +117,109 @@ StringRef GetSourceInRange(const SourceManager &SM, const LangOptions &LangOpts, BInfo.second); } -SymbolKind GetSymbolKind(const Decl *D) { +SymbolKind GetSymbolKind(const Decl *D, lsSymbolKind &kind) { switch (D->getKind()) { - case Decl::TranslationUnit: - return SymbolKind::File; - case Decl::ObjCMethod: - case Decl::FunctionTemplate: - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXConversion: - case Decl::CXXDestructor: - return SymbolKind::Func; + case Decl::LinkageSpec: + return SymbolKind::Invalid; case Decl::Namespace: + kind = lsSymbolKind::Namespace; + return SymbolKind::Type; case Decl::NamespaceAlias: + kind = lsSymbolKind::TypeAlias; + return SymbolKind::Type; case Decl::ObjCCategory: + case Decl::ObjCImplementation: case Decl::ObjCInterface: case Decl::ObjCProtocol: + kind = lsSymbolKind::Interface; + return SymbolKind::Type; + case Decl::ObjCMethod: + kind = lsSymbolKind::Method; + return SymbolKind::Func; + case Decl::ObjCProperty: + kind = lsSymbolKind::Property; + return SymbolKind::Type; case Decl::ClassTemplate: + kind = lsSymbolKind::Class; + return SymbolKind::Type; + case Decl::FunctionTemplate: + kind = lsSymbolKind::Function; + return SymbolKind::Func; case Decl::TypeAliasTemplate: + kind = lsSymbolKind::TypeAlias; + return SymbolKind::Type; + case Decl::VarTemplate: + kind = lsSymbolKind::Variable; + return SymbolKind::Var; case Decl::TemplateTemplateParm: + kind = lsSymbolKind::TypeParameter; + return SymbolKind::Type; case Decl::Enum: - case Decl::Record: + kind = lsSymbolKind::Enum; + return SymbolKind::Type; case Decl::CXXRecord: + case Decl::Record: + kind = lsSymbolKind::Class; + // spec has no Union, use Class + if (auto *RD = dyn_cast(D)) + if (RD->getTagKind() == TTK_Struct) + kind = lsSymbolKind::Struct; + return SymbolKind::Type; case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: + kind = lsSymbolKind::Class; + return SymbolKind::Type; case Decl::TypeAlias: case Decl::Typedef: case Decl::UnresolvedUsingTypename: + kind = lsSymbolKind::TypeAlias; return SymbolKind::Type; - case Decl::ObjCProperty: - case Decl::VarTemplate: case Decl::Binding: + kind = lsSymbolKind::Variable; + return SymbolKind::Var; case Decl::Field: case Decl::ObjCIvar: + kind = lsSymbolKind::Field; + return SymbolKind::Var; + case Decl::Function: + kind = lsSymbolKind::Function; + return SymbolKind::Func; + case Decl::CXXMethod: { + const auto *MD = cast(D); + kind = MD->isStatic() ? lsSymbolKind::StaticMethod : lsSymbolKind::Method; + return SymbolKind::Func; + } + case Decl::CXXConstructor: + kind = lsSymbolKind::Constructor; + return SymbolKind::Func; + case Decl::CXXConversion: + case Decl::CXXDestructor: + kind = lsSymbolKind::Method; + return SymbolKind::Func; case Decl::Var: - case Decl::ParmVar: - case Decl::ImplicitParam: case Decl::Decomposition: + kind = lsSymbolKind::Variable; + return SymbolKind::Var; + case Decl::ImplicitParam: + case Decl::ParmVar: + // ccls extension + kind = lsSymbolKind::Parameter; + return SymbolKind::Var; case Decl::VarTemplateSpecialization: case Decl::VarTemplatePartialSpecialization: - case Decl::EnumConstant: - case Decl::UnresolvedUsingValue: + kind = lsSymbolKind::Variable; return SymbolKind::Var; + case Decl::EnumConstant: + kind = lsSymbolKind::EnumMember; + return SymbolKind::Var; + case Decl::UnresolvedUsingValue: + kind = lsSymbolKind::Variable; + return SymbolKind::Var; + case Decl::TranslationUnit: + return SymbolKind::Invalid; + default: + LOG_S(INFO) << "unhandled " << int(D->getKind()); return SymbolKind::Invalid; } } @@ -421,23 +480,6 @@ public: return it->second.usr; } - Use GetUse(IndexFile *db, int lid, Range range, const DeclContext *DC, - Role role) const { - if (!DC) - return {{range, 0, SymbolKind::File, role}, lid}; - const Decl *D = cast(DC); - switch (GetSymbolKind(D)) { - case SymbolKind::Func: - return {{range, db->ToFunc(GetUsr(D)).usr, SymbolKind::Func, role}, lid}; - case SymbolKind::Type: - return {{range, db->ToType(GetUsr(D)).usr, SymbolKind::Type, role}, lid}; - case SymbolKind::Var: - return {{range, db->ToVar(GetUsr(D)).usr, SymbolKind::Var, role}, lid}; - default: - return {{range, 0, SymbolKind::File, role}, lid}; - } - } - PrintingPolicy GetDefaultPolicy() const { PrintingPolicy PP(Ctx->getLangOpts()); PP.AnonymousTagLocations = false; @@ -590,7 +632,7 @@ public: return; Range spell = FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, Spell)); - Use use{{spell, 0, SymbolKind::File, Role::Dynamic}, lid}; + Use use{{spell, Role::Dynamic}, lid}; switch (kind) { case SymbolKind::Func: db->ToFunc(usr).uses.push_back(use); @@ -704,7 +746,8 @@ public: IndexFunc *func = nullptr; IndexType *type = nullptr; IndexVar *var = nullptr; - SymbolKind kind = GetSymbolKind(D); + lsSymbolKind ls_kind; + SymbolKind kind = GetSymbolKind(D, ls_kind); if (is_def) switch (D->getKind()) { @@ -734,19 +777,20 @@ public: auto do_def_decl = [&](auto *entity) { if (is_def) { - entity->def.spell = GetUse(db, lid, loc, SemDC, role); + entity->def.spell = {{loc, role}, lid}; SourceRange R = OrigD->getSourceRange(); - entity->def.extent = - GetUse(db, lid, - R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc, - LexDC, Role::None); + entity->def.extent = { + {R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc, + Role::None}, + lid}; + GetSymbolKind(cast(SemDC), entity->def.parent_kind); } else if (is_decl) { DeclRef &dr = entity->declarations.emplace_back(); - static_cast(dr) = GetUse(db, lid, loc, LexDC, role); + static_cast(dr) = {{loc, role}, lid}; 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)); + entity->uses.push_back({{loc, role}, lid}); return; } if (entity->def.comments[0] == '\0' && g_config->index.comments) @@ -761,6 +805,7 @@ public: return true; case SymbolKind::Func: func = &db->ToFunc(usr); + func->def.kind = ls_kind; // Mark as Role::Implicit to span one more column to the left/right. if (!is_def && !is_decl && (D->getKind() == Decl::CXXConstructor || @@ -773,17 +818,18 @@ public: SetName(D, info->short_name, info->qualified, func->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); - if (GetSymbolKind(DC) == SymbolKind::Type) + if (GetSymbolKind(DC, ls_kind) == SymbolKind::Type) db->ToType(GetUsr(DC)).def.funcs.push_back(usr); } else { const Decl *DC = cast(LexDC); - if (GetSymbolKind(DC) == SymbolKind::Func) + if (GetSymbolKind(DC, ls_kind) == SymbolKind::Func) db->ToFunc(GetUsr(DC)) - .def.callees.push_back({{loc, usr, SymbolKind::Func, role}}); + .def.callees.push_back({loc, usr, SymbolKind::Func, role}); } break; case SymbolKind::Type: type = &db->ToType(usr); + type->def.kind = ls_kind; do_def_decl(type); if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Type, Spell); @@ -791,12 +837,13 @@ public: SetName(D, info->short_name, info->qualified, type->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); - if (GetSymbolKind(DC) == SymbolKind::Type) + if (GetSymbolKind(DC, ls_kind) == SymbolKind::Type) db->ToType(GetUsr(DC)).def.types.push_back(usr); } break; case SymbolKind::Var: var = &db->ToVar(usr); + var->def.kind = ls_kind; do_def_decl(var); if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Var, Spell); @@ -809,7 +856,7 @@ public: T = FD->getType(); if (is_def || is_decl) { const Decl *DC = cast(SemDC); - if (GetSymbolKind(DC) == SymbolKind::Func) + if (GetSymbolKind(DC, ls_kind) == SymbolKind::Func) db->ToFunc(GetUsr(DC)).def.vars.push_back(usr); else if (auto *ND = dyn_cast(SemDC)) db->ToType(GetUsr(ND)).def.vars.emplace_back(usr, -1); @@ -828,14 +875,15 @@ public: 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.spell = { + {FromTokenRange(SM, Lang, {L1, L1}), Role::Definition}, + lid}; + type1.def.extent = {{FromTokenRange(SM, Lang, R1), Role::None}, + lid}; type1.def.detailed_name = Intern(info1->short_name); type1.def.short_name_size = int16_t(info1->short_name.size()); type1.def.kind = lsSymbolKind::TypeParameter; + type1.def.parent_kind = lsSymbolKind::Class; var->def.type = usr1; type1.instances.push_back(usr); break; @@ -852,11 +900,11 @@ public: // e.g. lambda parameter 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, D->getSourceRange()), - LexDC, Role::None); + var->def.spell = { + {FromTokenRange(SM, Lang, {L, L}), Role::Definition}, lid}; + var->def.extent = { + {FromTokenRange(SM, Lang, D->getSourceRange()), Role::None}, lid}; + var->def.parent_kind = lsSymbolKind::Method; } } break; @@ -864,7 +912,6 @@ public: switch (D->getKind()) { case Decl::Namespace: - type->def.kind = lsSymbolKind::Namespace; if (D->isFirstDecl()) { auto *ND = cast(D); auto *ND1 = cast(ND->getParent()); @@ -876,7 +923,6 @@ public: } break; case Decl::NamespaceAlias: { - type->def.kind = lsSymbolKind::TypeAlias; auto *NAD = cast(D); if (const NamespaceDecl *ND = NAD->getNamespace()) { Usr usr1 = GetUsr(ND); @@ -885,36 +931,6 @@ public: } break; } - case Decl::ObjCCategory: - case Decl::ObjCImplementation: - case Decl::ObjCInterface: - case Decl::ObjCProtocol: - type->def.kind = lsSymbolKind::Interface; - break; - case Decl::ObjCMethod: - func->def.kind = lsSymbolKind::Method; - break; - case Decl::ObjCProperty: - var->def.kind = lsSymbolKind::Property; - break; - case Decl::ClassTemplate: - type->def.kind = lsSymbolKind::Class; - break; - case Decl::FunctionTemplate: - func->def.kind = lsSymbolKind::Function; - break; - case Decl::TypeAliasTemplate: - type->def.kind = lsSymbolKind::TypeAlias; - break; - case Decl::VarTemplate: - var->def.kind = lsSymbolKind::Variable; - break; - case Decl::TemplateTemplateParm: - type->def.kind = lsSymbolKind::TypeParameter; - break; - case Decl::Enum: - type->def.kind = lsSymbolKind::Enum; - break; case Decl::CXXRecord: if (is_def) { auto *RD = dyn_cast(D); @@ -930,9 +946,6 @@ public: [[fallthrough]]; case Decl::Record: if (auto *RD = dyn_cast(D)) { - // 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()) { StringRef Tag; switch (RD->getTagKind()) { @@ -990,7 +1003,6 @@ public: case Decl::TypeAlias: case Decl::Typedef: case Decl::UnresolvedUsingTypename: - type->def.kind = lsSymbolKind::TypeAlias; if (auto *TD = dyn_cast(D)) { bool specialization = false; QualType T = TD->getUnderlyingType(); @@ -1002,29 +1014,14 @@ public: if (specialization) { const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); SourceLocation L1 = TSI->getTypeLoc().getBeginLoc(); - if (SM.getFileID(L1) == LocFID) { - Range loc1 = FromTokenRange(SM, Lang, {L1, L1}); + if (SM.getFileID(L1) == LocFID) type1.uses.push_back( - GetUse(db, lid, loc1, LexDC, Role::Reference)); - } + {{FromTokenRange(SM, Lang, {L1, L1}), Role::Reference}, lid}); } } } break; - case Decl::Binding: - var->def.kind = lsSymbolKind::Variable; - break; - case Decl::Field: - case Decl::ObjCIvar: - var->def.kind = lsSymbolKind::Field; - break; - case Decl::Function: - func->def.kind = lsSymbolKind::Function; - break; - case Decl::CXXMethod: { - const auto *MD = cast(D); - func->def.kind = - MD->isStatic() ? lsSymbolKind::StaticMethod : lsSymbolKind::Method; + case Decl::CXXMethod: if (is_def || is_decl) { if (auto *ND = dyn_cast(D)) { SmallVector OverDecls; @@ -1037,29 +1034,7 @@ public: } } break; - } - case Decl::CXXConstructor: - func->def.kind = lsSymbolKind::Constructor; - break; - case Decl::CXXConversion: - case Decl::CXXDestructor: - func->def.kind = lsSymbolKind::Method; - break; - case Decl::Var: - case Decl::Decomposition: - var->def.kind = lsSymbolKind::Variable; - break; - case Decl::ImplicitParam: - case Decl::ParmVar: - // ccls extension - var->def.kind = lsSymbolKind::Parameter; - break; - case Decl::VarTemplateSpecialization: - case Decl::VarTemplatePartialSpecialization: - var->def.kind = lsSymbolKind::Variable; - break; case Decl::EnumConstant: - var->def.kind = lsSymbolKind::EnumMember; if (is_def && strchr(var->def.detailed_name, '=') == nullptr) { auto *ECD = cast(D); const auto &Val = ECD->getInitVal(); @@ -1069,11 +1044,7 @@ public: var->def.hover = Intern(var->def.detailed_name + init); } break; - case Decl::UnresolvedUsingValue: - var->def.kind = lsSymbolKind::Variable; - break; default: - LOG_S(INFO) << "Unhandled " << int(D->getKind()); break; } return true; @@ -1131,16 +1102,17 @@ public: IndexVar &var = db->ToVar(usr); auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID); var.def.kind = lsSymbolKind::Macro; + var.def.parent_kind = lsSymbolKind::File; 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}}; + var.def.spell = Use{{range, Role::Definition}}; const MacroInfo *MI = MD->getMacroInfo(); SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); range = FromTokenRange(SM, param.Ctx->getLangOpts(), R); - var.def.extent = Use{{range, 0, SymbolKind::File, Role::None}}; + var.def.extent = Use{{range, Role::None}}; if (var.def.detailed_name[0] == '\0') { var.def.detailed_name = Intern(Name); var.def.short_name_size = Name.size(); @@ -1162,8 +1134,8 @@ public: if (IndexFile *db = param.ConsumeFile(*FE)) { IndexVar &var = db->ToVar(GetMacro(Tok).second); var.uses.push_back( - {{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), 0, - SymbolKind::File, Role::Dynamic}}); + {{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), + Role::Dynamic}}); } } void MacroUndefined(const Token &Tok, const MacroDefinition &MD, @@ -1198,7 +1170,7 @@ public: }; } // namespace -const int IndexFile::kMajorVersion = 18; +const int IndexFile::kMajorVersion = 19; const int IndexFile::kMinorVersion = 0; IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, @@ -1390,10 +1362,7 @@ Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, } } // namespace ccls::idx -// |SymbolRef| is serialized this way. -// |Use| also uses this though it has an extra field |file|, -// which is not used by Index* so it does not need to be serialized. -void Reflect(Reader &vis, Reference &v) { +void Reflect(Reader &vis, SymbolRef &v) { if (vis.Format() == SerializeFormat::Json) { std::string t = vis.GetString(); char *s = const_cast(t.c_str()); @@ -1409,7 +1378,7 @@ void Reflect(Reader &vis, Reference &v) { Reflect(vis, v.role); } } -void Reflect(Writer &vis, Reference &v) { +void Reflect(Writer &vis, SymbolRef &v) { if (vis.Format() == SerializeFormat::Json) { char buf[99]; snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", @@ -1430,25 +1399,24 @@ void Reflect(Reader &vis, Use &v) { char *s = const_cast(t.c_str()); v.range = Range::FromString(s); s = strchr(s, '|'); - 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)); v.file_id = static_cast(strtol(s + 1, &s, 10)); } else { - Reflect(vis, static_cast(v)); + Reflect(vis, v.range); + Reflect(vis, v.role); Reflect(vis, v.file_id); } } void Reflect(Writer &vis, Use &v) { if (vis.Format() == SerializeFormat::Json) { char buf[99]; - 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|%d|%d", v.range.ToString().c_str(), + int(v.role), v.file_id); std::string s(buf); Reflect(vis, s); } else { - Reflect(vis, static_cast(v)); + Reflect(vis, v.range); + Reflect(vis, v.role); Reflect(vis, v.file_id); } } @@ -1460,9 +1428,7 @@ void Reflect(Reader &vis, DeclRef &v) { 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)); + s = strchr(s, '|'); v.role = static_cast(strtol(s + 1, &s, 10)); v.file_id = static_cast(strtol(s + 1, &s, 10)); } else { @@ -1473,9 +1439,8 @@ void Reflect(Reader &vis, DeclRef &v) { 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); + snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(), + v.extent.ToString().c_str(), int(v.role), v.file_id); std::string s(buf); Reflect(vis, s); } else { diff --git a/src/indexer.h b/src/indexer.h index 2a911067..36b9781e 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -49,28 +49,36 @@ struct SymbolIdx { }; MAKE_REFLECT_STRUCT(SymbolIdx, usr, kind); -struct Reference { +// |id,kind| refer to the referenced entity. +struct SymbolRef { Range range; Usr usr; SymbolKind kind; Role role; - - bool Valid() const { return range.Valid(); } operator SymbolIdx() const { return {usr, kind}; } std::tuple ToTuple() const { return std::make_tuple(range, usr, kind, role); } - bool operator==(const Reference &o) const { return ToTuple() == o.ToTuple(); } - bool operator<(const Reference &o) const { return ToTuple() < o.ToTuple(); } + bool operator==(const SymbolRef &o) const { return ToTuple() == o.ToTuple(); } + bool Valid() const { return range.Valid(); } }; - -// |id,kind| refer to the referenced entity. -struct SymbolRef : Reference {}; MAKE_HASHABLE(SymbolRef, t.range, t.usr, t.kind, t.role); +struct Ref { + Range range; + Role role; + + bool Valid() const { return range.Valid(); } + std::tuple ToTuple() const { + return std::make_tuple(range, role); + } + bool operator==(const Ref &o) const { return ToTuple() == o.ToTuple(); } + bool operator<(const Ref &o) const { return ToTuple() < o.ToTuple(); } +}; + // Represents an occurrence of a variable/type, |usr,kind| refer to the lexical // parent. -struct Use : Reference { +struct Use : Ref { // |file| is used in Query* but not in Index* int file_id = -1; bool operator==(const Use &o) const { @@ -85,8 +93,8 @@ struct DeclRef : Use { }; MAKE_HASHABLE(DeclRef, t.range, t.file_id) -void Reflect(Reader &visitor, Reference &value); -void Reflect(Writer &visitor, Reference &value); +void Reflect(Reader &visitor, SymbolRef &value); +void Reflect(Writer &visitor, SymbolRef &value); void Reflect(Reader &visitor, Use &value); void Reflect(Writer &visitor, Use &value); void Reflect(Reader &visitor, DeclRef &value); @@ -115,74 +123,71 @@ struct FuncDef : NameMixin { // Method this method overrides. std::vector bases; - // Local variables or parameters. std::vector vars; - // Functions that this function calls. std::vector callees; - int file_id = -1; + int file_id = -1; // not serialized int16_t qual_name_offset = 0; int16_t short_name_offset = 0; int16_t short_name_size = 0; lsSymbolKind kind = lsSymbolKind::Unknown; + lsSymbolKind parent_kind = lsSymbolKind::Unknown; uint8_t storage = clang::SC_None; std::vector GetBases() const { return bases; } }; -MAKE_REFLECT_STRUCT(FuncDef, detailed_name, qual_name_offset, short_name_offset, - short_name_size, kind, storage, hover, comments, spell, - extent, bases, vars, callees); +MAKE_REFLECT_STRUCT(FuncDef, detailed_name, hover, comments, spell, extent, + bases, vars, callees, qual_name_offset, short_name_offset, + short_name_size, kind, parent_kind, storage); struct IndexFunc : NameMixin { using Def = FuncDef; Usr usr; Def def; std::vector declarations; - std::vector uses; std::vector derived; + std::vector uses; }; struct TypeDef : NameMixin { const char *detailed_name = ""; const char *hover = ""; const char *comments = ""; - Maybe spell; Maybe extent; std::vector bases; - // Types, functions, and variables defined in this type. - std::vector types; std::vector funcs; + std::vector types; std::vector> vars; // If set, then this is the same underlying type as the given value (ie, this // type comes from a using or typedef statement). Usr alias_of = 0; - - int file_id = -1; + int file_id = -1; // not serialized int16_t qual_name_offset = 0; int16_t short_name_offset = 0; int16_t short_name_size = 0; lsSymbolKind kind = lsSymbolKind::Unknown; + lsSymbolKind parent_kind = lsSymbolKind::Unknown; std::vector GetBases() const { return bases; } }; -MAKE_REFLECT_STRUCT(TypeDef, detailed_name, qual_name_offset, short_name_offset, - short_name_size, kind, hover, comments, spell, extent, - alias_of, bases, types, funcs, vars); +MAKE_REFLECT_STRUCT(TypeDef, detailed_name, hover, comments, spell, extent, + bases, funcs, types, vars, alias_of, qual_name_offset, + short_name_offset, short_name_size, kind, parent_kind); struct IndexType { using Def = TypeDef; Usr usr; Def def; std::vector declarations; - std::vector uses; std::vector derived; std::vector instances; + std::vector uses; }; struct VarDef : NameMixin { @@ -195,27 +200,29 @@ struct VarDef : NameMixin { // Type of the variable. Usr type = 0; - - int file_id = -1; + int file_id = -1; // not serialized int16_t qual_name_offset = 0; int16_t short_name_offset = 0; int16_t short_name_size = 0; - lsSymbolKind kind = lsSymbolKind::Unknown; + lsSymbolKind parent_kind = lsSymbolKind::Unknown; // Note a variable may have instances of both |None| and |Extern| // (declaration). uint8_t storage = clang::SC_None; bool is_local() const { - return spell && spell->kind == SymbolKind::Func && + return spell && + (parent_kind == lsSymbolKind::Function || + parent_kind == lsSymbolKind::Method || + parent_kind == lsSymbolKind::StaticMethod) && storage == clang::SC_None; } std::vector GetBases() const { return {}; } }; -MAKE_REFLECT_STRUCT(VarDef, detailed_name, qual_name_offset, short_name_offset, - short_name_size, hover, comments, spell, extent, type, kind, - storage); +MAKE_REFLECT_STRUCT(VarDef, detailed_name, hover, comments, spell, extent, type, + qual_name_offset, short_name_offset, short_name_size, kind, + parent_kind, storage); struct IndexVar { using Def = VarDef; diff --git a/src/lsp.h b/src/lsp.h index 6e4c5d22..dbe73984 100644 --- a/src/lsp.h +++ b/src/lsp.h @@ -198,15 +198,6 @@ enum class lsSymbolKind : uint8_t { }; MAKE_REFLECT_TYPE_PROXY(lsSymbolKind); -// ccls extension -struct lsLocationEx : lsLocation { - std::optional containerName; - std::optional parentKind; - // Avoid circular dependency on symbol.h - std::optional role; -}; -MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, parentKind, role); - struct lsTextDocumentIdentifier { lsDocumentUri uri; }; @@ -346,6 +337,6 @@ void Reflect(TVisitor &visitor, Out_ShowLogMessage &value) { struct Out_LocationList : public lsOutMessage { lsRequestId id; - std::vector result; + std::vector result; }; MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result); diff --git a/src/message_handler.cc b/src/message_handler.cc index 98ef5dde..03cf15e2 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -156,24 +156,15 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { const QueryFunc::Def *def = func.AnyDef(); if (!def) continue; // applies to for loop - if (def->spell) - parent_kind = GetSymbolKind(db, *def->spell); - if (parent_kind == lsSymbolKind::Unknown) { - for (Use use : func.declarations) { - parent_kind = GetSymbolKind(db, use); - break; - } - } // Don't highlight overloadable operators or implicit lambda -> // std::function constructor. std::string_view short_name = def->Name(false); if (short_name.compare(0, 8, "operator") == 0) continue; // applies to for loop - if (def->spell) - parent_kind = GetSymbolKind(db, *def->spell); kind = def->kind; storage = def->storage; detailed_name = short_name; + parent_kind = def->parent_kind; // Check whether the function name is actually there. // If not, do not publish the semantic highlight. @@ -200,7 +191,7 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { kind = def.kind; detailed_name = def.detailed_name; if (def.spell) { - parent_kind = GetSymbolKind(db, *def.spell); + parent_kind = def.parent_kind; break; } } @@ -214,13 +205,7 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { storage = def.storage; detailed_name = def.detailed_name; if (def.spell) { - parent_kind = GetSymbolKind(db, *def.spell); - break; - } - } - if (parent_kind == lsSymbolKind::Unknown) { - for (Use use : var.declarations) { - parent_kind = GetSymbolKind(db, use); + parent_kind = def.parent_kind; break; } } diff --git a/src/messages/ccls_call.cc b/src/messages/ccls_call.cc index 0ec68f8b..46477987 100644 --- a/src/messages/ccls_call.cc +++ b/src/messages/ccls_call.cc @@ -77,6 +77,8 @@ struct Out_CclsCall : public lsOutMessage { int numChildren; // Empty if the |levels| limit is reached. std::vector children; + bool operator==(const Entry &o) const { return location == o.location; } + bool operator<(const Entry &o) const { return location < o.location; } }; lsRequestId id; @@ -94,13 +96,14 @@ bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee, entry->numChildren = 0; if (!def) return false; - auto handle = [&](Use use, CallType call_type1) { + auto handle = [&](SymbolRef sym, int file_id, CallType call_type1) { entry->numChildren++; if (levels > 0) { 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)) + entry1.id = std::to_string(sym.usr); + entry1.usr = sym.usr; + if (auto loc = GetLsLocation(m->db, m->working_files, + Use{{sym.range, sym.role}, file_id})) entry1.location = *loc; entry1.callType = call_type1; if (Expand(m, &entry1, callee, call_type, qualified, levels - 1)) @@ -110,14 +113,22 @@ bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee, auto handle_uses = [&](const QueryFunc &func, CallType call_type) { if (callee) { if (const auto *def = func.AnyDef()) - for (SymbolRef ref : def->callees) - if (ref.kind == SymbolKind::Func) - handle(Use{{ref.range, ref.usr, ref.kind, ref.role}, def->file_id}, - call_type); + for (SymbolRef sym : def->callees) + if (sym.kind == SymbolKind::Func) + handle(sym, def->file_id, call_type); } else { - for (Use use : func.uses) - if (use.kind == SymbolKind::Func) - handle(use, call_type); + for (Use use : func.uses) { + const QueryFile &file1 = m->db->files[use.file_id]; + Maybe best_sym; + for (auto [sym, refcnt] : file1.outline2refcnt) + if (refcnt > 0 && sym.kind == SymbolKind::Func && + sym.range.start <= use.range.start && + use.range.end <= sym.range.end && + (!best_sym || best_sym->range.start < sym.range.start)) + best_sym = sym; + if (best_sym) + handle(*best_sym, use.file_id, call_type); + } } }; @@ -160,6 +171,11 @@ bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee, }); } } + + std::sort(entry->children.begin(), entry->children.end()); + entry->children.erase( + std::unique(entry->children.begin(), entry->children.end()), + entry->children.end()); return true; } diff --git a/src/messages/ccls_navigate.cc b/src/messages/ccls_navigate.cc index 921ffae1..7a0fbb2d 100644 --- a/src/messages/ccls_navigate.cc +++ b/src/messages/ccls_navigate.cc @@ -104,7 +104,7 @@ struct Handler_CclsNavigate : BaseMessageHandler { out.id = request->id; if (res) if (auto ls_range = GetLsRange(wfile, *res)) { - lsLocationEx &ls_loc = out.result.emplace_back(); + lsLocation &ls_loc = out.result.emplace_back(); ls_loc.uri = params.textDocument.uri; ls_loc.range = *ls_range; } diff --git a/src/messages/ccls_vars.cc b/src/messages/ccls_vars.cc index 98dc53b8..ac2f24c7 100644 --- a/src/messages/ccls_vars.cc +++ b/src/messages/ccls_vars.cc @@ -63,7 +63,7 @@ struct Handler_CclsVars : BaseMessageHandler { [[fallthrough]]; } case SymbolKind::Type: - out.result = GetLsLocationExs( + out.result = GetLsLocations( db, working_files, GetVarDeclarations(db, db->Type(usr).instances, params.kind)); break; diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index da64859e..1957fc2a 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -117,19 +117,19 @@ struct Handler_TextDocumentCodeLens 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) + auto ToSpell = [&](SymbolRef sym, int file_id) -> Use { + Maybe def = GetDefinitionSpell(db, sym); + if (def && def->file_id == file_id && + def->range.start.line == sym.range.start.line) return *def; - return use; + return {{sym.range, sym.role}, file_id}; }; std::unordered_set seen; for (auto [sym, refcnt] : file->outline2refcnt) { if (refcnt <= 0 || !seen.insert(sym.range).second) continue; - Use use = ToSpell({{sym.range, sym.usr, sym.kind, sym.role}, file->id}); + Use use = ToSpell(sym, file->id); switch (sym.kind) { case SymbolKind::Func: { QueryFunc &func = db->GetFunc(sym); diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 2718abd7..cb35008f 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -33,13 +33,6 @@ struct In_TextDocumentDefinition : public RequestInMessage { MAKE_REFLECT_STRUCT(In_TextDocumentDefinition, id, params); REGISTER_IN_MESSAGE(In_TextDocumentDefinition); -struct Out_TextDocumentDefinition - : public lsOutMessage { - lsRequestId id; - std::vector result; -}; -MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result); - std::vector GetNonDefDeclarationTargets(DB *db, SymbolRef sym) { switch (sym.kind) { case SymbolKind::Var: { @@ -73,7 +66,7 @@ struct Handler_TextDocumentDefinition params.textDocument.uri.GetPath(), &file, &file_id)) return; - Out_TextDocumentDefinition out; + Out_LocationList out; out.id = request->id; Maybe on_def; @@ -110,7 +103,7 @@ struct Handler_TextDocumentDefinition if (uses.empty() && on_def) uses.push_back(*on_def); } - auto locs = GetLsLocationExs(db, working_files, uses); + auto locs = GetLsLocations(db, working_files, uses); out.result.insert(out.result.end(), locs.begin(), locs.end()); } @@ -123,9 +116,8 @@ struct Handler_TextDocumentDefinition // Check #include for (const IndexInclude &include : file->def->includes) { if (include.line == ls_pos.line) { - lsLocationEx result; - result.uri = lsDocumentUri::FromPath(include.resolved_path); - out.result.push_back(result); + out.result.push_back( + lsLocation{lsDocumentUri::FromPath(include.resolved_path)}); range = {{0, 0}, {0, 0}}; break; } @@ -184,9 +176,8 @@ struct Handler_TextDocumentDefinition if (best_sym.kind != SymbolKind::Invalid) { Maybe use = GetDefinitionSpell(db, best_sym); assert(use); - if (auto ls_loc = GetLsLocationEx(db, working_files, *use, - g_config->xref.container)) - out.result.push_back(*ls_loc); + if (auto loc = GetLsLocation(db, working_files, *use)) + out.result.push_back(*loc); } } } diff --git a/src/messages/textDocument_documentHighlight.cc b/src/messages/textDocument_documentHighlight.cc index e3d6e35d..337cd6b3 100644 --- a/src/messages/textDocument_documentHighlight.cc +++ b/src/messages/textDocument_documentHighlight.cc @@ -80,11 +80,9 @@ struct Handler_TextDocumentDocumentHighlight 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})) { + if (auto loc = GetLsLocation(db, working_files, sym, file_id)) { lsDocumentHighlight highlight; - highlight.range = ls_loc->range; + highlight.range = loc->range; if (sym.role & Role::Write) highlight.kind = lsDocumentHighlight::Write; else if (sym.role & Role::Read) diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index bda4a270..0b7a9ce8 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -107,10 +107,8 @@ struct Handler_TextDocumentDocumentSymbol 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( - db, working_files, - Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) - out.result.push_back(ls_loc->range); + if (auto loc = GetLsLocation(db, working_files, sym, file_id)) + out.result.push_back(loc->range); std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); } else if (g_config->client.hierarchicalDocumentSymbolSupport) { @@ -213,10 +211,8 @@ struct Handler_TextDocumentDocumentSymbol (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})) { - info->location = *location; + if (auto loc = GetLsLocation(db, working_files, sym, file_id)) { + info->location = *loc; out.result.push_back(*info); } } diff --git a/src/messages/textDocument_implementation.cc b/src/messages/textDocument_implementation.cc index 9059f287..e2db7078 100644 --- a/src/messages/textDocument_implementation.cc +++ b/src/messages/textDocument_implementation.cc @@ -47,13 +47,13 @@ struct Handler_TextDocumentImplementation FindSymbolsAtLocation(working_file, file, request->params.position)) { if (sym.kind == SymbolKind::Type) { QueryType &type = db->GetType(sym); - out.result = GetLsLocationExs(db, working_files, - GetTypeDeclarations(db, type.derived)); + out.result = GetLsLocations(db, working_files, + GetTypeDeclarations(db, type.derived)); break; } else if (sym.kind == SymbolKind::Func) { QueryFunc &func = db->GetFunc(sym); - out.result = GetLsLocationExs(db, working_files, - GetFuncDeclarations(db, func.derived)); + out.result = GetLsLocations(db, working_files, + GetFuncDeclarations(db, func.derived)); break; } } diff --git a/src/messages/textDocument_references.cc b/src/messages/textDocument_references.cc index f09adfc8..e5f2ac5b 100644 --- a/src/messages/textDocument_references.cc +++ b/src/messages/textDocument_references.cc @@ -50,13 +50,6 @@ MAKE_REFLECT_STRUCT(In_TextDocumentReferences::Params, textDocument, position, MAKE_REFLECT_STRUCT(In_TextDocumentReferences, id, params); REGISTER_IN_MESSAGE(In_TextDocumentReferences); -struct Out_TextDocumentReferences - : public lsOutMessage { - lsRequestId id; - std::vector result; -}; -MAKE_REFLECT_STRUCT(Out_TextDocumentReferences, jsonrpc, id, result); - struct Handler_TextDocumentReferences : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -67,7 +60,7 @@ struct Handler_TextDocumentReferences if (!FindFileOrFail(db, project, request->id, params.textDocument.uri.GetPath(), &file)) return; - Out_TextDocumentReferences out; + Out_LocationList out; out.id = request->id; WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); if (!file) { @@ -75,7 +68,6 @@ struct Handler_TextDocumentReferences return; } - bool container = g_config->xref.container; std::unordered_set seen_uses; int line = params.position.line; @@ -93,11 +85,8 @@ struct Handler_TextDocumentReferences if (Role(use.role & params.context.role) == params.context.role && !(use.role & params.context.excludeRole) && seen_uses.insert(use).second) - if (std::optional ls_loc = - GetLsLocationEx(db, working_files, use, container)) { - if (container) - ls_loc->parentKind = parent_kind; - out.result.push_back(*ls_loc); + if (auto loc = GetLsLocation(db, working_files, use)) { + out.result.push_back(*loc); } }; WithEntity(db, sym, [&](const auto &entity) { @@ -145,10 +134,9 @@ struct Handler_TextDocumentReferences for (const IndexInclude &include : file1.def->includes) if (include.resolved_path == path) { // Another file |file1| has the same include line. - lsLocationEx result; - result.uri = lsDocumentUri::FromPath(file1.def->path); - result.range.start.line = result.range.end.line = include.line; - out.result.push_back(std::move(result)); + lsLocation &loc = out.result.emplace_back(); + loc.uri = lsDocumentUri::FromPath(file1.def->path); + loc.range.start.line = loc.range.end.line = include.line; break; } } diff --git a/src/messages/textDocument_typeDefinition.cc b/src/messages/textDocument_typeDefinition.cc index 30786850..812bfe4a 100644 --- a/src/messages/textDocument_typeDefinition.cc +++ b/src/messages/textDocument_typeDefinition.cc @@ -28,13 +28,6 @@ struct In_TextDocumentTypeDefinition : public RequestInMessage { MAKE_REFLECT_STRUCT(In_TextDocumentTypeDefinition, id, params); REGISTER_IN_MESSAGE(In_TextDocumentTypeDefinition); -struct Out_TextDocumentTypeDefinition - : public lsOutMessage { - lsRequestId id; - std::vector result; -}; -MAKE_REFLECT_STRUCT(Out_TextDocumentTypeDefinition, jsonrpc, id, result); - struct Handler_TextDocumentTypeDefinition : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -47,19 +40,17 @@ struct Handler_TextDocumentTypeDefinition WorkingFile *working_file = working_files->GetFileByFilename(file->def->path); - Out_TextDocumentTypeDefinition out; + Out_LocationList 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)) + if (auto ls_loc = GetLsLocation(db, working_files, *def.spell)) 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)) + if (auto ls_loc = GetLsLocation(db, working_files, dr)) out.result.push_back(*ls_loc); }; for (SymbolRef sym : diff --git a/src/query.cc b/src/query.cc index f052c42c..07f67ace 100644 --- a/src/query.cc +++ b/src/query.cc @@ -34,8 +34,6 @@ void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Use &use) { use.file_id = file_id; else use.file_id = lid2file_id.find(use.file_id)->second; - if (use.kind == SymbolKind::File) - use.usr = use.file_id; } template @@ -238,7 +236,7 @@ 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}}; + SymbolRef sym{use.range, usr, kind, use.role}; if (k & 1) { int &v = files[use.file_id].symbol2refcnt[sym]; v += delta; @@ -258,7 +256,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { 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; + .outline2refcnt[SymbolRef{dr.extent, usr, kind, dr.role}] += delta; }; auto UpdateUses = @@ -401,12 +399,12 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, 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}}]++; + 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}}]++; + def.extent->range, u.first, SymbolKind::Func, def.extent->role}]++; } auto R = func_usr.try_emplace({u.first}, func_usr.size()); @@ -428,12 +426,12 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, 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}}]++; + 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}}]++; + def.extent->range, u.first, SymbolKind::Type, def.extent->role}]++; } auto R = type_usr.try_emplace({u.first}, type_usr.size()); if (R.second) @@ -454,12 +452,12 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, 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}}]++; + 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}}]++; + def.extent->range, u.first, SymbolKind::Var, def.extent->role}]++; } auto R = var_usr.try_emplace({u.first}, var_usr.size()); if (R.second) diff --git a/src/query.h b/src/query.h index 3cc50fd6..d968a3a6 100644 --- a/src/query.h +++ b/src/query.h @@ -85,17 +85,17 @@ struct QueryFunc : QueryEntity { Usr usr; llvm::SmallVector def; std::vector declarations; - std::vector uses; std::vector derived; + std::vector uses; }; struct QueryType : QueryEntity { Usr usr; llvm::SmallVector def; std::vector declarations; - std::vector uses; std::vector derived; std::vector instances; + std::vector uses; }; struct QueryVar : QueryEntity { diff --git a/src/query_utils.cc b/src/query_utils.cc index 27ce5f71..db7a3be7 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -61,8 +61,7 @@ Maybe GetDefinitionSpell(DB *db, SymbolIdx sym) { Maybe GetDefinitionExtent(DB *db, SymbolIdx sym) { // Used to jump to file. if (sym.kind == SymbolKind::File) - return Use{{Range{{0, 0}, {0, 0}}, sym.usr, sym.kind, Role::None}, - int(sym.usr)}; + return Use{{Range{{0, 0}, {0, 0}}, Role::None}, int(sym.usr)}; Maybe ret; EachEntityDef(db, sym, [&](const auto &def) { return !(ret = def.extent); }); return ret; @@ -216,40 +215,27 @@ lsDocumentUri GetLsDocumentUri(DB *db, int file_id) { } } -std::optional GetLsLocation(DB *db, WorkingFiles *working_files, +std::optional GetLsLocation(DB *db, WorkingFiles *wfiles, Use use) { std::string path; lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path); std::optional range = - GetLsRange(working_files->GetFileByFilename(path), use.range); + GetLsRange(wfiles->GetFileByFilename(path), use.range); if (!range) return std::nullopt; return lsLocation{uri, *range}; } -std::optional GetLsLocationEx(DB *db, WorkingFiles *working_files, - Use use, bool container) { - std::optional ls_loc = GetLsLocation(db, working_files, use); - if (!ls_loc) - return std::nullopt; - lsLocationEx ret; - ret.lsLocation::operator=(*ls_loc); - if (container) { - ret.role = uint16_t(use.role); - EachEntityDef(db, use, [&](const auto &def) { - ret.containerName = std::string_view(def.detailed_name); - return false; - }); - } - return ret; +std::optional GetLsLocation(DB *db, WorkingFiles *wfiles, + SymbolRef sym, int file_id) { + return GetLsLocation(db, wfiles, Use{{sym.range, sym.role}, file_id}); } -std::vector GetLsLocationExs(DB *db, WorkingFiles *working_files, - const std::vector &uses) { - std::vector ret; +std::vector GetLsLocations(DB *db, WorkingFiles *wfiles, + const std::vector &uses) { + std::vector ret; for (Use use : uses) - if (auto loc = - GetLsLocationEx(db, working_files, use, g_config->xref.container)) + if (auto loc = GetLsLocation(db, wfiles, use)) ret.push_back(*loc); std::sort(ret.begin(), ret.end()); ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); diff --git a/src/query_utils.h b/src/query_utils.h index 642a6ba1..e5641bd9 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -39,12 +39,11 @@ std::optional GetLsRange(WorkingFile *working_file, lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path); lsDocumentUri GetLsDocumentUri(DB *db, int file_id); -std::optional GetLsLocation(DB *db, WorkingFiles *working_files, - Use use); -std::optional GetLsLocationEx(DB *db, WorkingFiles *working_files, - Use use, bool container); -std::vector GetLsLocationExs(DB *db, WorkingFiles *working_files, - const std::vector &refs); +std::optional GetLsLocation(DB *db, WorkingFiles *wfiles, Use use); +std::optional GetLsLocation(DB *db, WorkingFiles *wfiles, + SymbolRef sym, int file_id); +std::vector GetLsLocations(DB *db, WorkingFiles *wfiles, + const std::vector &uses); // Returns a symbol. The symbol will *NOT* have a location assigned. std::optional GetSymbolInfo(DB *db, SymbolIdx sym, bool detailed); diff --git a/src/serializer.cc b/src/serializer.cc index 68c80493..07e1b2f5 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -255,45 +255,49 @@ template void ReflectShortName(Writer &visitor, Def &def) { } } -template void Reflect(TVisitor &visitor, IndexType &value) { - REFLECT_MEMBER_START(); - REFLECT_MEMBER2("usr", value.usr); - REFLECT_MEMBER2("detailed_name", value.def.detailed_name); - REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset); - ReflectShortName(visitor, value.def); - REFLECT_MEMBER2("kind", value.def.kind); - ReflectHoverAndComments(visitor, value.def); - REFLECT_MEMBER2("declarations", value.declarations); - REFLECT_MEMBER2("spell", value.def.spell); - REFLECT_MEMBER2("extent", value.def.extent); - REFLECT_MEMBER2("alias_of", value.def.alias_of); - REFLECT_MEMBER2("bases", value.def.bases); - REFLECT_MEMBER2("derived", value.derived); - REFLECT_MEMBER2("types", value.def.types); - REFLECT_MEMBER2("funcs", value.def.funcs); - REFLECT_MEMBER2("vars", value.def.vars); - REFLECT_MEMBER2("instances", value.instances); - REFLECT_MEMBER2("uses", value.uses); - REFLECT_MEMBER_END(); -} - template void Reflect(TVisitor &visitor, IndexFunc &value) { REFLECT_MEMBER_START(); REFLECT_MEMBER2("usr", value.usr); REFLECT_MEMBER2("detailed_name", value.def.detailed_name); REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset); ReflectShortName(visitor, value.def); - REFLECT_MEMBER2("kind", value.def.kind); - REFLECT_MEMBER2("storage", value.def.storage); + REFLECT_MEMBER2("spell", value.def.spell); + REFLECT_MEMBER2("extent", value.def.extent); ReflectHoverAndComments(visitor, value.def); + REFLECT_MEMBER2("bases", value.def.bases); + REFLECT_MEMBER2("vars", value.def.vars); + REFLECT_MEMBER2("callees", value.def.callees); + REFLECT_MEMBER2("kind", value.def.kind); + REFLECT_MEMBER2("parent_kind", value.def.parent_kind); + REFLECT_MEMBER2("storage", value.def.storage); + REFLECT_MEMBER2("declarations", value.declarations); + REFLECT_MEMBER2("derived", value.derived); + REFLECT_MEMBER2("uses", value.uses); + REFLECT_MEMBER_END(); +} + +template void Reflect(TVisitor &visitor, IndexType &value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER2("usr", value.usr); + REFLECT_MEMBER2("detailed_name", value.def.detailed_name); + REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset); + ReflectShortName(visitor, value.def); + ReflectHoverAndComments(visitor, value.def); REFLECT_MEMBER2("spell", value.def.spell); REFLECT_MEMBER2("extent", value.def.extent); REFLECT_MEMBER2("bases", value.def.bases); - REFLECT_MEMBER2("derived", value.derived); + REFLECT_MEMBER2("funcs", value.def.funcs); + REFLECT_MEMBER2("types", value.def.types); REFLECT_MEMBER2("vars", value.def.vars); + REFLECT_MEMBER2("alias_of", value.def.alias_of); + REFLECT_MEMBER2("kind", value.def.kind); + REFLECT_MEMBER2("parent_kind", value.def.parent_kind); + + REFLECT_MEMBER2("declarations", value.declarations); + REFLECT_MEMBER2("derived", value.derived); + REFLECT_MEMBER2("instances", value.instances); REFLECT_MEMBER2("uses", value.uses); - REFLECT_MEMBER2("callees", value.def.callees); REFLECT_MEMBER_END(); } @@ -304,13 +308,15 @@ template void Reflect(TVisitor &visitor, IndexVar &value) { REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset); ReflectShortName(visitor, value.def); ReflectHoverAndComments(visitor, value.def); - REFLECT_MEMBER2("declarations", value.declarations); REFLECT_MEMBER2("spell", value.def.spell); REFLECT_MEMBER2("extent", value.def.extent); REFLECT_MEMBER2("type", value.def.type); - REFLECT_MEMBER2("uses", value.uses); REFLECT_MEMBER2("kind", value.def.kind); + REFLECT_MEMBER2("parent_kind", value.def.parent_kind); REFLECT_MEMBER2("storage", value.def.storage); + + REFLECT_MEMBER2("declarations", value.declarations); + REFLECT_MEMBER2("uses", value.uses); REFLECT_MEMBER_END(); }