mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 07:35:08 +00:00
Redesign SymbolRef, Ref, Use
Remove lsLocationEx
This commit is contained in:
parent
0c5c3a11be
commit
08b09bc1da
@ -237,8 +237,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;
|
||||
@ -262,7 +260,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,
|
||||
|
290
src/indexer.cc
290
src/indexer.cc
@ -105,50 +105,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;
|
||||
}
|
||||
}
|
||||
@ -406,23 +465,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;
|
||||
@ -575,7 +617,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);
|
||||
@ -689,7 +731,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()) {
|
||||
@ -719,19 +762,21 @@ 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};
|
||||
entity->def.parent_kind = lsSymbolKind::File;
|
||||
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)
|
||||
@ -746,6 +791,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 ||
|
||||
@ -758,17 +804,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);
|
||||
@ -776,12 +823,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);
|
||||
@ -794,7 +842,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);
|
||||
@ -813,14 +861,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;
|
||||
@ -837,11 +886,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;
|
||||
@ -849,7 +898,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());
|
||||
@ -861,7 +909,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);
|
||||
@ -870,36 +917,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);
|
||||
@ -915,9 +932,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()) {
|
||||
@ -975,7 +989,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();
|
||||
@ -987,29 +1000,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;
|
||||
@ -1022,29 +1020,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();
|
||||
@ -1054,11 +1030,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;
|
||||
@ -1116,16 +1088,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();
|
||||
@ -1147,8 +1120,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,
|
||||
@ -1183,7 +1156,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,
|
||||
@ -1365,10 +1338,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());
|
||||
@ -1384,7 +1354,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",
|
||||
@ -1405,25 +1375,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);
|
||||
}
|
||||
}
|
||||
@ -1435,9 +1404,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 {
|
||||
@ -1448,9 +1415,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 {
|
||||
|
@ -37,28 +37,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 {
|
||||
@ -73,8 +81,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);
|
||||
@ -103,74 +111,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> {
|
||||
@ -183,27 +188,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;
|
||||
|
11
src/lsp.h
11
src/lsp.h
@ -186,15 +186,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;
|
||||
};
|
||||
@ -334,6 +325,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);
|
||||
|
@ -144,24 +144,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.
|
||||
@ -188,7 +179,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;
|
||||
}
|
||||
}
|
||||
@ -202,13 +193,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;
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,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;
|
||||
@ -82,13 +84,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))
|
||||
@ -98,14 +101,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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -148,6 +159,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;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,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;
|
||||
}
|
||||
|
@ -51,7 +51,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;
|
||||
|
@ -105,19 +105,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);
|
||||
|
@ -21,13 +21,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: {
|
||||
@ -61,7 +54,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;
|
||||
@ -98,7 +91,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());
|
||||
}
|
||||
|
||||
@ -111,9 +104,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;
|
||||
}
|
||||
@ -172,9 +164,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,11 +68,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)
|
||||
|
@ -95,10 +95,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) {
|
||||
@ -201,10 +199,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);
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ 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,
|
||||
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,
|
||||
out.result = GetLsLocations(db, working_files,
|
||||
GetFuncDeclarations(db, func.derived));
|
||||
break;
|
||||
}
|
||||
|
@ -38,13 +38,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; }
|
||||
@ -55,7 +48,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) {
|
||||
@ -63,7 +56,6 @@ struct Handler_TextDocumentReferences
|
||||
return;
|
||||
}
|
||||
|
||||
bool container = g_config->xref.container;
|
||||
std::unordered_set<Use> seen_uses;
|
||||
int line = params.position.line;
|
||||
|
||||
@ -81,11 +73,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) {
|
||||
@ -133,10 +122,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;
|
||||
}
|
||||
}
|
||||
|
@ -16,13 +16,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; }
|
||||
@ -35,19 +28,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 :
|
||||
|
18
src/query.cc
18
src/query.cc
@ -22,8 +22,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>
|
||||
@ -226,7 +224,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;
|
||||
@ -246,7 +244,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 =
|
||||
@ -389,12 +387,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());
|
||||
@ -416,12 +414,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)
|
||||
@ -442,12 +440,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)
|
||||
|
@ -74,17 +74,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> {
|
||||
|
@ -49,8 +49,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;
|
||||
@ -204,40 +203,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,
|
||||
std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
||||
const std::vector<Use> &uses) {
|
||||
std::vector<lsLocationEx> ret;
|
||||
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());
|
||||
|
@ -27,12 +27,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);
|
||||
|
@ -243,45 +243,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();
|
||||
}
|
||||
|
||||
@ -292,13 +296,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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user