Change is_implicit to role in {Index,Query}FuncRef

Add `FileId file` to *DefDefinitionData::Def
This commit is contained in:
Fangrui Song 2018-02-07 19:14:44 -08:00
parent 10c2843846
commit dbdab02ff4
10 changed files with 165 additions and 168 deletions

View File

@ -584,7 +584,7 @@ void OnIndexReference_Function(IndexFile* db,
ClangCursor caller_cursor, ClangCursor caller_cursor,
IndexFuncId called_id, IndexFuncId called_id,
IndexFunc* called, IndexFunc* called,
bool is_implicit) { SymbolRole role) {
if (IsFunctionCallContext(caller_cursor.get_kind())) { if (IsFunctionCallContext(caller_cursor.get_kind())) {
IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor); IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor);
IndexFunc* caller = db->Resolve(caller_id); IndexFunc* caller = db->Resolve(caller_id);
@ -592,10 +592,10 @@ void OnIndexReference_Function(IndexFile* db,
called = db->Resolve(called_id); called = db->Resolve(called_id);
AddFuncRef(&caller->def.callees, AddFuncRef(&caller->def.callees,
IndexFuncRef(called->id, loc, is_implicit)); IndexFuncRef{loc, called->id, role});
AddFuncRef(&called->callers, IndexFuncRef(caller->id, loc, is_implicit)); AddFuncRef(&called->callers, IndexFuncRef{loc, caller->id, role});
} else { } else {
AddFuncRef(&called->callers, IndexFuncRef(loc, is_implicit)); AddFuncRef(&called->callers, IndexFuncRef{loc, IndexFuncId(), role});
} }
} }
@ -603,7 +603,7 @@ void OnIndexReference_Function(IndexFile* db,
// static // static
const int IndexFile::kMajorVersion = 11; const int IndexFile::kMajorVersion = 11;
const int IndexFile::kMinorVersion = 1; const int IndexFile::kMinorVersion = 2;
IndexFile::IndexFile(const std::string& path, IndexFile::IndexFile(const std::string& path,
const std::string& contents) const std::string& contents)
@ -1258,7 +1258,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
IndexFunc* called = db->Resolve(called_id); IndexFunc* called = db->Resolve(called_id);
OnIndexReference_Function(db, cursor.get_spelling_range(), OnIndexReference_Function(db, cursor.get_spelling_range(),
data->container, called_id, called, data->container, called_id, called,
/*implicit=*/false); SymbolRole::None);
break; break;
} }
} }
@ -1992,8 +1992,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
else else
CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db); CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db);
OnIndexReference_Function(db, loc, ref->container->cursor, called_id, OnIndexReference_Function(
called, is_implicit); db, loc, ref->container->cursor, called_id, called,
is_implicit ? SymbolRole::Implicit : SymbolRole::None);
// Checks if |str| starts with |start|. Ignores case. // Checks if |str| starts with |start|. Ignores case.
auto str_begin = [](const char* start, const char* str) { auto str_begin = [](const char* start, const char* str) {
@ -2033,7 +2034,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
param->ctors.TryFindConstructorUsr(ctor_type_usr, call_type_desc); param->ctors.TryFindConstructorUsr(ctor_type_usr, call_type_desc);
if (ctor_usr) { if (ctor_usr) {
IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr)); IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr));
AddFuncRef(&ctor->callers, IndexFuncRef(loc, true /*is_implicit*/)); AddFuncRef(&ctor->callers,
IndexFuncRef{loc, IndexFuncId(), SymbolRole::Implicit});
} }
} }
} }
@ -2315,7 +2317,7 @@ void Reflect(Reader& visitor, IndexFuncRef& value) {
std::string s = visitor.GetString(); std::string s = visitor.GetString();
const char* str_value = s.c_str(); const char* str_value = s.c_str();
if (str_value[0] == '~') { if (str_value[0] == '~') {
value.is_implicit = true; value.role = SymbolRole::Implicit;
++str_value; ++str_value;
} }
RawId id = atol(str_value); RawId id = atol(str_value);
@ -2324,15 +2326,15 @@ void Reflect(Reader& visitor, IndexFuncRef& value) {
value.id = IndexFuncId(id); value.id = IndexFuncId(id);
value.loc = Range(loc_string); value.loc = Range(loc_string);
} else { } else {
Reflect(visitor, value.id);
Reflect(visitor, value.loc); Reflect(visitor, value.loc);
Reflect(visitor, value.is_implicit); Reflect(visitor, value.id);
Reflect(visitor, value.role);
} }
} }
void Reflect(Writer& visitor, IndexFuncRef& value) { void Reflect(Writer& visitor, IndexFuncRef& value) {
if (visitor.Format() == SerializeFormat::Json) { if (visitor.Format() == SerializeFormat::Json) {
std::string s; std::string s;
if (value.is_implicit) if (value.role & SymbolRole::Implicit)
s += "~"; s += "~";
// id.id is unsigned, special case -1 value // id.id is unsigned, special case -1 value
@ -2344,8 +2346,8 @@ void Reflect(Writer& visitor, IndexFuncRef& value) {
s += "@" + value.loc.ToString(); s += "@" + value.loc.ToString();
visitor.String(s.c_str()); visitor.String(s.c_str());
} else { } else {
Reflect(visitor, value.id);
Reflect(visitor, value.loc); Reflect(visitor, value.loc);
Reflect(visitor, value.is_implicit); Reflect(visitor, value.id);
Reflect(visitor, value.role);
} }
} }

View File

@ -27,6 +27,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
struct IndexFile;
struct IndexType; struct IndexType;
struct IndexFunc; struct IndexFunc;
struct IndexVar; struct IndexVar;
@ -61,7 +62,7 @@ struct Id {
namespace std { namespace std {
template <typename T> template <typename T>
struct hash<Id<T>> { struct hash<Id<T>> {
size_t operator()(const Id<T>& k) const { return hash<size_t>()(k.id); } size_t operator()(const Id<T>& k) const { return hash<RawId>()(k.id); }
}; };
} // namespace std } // namespace std
@ -70,6 +71,7 @@ void Reflect(TVisitor& visitor, Id<T>& id) {
Reflect(visitor, id.id); Reflect(visitor, id.id);
} }
using IndexFileId = Id<IndexFile>;
using IndexTypeId = Id<IndexType>; using IndexTypeId = Id<IndexType>;
using IndexFuncId = Id<IndexFunc>; using IndexFuncId = Id<IndexFunc>;
using IndexVarId = Id<IndexVar>; using IndexVarId = Id<IndexVar>;
@ -88,18 +90,10 @@ struct IndexFuncRef {
// NOTE: id can be -1 if the function call is not coming from a function. // NOTE: id can be -1 if the function call is not coming from a function.
Range loc; Range loc;
IndexFuncId id; IndexFuncId id;
SymbolRole role = SymbolRole::None; SymbolRole role;
bool is_implicit = false;
IndexFuncRef() {} // For serialization. std::tuple<IndexFuncId, Range, SymbolRole> ToTuple() const {
return std::make_tuple(id, loc, role);
IndexFuncRef(IndexFuncId id, Range loc, bool is_implicit)
: loc(loc), id(id), is_implicit(is_implicit) {}
IndexFuncRef(Range loc, bool is_implicit)
: loc(loc), is_implicit(is_implicit) {}
std::tuple<IndexFuncId, Range, bool> ToTuple() const {
return std::make_tuple(id, loc, is_implicit);
} }
bool operator==(const IndexFuncRef& o) { return ToTuple() == o.ToTuple(); } bool operator==(const IndexFuncRef& o) { return ToTuple() == o.ToTuple(); }
bool operator!=(const IndexFuncRef& o) { return !(*this == o); } bool operator!=(const IndexFuncRef& o) { return !(*this == o); }
@ -111,7 +105,11 @@ struct IndexFuncRef {
void Reflect(Reader& visitor, IndexFuncRef& value); void Reflect(Reader& visitor, IndexFuncRef& value);
void Reflect(Writer& visitor, IndexFuncRef& value); void Reflect(Writer& visitor, IndexFuncRef& value);
template <typename TypeId, typename FuncId, typename VarId, typename Range> template <typename FileId,
typename TypeId,
typename FuncId,
typename VarId,
typename Range>
struct TypeDefDefinitionData { struct TypeDefDefinitionData {
// General metadata. // General metadata.
std::string detailed_name; std::string detailed_name;
@ -130,10 +128,6 @@ struct TypeDefDefinitionData {
Maybe<Range> definition_spelling; Maybe<Range> definition_spelling;
Maybe<Range> definition_extent; Maybe<Range> definition_extent;
// If set, then this is the same underlying type as the given value (ie, this
// type comes from a using or typedef statement).
Maybe<TypeId> alias_of;
// Immediate parent types. // Immediate parent types.
std::vector<TypeId> parents; std::vector<TypeId> parents;
@ -142,6 +136,11 @@ struct TypeDefDefinitionData {
std::vector<FuncId> funcs; std::vector<FuncId> funcs;
std::vector<VarId> vars; std::vector<VarId> vars;
FileId file;
// If set, then this is the same underlying type as the given value (ie, this
// type comes from a using or typedef statement).
Maybe<TypeId> alias_of;
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
ClangSymbolKind kind = ClangSymbolKind::Unknown; ClangSymbolKind kind = ClangSymbolKind::Unknown;
@ -164,12 +163,14 @@ struct TypeDefDefinitionData {
} }
}; };
template <typename TVisitor, template <typename TVisitor,
typename FileId,
typename TypeId, typename TypeId,
typename FuncId, typename FuncId,
typename VarId, typename VarId,
typename Range> typename Range>
void Reflect(TVisitor& visitor, void Reflect(
TypeDefDefinitionData<TypeId, FuncId, VarId, Range>& value) { TVisitor& visitor,
TypeDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
REFLECT_MEMBER(detailed_name); REFLECT_MEMBER(detailed_name);
REFLECT_MEMBER(short_name_offset); REFLECT_MEMBER(short_name_offset);
@ -179,6 +180,7 @@ void Reflect(TVisitor& visitor,
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(definition_spelling);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(definition_extent);
REFLECT_MEMBER(file);
REFLECT_MEMBER(alias_of); REFLECT_MEMBER(alias_of);
REFLECT_MEMBER(parents); REFLECT_MEMBER(parents);
REFLECT_MEMBER(types); REFLECT_MEMBER(types);
@ -188,8 +190,11 @@ void Reflect(TVisitor& visitor,
} }
struct IndexType { struct IndexType {
using Def = using Def = TypeDefDefinitionData<IndexFileId,
TypeDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; IndexTypeId,
IndexFuncId,
IndexVarId,
Range>;
Usr usr; Usr usr;
IndexTypeId id; IndexTypeId id;
@ -213,7 +218,8 @@ struct IndexType {
}; };
MAKE_HASHABLE(IndexType, t.id); MAKE_HASHABLE(IndexType, t.id);
template <typename TypeId, template <typename FileId,
typename TypeId,
typename FuncId, typename FuncId,
typename VarId, typename VarId,
typename FuncRef, typename FuncRef,
@ -226,9 +232,6 @@ struct FuncDefDefinitionData {
Maybe<Range> definition_spelling; Maybe<Range> definition_spelling;
Maybe<Range> definition_extent; Maybe<Range> definition_extent;
// Type which declares this one (ie, it is a method)
Maybe<TypeId> declaring_type;
// Method this method overrides. // Method this method overrides.
std::vector<FuncId> base; std::vector<FuncId> base;
@ -238,6 +241,9 @@ struct FuncDefDefinitionData {
// Functions that this function calls. // Functions that this function calls.
std::vector<FuncRef> callees; std::vector<FuncRef> callees;
FileId file;
// Type which declares this one (ie, it is a method)
Maybe<TypeId> declaring_type;
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
ClangSymbolKind kind = ClangSymbolKind::Unknown; ClangSymbolKind kind = ClangSymbolKind::Unknown;
@ -262,6 +268,7 @@ struct FuncDefDefinitionData {
}; };
template <typename TVisitor, template <typename TVisitor,
typename FileId,
typename TypeId, typename TypeId,
typename FuncId, typename FuncId,
typename VarId, typename VarId,
@ -269,7 +276,8 @@ template <typename TVisitor,
typename Range> typename Range>
void Reflect( void Reflect(
TVisitor& visitor, TVisitor& visitor,
FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Range>& value) { FuncDefDefinitionData<FileId, TypeId, FuncId, VarId, FuncRef, Range>&
value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
REFLECT_MEMBER(detailed_name); REFLECT_MEMBER(detailed_name);
REFLECT_MEMBER(short_name_offset); REFLECT_MEMBER(short_name_offset);
@ -280,6 +288,7 @@ void Reflect(
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(definition_spelling);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(definition_extent);
REFLECT_MEMBER(file);
REFLECT_MEMBER(declaring_type); REFLECT_MEMBER(declaring_type);
REFLECT_MEMBER(base); REFLECT_MEMBER(base);
REFLECT_MEMBER(locals); REFLECT_MEMBER(locals);
@ -288,7 +297,8 @@ void Reflect(
} }
struct IndexFunc { struct IndexFunc {
using Def = FuncDefDefinitionData<IndexTypeId, using Def = FuncDefDefinitionData<IndexFileId,
IndexTypeId,
IndexFuncId, IndexFuncId,
IndexVarId, IndexVarId,
IndexFuncRef, IndexFuncRef,
@ -337,7 +347,11 @@ MAKE_REFLECT_STRUCT(IndexFunc::Declaration,
content, content,
param_spellings); param_spellings);
template <typename TypeId, typename FuncId, typename VarId, typename Range> template <typename FileId,
typename TypeId,
typename FuncId,
typename VarId,
typename Range>
struct VarDefDefinitionData { struct VarDefDefinitionData {
// General metadata. // General metadata.
std::string detailed_name; std::string detailed_name;
@ -348,6 +362,7 @@ struct VarDefDefinitionData {
Maybe<Range> definition_spelling; Maybe<Range> definition_spelling;
Maybe<Range> definition_extent; Maybe<Range> definition_extent;
FileId file;
// Type of the variable. // Type of the variable.
Maybe<TypeId> variable_type; Maybe<TypeId> variable_type;
@ -376,8 +391,7 @@ struct VarDefDefinitionData {
parent_kind == o.parent_kind && kind == o.kind && parent_kind == o.parent_kind && kind == o.kind &&
storage == o.storage && hover == o.hover && comments == o.comments; storage == o.storage && hover == o.hover && comments == o.comments;
} }
bool operator!=( bool operator!=(const VarDefDefinitionData& other) const {
const VarDefDefinitionData<TypeId, FuncId, VarId, Range>& other) const {
return !(*this == other); return !(*this == other);
} }
@ -388,12 +402,14 @@ struct VarDefDefinitionData {
}; };
template <typename TVisitor, template <typename TVisitor,
typename FileId,
typename TypeId, typename TypeId,
typename FuncId, typename FuncId,
typename VarId, typename VarId,
typename Range> typename Range>
void Reflect(TVisitor& visitor, void Reflect(
VarDefDefinitionData<TypeId, FuncId, VarId, Range>& value) { TVisitor& visitor,
VarDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
REFLECT_MEMBER(detailed_name); REFLECT_MEMBER(detailed_name);
REFLECT_MEMBER(short_name_size); REFLECT_MEMBER(short_name_size);
@ -402,6 +418,7 @@ void Reflect(TVisitor& visitor,
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(definition_spelling);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(definition_extent);
REFLECT_MEMBER(file);
REFLECT_MEMBER(variable_type); REFLECT_MEMBER(variable_type);
REFLECT_MEMBER(parent_id); REFLECT_MEMBER(parent_id);
REFLECT_MEMBER(parent_kind); REFLECT_MEMBER(parent_kind);
@ -411,7 +428,11 @@ void Reflect(TVisitor& visitor,
} }
struct IndexVar { struct IndexVar {
using Def = VarDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; using Def = VarDefDefinitionData<IndexFileId,
IndexTypeId,
IndexFuncId,
IndexVarId,
Range>;
Usr usr; Usr usr;
IndexVarId id; IndexVarId id;

View File

@ -73,8 +73,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* 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 &&
func.def->definition_extent->path != file_id) { func.def->definition_extent->FileId() != file_id) {
return func.def->definition_extent->path; return func.def->definition_extent->FileId();
} }
break; break;
} }
@ -83,8 +83,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* 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->path != file_id) { var.def->definition_extent->FileId() != file_id) {
return db->vars[sym.idx.idx].def->definition_extent->path; return db->vars[sym.idx.idx].def->definition_extent->FileId();
} }
break; break;
} }
@ -149,7 +149,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
QueryFunc& func) { QueryFunc& func) {
assert(func.def); assert(func.def);
for (const QueryLocation& decl : func.declarations) { for (const QueryLocation& decl : func.declarations) {
if (decl.path != decl_file_id) if (decl.FileId() != decl_file_id)
continue; continue;
optional<lsRange> ls_decl = GetLsRange(working_file, decl.range); optional<lsRange> ls_decl = GetLsRange(working_file, decl.range);
@ -203,7 +203,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
break; break;
for (QueryLocation& func_decl : sym_func.declarations) { for (QueryLocation& func_decl : sym_func.declarations) {
if (func_decl.path == decl_file_id) { if (func_decl.FileId() == decl_file_id) {
int dist = func_decl.range.start.line - decl.range.start.line; int dist = func_decl.range.start.line - decl.range.start.line;
if (abs(dist) < abs(best_dist)) { if (abs(dist) < abs(best_dist)) {
optional<lsLocation> def_loc = GetLsLocation( optional<lsLocation> def_loc = GetLsLocation(

View File

@ -90,7 +90,7 @@ void AddCodeLens(const char* singular,
code_lens.range = *range; code_lens.range = *range;
code_lens.command = lsCommand<lsCodeLensCommandArguments>(); code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->command = "cquery.showReferences"; code_lens.command->command = "cquery.showReferences";
code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.path); code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.FileId());
code_lens.command->arguments.position = code_lens.range.start; code_lens.command->arguments.position = code_lens.range.start;
// Add unique uses. // Add unique uses.
@ -179,7 +179,7 @@ struct TextDocumentCodeLensHandler
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.idx);
if (!def || def->path != sym.loc.path || if (!def || def->FileId() != sym.loc.FileId() ||
def->range.start.line != sym.loc.range.start.line) { def->range.start.line != sym.loc.range.start.line) {
return sym.loc; return sym.loc;
} }

View File

@ -90,7 +90,7 @@ struct TextDocumentDefinitionHandler
// the declaration if possible. We also want to use declarations if // the declaration if possible. We also want to use declarations if
// we're pointing to, ie, a pure virtual function which has no // we're pointing to, ie, a pure virtual function which has no
// definition. // definition.
if (!def_loc || (def_loc->path == file_id && if (!def_loc || (def_loc->FileId() == file_id &&
def_loc->range.Contains(target_line, target_column))) { def_loc->range.Contains(target_line, target_column))) {
// Goto declaration. // Goto declaration.

View File

@ -41,7 +41,7 @@ struct TextDocumentDocumentHighlightHandler
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true); std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true);
out.result.reserve(uses.size()); out.result.reserve(uses.size());
for (const QueryLocation& use : uses) { for (const QueryLocation& use : uses) {
if (use.path != file_id) if (use.FileId() != file_id)
continue; continue;
optional<lsLocation> ls_location = optional<lsLocation> ls_location =

View File

@ -16,20 +16,21 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
if (!ls_location) if (!ls_location)
continue; continue;
if (path_to_edit.find(location.path) == path_to_edit.end()) { QueryFileId file_id = location.FileId();
path_to_edit[location.path] = lsTextDocumentEdit(); if (path_to_edit.find(file_id) == path_to_edit.end()) {
path_to_edit[file_id] = lsTextDocumentEdit();
QueryFile& file = db->files[location.path.id]; QueryFile& file = db->files[file_id.id];
if (!file.def) if (!file.def)
continue; continue;
const std::string& path = file.def->path; const std::string& path = file.def->path;
path_to_edit[location.path].textDocument.uri = path_to_edit[file_id].textDocument.uri =
lsDocumentUri::FromPath(path); lsDocumentUri::FromPath(path);
WorkingFile* working_file = working_files->GetFileByFilename(path); WorkingFile* working_file = working_files->GetFileByFilename(path);
if (working_file) if (working_file)
path_to_edit[location.path].textDocument.version = path_to_edit[file_id].textDocument.version =
working_file->version; working_file->version;
} }
@ -38,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
edit.newText = new_text; edit.newText = new_text;
// vscode complains if we submit overlapping text edits. // vscode complains if we submit overlapping text edits.
auto& edits = path_to_edit[location.path].edits; auto& edits = path_to_edit[file_id].edits;
if (std::find(edits.begin(), edits.end(), edit) == edits.end()) if (std::find(edits.begin(), edits.end(), edit) == edits.end())
edits.push_back(edit); edits.push_back(edit);
} }

View File

@ -42,8 +42,12 @@ optional<QueryType::Def> ToQuery(const IdMap& id_map,
result.kind = type.kind; result.kind = type.kind;
result.hover = type.hover; result.hover = type.hover;
result.comments = type.comments; result.comments = type.comments;
result.definition_spelling = id_map.ToQuery(type.definition_spelling); if (type.definition_spelling)
result.definition_extent = id_map.ToQuery(type.definition_extent); result.definition_spelling =
id_map.ToQuery(*type.definition_spelling, SymbolRole::Definition);
if (type.definition_extent)
result.definition_extent =
id_map.ToQuery(*type.definition_extent, SymbolRole::None);
result.alias_of = id_map.ToQuery(type.alias_of); result.alias_of = id_map.ToQuery(type.alias_of);
result.parents = id_map.ToQuery(type.parents); result.parents = id_map.ToQuery(type.parents);
result.types = id_map.ToQuery(type.types); result.types = id_map.ToQuery(type.types);
@ -65,8 +69,12 @@ optional<QueryFunc::Def> ToQuery(const IdMap& id_map,
result.storage = func.storage; result.storage = func.storage;
result.hover = func.hover; result.hover = func.hover;
result.comments = func.comments; result.comments = func.comments;
result.definition_spelling = id_map.ToQuery(func.definition_spelling); if (func.definition_spelling)
result.definition_extent = id_map.ToQuery(func.definition_extent); result.definition_spelling =
id_map.ToQuery(*func.definition_spelling, SymbolRole::Definition);
if (func.definition_extent)
result.definition_extent =
id_map.ToQuery(*func.definition_extent, SymbolRole::None);
result.declaring_type = id_map.ToQuery(func.declaring_type); result.declaring_type = id_map.ToQuery(func.declaring_type);
result.base = id_map.ToQuery(func.base); result.base = id_map.ToQuery(func.base);
result.locals = id_map.ToQuery(func.locals); result.locals = id_map.ToQuery(func.locals);
@ -84,8 +92,12 @@ optional<QueryVar::Def> ToQuery(const IdMap& id_map, const IndexVar::Def& var) {
result.short_name_size = var.short_name_size; result.short_name_size = var.short_name_size;
result.hover = var.hover; result.hover = var.hover;
result.comments = var.comments; result.comments = var.comments;
result.definition_spelling = id_map.ToQuery(var.definition_spelling); if (var.definition_spelling)
result.definition_extent = id_map.ToQuery(var.definition_extent); result.definition_spelling =
id_map.ToQuery(*var.definition_spelling, SymbolRole::Definition);
if (var.definition_extent)
result.definition_extent =
id_map.ToQuery(*var.definition_extent, SymbolRole::None);
result.variable_type = id_map.ToQuery(var.variable_type); result.variable_type = id_map.ToQuery(var.variable_type);
result.parent_id = var.parent_id; result.parent_id = var.parent_id;
result.parent_kind = var.parent_kind; result.parent_kind = var.parent_kind;
@ -223,11 +235,13 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) { auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
def.outline.push_back( def.outline.push_back(
SymbolRef(idx, SymbolRole::Declaration, id_map.ToQuery(range))); SymbolRef(idx, SymbolRole::Declaration,
id_map.ToQuery(range, SymbolRole::Declaration)));
}; };
auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role, auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role,
Range range) { Range range) {
def.all_symbols.push_back(SymbolRef(idx, role, id_map.ToQuery(range))); def.all_symbols.push_back(
SymbolRef(idx, role, id_map.ToQuery(range, role)));
}; };
for (const IndexType& type : indexed.types) { for (const IndexType& type : indexed.types) {
@ -256,16 +270,13 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
// textDocument/definition on the space/semicolon in `A a;` or `return // textDocument/definition on the space/semicolon in `A a;` or `return
// 42;` will take you to the constructor. // 42;` will take you to the constructor.
Range range = caller.loc; Range range = caller.loc;
if (caller.is_implicit) { if (caller.role & SymbolRole::Implicit) {
if (range.start.column > 0) if (range.start.column > 0)
range.start.column--; range.start.column--;
range.end.column++; range.end.column++;
} }
add_all_symbols(id_map.ToSymbol(func.id), add_all_symbols(id_map.ToSymbol(func.id),
caller.is_implicit caller.role | SymbolRole::CalledBy, range);
? SymbolRole::Implicit | SymbolRole::CalledBy
: SymbolRole::CalledBy,
range);
} }
} }
for (const IndexVar& var : indexed.vars) { for (const IndexVar& var : indexed.vars) {
@ -396,8 +407,11 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
*GetQueryVarIdFromUsr(query_db, entry.second, true); *GetQueryVarIdFromUsr(query_db, entry.second, true);
} }
QueryLocation IdMap::ToQuery(Range range) const { QueryLocation IdMap::ToQuery(Range range, SymbolRole role) const {
return QueryLocation(primary_file, range); return QueryLocation{range, primary_file, role};
}
QueryFileId IdMap::ToQuery(IndexFileId) const {
return primary_file;
} }
QueryTypeId IdMap::ToQuery(IndexTypeId id) const { QueryTypeId IdMap::ToQuery(IndexTypeId id) const {
assert(cached_type_ids_.find(id) != cached_type_ids_.end()); assert(cached_type_ids_.find(id) != cached_type_ids_.end());
@ -414,11 +428,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 {
return QueryFuncRef(ToQuery(ref.id), ToQuery(ref.loc), ref.is_implicit); return QueryFuncRef{ToQuery(ref.id), ToQuery(ref.loc, ref.role)};
} }
QueryLocation IdMap::ToQuery(IndexFunc::Declaration decl) const { QueryLocation IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation. // TODO: expose more than just QueryLocation.
return QueryLocation(primary_file, decl.spelling); return QueryLocation{decl.spelling, primary_file, SymbolRole::Declaration};
}
std::vector<QueryLocation> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<QueryLocation> ret;
ret.reserve(a.size());
for (auto& x : a)
ret.push_back(ToQuery(x, SymbolRole::Reference));
return ret;
} }
SymbolIdx IdMap::ToSymbol(IndexTypeId id) const { SymbolIdx IdMap::ToSymbol(IndexTypeId id) const {
@ -734,7 +755,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
QueryType& type = types[usr_to_type[usr].id]; QueryType& type = types[usr_to_type[usr].id];
if (type.symbol_idx) if (type.symbol_idx)
symbols[type.symbol_idx->id].kind = SymbolKind::Invalid; symbols[type.symbol_idx->id].kind = SymbolKind::Invalid;
type.gen++;
//type.def = QueryType::Def(); //type.def = QueryType::Def();
type.def = nullopt; type.def = nullopt;
} }
@ -745,7 +765,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
QueryFunc& func = funcs[usr_to_func[usr].id]; QueryFunc& func = funcs[usr_to_func[usr].id];
if (func.symbol_idx) if (func.symbol_idx)
symbols[func.symbol_idx->id].kind = SymbolKind::Invalid; symbols[func.symbol_idx->id].kind = SymbolKind::Invalid;
func.gen++;
//func.def = QueryFunc::Def(); //func.def = QueryFunc::Def();
func.def = nullopt; func.def = nullopt;
} }
@ -756,7 +775,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
QueryVar& var = vars[usr_to_var[usr].id]; QueryVar& var = vars[usr_to_var[usr].id];
if (var.symbol_idx) if (var.symbol_idx)
symbols[var.symbol_idx->id].kind = SymbolKind::Invalid; symbols[var.symbol_idx->id].kind = SymbolKind::Invalid;
var.gen++;
//var.def = QueryVar::Def(); //var.def = QueryVar::Def();
var.def = nullopt; var.def = nullopt;
} }
@ -987,8 +1005,8 @@ TEST_SUITE("query") {
previous.Resolve(previous.ToTypeId(HashUsr("usr1"))) previous.Resolve(previous.ToTypeId(HashUsr("usr1")))
->uses.push_back(Range(Position(1, 0))); ->uses.push_back(Range(Position(1, 0)));
previous.Resolve(previous.ToFuncId(HashUsr("usr2"))) previous.Resolve(previous.ToFuncId(HashUsr("usr2")))
->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), ->callers.push_back(IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0),
false /*is_implicit*/)); SymbolRole::None});
previous.Resolve(previous.ToVarId(HashUsr("usr3"))) previous.Resolve(previous.ToVarId(HashUsr("usr3")))
->uses.push_back(Range(Position(3, 0))); ->uses.push_back(Range(Position(3, 0)));
@ -1006,10 +1024,10 @@ TEST_SUITE("query") {
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), pf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None});
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), cf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None});
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
@ -1051,14 +1069,14 @@ TEST_SUITE("query") {
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), pf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None});
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), pf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None});
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), cf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(4, 0)), IndexFuncId(0), SymbolRole::None});
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), cf->callers.push_back(
false /*is_implicit*/)); IndexFuncRef{Range(Position(5, 0)), IndexFuncId(0), SymbolRole::None});
QueryDatabase db; QueryDatabase db;
IdMap previous_map(&db, previous.id_cache); IdMap previous_map(&db, previous.id_cache);

