Rename Reference members

This commit is contained in:
Fangrui Song 2018-02-09 09:42:10 -08:00
parent c5f08c5eb8
commit c4bd7ef44b
23 changed files with 305 additions and 307 deletions

View File

@ -695,13 +695,13 @@ void UniqueAdd(std::vector<T>& values, T value) {
values.push_back(value); values.push_back(value);
} }
// FIXME Reference: set lex_parent_id in call sites and remove this // FIXME Reference: set id in call sites and remove this
void AddUse(std::vector<Reference>& values, Range value) { void AddUse(std::vector<Reference>& values, Range value) {
values.push_back(Reference{value, Id<void>(), SymbolKind::Invalid, values.push_back(Reference{value, Id<void>(), SymbolKind::Invalid,
SymbolRole::Reference}); SymbolRole::Reference});
} }
// FIXME Reference: set lex_parent_id in call sites and remove this // FIXME Reference: set id in call sites and remove this
void UniqueAdd(std::vector<Reference>& values, Range value) { void UniqueAdd(std::vector<Reference>& values, Range value) {
if (std::find_if(values.begin(), values.end(), [&](const Reference& ref) { if (std::find_if(values.begin(), values.end(), [&](const Reference& ref) {
return ref.range == value; return ref.range == value;
@ -2341,7 +2341,7 @@ void Reflect(Reader& visitor, IndexFuncRef& value) {
RawId id = atol(str_value); RawId id = atol(str_value);
const char* loc_string = strchr(str_value, '@') + 1; const char* loc_string = strchr(str_value, '@') + 1;
value.lex_parent_id = Id<void>(id); value.id = Id<void>(id);
value.range = Range(loc_string); value.range = Range(loc_string);
} else { } else {
Reflect(visitor, static_cast<Reference&>(value)); Reflect(visitor, static_cast<Reference&>(value));
@ -2354,8 +2354,8 @@ void Reflect(Writer& visitor, IndexFuncRef& value) {
s += "~"; s += "~";
// id.id is unsigned, special case -1 value // id.id is unsigned, special case -1 value
if (value.lex_parent_id.HasValue()) if (value.id.HasValue())
s += std::to_string(value.lex_parent_id.id); s += std::to_string(value.id.id);
else else
s += "-1"; s += "-1";
@ -2377,13 +2377,13 @@ void Reflect(Reader& visitor, Reference& value) {
else { else {
char* p = const_cast<char*>(s.c_str()) + sep; char* p = const_cast<char*>(s.c_str()) + sep;
value.role = SymbolRole(strtol(p + 1, &p, 10)); value.role = SymbolRole(strtol(p + 1, &p, 10));
value.lex_parent_kind = SymbolKind(strtol(p + 1, &p, 10)); value.kind = SymbolKind(strtol(p + 1, &p, 10));
value.lex_parent_id = Id<void>(strtol(p + 1, &p, 10)); value.id = Id<void>(strtol(p + 1, &p, 10));
} }
} else { } else {
Reflect(visitor, value.range); Reflect(visitor, value.range);
Reflect(visitor, value.lex_parent_id); Reflect(visitor, value.id);
Reflect(visitor, value.lex_parent_kind); Reflect(visitor, value.kind);
Reflect(visitor, value.role); Reflect(visitor, value.role);
} }
} }
@ -2391,16 +2391,16 @@ void Reflect(Writer& visitor, Reference& value) {
if (visitor.Format() == SerializeFormat::Json) { if (visitor.Format() == SerializeFormat::Json) {
std::string s = value.range.ToString(); std::string s = value.range.ToString();
if (value.role != SymbolRole::Reference || if (value.role != SymbolRole::Reference ||
value.lex_parent_kind != SymbolKind::Invalid) { value.kind != SymbolKind::Invalid) {
s += '|' + std::to_string(uint8_t(value.role)); s += '|' + std::to_string(uint8_t(value.role));
s += '|' + std::to_string(uint8_t(value.lex_parent_kind)); s += '|' + std::to_string(uint8_t(value.kind));
s += '|' + std::to_string(RawId(value.lex_parent_id)); s += '|' + std::to_string(RawId(value.id));
} }
visitor.String(s.c_str()); visitor.String(s.c_str());
} else { } else {
Reflect(visitor, value.range); Reflect(visitor, value.range);
Reflect(visitor, value.lex_parent_id); Reflect(visitor, value.id);
Reflect(visitor, value.lex_parent_kind); Reflect(visitor, value.kind);
Reflect(visitor, value.role); Reflect(visitor, value.role);
} }
} }

View File

@ -54,9 +54,9 @@ struct Id {
bool HasValue() const { return id != RawId(-1); } bool HasValue() const { return id != RawId(-1); }
bool operator==(const Id<T>& o) const { return id == o.id; } bool operator==(const Id& o) const { return id == o.id; }
bool operator!=(const Id<T>& o) const { return id != o.id; } bool operator!=(const Id& o) const { return id != o.id; }
bool operator<(const Id<T>& o) const { return id < o.id; } bool operator<(const Id& o) const { return id < o.id; }
}; };
namespace std { namespace std {
@ -80,13 +80,13 @@ struct IdCache;
struct Reference { struct Reference {
Range range; Range range;
Id<void> lex_parent_id; Id<void> id;
SymbolKind lex_parent_kind; SymbolKind kind;
SymbolRole role; SymbolRole role;
bool HasValue() const { return lex_parent_id.HasValue(); } bool HasValue() const { return id.HasValue(); }
std::tuple<Range, Id<void>, SymbolKind, SymbolRole> ToTuple() const { std::tuple<Range, Id<void>, SymbolKind, SymbolRole> ToTuple() const {
return std::make_tuple(range, lex_parent_id, lex_parent_kind, role); return std::make_tuple(range, id, kind, role);
} }
bool operator==(const Reference& o) const { bool operator==(const Reference& o) const {
return ToTuple() == o.ToTuple(); return ToTuple() == o.ToTuple();

View File

@ -115,18 +115,18 @@ void EmitSemanticHighlighting(QueryDatabase* db,
ClangSymbolKind kind = ClangSymbolKind::Unknown; ClangSymbolKind kind = ClangSymbolKind::Unknown;
StorageClass storage = StorageClass::Invalid; StorageClass storage = StorageClass::Invalid;
// This switch statement also filters out symbols that are not highlighted. // This switch statement also filters out symbols that are not highlighted.
switch (sym.idx.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc* func = &db->funcs[sym.idx.idx]; QueryFunc& func = sym.Func(db);
if (!func->def) if (!func.def)
continue; // applies to for loop continue; // applies to for loop
// 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 = func->def->ShortName(); std::string_view short_name = func.def->ShortName();
if (short_name.compare(0, 8, "operator") == 0 || if (short_name.compare(0, 8, "operator") == 0 ||
short_name.compare(0, 27, "function<type-parameter-0-0") == 0) short_name.compare(0, 27, "function<type-parameter-0-0") == 0)
continue; // applies to for loop continue; // applies to for loop
kind = func->def->kind; kind = func.def->kind;
detailed_name = short_name; detailed_name = short_name;
// Check whether the function name is actually there. // Check whether the function name is actually there.
@ -135,54 +135,55 @@ void EmitSemanticHighlighting(QueryDatabase* db,
// but we still want to keep the range for jumping to definition. // but we still want to keep the range for jumping to definition.
std::string_view concise_name = std::string_view concise_name =
detailed_name.substr(0, detailed_name.find('<')); detailed_name.substr(0, detailed_name.find('<'));
int16_t start_line = sym.loc.range.start.line; int16_t start_line = sym.range.start.line;
int16_t start_col = sym.loc.range.start.column; int16_t start_col = sym.range.start.column;
if (start_line >= 0 && start_line < working_file->index_lines.size()) { if (start_line >= 0 && start_line < working_file->index_lines.size()) {
std::string_view line = working_file->index_lines[start_line]; std::string_view line = working_file->index_lines[start_line];
sym.loc.range.end.line = start_line; sym.range.end.line = start_line;
if (line.compare(start_col, concise_name.size(), concise_name) == 0) if (line.compare(start_col, concise_name.size(), concise_name) == 0)
sym.loc.range.end.column = start_col + concise_name.size(); sym.range.end.column = start_col + concise_name.size();
else else
continue; // applies to for loop continue; // applies to for loop
} }
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar* var = &db->vars[sym.idx.idx]; QueryVar& var = sym.Var(db);
if (!var->def) if (!var.def)
continue; // applies to for loop continue; // applies to for loop
parent_kind = var->def->parent_kind; parent_kind = var.def->parent_kind;
kind = var->def->kind; kind = var.def->kind;
storage = var->def->storage; storage = var.def->storage;
detailed_name = var->def->ShortName(); detailed_name = var.def->ShortName();
break; break;
} }
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType* type = &db->types[sym.idx.idx]; QueryType& type = sym.Type(db);
if (!type->def) if (!type.def)
continue; // applies to for loop continue; // applies to for loop
kind = type->def->kind; kind = type.def->kind;
detailed_name = type->def->detailed_name; detailed_name = type.def->detailed_name;
break; break;
} }
default: default:
continue; // applies to for loop continue; // applies to for loop
} }
optional<lsRange> loc = GetLsRange(working_file, sym.loc.range); optional<lsRange> loc = GetLsRange(working_file, sym.range);
if (loc) { if (loc) {
auto it = grouped_symbols.find(sym.idx); auto key = SymbolIdx(sym.kind, RawId(sym.id));
auto it = grouped_symbols.find(key);
if (it != grouped_symbols.end()) { if (it != grouped_symbols.end()) {
it->second.ranges.push_back(*loc); it->second.ranges.push_back(*loc);
} else { } else {
Out_CqueryPublishSemanticHighlighting::Symbol symbol; Out_CqueryPublishSemanticHighlighting::Symbol symbol;
symbol.stableId = semantic_cache_for_file->GetStableId( symbol.stableId = semantic_cache_for_file->GetStableId(
sym.idx.kind, std::string(detailed_name)); sym.kind, std::string(detailed_name));
symbol.parentKind = parent_kind; symbol.parentKind = parent_kind;
symbol.kind = kind; symbol.kind = kind;
symbol.storage = storage; symbol.storage = storage;
symbol.ranges.push_back(*loc); symbol.ranges.push_back(*loc);
grouped_symbols[sym.idx] = symbol; grouped_symbols[key] = symbol;
} }
} }
} }

View File

@ -23,25 +23,25 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
Out_LocationList out; Out_LocationList out;
out.id = request->id; out.id = request->id;
std::vector<SymbolRef> refs = std::vector<SymbolRef> syms =
FindSymbolsAtLocation(working_file, file, request->params.position); FindSymbolsAtLocation(working_file, file, request->params.position);
// A template definition may be a use of its primary template. // A template definition may be a use of its primary template.
// We want to get the definition instead of the use. // We want to get the definition instead of the use.
// Order by |Definition| DESC, range size ASC. // Order by |Definition| DESC, range size ASC.
std::stable_sort(refs.begin(), refs.end(), std::stable_sort(syms.begin(), syms.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return (a.role & SymbolRole::Definition) > return (a.role & SymbolRole::Definition) >
(b.role & SymbolRole::Definition); (b.role & SymbolRole::Definition);
}); });
for (const SymbolRef& ref : refs) { for (const SymbolRef& sym : syms) {
if (ref.idx.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = sym.Type(db);
if (type.def) if (type.def)
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files,
ToReference(db, type.def->parents)); ToReference(db, type.def->parents));
break; break;
} else if (ref.idx.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = sym.Func(db);
if (func.def) if (func.def)
out.result = out.result =
GetLsLocations(db, working_files, ToReference(db, func.def->base)); GetLsLocations(db, working_files, ToReference(db, func.def->base));

View File

@ -171,11 +171,11 @@ struct CqueryCallTreeInitialHandler
Out_CqueryCallTree out; Out_CqueryCallTree out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Func) { if (sym.kind == SymbolKind::Func) {
out.result = out.result =
BuildInitialCallTree(db, working_files, QueryFuncId(ref.idx.idx)); BuildInitialCallTree(db, working_files, QueryFuncId(sym.Idx()));
break; break;
} }
} }

View File

@ -23,10 +23,10 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
Out_LocationList out; Out_LocationList out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Func) { if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[sym.Idx()];
std::vector<Reference> uses = ToReference(db, func.callers); std::vector<Reference> uses = ToReference(db, func.callers);
for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func)) for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func))
uses.push_back(func_ref); uses.push_back(func_ref);

