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; } workspaceSymbol;
struct Xref { struct Xref {
// If true, |Location[]| response will include lexical container.
bool container = false;
// Maximum number of definition/reference/... results. // Maximum number of definition/reference/... results.
int maxNum = 2000; int maxNum = 2000;
} xref; } xref;
@ -274,7 +272,7 @@ MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist,
multiVersionWhitelist, onChange, threads, trackDependency, multiVersionWhitelist, onChange, threads, trackDependency,
whitelist); whitelist);
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); 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, MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand,
compilationDatabaseDirectory, cacheDirectory, cacheFormat, compilationDatabaseDirectory, cacheDirectory, cacheFormat,
clang, client, codeLens, completion, diagnostics, highlight, clang, client, codeLens, completion, diagnostics, highlight,

View File

@ -117,50 +117,109 @@ StringRef GetSourceInRange(const SourceManager &SM, const LangOptions &LangOpts,
BInfo.second); BInfo.second);
} }
SymbolKind GetSymbolKind(const Decl *D) { SymbolKind GetSymbolKind(const Decl *D, lsSymbolKind &kind) {
switch (D->getKind()) { switch (D->getKind()) {
case Decl::TranslationUnit: case Decl::LinkageSpec:
return SymbolKind::File; return SymbolKind::Invalid;
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::Namespace: case Decl::Namespace:
kind = lsSymbolKind::Namespace;
return SymbolKind::Type;
case Decl::NamespaceAlias: case Decl::NamespaceAlias:
kind = lsSymbolKind::TypeAlias;
return SymbolKind::Type;
case Decl::ObjCCategory: case Decl::ObjCCategory:
case Decl::ObjCImplementation:
case Decl::ObjCInterface: case Decl::ObjCInterface:
case Decl::ObjCProtocol: 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: case Decl::ClassTemplate:
kind = lsSymbolKind::Class;
return SymbolKind::Type;
case Decl::FunctionTemplate:
kind = lsSymbolKind::Function;
return SymbolKind::Func;
case Decl::TypeAliasTemplate: case Decl::TypeAliasTemplate:
kind = lsSymbolKind::TypeAlias;
return SymbolKind::Type;
case Decl::VarTemplate:
kind = lsSymbolKind::Variable;
return SymbolKind::Var;
case Decl::TemplateTemplateParm: case Decl::TemplateTemplateParm:
kind = lsSymbolKind::TypeParameter;
return SymbolKind::Type;
case Decl::Enum: case Decl::Enum:
case Decl::Record: kind = lsSymbolKind::Enum;
return SymbolKind::Type;
case Decl::CXXRecord: 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::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization: case Decl::ClassTemplatePartialSpecialization:
kind = lsSymbolKind::Class;
return SymbolKind::Type;
case Decl::TypeAlias: case Decl::TypeAlias:
case Decl::Typedef: case Decl::Typedef:
case Decl::UnresolvedUsingTypename: case Decl::UnresolvedUsingTypename:
kind = lsSymbolKind::TypeAlias;
return SymbolKind::Type; return SymbolKind::Type;
case Decl::ObjCProperty:
case Decl::VarTemplate:
case Decl::Binding: case Decl::Binding:
kind = lsSymbolKind::Variable;
return SymbolKind::Var;
case Decl::Field: case Decl::Field:
case Decl::ObjCIvar: 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::Var:
case Decl::ParmVar:
case Decl::ImplicitParam:
case Decl::Decomposition: 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::VarTemplateSpecialization:
case Decl::VarTemplatePartialSpecialization: case Decl::VarTemplatePartialSpecialization:
case Decl::EnumConstant: kind = lsSymbolKind::Variable;
case Decl::UnresolvedUsingValue:
return SymbolKind::Var; 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: default:
LOG_S(INFO) << "unhandled " << int(D->getKind());
return SymbolKind::Invalid; return SymbolKind::Invalid;
} }
} }
@ -421,23 +480,6 @@ public:
return it->second.usr; 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 GetDefaultPolicy() const {
PrintingPolicy PP(Ctx->getLangOpts()); PrintingPolicy PP(Ctx->getLangOpts());
PP.AnonymousTagLocations = false; PP.AnonymousTagLocations = false;
@ -590,7 +632,7 @@ public:
return; return;
Range spell = Range spell =
FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, 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) { switch (kind) {
case SymbolKind::Func: case SymbolKind::Func:
db->ToFunc(usr).uses.push_back(use); db->ToFunc(usr).uses.push_back(use);
@ -704,7 +746,8 @@ public:
IndexFunc *func = nullptr; IndexFunc *func = nullptr;
IndexType *type = nullptr; IndexType *type = nullptr;
IndexVar *var = nullptr; IndexVar *var = nullptr;
SymbolKind kind = GetSymbolKind(D); lsSymbolKind ls_kind;
SymbolKind kind = GetSymbolKind(D, ls_kind);
if (is_def) if (is_def)
switch (D->getKind()) { switch (D->getKind()) {
@ -734,19 +777,20 @@ public:
auto do_def_decl = [&](auto *entity) { auto do_def_decl = [&](auto *entity) {
if (is_def) { if (is_def) {
entity->def.spell = GetUse(db, lid, loc, SemDC, role); entity->def.spell = {{loc, role}, lid};
SourceRange R = OrigD->getSourceRange(); SourceRange R = OrigD->getSourceRange();
entity->def.extent = entity->def.extent = {
GetUse(db, lid, {R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc,
R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc, Role::None},
LexDC, Role::None); lid};
GetSymbolKind(cast<Decl>(SemDC), entity->def.parent_kind);
} else if (is_decl) { } else if (is_decl) {
DeclRef &dr = entity->declarations.emplace_back(); 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(); SourceRange R = OrigD->getSourceRange();
dr.extent = R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc; dr.extent = R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc;
} else { } else {
entity->uses.push_back(GetUse(db, lid, loc, LexDC, role)); entity->uses.push_back({{loc, role}, lid});
return; return;
} }
if (entity->def.comments[0] == '\0' && g_config->index.comments) if (entity->def.comments[0] == '\0' && g_config->index.comments)
@ -761,6 +805,7 @@ public:
return true; return true;
case SymbolKind::Func: case SymbolKind::Func:
func = &db->ToFunc(usr); func = &db->ToFunc(usr);
func->def.kind = ls_kind;
// Mark as Role::Implicit to span one more column to the left/right. // Mark as Role::Implicit to span one more column to the left/right.
if (!is_def && !is_decl && if (!is_def && !is_decl &&
(D->getKind() == Decl::CXXConstructor || (D->getKind() == Decl::CXXConstructor ||
@ -773,17 +818,18 @@ public:
SetName(D, info->short_name, info->qualified, func->def); SetName(D, info->short_name, info->qualified, func->def);
if (is_def || is_decl) { if (is_def || is_decl) {
const Decl *DC = cast<Decl>(SemDC); 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); db->ToType(GetUsr(DC)).def.funcs.push_back(usr);
} else { } else {
const Decl *DC = cast<Decl>(LexDC); const Decl *DC = cast<Decl>(LexDC);
if (GetSymbolKind(DC) == SymbolKind::Func) if (GetSymbolKind(DC, ls_kind) == SymbolKind::Func)
db->ToFunc(GetUsr(DC)) db->ToFunc(GetUsr(DC))
.def.callees.push_back({{loc, usr, SymbolKind::Func, role}}); .def.callees.push_back({loc, usr, SymbolKind::Func, role});
} }
break; break;
case SymbolKind::Type: case SymbolKind::Type:
type = &db->ToType(usr); type = &db->ToType(usr);
type->def.kind = ls_kind;
do_def_decl(type); do_def_decl(type);
if (Spell != Loc) if (Spell != Loc)
AddMacroUse(db, SM, usr, SymbolKind::Type, Spell); AddMacroUse(db, SM, usr, SymbolKind::Type, Spell);
@ -791,12 +837,13 @@ public:
SetName(D, info->short_name, info->qualified, type->def); SetName(D, info->short_name, info->qualified, type->def);
if (is_def || is_decl) { if (is_def || is_decl) {
const Decl *DC = cast<Decl>(SemDC); 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); db->ToType(GetUsr(DC)).def.types.push_back(usr);
} }
break; break;
case SymbolKind::Var: case SymbolKind::Var:
var = &db->ToVar(usr); var = &db->ToVar(usr);
var->def.kind = ls_kind;
do_def_decl(var); do_def_decl(var);
if (Spell != Loc) if (Spell != Loc)
AddMacroUse(db, SM, usr, SymbolKind::Var, Spell); AddMacroUse(db, SM, usr, SymbolKind::Var, Spell);
@ -809,7 +856,7 @@ public:
T = FD->getType(); T = FD->getType();
if (is_def || is_decl) { if (is_def || is_decl) {
const Decl *DC = cast<Decl>(SemDC); 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); db->ToFunc(GetUsr(DC)).def.vars.push_back(usr);
else if (auto *ND = dyn_cast<NamespaceDecl>(SemDC)) else if (auto *ND = dyn_cast<NamespaceDecl>(SemDC))
db->ToType(GetUsr(ND)).def.vars.emplace_back(usr, -1); db->ToType(GetUsr(ND)).def.vars.emplace_back(usr, -1);
@ -828,14 +875,15 @@ public:
Usr usr1 = GetUsr(D1, &info1); Usr usr1 = GetUsr(D1, &info1);
IndexType &type1 = db->ToType(usr1); IndexType &type1 = db->ToType(usr1);
SourceLocation L1 = D1->getLocation(); SourceLocation L1 = D1->getLocation();
type1.def.spell = type1.def.spell = {
GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, {FromTokenRange(SM, Lang, {L1, L1}), Role::Definition},
Role::Definition); lid};
type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), type1.def.extent = {{FromTokenRange(SM, Lang, R1), Role::None},
LexDC, Role::None); lid};
type1.def.detailed_name = Intern(info1->short_name); type1.def.detailed_name = Intern(info1->short_name);
type1.def.short_name_size = int16_t(info1->short_name.size()); type1.def.short_name_size = int16_t(info1->short_name.size());
type1.def.kind = lsSymbolKind::TypeParameter; type1.def.kind = lsSymbolKind::TypeParameter;
type1.def.parent_kind = lsSymbolKind::Class;
var->def.type = usr1; var->def.type = usr1;
type1.instances.push_back(usr); type1.instances.push_back(usr);
break; break;
@ -852,11 +900,11 @@ public:
// e.g. lambda parameter // e.g. lambda parameter
SourceLocation L = D->getLocation(); SourceLocation L = D->getLocation();
if (SM.getFileID(L) == LocFID) { if (SM.getFileID(L) == LocFID) {
var->def.spell = GetUse(db, lid, FromTokenRange(SM, Lang, {L, L}), var->def.spell = {
SemDC, Role::Definition); {FromTokenRange(SM, Lang, {L, L}), Role::Definition}, lid};
var->def.extent = var->def.extent = {
GetUse(db, lid, FromTokenRange(SM, Lang, D->getSourceRange()), {FromTokenRange(SM, Lang, D->getSourceRange()), Role::None}, lid};
LexDC, Role::None); var->def.parent_kind = lsSymbolKind::Method;
} }
} }
break; break;
@ -864,7 +912,6 @@ public:
switch (D->getKind()) { switch (D->getKind()) {
case Decl::Namespace: case Decl::Namespace:
type->def.kind = lsSymbolKind::Namespace;
if (D->isFirstDecl()) { if (D->isFirstDecl()) {
auto *ND = cast<NamespaceDecl>(D); auto *ND = cast<NamespaceDecl>(D);
auto *ND1 = cast<Decl>(ND->getParent()); auto *ND1 = cast<Decl>(ND->getParent());
@ -876,7 +923,6 @@ public:
} }
break; break;
case Decl::NamespaceAlias: { case Decl::NamespaceAlias: {
type->def.kind = lsSymbolKind::TypeAlias;
auto *NAD = cast<NamespaceAliasDecl>(D); auto *NAD = cast<NamespaceAliasDecl>(D);
if (const NamespaceDecl *ND = NAD->getNamespace()) { if (const NamespaceDecl *ND = NAD->getNamespace()) {
Usr usr1 = GetUsr(ND); Usr usr1 = GetUsr(ND);
@ -885,36 +931,6 @@ public:
} }
break; 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: case Decl::CXXRecord:
if (is_def) { if (is_def) {
auto *RD = dyn_cast<CXXRecordDecl>(D); auto *RD = dyn_cast<CXXRecordDecl>(D);
@ -930,9 +946,6 @@ public:
[[fallthrough]]; [[fallthrough]];
case Decl::Record: case Decl::Record:
if (auto *RD = dyn_cast<RecordDecl>(D)) { 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()) { if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) {
StringRef Tag; StringRef Tag;
switch (RD->getTagKind()) { switch (RD->getTagKind()) {
@ -990,7 +1003,6 @@ public:
case Decl::TypeAlias: case Decl::TypeAlias:
case Decl::Typedef: case Decl::Typedef:
case Decl::UnresolvedUsingTypename: case Decl::UnresolvedUsingTypename:
type->def.kind = lsSymbolKind::TypeAlias;
if (auto *TD = dyn_cast<TypedefNameDecl>(D)) { if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
bool specialization = false; bool specialization = false;
QualType T = TD->getUnderlyingType(); QualType T = TD->getUnderlyingType();
@ -1002,29 +1014,14 @@ public:
if (specialization) { if (specialization) {
const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); const TypeSourceInfo *TSI = TD->getTypeSourceInfo();
SourceLocation L1 = TSI->getTypeLoc().getBeginLoc(); SourceLocation L1 = TSI->getTypeLoc().getBeginLoc();
if (SM.getFileID(L1) == LocFID) { if (SM.getFileID(L1) == LocFID)
Range loc1 = FromTokenRange(SM, Lang, {L1, L1});
type1.uses.push_back( type1.uses.push_back(
GetUse(db, lid, loc1, LexDC, Role::Reference)); {{FromTokenRange(SM, Lang, {L1, L1}), Role::Reference}, lid});
}
} }
} }
} }
break; break;
case Decl::Binding: case Decl::CXXMethod:
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;
if (is_def || is_decl) { if (is_def || is_decl) {
if (auto *ND = dyn_cast<NamedDecl>(D)) { if (auto *ND = dyn_cast<NamedDecl>(D)) {
SmallVector<const NamedDecl *, 8> OverDecls; SmallVector<const NamedDecl *, 8> OverDecls;
@ -1037,29 +1034,7 @@ public:
} }
} }
break; 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: case Decl::EnumConstant:
var->def.kind = lsSymbolKind::EnumMember;
if (is_def && strchr(var->def.detailed_name, '=') == nullptr) { if (is_def && strchr(var->def.detailed_name, '=') == nullptr) {
auto *ECD = cast<EnumConstantDecl>(D); auto *ECD = cast<EnumConstantDecl>(D);
const auto &Val = ECD->getInitVal(); const auto &Val = ECD->getInitVal();
@ -1069,11 +1044,7 @@ public:
var->def.hover = Intern(var->def.detailed_name + init); var->def.hover = Intern(var->def.detailed_name + init);
} }
break; break;
case Decl::UnresolvedUsingValue:
var->def.kind = lsSymbolKind::Variable;
break;
default: default:
LOG_S(INFO) << "Unhandled " << int(D->getKind());
break; break;
} }
return true; return true;
@ -1131,16 +1102,17 @@ public:
IndexVar &var = db->ToVar(usr); IndexVar &var = db->ToVar(usr);
auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID); auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID);
var.def.kind = lsSymbolKind::Macro; var.def.kind = lsSymbolKind::Macro;
var.def.parent_kind = lsSymbolKind::File;
if (var.def.spell) { if (var.def.spell) {
DeclRef &d = var.declarations.emplace_back(); DeclRef &d = var.declarations.emplace_back();
static_cast<Use&>(d) = *var.def.spell; static_cast<Use&>(d) = *var.def.spell;
d.extent = var.def.spell->range; 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(); const MacroInfo *MI = MD->getMacroInfo();
SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
range = FromTokenRange(SM, param.Ctx->getLangOpts(), R); 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') { if (var.def.detailed_name[0] == '\0') {
var.def.detailed_name = Intern(Name); var.def.detailed_name = Intern(Name);
var.def.short_name_size = Name.size(); var.def.short_name_size = Name.size();
@ -1162,8 +1134,8 @@ public:
if (IndexFile *db = param.ConsumeFile(*FE)) { if (IndexFile *db = param.ConsumeFile(*FE)) {
IndexVar &var = db->ToVar(GetMacro(Tok).second); IndexVar &var = db->ToVar(GetMacro(Tok).second);
var.uses.push_back( var.uses.push_back(
{{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), 0, {{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID),
SymbolKind::File, Role::Dynamic}}); Role::Dynamic}});
} }
} }
void MacroUndefined(const Token &Tok, const MacroDefinition &MD, void MacroUndefined(const Token &Tok, const MacroDefinition &MD,
@ -1198,7 +1170,7 @@ public:
}; };
} // namespace } // namespace
const int IndexFile::kMajorVersion = 18; const int IndexFile::kMajorVersion = 19;
const int IndexFile::kMinorVersion = 0; const int IndexFile::kMinorVersion = 0;
IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, 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 } // namespace ccls::idx
// |SymbolRef| is serialized this way. void Reflect(Reader &vis, SymbolRef &v) {
// |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) {
if (vis.Format() == SerializeFormat::Json) { if (vis.Format() == SerializeFormat::Json) {
std::string t = vis.GetString(); std::string t = vis.GetString();
char *s = const_cast<char *>(t.c_str()); char *s = const_cast<char *>(t.c_str());
@ -1409,7 +1378,7 @@ void Reflect(Reader &vis, Reference &v) {
Reflect(vis, v.role); Reflect(vis, v.role);
} }
} }
void Reflect(Writer &vis, Reference &v) { void Reflect(Writer &vis, SymbolRef &v) {
if (vis.Format() == SerializeFormat::Json) { if (vis.Format() == SerializeFormat::Json) {
char buf[99]; char buf[99];
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", 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()); char *s = const_cast<char *>(t.c_str());
v.range = Range::FromString(s); v.range = Range::FromString(s);
s = strchr(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.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10)); v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else { } else {
Reflect(vis, static_cast<Reference &>(v)); Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id); Reflect(vis, v.file_id);
} }
} }
void Reflect(Writer &vis, Use &v) { void Reflect(Writer &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) { if (vis.Format() == SerializeFormat::Json) {
char buf[99]; char buf[99];
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d|%d", snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(),
v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role), int(v.role), v.file_id);
v.file_id);
std::string s(buf); std::string s(buf);
Reflect(vis, s); Reflect(vis, s);
} else { } else {
Reflect(vis, static_cast<Reference &>(v)); Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id); Reflect(vis, v.file_id);
} }
} }
@ -1460,9 +1428,7 @@ void Reflect(Reader &vis, DeclRef &v) {
v.range = Range::FromString(s); v.range = Range::FromString(s);
s = strchr(s, '|') + 1; s = strchr(s, '|') + 1;
v.extent = Range::FromString(s); v.extent = Range::FromString(s);
s = strchr(s, '|') + 1; s = strchr(s, '|');
v.usr = strtoull(s, &s, 10);
v.kind = static_cast<SymbolKind>(strtol(s + 1, &s, 10));
v.role = static_cast<Role>(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)); v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else { } else {
@ -1473,9 +1439,8 @@ void Reflect(Reader &vis, DeclRef &v) {
void Reflect(Writer &vis, DeclRef &v) { void Reflect(Writer &vis, DeclRef &v) {
if (vis.Format() == SerializeFormat::Json) { if (vis.Format() == SerializeFormat::Json) {
char buf[99]; char buf[99];
snprintf(buf, sizeof buf, "%s|%s|%" PRIu64 "|%d|%d|%d", snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(),
v.range.ToString().c_str(), v.extent.ToString().c_str(), v.usr, v.extent.ToString().c_str(), int(v.role), v.file_id);
int(v.kind), int(v.role), v.file_id);
std::string s(buf); std::string s(buf);
Reflect(vis, s); Reflect(vis, s);
} else { } else {

View File

@ -49,28 +49,36 @@ struct SymbolIdx {
}; };
MAKE_REFLECT_STRUCT(SymbolIdx, usr, kind); MAKE_REFLECT_STRUCT(SymbolIdx, usr, kind);
struct Reference { // |id,kind| refer to the referenced entity.
struct SymbolRef {
Range range; Range range;
Usr usr; Usr usr;
SymbolKind kind; SymbolKind kind;
Role role; Role role;
bool Valid() const { return range.Valid(); }
operator SymbolIdx() const { return {usr, kind}; } operator SymbolIdx() const { return {usr, kind}; }
std::tuple<Range, Usr, SymbolKind, Role> ToTuple() const { std::tuple<Range, Usr, SymbolKind, Role> ToTuple() const {
return std::make_tuple(range, usr, kind, role); return std::make_tuple(range, usr, kind, role);
} }
bool operator==(const Reference &o) const { return ToTuple() == o.ToTuple(); } bool operator==(const SymbolRef &o) const { return ToTuple() == o.ToTuple(); }
bool operator<(const Reference &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); 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 // Represents an occurrence of a variable/type, |usr,kind| refer to the lexical
// parent. // parent.
struct Use : Reference { struct Use : Ref {
// |file| is used in Query* but not in Index* // |file| is used in Query* but not in Index*
int file_id = -1; int file_id = -1;
bool operator==(const Use &o) const { bool operator==(const Use &o) const {
@ -85,8 +93,8 @@ struct DeclRef : Use {
}; };
MAKE_HASHABLE(DeclRef, t.range, t.file_id) MAKE_HASHABLE(DeclRef, t.range, t.file_id)
void Reflect(Reader &visitor, Reference &value); void Reflect(Reader &visitor, SymbolRef &value);
void Reflect(Writer &visitor, Reference &value); void Reflect(Writer &visitor, SymbolRef &value);
void Reflect(Reader &visitor, Use &value); void Reflect(Reader &visitor, Use &value);
void Reflect(Writer &visitor, Use &value); void Reflect(Writer &visitor, Use &value);
void Reflect(Reader &visitor, DeclRef &value); void Reflect(Reader &visitor, DeclRef &value);
@ -115,74 +123,71 @@ struct FuncDef : NameMixin<FuncDef> {
// Method this method overrides. // Method this method overrides.
std::vector<Usr> bases; std::vector<Usr> bases;
// Local variables or parameters. // Local variables or parameters.
std::vector<Usr> vars; std::vector<Usr> vars;
// Functions that this function calls. // Functions that this function calls.
std::vector<SymbolRef> callees; std::vector<SymbolRef> callees;
int file_id = -1; int file_id = -1; // not serialized
int16_t qual_name_offset = 0; int16_t qual_name_offset = 0;
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown;
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
uint8_t storage = clang::SC_None; uint8_t storage = clang::SC_None;
std::vector<Usr> GetBases() const { return bases; } std::vector<Usr> GetBases() const { return bases; }
}; };
MAKE_REFLECT_STRUCT(FuncDef, detailed_name, qual_name_offset, short_name_offset, MAKE_REFLECT_STRUCT(FuncDef, detailed_name, hover, comments, spell, extent,
short_name_size, kind, storage, hover, comments, spell, bases, vars, callees, qual_name_offset, short_name_offset,
extent, bases, vars, callees); short_name_size, kind, parent_kind, storage);
struct IndexFunc : NameMixin<IndexFunc> { struct IndexFunc : NameMixin<IndexFunc> {
using Def = FuncDef; using Def = FuncDef;
Usr usr; Usr usr;
Def def; Def def;
std::vector<DeclRef> declarations; std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<Use> uses;
}; };
struct TypeDef : NameMixin<TypeDef> { struct TypeDef : NameMixin<TypeDef> {
const char *detailed_name = ""; const char *detailed_name = "";
const char *hover = ""; const char *hover = "";
const char *comments = ""; const char *comments = "";
Maybe<Use> spell; Maybe<Use> spell;
Maybe<Use> extent; Maybe<Use> extent;
std::vector<Usr> bases; std::vector<Usr> bases;
// Types, functions, and variables defined in this type. // Types, functions, and variables defined in this type.
std::vector<Usr> types;
std::vector<Usr> funcs; std::vector<Usr> funcs;
std::vector<Usr> types;
std::vector<std::pair<Usr, int64_t>> vars; std::vector<std::pair<Usr, int64_t>> vars;
// If set, then this is the same underlying type as the given value (ie, this // If set, then this is the same underlying type as the given value (ie, this
// type comes from a using or typedef statement). // type comes from a using or typedef statement).
Usr alias_of = 0; Usr alias_of = 0;
int file_id = -1; // not serialized
int file_id = -1;
int16_t qual_name_offset = 0; int16_t qual_name_offset = 0;
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown;
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
std::vector<Usr> GetBases() const { return bases; } std::vector<Usr> GetBases() const { return bases; }
}; };
MAKE_REFLECT_STRUCT(TypeDef, detailed_name, qual_name_offset, short_name_offset, MAKE_REFLECT_STRUCT(TypeDef, detailed_name, hover, comments, spell, extent,
short_name_size, kind, hover, comments, spell, extent, bases, funcs, types, vars, alias_of, qual_name_offset,
alias_of, bases, types, funcs, vars); short_name_offset, short_name_size, kind, parent_kind);
struct IndexType { struct IndexType {
using Def = TypeDef; using Def = TypeDef;
Usr usr; Usr usr;
Def def; Def def;
std::vector<DeclRef> declarations; std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<Usr> instances; std::vector<Usr> instances;
std::vector<Use> uses;
}; };
struct VarDef : NameMixin<VarDef> { struct VarDef : NameMixin<VarDef> {
@ -195,27 +200,29 @@ struct VarDef : NameMixin<VarDef> {
// Type of the variable. // Type of the variable.
Usr type = 0; Usr type = 0;
int file_id = -1; // not serialized
int file_id = -1;
int16_t qual_name_offset = 0; int16_t qual_name_offset = 0;
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown;
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
// Note a variable may have instances of both |None| and |Extern| // Note a variable may have instances of both |None| and |Extern|
// (declaration). // (declaration).
uint8_t storage = clang::SC_None; uint8_t storage = clang::SC_None;
bool is_local() const { 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; storage == clang::SC_None;
} }
std::vector<Usr> GetBases() const { return {}; } std::vector<Usr> GetBases() const { return {}; }
}; };
MAKE_REFLECT_STRUCT(VarDef, detailed_name, qual_name_offset, short_name_offset, MAKE_REFLECT_STRUCT(VarDef, detailed_name, hover, comments, spell, extent, type,
short_name_size, hover, comments, spell, extent, type, kind, qual_name_offset, short_name_offset, short_name_size, kind,
storage); parent_kind, storage);
struct IndexVar { struct IndexVar {
using Def = VarDef; using Def = VarDef;

View File

@ -198,15 +198,6 @@ enum class lsSymbolKind : uint8_t {
}; };
MAKE_REFLECT_TYPE_PROXY(lsSymbolKind); 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 { struct lsTextDocumentIdentifier {
lsDocumentUri uri; lsDocumentUri uri;
}; };
@ -346,6 +337,6 @@ void Reflect(TVisitor &visitor, Out_ShowLogMessage &value) {
struct Out_LocationList : public lsOutMessage<Out_LocationList> { struct Out_LocationList : public lsOutMessage<Out_LocationList> {
lsRequestId id; lsRequestId id;
std::vector<lsLocationEx> result; std::vector<lsLocation> result;
}; };
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, 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(); const QueryFunc::Def *def = func.AnyDef();
if (!def) if (!def)
continue; // applies to for loop 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 -> // Don't highlight overloadable operators or implicit lambda ->
// std::function constructor. // std::function constructor.
std::string_view short_name = def->Name(false); std::string_view short_name = def->Name(false);
if (short_name.compare(0, 8, "operator") == 0) if (short_name.compare(0, 8, "operator") == 0)
continue; // applies to for loop continue; // applies to for loop
if (def->spell)
parent_kind = GetSymbolKind(db, *def->spell);
kind = def->kind; kind = def->kind;
storage = def->storage; storage = def->storage;
detailed_name = short_name; detailed_name = short_name;
parent_kind = def->parent_kind;
// Check whether the function name is actually there. // Check whether the function name is actually there.
// If not, do not publish the semantic highlight. // If not, do not publish the semantic highlight.
@ -200,7 +191,7 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) {
kind = def.kind; kind = def.kind;
detailed_name = def.detailed_name; detailed_name = def.detailed_name;
if (def.spell) { if (def.spell) {
parent_kind = GetSymbolKind(db, *def.spell); parent_kind = def.parent_kind;
break; break;
} }
} }
@ -214,13 +205,7 @@ void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) {
storage = def.storage; storage = def.storage;
detailed_name = def.detailed_name; detailed_name = def.detailed_name;
if (def.spell) { if (def.spell) {
parent_kind = GetSymbolKind(db, *def.spell); parent_kind = def.parent_kind;
break;
}
}
if (parent_kind == lsSymbolKind::Unknown) {
for (Use use : var.declarations) {
parent_kind = GetSymbolKind(db, use);
break; break;
} }
} }

View File

@ -77,6 +77,8 @@ struct Out_CclsCall : public lsOutMessage<Out_CclsCall> {
int numChildren; int numChildren;
// Empty if the |levels| limit is reached. // Empty if the |levels| limit is reached.
std::vector<Entry> children; 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; lsRequestId id;
@ -94,13 +96,14 @@ bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee,
entry->numChildren = 0; entry->numChildren = 0;
if (!def) if (!def)
return false; return false;
auto handle = [&](Use use, CallType call_type1) { auto handle = [&](SymbolRef sym, int file_id, CallType call_type1) {
entry->numChildren++; entry->numChildren++;
if (levels > 0) { if (levels > 0) {
Out_CclsCall::Entry entry1; Out_CclsCall::Entry entry1;
entry1.id = std::to_string(use.usr); entry1.id = std::to_string(sym.usr);
entry1.usr = use.usr; entry1.usr = sym.usr;
if (auto loc = GetLsLocation(m->db, m->working_files, use)) if (auto loc = GetLsLocation(m->db, m->working_files,
Use{{sym.range, sym.role}, file_id}))
entry1.location = *loc; entry1.location = *loc;
entry1.callType = call_type1; entry1.callType = call_type1;
if (Expand(m, &entry1, callee, call_type, qualified, levels - 1)) 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) { auto handle_uses = [&](const QueryFunc &func, CallType call_type) {
if (callee) { if (callee) {
if (const auto *def = func.AnyDef()) if (const auto *def = func.AnyDef())
for (SymbolRef ref : def->callees) for (SymbolRef sym : def->callees)
if (ref.kind == SymbolKind::Func) if (sym.kind == SymbolKind::Func)
handle(Use{{ref.range, ref.usr, ref.kind, ref.role}, def->file_id}, handle(sym, def->file_id, call_type);
call_type);
} else { } else {
for (Use use : func.uses) for (Use use : func.uses) {
if (use.kind == SymbolKind::Func) const QueryFile &file1 = m->db->files[use.file_id];
handle(use, call_type); 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; return true;
} }

View File

@ -104,7 +104,7 @@ struct Handler_CclsNavigate : BaseMessageHandler<In_CclsNavigate> {
out.id = request->id; out.id = request->id;
if (res) if (res)
if (auto ls_range = GetLsRange(wfile, *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.uri = params.textDocument.uri;
ls_loc.range = *ls_range; ls_loc.range = *ls_range;
} }

View File

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

View File

@ -117,19 +117,19 @@ struct Handler_TextDocumentCodeLens
code_lens.command->arguments.push_back(ToString(show)); code_lens.command->arguments.push_back(ToString(show));
}; };
auto ToSpell = [&](Use use) { auto ToSpell = [&](SymbolRef sym, int file_id) -> Use {
Maybe<Use> def = GetDefinitionSpell(db, use); Maybe<Use> def = GetDefinitionSpell(db, sym);
if (def && def->file_id == use.file_id && if (def && def->file_id == file_id &&
def->range.start.line == use.range.start.line) def->range.start.line == sym.range.start.line)
return *def; return *def;
return use; return {{sym.range, sym.role}, file_id};
}; };
std::unordered_set<Range> seen; std::unordered_set<Range> seen;
for (auto [sym, refcnt] : file->outline2refcnt) { for (auto [sym, refcnt] : file->outline2refcnt) {
if (refcnt <= 0 || !seen.insert(sym.range).second) if (refcnt <= 0 || !seen.insert(sym.range).second)
continue; continue;
Use use = ToSpell({{sym.range, sym.usr, sym.kind, sym.role}, file->id}); Use use = ToSpell(sym, file->id);
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc &func = db->GetFunc(sym); QueryFunc &func = db->GetFunc(sym);

View File

@ -33,13 +33,6 @@ struct In_TextDocumentDefinition : public RequestInMessage {
MAKE_REFLECT_STRUCT(In_TextDocumentDefinition, id, params); MAKE_REFLECT_STRUCT(In_TextDocumentDefinition, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentDefinition); 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) { std::vector<Use> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Var: { case SymbolKind::Var: {
@ -73,7 +66,7 @@ struct Handler_TextDocumentDefinition
params.textDocument.uri.GetPath(), &file, &file_id)) params.textDocument.uri.GetPath(), &file, &file_id))
return; return;
Out_TextDocumentDefinition out; Out_LocationList out;
out.id = request->id; out.id = request->id;
Maybe<Use> on_def; Maybe<Use> on_def;
@ -110,7 +103,7 @@ struct Handler_TextDocumentDefinition
if (uses.empty() && on_def) if (uses.empty() && on_def)
uses.push_back(*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()); out.result.insert(out.result.end(), locs.begin(), locs.end());
} }
@ -123,9 +116,8 @@ struct Handler_TextDocumentDefinition
// Check #include // Check #include
for (const IndexInclude &include : file->def->includes) { for (const IndexInclude &include : file->def->includes) {
if (include.line == ls_pos.line) { if (include.line == ls_pos.line) {
lsLocationEx result; out.result.push_back(
result.uri = lsDocumentUri::FromPath(include.resolved_path); lsLocation{lsDocumentUri::FromPath(include.resolved_path)});
out.result.push_back(result);
range = {{0, 0}, {0, 0}}; range = {{0, 0}, {0, 0}};
break; break;
} }
@ -184,9 +176,8 @@ struct Handler_TextDocumentDefinition
if (best_sym.kind != SymbolKind::Invalid) { if (best_sym.kind != SymbolKind::Invalid) {
Maybe<Use> use = GetDefinitionSpell(db, best_sym); Maybe<Use> use = GetDefinitionSpell(db, best_sym);
assert(use); assert(use);
if (auto ls_loc = GetLsLocationEx(db, working_files, *use, if (auto loc = GetLsLocation(db, working_files, *use))
g_config->xref.container)) out.result.push_back(*loc);
out.result.push_back(*ls_loc);
} }
} }
} }

View File

@ -80,11 +80,9 @@ struct Handler_TextDocumentDocumentHighlight
return usr == sym1.usr && kind == sym1.kind; return usr == sym1.usr && kind == sym1.kind;
})) }))
continue; continue;
if (auto ls_loc = if (auto loc = GetLsLocation(db, working_files, sym, file_id)) {
GetLsLocation(db, working_files,
Use{{sym.range, usr, kind, sym.role}, file_id})) {
lsDocumentHighlight highlight; lsDocumentHighlight highlight;
highlight.range = ls_loc->range; highlight.range = loc->range;
if (sym.role & Role::Write) if (sym.role & Role::Write)
highlight.kind = lsDocumentHighlight::Write; highlight.kind = lsDocumentHighlight::Write;
else if (sym.role & Role::Read) else if (sym.role & Role::Read)

View File

@ -107,10 +107,8 @@ struct Handler_TextDocumentDocumentSymbol
for (auto [sym, refcnt] : symbol2refcnt) for (auto [sym, refcnt] : symbol2refcnt)
if (refcnt > 0 && params.startLine <= sym.range.start.line && if (refcnt > 0 && params.startLine <= sym.range.start.line &&
sym.range.start.line <= params.endLine) sym.range.start.line <= params.endLine)
if (auto ls_loc = GetLsLocation( if (auto loc = GetLsLocation(db, working_files, sym, file_id))
db, working_files, out.result.push_back(loc->range);
Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id}))
out.result.push_back(ls_loc->range);
std::sort(out.result.begin(), out.result.end()); std::sort(out.result.begin(), out.result.end());
pipeline::WriteStdout(kMethodType, out); pipeline::WriteStdout(kMethodType, out);
} else if (g_config->client.hierarchicalDocumentSymbolSupport) { } else if (g_config->client.hierarchicalDocumentSymbolSupport) {
@ -213,10 +211,8 @@ struct Handler_TextDocumentDocumentSymbol
(sym.kind == SymbolKind::Var && (sym.kind == SymbolKind::Var &&
IgnoreVar(db->GetVar(sym).AnyDef()))) IgnoreVar(db->GetVar(sym).AnyDef())))
continue; continue;
if (std::optional<lsLocation> location = GetLsLocation( if (auto loc = GetLsLocation(db, working_files, sym, file_id)) {
db, working_files, info->location = *loc;
Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) {
info->location = *location;
out.result.push_back(*info); out.result.push_back(*info);
} }
} }

View File

@ -47,13 +47,13 @@ struct Handler_TextDocumentImplementation
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
QueryType &type = db->GetType(sym); QueryType &type = db->GetType(sym);
out.result = GetLsLocationExs(db, working_files, out.result = GetLsLocations(db, working_files,
GetTypeDeclarations(db, type.derived)); GetTypeDeclarations(db, type.derived));
break; break;
} else if (sym.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
QueryFunc &func = db->GetFunc(sym); QueryFunc &func = db->GetFunc(sym);
out.result = GetLsLocationExs(db, working_files, out.result = GetLsLocations(db, working_files,
GetFuncDeclarations(db, func.derived)); GetFuncDeclarations(db, func.derived));
break; break;
} }
} }