View File

@ -20,40 +20,10 @@ using QueryVarId = Id<QueryVar>;
struct IdMap; struct IdMap;
using Generation = uint32_t;
// Example use: |WithGen<Id<QueryType>>|, to mark an |Id| reference with
// generation, so that by comparising the generation with that stored in the
// referenced Query object, we can tell if the reference is stale (the
// referenced object has been deleted or reused).
template <typename T>
struct WithGen {
Generation gen;
T value;
WithGen() : gen(-1) {}
WithGen(const T& value) : gen(-1), value(value) {}
WithGen(Generation gen, const T& value) : gen(gen), value(value) {}
bool HasValue() const { return value.HasValue(); }
explicit operator bool() const { return HasValue(); }
bool operator==(const WithGen& o) const {
return gen == o.gen && value == o.value;
}
};
template <typename TVisitor, typename T>
void Reflect(TVisitor& visitor, WithGen<T>& value) {
Reflect(visitor, value.value);
}
struct QueryLocation { struct QueryLocation {
Range range; Range range;
QueryFileId path; QueryFileId path;
SymbolRole role = SymbolRole::None; SymbolRole role;
QueryLocation() {} // Do not use, needed for reflect.
QueryLocation(QueryFileId path, Range range) : range(range), path(path) {}
QueryLocation OffsetStartColumn(int16_t offset) const { QueryLocation OffsetStartColumn(int16_t offset) const {
QueryLocation result = *this; QueryLocation result = *this;
@ -62,6 +32,7 @@ struct QueryLocation {
} }
bool HasValue() const { return range.HasValue(); } bool HasValue() const { return range.HasValue(); }
QueryFileId FileId() const { return path; }
bool operator==(const QueryLocation& o) const { bool operator==(const QueryLocation& o) const {
return path == o.path && range == o.range; return path == o.path && range == o.range;
@ -129,16 +100,11 @@ struct QueryFuncRef {
// NOTE: id_ can be -1 if the function call is not coming from a function. // NOTE: id_ can be -1 if the function call is not coming from a function.
QueryFuncId id_; QueryFuncId id_;
QueryLocation loc; QueryLocation loc;
bool is_implicit = false;
bool HasValue() const { return id_.HasValue(); } bool HasValue() const { return id_.HasValue(); }
QueryFuncRef() {} // Do not use, needed for reflect. std::tuple<QueryFuncId, QueryLocation> ToTuple() const {
QueryFuncRef(QueryFuncId id, QueryLocation loc, bool is_implicit) return std::make_tuple(id_, loc);
: id_(id), loc(loc), is_implicit(is_implicit) {}
std::tuple<QueryFuncId, QueryLocation, bool> ToTuple() const {
return std::make_tuple(id_, loc, is_implicit);
} }
bool operator==(const QueryFuncRef& o) const { bool operator==(const QueryFuncRef& o) const {
return ToTuple() == o.ToTuple(); return ToTuple() == o.ToTuple();
@ -148,7 +114,7 @@ struct QueryFuncRef {
return ToTuple() < o.ToTuple(); return ToTuple() < o.ToTuple();
} }
}; };
MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc, is_implicit); MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc);
// There are two sources of reindex updates: the (single) definition of a // There are two sources of reindex updates: the (single) definition of a
// symbol has changed, or one of many users of the symbol has changed. // symbol has changed, or one of many users of the symbol has changed.
@ -251,7 +217,8 @@ MAKE_REFLECT_STRUCT(QueryFile::Def,
dependencies); dependencies);
struct QueryType { struct QueryType {
using Def = TypeDefDefinitionData<QueryTypeId, using Def = TypeDefDefinitionData<QueryFileId,
QueryTypeId,
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryLocation>; QueryLocation>;
@ -261,18 +228,18 @@ struct QueryType {
using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>; using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>;
Usr usr; Usr usr;
Generation gen;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<QueryTypeId> derived; std::vector<QueryTypeId> derived;
std::vector<QueryVarId> instances; std::vector<QueryVarId> instances;
std::vector<QueryLocation> uses; std::vector<QueryLocation> uses;
explicit QueryType(const Usr& usr) : usr(usr), gen(0) {} explicit QueryType(const Usr& usr) : usr(usr) {}
}; };
struct QueryFunc { struct QueryFunc {
using Def = FuncDefDefinitionData<QueryTypeId, using Def = FuncDefDefinitionData<QueryFileId,
QueryTypeId,
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryFuncRef, QueryFuncRef,
@ -283,18 +250,18 @@ struct QueryFunc {
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>; using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>;
Usr usr; Usr usr;
Generation gen;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<QueryLocation> declarations; std::vector<QueryLocation> declarations;
std::vector<QueryFuncId> derived; std::vector<QueryFuncId> derived;
std::vector<QueryFuncRef> callers; std::vector<QueryFuncRef> callers;
explicit QueryFunc(const Usr& usr) : usr(usr), gen(0) {} explicit QueryFunc(const Usr& usr) : usr(usr) {}
}; };
struct QueryVar { struct QueryVar {
using Def = VarDefDefinitionData<QueryTypeId, using Def = VarDefDefinitionData<QueryFileId,
QueryTypeId,
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryLocation>; QueryLocation>;
@ -303,13 +270,12 @@ struct QueryVar {
using UsesUpdate = MergeableUpdate<QueryVarId, QueryLocation>; using UsesUpdate = MergeableUpdate<QueryVarId, QueryLocation>;
Usr usr; Usr usr;
Generation gen;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<QueryLocation> declarations; std::vector<QueryLocation> declarations;
std::vector<QueryLocation> uses; std::vector<QueryLocation> uses;
explicit QueryVar(const Usr& usr) : usr(usr), gen(0) {} explicit QueryVar(const Usr& usr) : usr(usr) {}
}; };
struct IndexUpdate { struct IndexUpdate {
@ -428,6 +394,7 @@ template <typename I>
struct IndexToQuery; struct IndexToQuery;
// clang-format off // clang-format off
template <> struct IndexToQuery<IndexFileId> { using type = QueryFileId; };
template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; }; template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; };
template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; }; template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; };
template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; }; template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; };
@ -450,7 +417,8 @@ struct IdMap {
// FIXME Too verbose // FIXME Too verbose
// clang-format off // clang-format off
QueryLocation ToQuery(Range range) const; QueryLocation ToQuery(Range range, SymbolRole role) const;
QueryFileId ToQuery(IndexFileId) const;
QueryTypeId ToQuery(IndexTypeId id) const; QueryTypeId ToQuery(IndexTypeId id) const;
QueryFuncId ToQuery(IndexFuncId id) const; QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const; QueryVarId ToQuery(IndexVarId id) const;
@ -463,12 +431,6 @@ struct IdMap {
return ToQuery(*id); return ToQuery(*id);
} }
template <typename I> template <typename I>
Maybe<WithGen<typename IndexToQuery<I>::type>> ToQuery(Maybe<I> id, int) const {
if (!id)
return nullopt;
return ToQuery(*id, 0);
}
template <typename I>
std::vector<typename IndexToQuery<I>::type> ToQuery(const std::vector<I>& a) const { std::vector<typename IndexToQuery<I>::type> ToQuery(const std::vector<I>& a) const {
std::vector<typename IndexToQuery<I>::type> ret; std::vector<typename IndexToQuery<I>::type> ret;
ret.reserve(a.size()); ret.reserve(a.size());
@ -476,14 +438,7 @@ struct IdMap {
ret.push_back(ToQuery(x)); ret.push_back(ToQuery(x));
return ret; return ret;
} }
template <typename I> std::vector<QueryLocation> ToQuery(const std::vector<Range>& a) const;
std::vector<WithGen<typename IndexToQuery<I>::type>> ToQuery(std::vector<I> a, int) const {
std::vector<WithGen<typename IndexToQuery<I>::type>> ret;
ret.reserve(a.size());
for (auto& x : a)
ret.push_back(ToQuery(x, 0));
return ret;
}
// clang-format on // clang-format on
SymbolIdx ToSymbol(IndexTypeId id) const; SymbolIdx ToSymbol(IndexTypeId id) const;

View File

@ -106,8 +106,8 @@ optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
break; break;
} }
case SymbolKind::File: { case SymbolKind::File: {
return QueryLocation(QueryFileId(symbol.idx), return QueryLocation{Range(Position(0, 0), Position(0, 0)),
Range(Position(1, 1), Position(1, 1))); QueryFileId(symbol.idx), SymbolRole::None};
} }
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
@ -123,21 +123,21 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = db->types[symbol.idx];
if (type.def && type.def->definition_spelling) if (type.def && type.def->definition_spelling)
return type.def->definition_spelling->path; return type.def->definition_spelling->FileId();
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = db->funcs[symbol.idx];
if (!func.declarations.empty()) if (!func.declarations.empty())
return func.declarations[0].path; return func.declarations[0].FileId();
if (func.def && func.def->definition_spelling) if (func.def && func.def->definition_spelling)
return func.def->definition_spelling->path; return func.def->definition_spelling->FileId();
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = db->vars[symbol.idx];
if (var.def && var.def->definition_spelling) if (var.def && var.def->definition_spelling)
return var.def->definition_spelling->path; return var.def->definition_spelling->FileId();
break; break;
} }
case SymbolKind::File: { case SymbolKind::File: {
@ -401,7 +401,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
const QueryLocation& location) { const QueryLocation& location) {
std::string path; std::string path;
lsDocumentUri uri = GetLsDocumentUri(db, location.path, &path); lsDocumentUri uri = GetLsDocumentUri(db, location.FileId(), &path);
optional<lsRange> range = optional<lsRange> range =
GetLsRange(working_files->GetFileByFilename(path), location.range); GetLsRange(working_files->GetFileByFilename(path), location.range);
if (!range) if (!range)