View File

@ -23,24 +23,24 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
Out_LocationList out; Out_LocationList out;
out.id = request->id; out.id = request->id;
std::vector<SymbolRef> refs = std::vector<SymbolRef> syms =
FindSymbolsAtLocation(working_file, file, request->params.position); FindSymbolsAtLocation(working_file, file, request->params.position);
// A template definition may be a use of its primary template. // A template definition may be a use of its primary template.
// We want to get the definition instead of the use. // We want to get the definition instead of the use.
// Order by |Definition| DESC, range size ASC. // Order by |Definition| DESC, range size ASC.
std::stable_sort(refs.begin(), refs.end(), std::stable_sort(syms.begin(), syms.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return (a.role & SymbolRole::Definition) > return (a.role & SymbolRole::Definition) >
(b.role & SymbolRole::Definition); (b.role & SymbolRole::Definition);
}); });
for (const SymbolRef& ref : refs) { for (const SymbolRef& sym : syms) {
if (ref.idx.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = sym.Type(db);
out.result = out.result =
GetLsLocations(db, working_files, ToReference(db, type.derived)); GetLsLocations(db, working_files, ToReference(db, type.derived));
break; break;
} else if (ref.idx.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = sym.Func(db);
out.result = out.result =
GetLsLocations(db, working_files, ToReference(db, func.derived)); GetLsLocations(db, working_files, ToReference(db, func.derived));
break; break;

View File

@ -92,14 +92,14 @@ struct CqueryMemberHierarchyInitialHandler
Out_CqueryMemberHierarchy out; Out_CqueryMemberHierarchy out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
out.result = BuildInitial(db, working_files, QueryTypeId(ref.idx.idx)); out.result = BuildInitial(db, working_files, QueryTypeId(sym.Idx()));
break; break;
} }
if (ref.idx.kind == SymbolKind::Var) { if (sym.kind == SymbolKind::Var) {
QueryVar& var = db->vars[ref.idx.idx]; QueryVar& var = sym.Var(db);
if (var.def && var.def->variable_type) if (var.def && var.def->variable_type)
out.result = BuildInitial(db, working_files, *var.def->variable_type); out.result = BuildInitial(db, working_files, *var.def->variable_type);
break; break;

View File

@ -165,18 +165,18 @@ struct CqueryTypeHierarchyTreeHandler
Out_CqueryTypeHierarchyTree out; Out_CqueryTypeHierarchyTree out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = sym.Type(db);
if (type.def) if (type.def)
out.result = out.result =
BuildInheritanceHierarchyForType(db, working_files, type); BuildInheritanceHierarchyForType(db, working_files, type);
break; break;
} }
if (ref.idx.kind == SymbolKind::Func) { if (sym.kind == SymbolKind::Func) {
out.result = BuildInheritanceHierarchyForFunc(db, working_files, out.result = BuildInheritanceHierarchyForFunc(db, working_files,
QueryFuncId(ref.idx.idx)); QueryFuncId(sym.id));
break; break;
} }
} }