View File

@ -50,13 +50,6 @@ MAKE_REFLECT_STRUCT(In_TextDocumentReferences::Params, textDocument, position,
MAKE_REFLECT_STRUCT(In_TextDocumentReferences, id, params); MAKE_REFLECT_STRUCT(In_TextDocumentReferences, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentReferences); 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 struct Handler_TextDocumentReferences
: BaseMessageHandler<In_TextDocumentReferences> { : BaseMessageHandler<In_TextDocumentReferences> {
MethodType GetMethodType() const override { return kMethodType; } MethodType GetMethodType() const override { return kMethodType; }
@ -67,7 +60,7 @@ struct Handler_TextDocumentReferences
if (!FindFileOrFail(db, project, request->id, if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file)) params.textDocument.uri.GetPath(), &file))
return; return;
Out_TextDocumentReferences out; Out_LocationList out;
out.id = request->id; out.id = request->id;
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
if (!file) { if (!file) {
@ -75,7 +68,6 @@ struct Handler_TextDocumentReferences
return; return;
} }
bool container = g_config->xref.container;
std::unordered_set<Use> seen_uses; std::unordered_set<Use> seen_uses;
int line = params.position.line; int line = params.position.line;
@ -93,11 +85,8 @@ struct Handler_TextDocumentReferences
if (Role(use.role & params.context.role) == params.context.role && if (Role(use.role & params.context.role) == params.context.role &&
!(use.role & params.context.excludeRole) && !(use.role & params.context.excludeRole) &&
seen_uses.insert(use).second) seen_uses.insert(use).second)
if (std::optional<lsLocationEx> ls_loc = if (auto loc = GetLsLocation(db, working_files, use)) {
GetLsLocationEx(db, working_files, use, container)) { out.result.push_back(*loc);
if (container)
ls_loc->parentKind = parent_kind;
out.result.push_back(*ls_loc);
} }
}; };
WithEntity(db, sym, [&](const auto &entity) { WithEntity(db, sym, [&](const auto &entity) {
@ -145,10 +134,9 @@ struct Handler_TextDocumentReferences
for (const IndexInclude &include : file1.def->includes) for (const IndexInclude &include : file1.def->includes)
if (include.resolved_path == path) { if (include.resolved_path == path) {
// Another file |file1| has the same include line. // Another file |file1| has the same include line.
lsLocationEx result; lsLocation &loc = out.result.emplace_back();
result.uri = lsDocumentUri::FromPath(file1.def->path); loc.uri = lsDocumentUri::FromPath(file1.def->path);
result.range.start.line = result.range.end.line = include.line; loc.range.start.line = loc.range.end.line = include.line;
out.result.push_back(std::move(result));
break; break;
} }
} }

View File

@ -28,13 +28,6 @@ struct In_TextDocumentTypeDefinition : public RequestInMessage {
MAKE_REFLECT_STRUCT(In_TextDocumentTypeDefinition, id, params); MAKE_REFLECT_STRUCT(In_TextDocumentTypeDefinition, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentTypeDefinition); 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 struct Handler_TextDocumentTypeDefinition
: BaseMessageHandler<In_TextDocumentTypeDefinition> { : BaseMessageHandler<In_TextDocumentTypeDefinition> {
MethodType GetMethodType() const override { return kMethodType; } MethodType GetMethodType() const override { return kMethodType; }
@ -47,19 +40,17 @@ struct Handler_TextDocumentTypeDefinition
WorkingFile *working_file = WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentTypeDefinition out; Out_LocationList out;
out.id = request->id; out.id = request->id;
auto Add = [&](const QueryType &type) { auto Add = [&](const QueryType &type) {
for (const auto &def : type.def) for (const auto &def : type.def)
if (def.spell) { if (def.spell) {
if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, if (auto ls_loc = GetLsLocation(db, working_files, *def.spell))
g_config->xref.container))
out.result.push_back(*ls_loc); out.result.push_back(*ls_loc);
} }
if (out.result.empty()) if (out.result.empty())
for (const DeclRef &dr : type.declarations) for (const DeclRef &dr : type.declarations)
if (auto ls_loc = GetLsLocationEx(db, working_files, dr, if (auto ls_loc = GetLsLocation(db, working_files, dr))
g_config->xref.container))
out.result.push_back(*ls_loc); out.result.push_back(*ls_loc);
}; };
for (SymbolRef sym : 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; use.file_id = file_id;
else else
use.file_id = lid2file_id.find(use.file_id)->second; use.file_id = lid2file_id.find(use.file_id)->second;
if (use.kind == SymbolKind::File)
use.usr = use.file_id;
} }
template <typename T> template <typename T>
@ -238,7 +236,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
SymbolKind kind, Use &use, int delta, int k = 1) { SymbolKind kind, Use &use, int delta, int k = 1) {
use.file_id = use.file_id =
use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; 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) { if (k & 1) {
int &v = files[use.file_id].symbol2refcnt[sym]; int &v = files[use.file_id].symbol2refcnt[sym];
v += delta; v += delta;
@ -258,7 +256,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
SymbolKind kind, DeclRef &dr, int delta) { SymbolKind kind, DeclRef &dr, int delta) {
Ref(lid2fid, usr, kind, dr, delta, 1); Ref(lid2fid, usr, kind, dr, delta, 1);
files[dr.file_id] files[dr.file_id]
.outline2refcnt[SymbolRef{{dr.extent, usr, kind, dr.role}}] += delta; .outline2refcnt[SymbolRef{dr.extent, usr, kind, dr.role}] += delta;
}; };
auto UpdateUses = auto UpdateUses =
@ -401,12 +399,12 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
if (def.spell) { if (def.spell) {
AssignFileId(lid2file_id, file_id, *def.spell); AssignFileId(lid2file_id, file_id, *def.spell);
files[def.spell->file_id].symbol2refcnt[{ 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) { if (def.extent) {
AssignFileId(lid2file_id, file_id, *def.extent); AssignFileId(lid2file_id, file_id, *def.extent);
files[def.extent->file_id].outline2refcnt[{ 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()); 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) { if (def.spell) {
AssignFileId(lid2file_id, file_id, *def.spell); AssignFileId(lid2file_id, file_id, *def.spell);
files[def.spell->file_id].symbol2refcnt[{ 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) { if (def.extent) {
AssignFileId(lid2file_id, file_id, *def.extent); AssignFileId(lid2file_id, file_id, *def.extent);
files[def.extent->file_id].outline2refcnt[{ 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()); auto R = type_usr.try_emplace({u.first}, type_usr.size());
if (R.second) if (R.second)
@ -454,12 +452,12 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
if (def.spell) { if (def.spell) {
AssignFileId(lid2file_id, file_id, *def.spell); AssignFileId(lid2file_id, file_id, *def.spell);
files[def.spell->file_id].symbol2refcnt[{ 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) { if (def.extent) {
AssignFileId(lid2file_id, file_id, *def.extent); AssignFileId(lid2file_id, file_id, *def.extent);
files[def.extent->file_id].outline2refcnt[{ 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()); auto R = var_usr.try_emplace({u.first}, var_usr.size());
if (R.second) if (R.second)

View File

@ -85,17 +85,17 @@ struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
Usr usr; Usr usr;
llvm::SmallVector<Def, 1> def; llvm::SmallVector<Def, 1> def;
std::vector<DeclRef> declarations; std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<Use> uses;
}; };
struct QueryType : QueryEntity<QueryType, TypeDef> { struct QueryType : QueryEntity<QueryType, TypeDef> {
Usr usr; Usr usr;
llvm::SmallVector<Def, 1> def; llvm::SmallVector<Def, 1> def;
std::vector<DeclRef> declarations; std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<Usr> instances; std::vector<Usr> instances;
std::vector<Use> uses;
}; };
struct QueryVar : QueryEntity<QueryVar, VarDef> { 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) { Maybe<Use> GetDefinitionExtent(DB *db, SymbolIdx sym) {
// Used to jump to file. // Used to jump to file.
if (sym.kind == SymbolKind::File) if (sym.kind == SymbolKind::File)
return Use{{Range{{0, 0}, {0, 0}}, sym.usr, sym.kind, Role::None}, return Use{{Range{{0, 0}, {0, 0}}, Role::None}, int(sym.usr)};
int(sym.usr)};
Maybe<Use> ret; Maybe<Use> ret;
EachEntityDef(db, sym, [&](const auto &def) { return !(ret = def.extent); }); EachEntityDef(db, sym, [&](const auto &def) { return !(ret = def.extent); });
return ret; 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) { Use use) {
std::string path; std::string path;
lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path); lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path);
std::optional<lsRange> range = std::optional<lsRange> range =
GetLsRange(working_files->GetFileByFilename(path), use.range); GetLsRange(wfiles->GetFileByFilename(path), use.range);
if (!range) if (!range)
return std::nullopt; return std::nullopt;
return lsLocation{uri, *range}; return lsLocation{uri, *range};
} }
std::optional<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files, std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
Use use, bool container) { SymbolRef sym, int file_id) {
std::optional<lsLocation> ls_loc = GetLsLocation(db, working_files, use); return GetLsLocation(db, wfiles, Use{{sym.range, sym.role}, file_id});
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::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files, std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
const std::vector<Use> &uses) { const std::vector<Use> &uses) {
std::vector<lsLocationEx> ret; std::vector<lsLocation> ret;
for (Use use : uses) for (Use use : uses)
if (auto loc = if (auto loc = GetLsLocation(db, wfiles, use))
GetLsLocationEx(db, working_files, use, g_config->xref.container))
ret.push_back(*loc); ret.push_back(*loc);
std::sort(ret.begin(), ret.end()); std::sort(ret.begin(), ret.end());
ret.erase(std::unique(ret.begin(), ret.end()), 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::string *path);
lsDocumentUri GetLsDocumentUri(DB *db, int file_id); 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);
Use use); std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
std::optional<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files, SymbolRef sym, int file_id);
Use use, bool container); std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
std::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files, const std::vector<Use> &uses);
const std::vector<Use> &refs);
// Returns a symbol. The symbol will *NOT* have a location assigned. // Returns a symbol. The symbol will *NOT* have a location assigned.
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym, std::optional<lsSymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
bool detailed); 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) { template <typename TVisitor> void Reflect(TVisitor &visitor, IndexFunc &value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
REFLECT_MEMBER2("usr", value.usr); REFLECT_MEMBER2("usr", value.usr);
REFLECT_MEMBER2("detailed_name", value.def.detailed_name); REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset); REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset);
ReflectShortName(visitor, value.def); ReflectShortName(visitor, value.def);
REFLECT_MEMBER2("kind", value.def.kind); REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("storage", value.def.storage); REFLECT_MEMBER2("extent", value.def.extent);
ReflectHoverAndComments(visitor, value.def); 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("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("spell", value.def.spell);
REFLECT_MEMBER2("extent", value.def.extent); REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("bases", value.def.bases); 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("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("uses", value.uses);
REFLECT_MEMBER2("callees", value.def.callees);
REFLECT_MEMBER_END(); 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); REFLECT_MEMBER2("qual_name_offset", value.def.qual_name_offset);
ReflectShortName(visitor, value.def); ReflectShortName(visitor, value.def);
ReflectHoverAndComments(visitor, value.def); ReflectHoverAndComments(visitor, value.def);
REFLECT_MEMBER2("declarations", value.declarations);
REFLECT_MEMBER2("spell", value.def.spell); REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("extent", value.def.extent); REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("type", value.def.type); REFLECT_MEMBER2("type", value.def.type);
REFLECT_MEMBER2("uses", value.uses);
REFLECT_MEMBER2("kind", value.def.kind); REFLECT_MEMBER2("kind", value.def.kind);
REFLECT_MEMBER2("parent_kind", value.def.parent_kind);
REFLECT_MEMBER2("storage", value.def.storage); REFLECT_MEMBER2("storage", value.def.storage);
REFLECT_MEMBER2("declarations", value.declarations);
REFLECT_MEMBER2("uses", value.uses);
REFLECT_MEMBER_END(); REFLECT_MEMBER_END();
} }