Redesign SymbolRef, Ref, Use

Remove lsLocationEx
This commit is contained in:
Fangrui Song 2018-10-04 16:13:30 -07:00
parent 38feb8d277
commit 6ec032c2a0
20 changed files with 292 additions and 377 deletions

View File

@ -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,

View File

@ -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<RecordDecl>(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<CXXMethodDecl>(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<Decl>(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<Decl>(SemDC), entity->def.parent_kind);
} else if (is_decl) {
DeclRef &dr = entity->declarations.emplace_back();
static_cast<Use&>(dr) = GetUse(db, lid, loc, LexDC, role);
static_cast<Use&>(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<Decl>(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<Decl>(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<Decl>(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<Decl>(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<NamespaceDecl>(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<NamespaceDecl>(D);
auto *ND1 = cast<Decl>(ND->getParent());
@ -876,7 +923,6 @@ public:
}
break;
case Decl::NamespaceAlias: {
type->def.kind = lsSymbolKind::TypeAlias;
auto *NAD = cast<NamespaceAliasDecl>(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<CXXRecordDecl>(D);
@ -930,9 +946,6 @@ public:
[[fallthrough]];
case Decl::Record:
if (auto *RD = dyn_cast<RecordDecl>(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<TypedefNameDecl>(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<CXXMethodDecl>(D);
func->def.kind =
MD->isStatic() ? lsSymbolKind::StaticMethod : lsSymbolKind::Method;
case Decl::CXXMethod:
if (is_def || is_decl) {
if (auto *ND = dyn_cast<NamedDecl>(D)) {
SmallVector<const NamedDecl *, 8> 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<EnumConstantDecl>(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<Use&>(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<char *>(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<char *>(t.c_str());
v.range = Range::FromString(s);
s = strchr(s, '|');
v.usr = strtoull(s + 1, &s, 10);
v.kind = static_cast<SymbolKind>(strtol(s + 1, &s, 10));
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, static_cast<Reference &>(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<Reference &>(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<SymbolKind>(strtol(s + 1, &s, 10));
s = strchr(s, '|');
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(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 {

View File

@ -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<Range, Usr, SymbolKind, Role> 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<Range, Role> 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<FuncDef> {
// Method this method overrides.
std::vector<Usr> bases;
// Local variables or parameters.
std::vector<Usr> vars;
// Functions that this function calls.
std::vector<SymbolRef> 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<Usr> 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<IndexFunc> {
using Def = FuncDef;
Usr usr;
Def def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
std::vector<Use> uses;
};
struct TypeDef : NameMixin<TypeDef> {
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
std::vector<Usr> bases;
// Types, functions, and variables defined in this type.
std::vector<Usr> types;
std::vector<Usr> funcs;
std::vector<Usr> types;
std::vector<std::pair<Usr, int64_t>> 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<Usr> 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<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
std::vector<Usr> instances;
std::vector<Use> uses;
};
struct VarDef : NameMixin<VarDef> {
@ -195,27 +200,29 @@ struct VarDef : NameMixin<VarDef> {
// 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<Usr> 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;

View File

@ -198,15 +198,6 @@ enum class lsSymbolKind : uint8_t {
};
MAKE_REFLECT_TYPE_PROXY(lsSymbolKind);
// ccls extension
struct lsLocationEx : lsLocation {
std::optional<std::string_view> containerName;
std::optional<lsSymbolKind> parentKind;
// Avoid circular dependency on symbol.h
std::optional<uint16_t> 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<Out_LocationList> {
lsRequestId id;
std::vector<lsLocationEx> result;
std::vector<lsLocation> result;
};
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);

View File

@ -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;
}
}

View File

@ -77,6 +77,8 @@ struct Out_CclsCall : public lsOutMessage<Out_CclsCall> {
int numChildren;
// Empty if the |levels| limit is reached.
std::vector<Entry> 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<SymbolRef> 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;
}

View File

@ -104,7 +104,7 @@ struct Handler_CclsNavigate : BaseMessageHandler<In_CclsNavigate> {
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;
}

View File

@ -63,7 +63,7 @@ struct Handler_CclsVars : BaseMessageHandler<In_CclsVars> {
[[fallthrough]];
}
case SymbolKind::Type:
out.result = GetLsLocationExs(
out.result = GetLsLocations(
db, working_files,
GetVarDeclarations(db, db->Type(usr).instances, params.kind));
break;

View File

@ -117,19 +117,19 @@ struct Handler_TextDocumentCodeLens
code_lens.command->arguments.push_back(ToString(show));
};
auto ToSpell = [&](Use use) {
Maybe<Use> 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<Use> 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<Range> 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);

View File

@ -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<Out_TextDocumentDefinition> {
lsRequestId id;
std::vector<lsLocationEx> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<Use> 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<Use> 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> 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);
}
}
}

View File

@ -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)

View File

@ -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<lsLocation> 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);
}
}

View File

@ -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;
}
}

View File

@ -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<Out_TextDocumentReferences> {
lsRequestId id;
std::vector<lsLocationEx> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentReferences, jsonrpc, id, result);
struct Handler_TextDocumentReferences
: BaseMessageHandler<In_TextDocumentReferences> {
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<Use> 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<lsLocationEx> 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;
}
}

View File

@ -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<Out_TextDocumentTypeDefinition> {
lsRequestId id;
std::vector<lsLocationEx> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentTypeDefinition, jsonrpc, id, result);
struct Handler_TextDocumentTypeDefinition
: BaseMessageHandler<In_TextDocumentTypeDefinition> {
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 :

View File

@ -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 <typename T>
@ -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)

View File

@ -85,17 +85,17 @@ struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
Usr usr;
llvm::SmallVector<Def, 1> def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
std::vector<Use> uses;
};
struct QueryType : QueryEntity<QueryType, TypeDef> {
Usr usr;
llvm::SmallVector<Def, 1> def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
std::vector<Usr> instances;
std::vector<Use> uses;
};
struct QueryVar : QueryEntity<QueryVar, VarDef> {

View File

@ -61,8 +61,7 @@ Maybe<Use> GetDefinitionSpell(DB *db, SymbolIdx sym) {
Maybe<Use> 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<Use> 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<lsLocation> GetLsLocation(DB *db, WorkingFiles *working_files,
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
Use use) {
std::string path;
lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path);
std::optional<lsRange> 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<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files,
Use use, bool container) {
std::optional<lsLocation> 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<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
SymbolRef sym, int file_id) {
return GetLsLocation(db, wfiles, Use{{sym.range, sym.role}, file_id});
}
std::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files,
const std::vector<Use> &uses) {
std::vector<lsLocationEx> ret;
std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
const std::vector<Use> &uses) {
std::vector<lsLocation> 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());

View File

@ -39,12 +39,11 @@ std::optional<lsRange> GetLsRange(WorkingFile *working_file,
lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path);
lsDocumentUri GetLsDocumentUri(DB *db, int file_id);
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *working_files,
Use use);
std::optional<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files,
Use use, bool container);
std::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files,
const std::vector<Use> &refs);
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles, Use use);
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
SymbolRef sym, int file_id);
std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
const std::vector<Use> &uses);
// Returns a symbol. The symbol will *NOT* have a location assigned.
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
bool detailed);

View File

@ -255,45 +255,49 @@ template <typename Def> void ReflectShortName(Writer &visitor, Def &def) {
}
}
template <typename TVisitor> 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 <typename TVisitor> 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 <typename TVisitor> 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 <typename TVisitor> 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();
}