View File

@ -25,19 +25,19 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
size_t id = ref.idx.idx; RawId idx = ref.Idx();
switch (ref.idx.kind) { switch (ref.kind) {
default: default:
break; break;
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[id]; QueryVar& var = db->vars[idx];
if (!var.def || !var.def->variable_type) if (!var.def || !var.def->variable_type)
continue; continue;
id = var.def->variable_type->id; idx = var.def->variable_type->id;
} }
// fallthrough // fallthrough
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[id]; QueryType& type = db->types[idx];
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files,
ToReference(db, type.instances)); ToReference(db, type.instances));
break; break;

View File

@ -67,9 +67,9 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
QueryFileId file_id, QueryFileId file_id,
QueryFile* file) { QueryFile* file) {
for (SymbolRef sym : file->def->outline) { for (SymbolRef sym : file->def->outline) {
switch (sym.idx.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[sym.idx.idx]; QueryFunc& func = sym.Func(db);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (func.def && func.def->definition_extent && if (func.def && func.def->definition_extent &&
@ -79,12 +79,12 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[sym.idx.idx]; QueryVar& var = sym.Var(db);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (var.def && var.def->definition_extent && if (var.def && var.def->definition_extent &&
var.def->definition_extent->FileId() != file_id) { var.def->definition_extent->FileId() != file_id) {
return db->vars[sym.idx.idx].def->definition_extent->FileId(); return var.def->definition_extent->FileId();
} }
break; break;
} }
@ -196,9 +196,9 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
QueryFile& file = db->files[impl_file_id.id]; QueryFile& file = db->files[impl_file_id.id];
assert(file.def); assert(file.def);
for (SymbolRef sym : file.def->outline) { for (SymbolRef sym : file.def->outline) {
switch (sym.idx.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& sym_func = db->funcs[sym.idx.idx]; QueryFunc& sym_func = sym.Func(db);
if (!sym_func.def || !sym_func.def->definition_extent) if (!sym_func.def || !sym_func.def->definition_extent)
break; break;
@ -231,7 +231,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
case SymbolKind::File: case SymbolKind::File:
case SymbolKind::Type: case SymbolKind::Type:
LOG_S(WARNING) << "Unexpected SymbolKind " LOG_S(WARNING) << "Unexpected SymbolKind "
<< static_cast<int>(sym.idx.kind); << static_cast<int>(sym.kind);
break; break;
} }
} }
@ -342,9 +342,9 @@ struct TextDocumentCodeActionHandler
std::vector<SymbolRef> syms = std::vector<SymbolRef> syms =
FindSymbolsAtLocation(working_file, file, request->params.range.start); FindSymbolsAtLocation(working_file, file, request->params.range.start);
for (SymbolRef sym : syms) { for (SymbolRef sym : syms) {
switch (sym.idx.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[sym.idx.idx]; QueryType& type = sym.Type(db);
if (!type.def) if (!type.def)
break; break;
@ -395,7 +395,7 @@ struct TextDocumentCodeActionHandler
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[sym.idx.idx]; QueryFunc& func = sym.Func(db);
if (!func.def || func.def->definition_extent) if (!func.def || func.def->definition_extent)
break; break;

View File

@ -143,32 +143,30 @@ struct TextDocumentCodeLensHandler
common.working_files = working_files; common.working_files = working_files;
common.working_file = working_files->GetFileByFilename(file->def->path); common.working_file = working_files->GetFileByFilename(file->def->path);
for (SymbolRef ref : file->def->outline) { for (SymbolRef sym : file->def->outline) {
// NOTE: We OffsetColumn so that the code lens always show up in a // NOTE: We OffsetColumn so that the code lens always show up in a
// predictable order. Otherwise, the client may randomize it. // predictable order. Otherwise, the client may randomize it.
SymbolIdx symbol = ref.idx; switch (sym.kind) {
switch (symbol.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (!type.def) if (!type.def)
continue; continue;
if (type.def->kind == ClangSymbolKind::Namespace) if (type.def->kind == ClangSymbolKind::Namespace)
continue; continue;
AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0),
type.uses, type.def->definition_spelling, type.uses, type.def->definition_spelling,
true /*force_display*/); true /*force_display*/);
AddCodeLens("derived", "derived", &common, AddCodeLens(
ref.loc.OffsetStartColumn(1), "derived", "derived", &common, sym.OffsetStartColumn(db, 1),
ToReference(db, type.derived), nullopt, ToReference(db, type.derived), nullopt, false /*force_display*/);
false /*force_display*/); AddCodeLens("var", "vars", &common, sym.OffsetStartColumn(db, 2),
AddCodeLens("var", "vars", &common, ref.loc.OffsetStartColumn(2),
ToReference(db, type.instances), nullopt, ToReference(db, type.instances), nullopt,
false /*force_display*/); false /*force_display*/);
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = sym.Func(db);
if (!func.def) if (!func.def)
continue; continue;
@ -179,12 +177,13 @@ struct TextDocumentCodeLensHandler
// extent location to the spelling location. // extent location to the spelling location.
auto try_ensure_spelling = [&](SymbolRef sym) { auto try_ensure_spelling = [&](SymbolRef sym) {
optional<QueryLocation> def = optional<QueryLocation> def =
GetDefinitionSpellingOfSymbol(db, sym.idx); GetDefinitionSpellingOfSymbol(db, sym);
if (!def || def->FileId() != sym.loc.FileId() || if (!def || def->FileId() != GetFileId(db, sym) ||
def->range.start.line != sym.loc.range.start.line) { def->range.start.line != sym.range.start.line) {
return sym.loc; return sym;
} }
return *def; return SymbolRef(def->range, Id<void>(def->FileId()),
SymbolKind::File, SymbolRole::None);
}; };
std::vector<QueryFuncRef> base_callers = std::vector<QueryFuncRef> base_callers =
@ -192,31 +191,31 @@ struct TextDocumentCodeLensHandler
std::vector<QueryFuncRef> derived_callers = std::vector<QueryFuncRef> derived_callers =
GetCallersForAllDerivedFunctions(db, func); GetCallersForAllDerivedFunctions(db, func);
if (base_callers.empty() && derived_callers.empty()) { if (base_callers.empty() && derived_callers.empty()) {
QueryLocation loc = try_ensure_spelling(ref); SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("call", "calls", &common, AddCodeLens("call", "calls", &common,
loc.OffsetStartColumn(offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, func.callers), nullopt, ToReference(db, func.callers), nullopt,
true /*force_display*/); true /*force_display*/);
} else { } else {
QueryLocation loc = try_ensure_spelling(ref); SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("direct call", "direct calls", &common, AddCodeLens("direct call", "direct calls", &common,
loc.OffsetStartColumn(offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, func.callers), nullopt, ToReference(db, func.callers), nullopt,
false /*force_display*/); false /*force_display*/);
if (!base_callers.empty()) if (!base_callers.empty())
AddCodeLens("base call", "base calls", &common, AddCodeLens("base call", "base calls", &common,
loc.OffsetStartColumn(offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, base_callers), nullopt, ToReference(db, base_callers), nullopt,
false /*force_display*/); false /*force_display*/);
if (!derived_callers.empty()) if (!derived_callers.empty())
AddCodeLens("derived call", "derived calls", &common, AddCodeLens("derived call", "derived calls", &common,
loc.OffsetStartColumn(offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, derived_callers), nullopt, ToReference(db, derived_callers), nullopt,
false /*force_display*/); false /*force_display*/);
} }
AddCodeLens("derived", "derived", &common, AddCodeLens("derived", "derived", &common,
ref.loc.OffsetStartColumn(offset++), sym.OffsetStartColumn(db, offset++),
ToReference(db, func.derived), nullopt, ToReference(db, func.derived), nullopt,
false /*force_display*/); false /*force_display*/);
@ -230,7 +229,7 @@ struct TextDocumentCodeLensHandler
GetLsLocation(db, working_files, *base_loc); GetLsLocation(db, working_files, *base_loc);
if (ls_base) { if (ls_base) {
optional<lsRange> range = optional<lsRange> range =
GetLsRange(common.working_file, ref.loc.range); GetLsRange(common.working_file, sym.range);
if (range) { if (range) {
TCodeLens code_lens; TCodeLens code_lens;
code_lens.range = *range; code_lens.range = *range;
@ -245,7 +244,7 @@ struct TextDocumentCodeLensHandler
} }
} }
} else { } else {
AddCodeLens("base", "base", &common, ref.loc.OffsetStartColumn(1), AddCodeLens("base", "base", &common, sym.OffsetStartColumn(db, 1),
ToReference(db, func.def->base), nullopt, ToReference(db, func.def->base), nullopt,
false /*force_display*/); false /*force_display*/);
} }
@ -253,7 +252,7 @@ struct TextDocumentCodeLensHandler
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (!var.def) if (!var.def)
continue; continue;
@ -266,7 +265,7 @@ struct TextDocumentCodeLensHandler
if (var.def->is_macro()) if (var.def->is_macro())
force_display = false; force_display = false;
AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0),
var.uses, var.def->definition_spelling, force_display); var.uses, var.def->definition_spelling, force_display);
break; break;
} }

View File

@ -24,23 +24,24 @@ struct Out_TextDocumentDefinition
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result); MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<Reference> GetGotoDefinitionTargets(QueryDatabase* db, std::vector<Reference> GetGotoDefinitionTargets(QueryDatabase* db,
const SymbolIdx& symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
// Returns GetDeclarationsOfSymbolForGotoDefinition and // Returns GetDeclarationsOfSymbolForGotoDefinition and
// variable type definition. // variable type definition.
case SymbolKind::Var: { case SymbolKind::Var: {
std::vector<Reference> ret = std::vector<Reference> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, symbol); GetDeclarationsOfSymbolForGotoDefinition(db, sym);
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (var.def && var.def->variable_type) { if (var.def && var.def->variable_type) {
std::vector<Reference> types = GetDeclarationsOfSymbolForGotoDefinition( std::vector<Reference> types = GetDeclarationsOfSymbolForGotoDefinition(
db, SymbolIdx(SymbolKind::Type, var.def->variable_type->id)); db, SymbolRef(Range(), Id<void>(var.def->variable_type->id),
SymbolKind::Type, SymbolRole::None));
ret.insert(ret.end(), types.begin(), types.end()); ret.insert(ret.end(), types.begin(), types.end());
} }
return ret; return ret;
} }
default: default:
return GetDeclarationsOfSymbolForGotoDefinition(db, symbol); return GetDeclarationsOfSymbolForGotoDefinition(db, sym);
} }
} }
@ -64,7 +65,7 @@ struct TextDocumentDefinitionHandler
int target_line = request->params.position.line; int target_line = request->params.position.line;
int target_column = request->params.position.character; int target_column = request->params.position.character;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return definition. // Found symbol. Return definition.
@ -73,14 +74,12 @@ struct TextDocumentDefinitionHandler
// - start at spelling but end at extent for better mouse tooltip // - start at spelling but end at extent for better mouse tooltip
// - goto declaration while in definition of recursive type // - goto declaration while in definition of recursive type
optional<QueryLocation> def_loc = optional<QueryLocation> def_loc = GetDefinitionSpellingOfSymbol(db, sym);
GetDefinitionSpellingOfSymbol(db, ref.idx);
// We use spelling start and extent end because this causes vscode to // We use spelling start and extent end because this causes vscode to
// highlight the entire definition when previewing / hoving with the // highlight the entire definition when previewing / hoving with the
// mouse. // mouse.
optional<QueryLocation> def_extent = optional<QueryLocation> def_extent = GetDefinitionExtentOfSymbol(db, sym);
GetDefinitionExtentOfSymbol(db, ref.idx);
if (def_loc && def_extent) if (def_loc && def_extent)
def_loc->range.end = def_extent->range.end; def_loc->range.end = def_extent->range.end;
@ -92,7 +91,7 @@ struct TextDocumentDefinitionHandler
def_loc->range.Contains(target_line, target_column))) { def_loc->range.Contains(target_line, target_column))) {
// Goto declaration. // Goto declaration.
std::vector<Reference> targets = GetGotoDefinitionTargets(db, ref.idx); std::vector<Reference> targets = GetGotoDefinitionTargets(db, sym);
for (Reference target : targets) { for (Reference target : targets) {
optional<lsLocation> ls_target = optional<lsLocation> ls_target =
GetLsLocation(db, working_files, target); GetLsLocation(db, working_files, target);

View File

@ -35,13 +35,13 @@ struct TextDocumentDocumentSymbolHandler
return; return;
} }
for (SymbolRef ref : file->def->outline) { for (SymbolRef sym : file->def->outline) {
optional<lsSymbolInformation> info = optional<lsSymbolInformation> info =
GetSymbolInfo(db, working_files, ref.idx, true /*use_short_name*/); GetSymbolInfo(db, working_files, sym, true /*use_short_name*/);
if (!info) if (!info)
continue; continue;
optional<lsLocation> location = GetLsLocation(db, working_files, ref.loc); optional<lsLocation> location = GetLsLocation(db, working_files, sym);
if (!location) if (!location)
continue; continue;
info->location = *location; info->location = *location;

View File

@ -35,10 +35,10 @@ struct TextDocumentDocumentHighlightHandler
Out_TextDocumentDocumentHighlight out; Out_TextDocumentDocumentHighlight out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to highlight. // Found symbol. Return references to highlight.
std::vector<Reference> uses = GetUsesOfSymbol(db, ref.idx, true); std::vector<Reference> uses = GetUsesOfSymbol(db, sym, true);
out.result.reserve(uses.size()); out.result.reserve(uses.size());
for (const Reference& use : uses) { for (const Reference& use : uses) {
if (GetFileId(db, use) != file_id) if (GetFileId(db, use) != file_id)

View File

@ -6,10 +6,10 @@ namespace {
std::pair<std::string_view, std::string_view> GetCommentsAndHover( std::pair<std::string_view, std::string_view> GetCommentsAndHover(
QueryDatabase* db, QueryDatabase* db,
const SymbolIdx& symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = db->types[sym.Idx()];
if (type.def) if (type.def)
return {type.def->comments, type.def->hover.size() return {type.def->comments, type.def->hover.size()
? type.def->hover ? type.def->hover
@ -17,7 +17,7 @@ std::pair<std::string_view, std::string_view> GetCommentsAndHover(
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = db->funcs[sym.Idx()];
if (func.def) if (func.def)
return {func.def->comments, func.def->hover.size() return {func.def->comments, func.def->hover.size()
? func.def->hover ? func.def->hover
@ -25,7 +25,7 @@ std::pair<std::string_view, std::string_view> GetCommentsAndHover(
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = db->vars[sym.Idx()];
if (var.def) if (var.def)
return {var.def->comments, var.def->hover.size() return {var.def->comments, var.def->hover.size()
? var.def->hover ? var.def->hover
@ -87,16 +87,16 @@ struct TextDocumentHoverHandler : BaseMessageHandler<Ipc_TextDocumentHover> {
Out_TextDocumentHover out; Out_TextDocumentHover out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return hover. // Found symbol. Return hover.
optional<lsRange> ls_range = GetLsRange( optional<lsRange> ls_range = GetLsRange(
working_files->GetFileByFilename(file->def->path), ref.loc.range); working_files->GetFileByFilename(file->def->path), sym.range);
if (!ls_range) if (!ls_range)
continue; continue;
std::pair<std::string_view, std::string_view> comments_hover = std::pair<std::string_view, std::string_view> comments_hover =
GetCommentsAndHover(db, ref.idx); GetCommentsAndHover(db, sym);
if (comments_hover.first.size() || comments_hover.second.size()) { if (comments_hover.first.size() || comments_hover.second.size()) {
out.result = Out_TextDocumentHover::Result(); out.result = Out_TextDocumentHover::Result();
if (comments_hover.first.size()) { if (comments_hover.first.size()) {

View File

@ -51,11 +51,11 @@ struct TextDocumentReferencesHandler
Out_TextDocumentReferences out; Out_TextDocumentReferences out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references. // Found symbol. Return references.
std::vector<Reference> uses = GetUsesOfSymbol( std::vector<Reference> uses = GetUsesOfSymbol(
db, ref.idx, request->params.context.includeDeclaration); db, sym, request->params.context.includeDeclaration);
out.result.reserve(uses.size()); out.result.reserve(uses.size());
for (const Reference& use : uses) { for (const Reference& use : uses) {
optional<lsLocation> ls_location = optional<lsLocation> ls_location =

View File

@ -95,11 +95,11 @@ struct TextDocumentRenameHandler : BaseMessageHandler<Ipc_TextDocumentRename> {
Out_TextDocumentRename out; Out_TextDocumentRename out;
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to rename. // Found symbol. Return references to rename.
out.result = BuildWorkspaceEdit(db, working_files, out.result = BuildWorkspaceEdit(db, working_files,
GetUsesOfSymbol(db, ref.idx, true), GetUsesOfSymbol(db, sym, true),
request->params.newName); request->params.newName);
break; break;
} }

View File

@ -237,36 +237,38 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
} }
}(); }();
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) { auto add_outline = [&](Range range, RawId id, SymbolKind kind,
def.outline.push_back( SymbolRole role) {
SymbolRef(idx, SymbolRole::Declaration, def.outline.push_back(SymbolRef(range, Id<void>(id), kind, role));
id_map.ToQuery(range, SymbolRole::Declaration)));
}; };
auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role, auto add_all_symbols = [&](Range range, RawId id, SymbolKind kind,
Range range) { SymbolRole role) {
def.all_symbols.push_back( def.all_symbols.push_back(SymbolRef(range, Id<void>(id), kind, role));
SymbolRef(idx, role, id_map.ToQuery(range, role)));
}; };
for (const IndexType& type : indexed.types) { for (const IndexType& type : indexed.types) {
RawId id = id_map.ToQuery(type.id).id;
if (type.def.definition_spelling.has_value()) if (type.def.definition_spelling.has_value())
add_all_symbols(id_map.ToSymbol(type.id), SymbolRole::Definition, add_all_symbols(*type.def.definition_spelling, id, SymbolKind::Type,
*type.def.definition_spelling); SymbolRole::Definition);
if (type.def.definition_extent.has_value()) if (type.def.definition_extent)
add_outline(id_map.ToSymbol(type.id), *type.def.definition_extent); add_outline(*type.def.definition_extent, id, SymbolKind::Type,
SymbolRole::None);
for (const Reference& use : type.uses) for (const Reference& use : type.uses)
add_all_symbols(id_map.ToSymbol(type.id), use.role, use.range); add_all_symbols(use.range, id, SymbolKind::Type, use.role);
} }
for (const IndexFunc& func : indexed.funcs) { for (const IndexFunc& func : indexed.funcs) {
RawId id = id_map.ToQuery(func.id).id;
if (func.def.definition_spelling.has_value()) if (func.def.definition_spelling.has_value())
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Definition, add_all_symbols(*func.def.definition_spelling, id, SymbolKind::Func,
*func.def.definition_spelling); SymbolRole::Definition);
if (func.def.definition_extent.has_value()) if (func.def.definition_extent.has_value())
add_outline(id_map.ToSymbol(func.id), *func.def.definition_extent); add_outline(*func.def.definition_extent, id,
SymbolKind::Func, SymbolRole::None);
for (const IndexFunc::Declaration& decl : func.declarations) { for (const IndexFunc::Declaration& decl : func.declarations) {
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration, add_all_symbols(decl.spelling, id, SymbolKind::Func,
decl.spelling); SymbolRole::Declaration);
add_outline(id_map.ToSymbol(func.id), decl.spelling); add_outline(decl.spelling, id, SymbolKind::Func, SymbolRole::Declaration);
} }
for (const IndexFuncRef& caller : func.callers) { for (const IndexFuncRef& caller : func.callers) {
// Make ranges of implicit function calls larger (spanning one more column // Make ranges of implicit function calls larger (spanning one more column
@ -279,31 +281,35 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
range.start.column--; range.start.column--;
range.end.column++; range.end.column++;
} }
add_all_symbols(id_map.ToSymbol(func.id), add_all_symbols(range, id, SymbolKind::Func,
caller.role | SymbolRole::CalledBy, range); caller.role | SymbolRole::CalledBy);
} }
} }
for (const IndexVar& var : indexed.vars) { for (const IndexVar& var : indexed.vars) {
if (var.def.definition_spelling.has_value()) if (var.def.definition_spelling)
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Definition, add_all_symbols(*var.def.definition_spelling, id_map.ToQuery(var.id).id,
*var.def.definition_spelling); SymbolKind::Var, SymbolRole::Definition);
if (var.def.definition_extent.has_value()) if (var.def.definition_extent.has_value())
add_outline(id_map.ToSymbol(var.id), *var.def.definition_extent); add_outline(*var.def.definition_extent, id_map.ToQuery(var.id).id,
SymbolKind::Var, SymbolRole::None);
for (const Range& decl : var.declarations) { for (const Range& decl : var.declarations) {
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Declaration, decl); add_all_symbols(decl, id_map.ToQuery(var.id).id, SymbolKind::Var,
add_outline(id_map.ToSymbol(var.id), decl); SymbolRole::Definition);
add_outline(decl, id_map.ToQuery(var.id).id, SymbolKind::Var,
SymbolRole::Declaration);
} }
for (auto& use : var.uses) for (auto& use : var.uses)
add_all_symbols(id_map.ToSymbol(var.id), use.role, use.range); add_all_symbols(use.range, id_map.ToQuery(var.id).id, SymbolKind::Var,
use.role);
} }
std::sort(def.outline.begin(), def.outline.end(), std::sort(def.outline.begin(), def.outline.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return a.loc.range.start < b.loc.range.start; return a.range.start < b.range.start;
}); });
std::sort(def.all_symbols.begin(), def.all_symbols.end(), std::sort(def.all_symbols.begin(), def.all_symbols.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return a.loc.range.start < b.loc.range.start; return a.range.start < b.range.start;
}); });
return QueryFile::DefUpdate(def, indexed.file_contents); return QueryFile::DefUpdate(def, indexed.file_contents);
@ -372,6 +378,44 @@ Maybe<QueryVarId> GetQueryVarIdFromUsr(QueryDatabase* query_db,
} // namespace } // namespace
QueryFileId GetFileId(QueryDatabase* db, Reference ref) {
switch (ref.kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.id);
case SymbolKind::Func: {
QueryFunc& file = db->funcs[ref.id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = db->types[ref.id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[ref.id.id];
if (var.def)
return var.def->file;
break;
}
}
return QueryFileId();
}
QueryFunc& SymbolRef::Func(QueryDatabase* db) const {
return db->funcs[Idx()];
}
QueryType& SymbolRef::Type(QueryDatabase* db) const {
return db->types[Idx()];
}
QueryVar& SymbolRef::Var(QueryDatabase* db) const {
return db->vars[Idx()];
}
Maybe<QueryFileId> QueryDatabase::GetQueryFileIdFromPath( Maybe<QueryFileId> QueryDatabase::GetQueryFileIdFromPath(
const std::string& path) { const std::string& path) {
return ::GetQueryFileIdFromPath(this, path, false); return ::GetQueryFileIdFromPath(this, path, false);
@ -415,23 +459,23 @@ QueryLocation IdMap::ToQuery(Range range, SymbolRole role) const {
return QueryLocation{range, primary_file, role}; return QueryLocation{range, primary_file, role};
} }
Reference IdMap::ToQuery(Reference ref) const { Reference IdMap::ToQuery(Reference ref) const {
switch (ref.lex_parent_kind) { switch (ref.kind) {
case SymbolKind::Invalid: case SymbolKind::Invalid:
case SymbolKind::File: case SymbolKind::File:
ref.lex_parent_kind = SymbolKind::File; ref.kind = SymbolKind::File;
ref.lex_parent_id = Id<void>(primary_file); ref.id = Id<void>(primary_file);
break; break;
case SymbolKind::Func: case SymbolKind::Func:
ref.lex_parent_id = Id<void>( ref.id = Id<void>(
cached_func_ids_.find(IndexFuncId(ref.lex_parent_id))->second); cached_func_ids_.find(IndexFuncId(ref.id))->second);
break; break;
case SymbolKind::Type: case SymbolKind::Type:
ref.lex_parent_id = Id<void>( ref.id = Id<void>(
cached_type_ids_.find(IndexTypeId(ref.lex_parent_id))->second); cached_type_ids_.find(IndexTypeId(ref.id))->second);
break; break;
case SymbolKind::Var: case SymbolKind::Var:
ref.lex_parent_id = ref.id =
Id<void>(cached_var_ids_.find(IndexVarId(ref.lex_parent_id))->second); Id<void>(cached_var_ids_.find(IndexVarId(ref.id))->second);
break; break;
} }
return ref; return ref;
@ -451,18 +495,18 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const {
return QueryVarId(cached_var_ids_.find(id)->second); return QueryVarId(cached_var_ids_.find(id)->second);
} }
QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const { QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const {
QueryFuncRef ret(ref.range, ref.lex_parent_id, ref.lex_parent_kind, ref.role); QueryFuncRef ret(ref.range, ref.id, ref.kind, ref.role);
switch (ref.lex_parent_kind) { switch (ref.kind) {
default: default:
break; break;
case SymbolKind::File: case SymbolKind::File:
ret.lex_parent_id = Id<void>(primary_file); ret.id = Id<void>(primary_file);
break; break;
case SymbolKind::Func: case SymbolKind::Func:
ret.lex_parent_id = Id<void>(ToQuery(IndexFuncId(ref.lex_parent_id))); ret.id = Id<void>(ToQuery(IndexFuncId(ref.id)));
break; break;
case SymbolKind::Type: case SymbolKind::Type:
ret.lex_parent_id = Id<void>(ToQuery(IndexTypeId(ref.lex_parent_id))); ret.id = Id<void>(ToQuery(IndexTypeId(ref.id)));
break; break;
} }
return ret; return ret;

View File

@ -25,12 +25,6 @@ struct QueryLocation {
QueryFileId path; QueryFileId path;
SymbolRole role; SymbolRole role;
QueryLocation OffsetStartColumn(int16_t offset) const {
QueryLocation result = *this;
result.range.start.column += offset;
return result;
}
bool HasValue() const { return range.HasValue(); } bool HasValue() const { return range.HasValue(); }
QueryFileId FileId() const { return path; } QueryFileId FileId() const { return path; }
@ -52,15 +46,6 @@ struct QueryLocation {
MAKE_REFLECT_STRUCT(QueryLocation, range, path, role); MAKE_REFLECT_STRUCT(QueryLocation, range, path, role);
MAKE_HASHABLE(QueryLocation, t.range, t.path, t.role); MAKE_HASHABLE(QueryLocation, t.range, t.path, t.role);
namespace std {
template <>
struct hash<::SymbolKind> {
size_t operator()(const ::SymbolKind& instance) const {
return std::hash<int>()(static_cast<int>(instance));
}
};
} // namespace std
struct SymbolIdx { struct SymbolIdx {
SymbolKind kind; SymbolKind kind;
RawId idx; RawId idx;
@ -83,23 +68,27 @@ struct SymbolIdx {
MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx); MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx);
MAKE_HASHABLE(SymbolIdx, t.kind, t.idx); MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
struct SymbolRef { QueryFileId GetFileId(QueryDatabase* db, Reference ref);
SymbolIdx idx;
SymbolRole role;
QueryLocation loc;
SymbolRef() {} // Do not use, needed for reflect. struct SymbolRef : Reference {
SymbolRef(SymbolIdx idx, SymbolRole role, QueryLocation loc) SymbolRef() = default;
: idx(idx), role(role), loc(loc) {} SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {}
SymbolRef(SymbolIdx si)
: Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {}
std::tuple<SymbolIdx, SymbolRole, QueryLocation> ToTuple() const { RawId Idx() const { return RawId(id); }
return std::make_tuple(idx, role, loc); operator SymbolIdx() const { return SymbolIdx(kind, Idx()); }
QueryFunc& Func(QueryDatabase* db) const;
QueryType& Type(QueryDatabase* db) const;
QueryVar& Var(QueryDatabase* db) const;
QueryLocation OffsetStartColumn(QueryDatabase* db, int16_t offset) const {
QueryLocation ret = {range, GetFileId(db, *this), role};
ret.range.start.column += offset;
return ret;
} }
bool operator==(const SymbolRef& o) const { return ToTuple() == o.ToTuple(); }
bool operator!=(const SymbolRef& o) const { return !(*this == o); }
bool operator<(const SymbolRef& o) const { return ToTuple() < o.ToTuple(); }
}; };
MAKE_REFLECT_STRUCT(SymbolRef, idx, loc);
struct QueryFuncRef : Reference { struct QueryFuncRef : Reference {
QueryFuncRef() = default; QueryFuncRef() = default;
@ -107,8 +96,8 @@ struct QueryFuncRef : Reference {
: Reference{range, id, kind, role} {} : Reference{range, id, kind, role} {}
QueryFuncId FuncId() const { QueryFuncId FuncId() const {
if (lex_parent_kind == SymbolKind::Func) if (kind == SymbolKind::Func)
return QueryFuncId(lex_parent_id); return QueryFuncId(id);
return QueryFuncId(); return QueryFuncId();
} }
}; };
@ -448,5 +437,3 @@ struct IdMap {
spp::sparse_hash_map<IndexFuncId, QueryFuncId> cached_func_ids_; spp::sparse_hash_map<IndexFuncId, QueryFuncId> cached_func_ids_;
spp::sparse_hash_map<IndexVarId, QueryVarId> cached_var_ids_; spp::sparse_hash_map<IndexVarId, QueryVarId> cached_var_ids_;
}; };
QueryFileId GetFileId(const Reference& ref, QueryDatabase* db);

View File

@ -16,34 +16,6 @@ int ComputeRangeSize(const Range& range) {
} // namespace } // namespace
QueryFileId GetFileId(QueryDatabase* db, Reference ref) {
switch (ref.lex_parent_kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.lex_parent_id);
case SymbolKind::Func: {
QueryFunc& file = db->funcs[ref.lex_parent_id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = db->types[ref.lex_parent_id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[ref.lex_parent_id.id];
if (var.def)
return var.def->file;
break;
}
}
return QueryFileId();
}
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryTypeId& id) { const QueryTypeId& id) {
QueryType& type = db->types[id.id]; QueryType& type = db->types[id.id];
@ -69,22 +41,22 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
} }
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (type.def) if (type.def)
return *type.def->definition_spelling; return *type.def->definition_spelling;
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = sym.Func(db);
if (func.def) if (func.def)
return func.def->definition_spelling; return func.def->definition_spelling;
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (var.def) if (var.def)
return var.def->definition_spelling; return var.def->definition_spelling;
break; break;
@ -99,29 +71,29 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
} }
optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (type.def) if (type.def)
return type.def->definition_extent; return type.def->definition_extent;
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = sym.Func(db);
if (func.def) if (func.def)
return func.def->definition_extent; return func.def->definition_extent;
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (var.def) if (var.def)
return var.def->definition_extent; return var.def->definition_extent;
break; break;
} }
case SymbolKind::File: { case SymbolKind::File: {
return QueryLocation{Range(Position(0, 0), Position(0, 0)), return QueryLocation{Range(Position(0, 0), Position(0, 0)),
QueryFileId(symbol.idx), SymbolRole::None}; QueryFileId(sym.Idx()), SymbolRole::None};
} }
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
@ -132,16 +104,16 @@ optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
} }
optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
const SymbolIdx& symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (type.def && type.def->definition_spelling) if (type.def && type.def->definition_spelling)
return type.def->definition_spelling->FileId(); return type.def->definition_spelling->FileId();
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = sym.Func(db);
if (!func.declarations.empty()) if (!func.declarations.empty())
return GetFileId(db, func.declarations[0]); return GetFileId(db, func.declarations[0]);
if (func.def && func.def->definition_spelling) if (func.def && func.def->definition_spelling)
@ -149,13 +121,13 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (var.def && var.def->definition_spelling) if (var.def && var.def->definition_spelling)
return var.def->definition_spelling->FileId(); return var.def->definition_spelling->FileId();
break; break;
} }
case SymbolKind::File: { case SymbolKind::File: {
return QueryFileId(symbol.idx); return QueryFileId(sym.Idx());
} }
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
@ -175,11 +147,11 @@ std::vector<Reference> ToReference(QueryDatabase* db,
} }
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol, SymbolRef sym,
bool include_decl) { bool include_decl) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = db->types[sym.Idx()];
std::vector<Reference> ret = type.uses; std::vector<Reference> ret = type.uses;
if (include_decl && type.def && type.def->definition_spelling) if (include_decl && type.def && type.def->definition_spelling)
ret.push_back(*type.def->definition_spelling); ret.push_back(*type.def->definition_spelling);
@ -187,7 +159,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
} }
case SymbolKind::Func: { case SymbolKind::Func: {
// TODO: the vector allocation could be avoided. // TODO: the vector allocation could be avoided.
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = db->funcs[sym.Idx()];
std::vector<Reference> ret = ToReference(db, func.callers); std::vector<Reference> ret = ToReference(db, func.callers);
if (include_decl) { if (include_decl) {
AddRange(&ret, func.declarations); AddRange(&ret, func.declarations);
@ -197,7 +169,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
return ret; return ret;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = db->vars[sym.Idx()];
std::vector<Reference> ret = var.uses; std::vector<Reference> ret = var.uses;
if (include_decl) { if (include_decl) {
if (var.def && var.def->definition_spelling) if (var.def && var.def->definition_spelling)
@ -216,14 +188,14 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition( std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db, QueryDatabase* db,
SymbolIdx symbol) { SymbolRef sym) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
// Returning the definition spelling of a type is a hack (and is why the // Returning the definition spelling of a type is a hack (and is why the
// function has the postfix `ForGotoDefintion`, but it lets the user // function has the postfix `ForGotoDefintion`, but it lets the user
// jump to the start of a type if clicking goto-definition on the same // jump to the start of a type if clicking goto-definition on the same
// type from within the type definition. // type from within the type definition.
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (type.def) { if (type.def) {
optional<QueryLocation> declaration = type.def->definition_spelling; optional<QueryLocation> declaration = type.def->definition_spelling;
if (declaration) if (declaration)
@ -232,9 +204,9 @@ std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
break; break;
} }
case SymbolKind::Func: case SymbolKind::Func:
return db->funcs[symbol.idx].declarations; return sym.Func(db).declarations;
case SymbolKind::Var: case SymbolKind::Var:
return db->vars[symbol.idx].declarations; return sym.Var(db).declarations;
default: default:
break; break;
} }
@ -425,13 +397,13 @@ std::vector<lsLocation> GetLsLocations(
// Returns a symbol. The symbol will have *NOT* have a location assigned. // Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
SymbolIdx symbol, SymbolRef sym,
bool use_short_name) { bool use_short_name) {
switch (symbol.kind) { switch (sym.kind) {
case SymbolKind::File: { case SymbolKind::File: {
QueryFile& file = db->files[symbol.idx]; QueryFile& file = db->files[sym.Idx()];
if (!file.def) if (!file.def)
return nullopt; break;
lsSymbolInformation info; lsSymbolInformation info;
info.name = file.def->path; info.name = file.def->path;
@ -439,9 +411,9 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
return info; return info;
} }
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = sym.Type(db);
if (!type.def) if (!type.def)
return nullopt; break;
lsSymbolInformation info; lsSymbolInformation info;
if (use_short_name) if (use_short_name)
@ -462,9 +434,9 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
return info; return info;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = sym.Func(db);
if (!func.def) if (!func.def)
return nullopt; break;
lsSymbolInformation info; lsSymbolInformation info;
if (use_short_name) if (use_short_name)
@ -483,9 +455,9 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
return info; return info;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = sym.Var(db);
if (!var.def) if (!var.def)
return nullopt; break;
lsSymbolInformation info; lsSymbolInformation info;
if (use_short_name) if (use_short_name)
@ -496,10 +468,9 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
info.kind = lsSymbolKind::Variable; info.kind = lsSymbolKind::Variable;
return info; return info;
} }
case SymbolKind::Invalid: { case SymbolKind::Invalid:
return nullopt; break;
} }
};
return nullopt; return nullopt;
} }
@ -520,9 +491,9 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
target_line = *index_line; target_line = *index_line;
} }
for (const SymbolRef& ref : file->def->all_symbols) { for (const SymbolRef& sym : file->def->all_symbols) {
if (ref.loc.range.Contains(target_line, target_column)) if (sym.range.Contains(target_line, target_column))
symbols.push_back(ref); symbols.push_back(sym);
} }
// Order shorter ranges first, since they are more detailed/precise. This is // Order shorter ranges first, since they are more detailed/precise. This is
@ -538,17 +509,16 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
// better on constructors. // better on constructors.
std::sort(symbols.begin(), symbols.end(), std::sort(symbols.begin(), symbols.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
int a_size = ComputeRangeSize(a.loc.range); int a_size = ComputeRangeSize(a.range);
int b_size = ComputeRangeSize(b.loc.range); int b_size = ComputeRangeSize(b.range);
if (a_size != b_size) if (a_size != b_size)
return a_size < b_size; return a_size < b_size;
// operator> orders Var/Func before Type. // operator> orders Var/Func before Type.
int t = int t = static_cast<int>(a.kind) - static_cast<int>(b.kind);
static_cast<int>(a.idx.kind) - static_cast<int>(b.idx.kind);
if (t) if (t)
return t > 0; return t > 0;
return a.idx.idx < b.idx.idx; return a.Idx() < b.Idx();
}); });
return symbols; return symbols;

View File

@ -14,13 +14,11 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryVarId& id); const QueryVarId& id);
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol); SymbolRef sym);
optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db, optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol); SymbolRef sym);
optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
const SymbolIdx& symbol); SymbolRef sym);
QueryFileId GetFileId(QueryDatabase* db, Reference ref);
std::vector<Reference> ToReference(QueryDatabase* db, std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs); const std::vector<QueryFuncRef>& refs);
@ -39,11 +37,11 @@ std::vector<Reference> ToReference(QueryDatabase* db,
} }
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol, SymbolRef sym,
bool include_decl); bool include_decl);
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition( std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db, QueryDatabase* db,
SymbolIdx symbol); SymbolRef sym);
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root); bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db, std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
@ -68,7 +66,7 @@ std::vector<lsLocation> GetLsLocations(
// Returns a symbol. The symbol will have *NOT* have a location assigned. // Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
SymbolIdx symbol, SymbolRef sym,
bool use_short_name); bool use_short_name);
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file, std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,

2
third_party/loguru vendored

@ -1 +1 @@
Subproject commit 2c35b5e7251ab5d364b1b3164eccef7b5d2293c5 Subproject commit bead38889d44d9fdb5c52916d1f26c4d6af09e66