mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-21 07:59:27 +00:00
Change is_implicit to role in {Index,Query}FuncRef
Add `FileId file` to *DefDefinitionData::Def
This commit is contained in:
parent
10c2843846
commit
dbdab02ff4
@ -584,7 +584,7 @@ void OnIndexReference_Function(IndexFile* db,
|
||||
ClangCursor caller_cursor,
|
||||
IndexFuncId called_id,
|
||||
IndexFunc* called,
|
||||
bool is_implicit) {
|
||||
SymbolRole role) {
|
||||
if (IsFunctionCallContext(caller_cursor.get_kind())) {
|
||||
IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor);
|
||||
IndexFunc* caller = db->Resolve(caller_id);
|
||||
@ -592,10 +592,10 @@ void OnIndexReference_Function(IndexFile* db,
|
||||
called = db->Resolve(called_id);
|
||||
|
||||
AddFuncRef(&caller->def.callees,
|
||||
IndexFuncRef(called->id, loc, is_implicit));
|
||||
AddFuncRef(&called->callers, IndexFuncRef(caller->id, loc, is_implicit));
|
||||
IndexFuncRef{loc, called->id, role});
|
||||
AddFuncRef(&called->callers, IndexFuncRef{loc, caller->id, role});
|
||||
} 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
|
||||
const int IndexFile::kMajorVersion = 11;
|
||||
const int IndexFile::kMinorVersion = 1;
|
||||
const int IndexFile::kMinorVersion = 2;
|
||||
|
||||
IndexFile::IndexFile(const std::string& path,
|
||||
const std::string& contents)
|
||||
@ -1258,7 +1258,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
IndexFunc* called = db->Resolve(called_id);
|
||||
OnIndexReference_Function(db, cursor.get_spelling_range(),
|
||||
data->container, called_id, called,
|
||||
/*implicit=*/false);
|
||||
SymbolRole::None);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1992,8 +1992,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
||||
else
|
||||
CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db);
|
||||
|
||||
OnIndexReference_Function(db, loc, ref->container->cursor, called_id,
|
||||
called, is_implicit);
|
||||
OnIndexReference_Function(
|
||||
db, loc, ref->container->cursor, called_id, called,
|
||||
is_implicit ? SymbolRole::Implicit : SymbolRole::None);
|
||||
|
||||
// Checks if |str| starts with |start|. Ignores case.
|
||||
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);
|
||||
if (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();
|
||||
const char* str_value = s.c_str();
|
||||
if (str_value[0] == '~') {
|
||||
value.is_implicit = true;
|
||||
value.role = SymbolRole::Implicit;
|
||||
++str_value;
|
||||
}
|
||||
RawId id = atol(str_value);
|
||||
@ -2324,15 +2326,15 @@ void Reflect(Reader& visitor, IndexFuncRef& value) {
|
||||
value.id = IndexFuncId(id);
|
||||
value.loc = Range(loc_string);
|
||||
} else {
|
||||
Reflect(visitor, value.id);
|
||||
Reflect(visitor, value.loc);
|
||||
Reflect(visitor, value.is_implicit);
|
||||
Reflect(visitor, value.id);
|
||||
Reflect(visitor, value.role);
|
||||
}
|
||||
}
|
||||
void Reflect(Writer& visitor, IndexFuncRef& value) {
|
||||
if (visitor.Format() == SerializeFormat::Json) {
|
||||
std::string s;
|
||||
if (value.is_implicit)
|
||||
if (value.role & SymbolRole::Implicit)
|
||||
s += "~";
|
||||
|
||||
// id.id is unsigned, special case -1 value
|
||||
@ -2344,8 +2346,8 @@ void Reflect(Writer& visitor, IndexFuncRef& value) {
|
||||
s += "@" + value.loc.ToString();
|
||||
visitor.String(s.c_str());
|
||||
} else {
|
||||
Reflect(visitor, value.id);
|
||||
Reflect(visitor, value.loc);
|
||||
Reflect(visitor, value.is_implicit);
|
||||
Reflect(visitor, value.id);
|
||||
Reflect(visitor, value.role);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct IndexFile;
|
||||
struct IndexType;
|
||||
struct IndexFunc;
|
||||
struct IndexVar;
|
||||
@ -61,7 +62,7 @@ struct Id {
|
||||
namespace std {
|
||||
template <typename 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
|
||||
|
||||
@ -70,6 +71,7 @@ void Reflect(TVisitor& visitor, Id<T>& id) {
|
||||
Reflect(visitor, id.id);
|
||||
}
|
||||
|
||||
using IndexFileId = Id<IndexFile>;
|
||||
using IndexTypeId = Id<IndexType>;
|
||||
using IndexFuncId = Id<IndexFunc>;
|
||||
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.
|
||||
Range loc;
|
||||
IndexFuncId id;
|
||||
SymbolRole role = SymbolRole::None;
|
||||
bool is_implicit = false;
|
||||
SymbolRole role;
|
||||
|
||||
IndexFuncRef() {} // For serialization.
|
||||
|
||||
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);
|
||||
std::tuple<IndexFuncId, Range, SymbolRole> ToTuple() const {
|
||||
return std::make_tuple(id, loc, role);
|
||||
}
|
||||
bool operator==(const IndexFuncRef& o) { return ToTuple() == o.ToTuple(); }
|
||||
bool operator!=(const IndexFuncRef& o) { return !(*this == o); }
|
||||
@ -111,7 +105,11 @@ struct IndexFuncRef {
|
||||
void Reflect(Reader& 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 {
|
||||
// General metadata.
|
||||
std::string detailed_name;
|
||||
@ -130,10 +128,6 @@ struct TypeDefDefinitionData {
|
||||
Maybe<Range> definition_spelling;
|
||||
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.
|
||||
std::vector<TypeId> parents;
|
||||
|
||||
@ -142,6 +136,11 @@ struct TypeDefDefinitionData {
|
||||
std::vector<FuncId> funcs;
|
||||
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_size = 0;
|
||||
ClangSymbolKind kind = ClangSymbolKind::Unknown;
|
||||
@ -164,12 +163,14 @@ struct TypeDefDefinitionData {
|
||||
}
|
||||
};
|
||||
template <typename TVisitor,
|
||||
typename FileId,
|
||||
typename TypeId,
|
||||
typename FuncId,
|
||||
typename VarId,
|
||||
typename Range>
|
||||
void Reflect(TVisitor& visitor,
|
||||
TypeDefDefinitionData<TypeId, FuncId, VarId, Range>& value) {
|
||||
void Reflect(
|
||||
TVisitor& visitor,
|
||||
TypeDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) {
|
||||
REFLECT_MEMBER_START();
|
||||
REFLECT_MEMBER(detailed_name);
|
||||
REFLECT_MEMBER(short_name_offset);
|
||||
@ -179,6 +180,7 @@ void Reflect(TVisitor& visitor,
|
||||
REFLECT_MEMBER(comments);
|
||||
REFLECT_MEMBER(definition_spelling);
|
||||
REFLECT_MEMBER(definition_extent);
|
||||
REFLECT_MEMBER(file);
|
||||
REFLECT_MEMBER(alias_of);
|
||||
REFLECT_MEMBER(parents);
|
||||
REFLECT_MEMBER(types);
|
||||
@ -188,8 +190,11 @@ void Reflect(TVisitor& visitor,
|
||||
}
|
||||
|
||||
struct IndexType {
|
||||
using Def =
|
||||
TypeDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>;
|
||||
using Def = TypeDefDefinitionData<IndexFileId,
|
||||
IndexTypeId,
|
||||
IndexFuncId,
|
||||
IndexVarId,
|
||||
Range>;
|
||||
|
||||
Usr usr;
|
||||
IndexTypeId id;
|
||||
@ -213,7 +218,8 @@ struct IndexType {
|
||||
};
|
||||
MAKE_HASHABLE(IndexType, t.id);
|
||||
|
||||
template <typename TypeId,
|
||||
template <typename FileId,
|
||||
typename TypeId,
|
||||
typename FuncId,
|
||||
typename VarId,
|
||||
typename FuncRef,
|
||||
@ -226,9 +232,6 @@ struct FuncDefDefinitionData {
|
||||
Maybe<Range> definition_spelling;
|
||||
Maybe<Range> definition_extent;
|
||||
|
||||
// Type which declares this one (ie, it is a method)
|
||||
Maybe<TypeId> declaring_type;
|
||||
|
||||
// Method this method overrides.
|
||||
std::vector<FuncId> base;
|
||||
|
||||
@ -238,6 +241,9 @@ struct FuncDefDefinitionData {
|
||||
// Functions that this function calls.
|
||||
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_size = 0;
|
||||
ClangSymbolKind kind = ClangSymbolKind::Unknown;
|
||||
@ -262,6 +268,7 @@ struct FuncDefDefinitionData {
|
||||
};
|
||||
|
||||
template <typename TVisitor,
|
||||
typename FileId,
|
||||
typename TypeId,
|
||||
typename FuncId,
|
||||
typename VarId,
|
||||
@ -269,7 +276,8 @@ template <typename TVisitor,
|
||||
typename Range>
|
||||
void Reflect(
|
||||
TVisitor& visitor,
|
||||
FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Range>& value) {
|
||||
FuncDefDefinitionData<FileId, TypeId, FuncId, VarId, FuncRef, Range>&
|
||||
value) {
|
||||
REFLECT_MEMBER_START();
|
||||
REFLECT_MEMBER(detailed_name);
|
||||
REFLECT_MEMBER(short_name_offset);
|
||||
@ -280,6 +288,7 @@ void Reflect(
|
||||
REFLECT_MEMBER(comments);
|
||||
REFLECT_MEMBER(definition_spelling);
|
||||
REFLECT_MEMBER(definition_extent);
|
||||
REFLECT_MEMBER(file);
|
||||
REFLECT_MEMBER(declaring_type);
|
||||
REFLECT_MEMBER(base);
|
||||
REFLECT_MEMBER(locals);
|
||||
@ -288,7 +297,8 @@ void Reflect(
|
||||
}
|
||||
|
||||
struct IndexFunc {
|
||||
using Def = FuncDefDefinitionData<IndexTypeId,
|
||||
using Def = FuncDefDefinitionData<IndexFileId,
|
||||
IndexTypeId,
|
||||
IndexFuncId,
|
||||
IndexVarId,
|
||||
IndexFuncRef,
|
||||
@ -337,7 +347,11 @@ MAKE_REFLECT_STRUCT(IndexFunc::Declaration,
|
||||
content,
|
||||
param_spellings);
|
||||
|
||||
template <typename TypeId, typename FuncId, typename VarId, typename Range>
|
||||
template <typename FileId,
|
||||
typename TypeId,
|
||||
typename FuncId,
|
||||
typename VarId,
|
||||
typename Range>
|
||||
struct VarDefDefinitionData {
|
||||
// General metadata.
|
||||
std::string detailed_name;
|
||||
@ -348,6 +362,7 @@ struct VarDefDefinitionData {
|
||||
Maybe<Range> definition_spelling;
|
||||
Maybe<Range> definition_extent;
|
||||
|
||||
FileId file;
|
||||
// Type of the variable.
|
||||
Maybe<TypeId> variable_type;
|
||||
|
||||
@ -376,8 +391,7 @@ struct VarDefDefinitionData {
|
||||
parent_kind == o.parent_kind && kind == o.kind &&
|
||||
storage == o.storage && hover == o.hover && comments == o.comments;
|
||||
}
|
||||
bool operator!=(
|
||||
const VarDefDefinitionData<TypeId, FuncId, VarId, Range>& other) const {
|
||||
bool operator!=(const VarDefDefinitionData& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
@ -388,12 +402,14 @@ struct VarDefDefinitionData {
|
||||
};
|
||||
|
||||
template <typename TVisitor,
|
||||
typename FileId,
|
||||
typename TypeId,
|
||||
typename FuncId,
|
||||
typename VarId,
|
||||
typename Range>
|
||||
void Reflect(TVisitor& visitor,
|
||||
VarDefDefinitionData<TypeId, FuncId, VarId, Range>& value) {
|
||||
void Reflect(
|
||||
TVisitor& visitor,
|
||||
VarDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) {
|
||||
REFLECT_MEMBER_START();
|
||||
REFLECT_MEMBER(detailed_name);
|
||||
REFLECT_MEMBER(short_name_size);
|
||||
@ -402,6 +418,7 @@ void Reflect(TVisitor& visitor,
|
||||
REFLECT_MEMBER(comments);
|
||||
REFLECT_MEMBER(definition_spelling);
|
||||
REFLECT_MEMBER(definition_extent);
|
||||
REFLECT_MEMBER(file);
|
||||
REFLECT_MEMBER(variable_type);
|
||||
REFLECT_MEMBER(parent_id);
|
||||
REFLECT_MEMBER(parent_kind);
|
||||
@ -411,7 +428,11 @@ void Reflect(TVisitor& visitor,
|
||||
}
|
||||
|
||||
struct IndexVar {
|
||||
using Def = VarDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>;
|
||||
using Def = VarDefDefinitionData<IndexFileId,
|
||||
IndexTypeId,
|
||||
IndexFuncId,
|
||||
IndexVarId,
|
||||
Range>;
|
||||
|
||||
Usr usr;
|
||||
IndexVarId id;
|
||||
|
@ -73,8 +73,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
|
||||
// Note: we ignore the definition if it is in the same file (ie,
|
||||
// possibly a header).
|
||||
if (func.def && func.def->definition_extent &&
|
||||
func.def->definition_extent->path != file_id) {
|
||||
return func.def->definition_extent->path;
|
||||
func.def->definition_extent->FileId() != file_id) {
|
||||
return func.def->definition_extent->FileId();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -83,8 +83,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
|
||||
// Note: we ignore the definition if it is in the same file (ie,
|
||||
// possibly a header).
|
||||
if (var.def && var.def->definition_extent &&
|
||||
var.def->definition_extent->path != file_id) {
|
||||
return db->vars[sym.idx.idx].def->definition_extent->path;
|
||||
var.def->definition_extent->FileId() != file_id) {
|
||||
return db->vars[sym.idx.idx].def->definition_extent->FileId();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -149,7 +149,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
|
||||
QueryFunc& func) {
|
||||
assert(func.def);
|
||||
for (const QueryLocation& decl : func.declarations) {
|
||||
if (decl.path != decl_file_id)
|
||||
if (decl.FileId() != decl_file_id)
|
||||
continue;
|
||||
|
||||
optional<lsRange> ls_decl = GetLsRange(working_file, decl.range);
|
||||
@ -203,7 +203,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
|
||||
break;
|
||||
|
||||
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;
|
||||
if (abs(dist) < abs(best_dist)) {
|
||||
optional<lsLocation> def_loc = GetLsLocation(
|
||||
|
@ -90,7 +90,7 @@ void AddCodeLens(const char* singular,
|
||||
code_lens.range = *range;
|
||||
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
|
||||
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;
|
||||
|
||||
// Add unique uses.
|
||||
@ -179,7 +179,7 @@ struct TextDocumentCodeLensHandler
|
||||
auto try_ensure_spelling = [&](SymbolRef sym) {
|
||||
optional<QueryLocation> def =
|
||||
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) {
|
||||
return sym.loc;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ struct TextDocumentDefinitionHandler
|
||||
// the declaration if possible. We also want to use declarations if
|
||||
// we're pointing to, ie, a pure virtual function which has no
|
||||
// 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))) {
|
||||
// Goto declaration.
|
||||
|
||||
|
@ -41,7 +41,7 @@ struct TextDocumentDocumentHighlightHandler
|
||||
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true);
|
||||
out.result.reserve(uses.size());
|
||||
for (const QueryLocation& use : uses) {
|
||||
if (use.path != file_id)
|
||||
if (use.FileId() != file_id)
|
||||
continue;
|
||||
|
||||
optional<lsLocation> ls_location =
|
||||
|
@ -16,20 +16,21 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
||||
if (!ls_location)
|
||||
continue;
|
||||
|
||||
if (path_to_edit.find(location.path) == path_to_edit.end()) {
|
||||
path_to_edit[location.path] = lsTextDocumentEdit();
|
||||
QueryFileId file_id = location.FileId();
|
||||
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)
|
||||
continue;
|
||||
|
||||
const std::string& path = file.def->path;
|
||||
path_to_edit[location.path].textDocument.uri =
|
||||
path_to_edit[file_id].textDocument.uri =
|
||||
lsDocumentUri::FromPath(path);
|
||||
|
||||
WorkingFile* working_file = working_files->GetFileByFilename(path);
|
||||
if (working_file)
|
||||
path_to_edit[location.path].textDocument.version =
|
||||
path_to_edit[file_id].textDocument.version =
|
||||
working_file->version;
|
||||
}
|
||||
|
||||
@ -38,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
||||
edit.newText = new_text;
|
||||
|
||||
// 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())
|
||||
edits.push_back(edit);
|
||||
}
|
||||
|
86
src/query.cc
86
src/query.cc
@ -42,8 +42,12 @@ optional<QueryType::Def> ToQuery(const IdMap& id_map,
|
||||
result.kind = type.kind;
|
||||
result.hover = type.hover;
|
||||
result.comments = type.comments;
|
||||
result.definition_spelling = id_map.ToQuery(type.definition_spelling);
|
||||
result.definition_extent = id_map.ToQuery(type.definition_extent);
|
||||
if (type.definition_spelling)
|
||||
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.parents = id_map.ToQuery(type.parents);
|
||||
result.types = id_map.ToQuery(type.types);
|
||||
@ -65,8 +69,12 @@ optional<QueryFunc::Def> ToQuery(const IdMap& id_map,
|
||||
result.storage = func.storage;
|
||||
result.hover = func.hover;
|
||||
result.comments = func.comments;
|
||||
result.definition_spelling = id_map.ToQuery(func.definition_spelling);
|
||||
result.definition_extent = id_map.ToQuery(func.definition_extent);
|
||||
if (func.definition_spelling)
|
||||
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.base = id_map.ToQuery(func.base);
|
||||
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.hover = var.hover;
|
||||
result.comments = var.comments;
|
||||
result.definition_spelling = id_map.ToQuery(var.definition_spelling);
|
||||
result.definition_extent = id_map.ToQuery(var.definition_extent);
|
||||
if (var.definition_spelling)
|
||||
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.parent_id = var.parent_id;
|
||||
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) {
|
||||
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,
|
||||
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) {
|
||||
@ -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
|
||||
// 42;` will take you to the constructor.
|
||||
Range range = caller.loc;
|
||||
if (caller.is_implicit) {
|
||||
if (caller.role & SymbolRole::Implicit) {
|
||||
if (range.start.column > 0)
|
||||
range.start.column--;
|
||||
range.end.column++;
|
||||
}
|
||||
add_all_symbols(id_map.ToSymbol(func.id),
|
||||
caller.is_implicit
|
||||
? SymbolRole::Implicit | SymbolRole::CalledBy
|
||||
: SymbolRole::CalledBy,
|
||||
range);
|
||||
caller.role | SymbolRole::CalledBy, range);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
QueryLocation IdMap::ToQuery(Range range) const {
|
||||
return QueryLocation(primary_file, range);
|
||||
QueryLocation IdMap::ToQuery(Range range, SymbolRole role) const {
|
||||
return QueryLocation{range, primary_file, role};
|
||||
}
|
||||
QueryFileId IdMap::ToQuery(IndexFileId) const {
|
||||
return primary_file;
|
||||
}
|
||||
QueryTypeId IdMap::ToQuery(IndexTypeId id) const {
|
||||
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);
|
||||
}
|
||||
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 {
|
||||
// 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 {
|
||||
@ -734,7 +755,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
|
||||
QueryType& type = types[usr_to_type[usr].id];
|
||||
if (type.symbol_idx)
|
||||
symbols[type.symbol_idx->id].kind = SymbolKind::Invalid;
|
||||
type.gen++;
|
||||
//type.def = QueryType::Def();
|
||||
type.def = nullopt;
|
||||
}
|
||||
@ -745,7 +765,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
|
||||
QueryFunc& func = funcs[usr_to_func[usr].id];
|
||||
if (func.symbol_idx)
|
||||
symbols[func.symbol_idx->id].kind = SymbolKind::Invalid;
|
||||
func.gen++;
|
||||
//func.def = QueryFunc::Def();
|
||||
func.def = nullopt;
|
||||
}
|
||||
@ -756,7 +775,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
|
||||
QueryVar& var = vars[usr_to_var[usr].id];
|
||||
if (var.symbol_idx)
|
||||
symbols[var.symbol_idx->id].kind = SymbolKind::Invalid;
|
||||
var.gen++;
|
||||
//var.def = QueryVar::Def();
|
||||
var.def = nullopt;
|
||||
}
|
||||
@ -987,8 +1005,8 @@ TEST_SUITE("query") {
|
||||
previous.Resolve(previous.ToTypeId(HashUsr("usr1")))
|
||||
->uses.push_back(Range(Position(1, 0)));
|
||||
previous.Resolve(previous.ToFuncId(HashUsr("usr2")))
|
||||
->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)),
|
||||
false /*is_implicit*/));
|
||||
->callers.push_back(IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0),
|
||||
SymbolRole::None});
|
||||
previous.Resolve(previous.ToVarId(HashUsr("usr3")))
|
||||
->uses.push_back(Range(Position(3, 0)));
|
||||
|
||||
@ -1006,10 +1024,10 @@ TEST_SUITE("query") {
|
||||
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
|
||||
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
|
||||
|
||||
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)),
|
||||
false /*is_implicit*/));
|
||||
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)),
|
||||
false /*is_implicit*/));
|
||||
pf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
cf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
|
||||
IndexUpdate update = GetDelta(previous, current);
|
||||
|
||||
@ -1051,14 +1069,14 @@ TEST_SUITE("query") {
|
||||
|
||||
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
|
||||
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
|
||||
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)),
|
||||
false /*is_implicit*/));
|
||||
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)),
|
||||
false /*is_implicit*/));
|
||||
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)),
|
||||
false /*is_implicit*/));
|
||||
cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)),
|
||||
false /*is_implicit*/));
|
||||
pf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
pf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
cf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(4, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
cf->callers.push_back(
|
||||
IndexFuncRef{Range(Position(5, 0)), IndexFuncId(0), SymbolRole::None});
|
||||
|
||||
QueryDatabase db;
|
||||
IdMap previous_map(&db, previous.id_cache);
|
||||
|
81
src/query.h
81
src/query.h
@ -20,40 +20,10 @@ using QueryVarId = Id<QueryVar>;
|
||||
|
||||
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 {
|
||||
Range range;
|
||||
QueryFileId path;
|
||||
SymbolRole role = SymbolRole::None;
|
||||
|
||||
QueryLocation() {} // Do not use, needed for reflect.
|
||||
QueryLocation(QueryFileId path, Range range) : range(range), path(path) {}
|
||||
SymbolRole role;
|
||||
|
||||
QueryLocation OffsetStartColumn(int16_t offset) const {
|
||||
QueryLocation result = *this;
|
||||
@ -62,6 +32,7 @@ struct QueryLocation {
|
||||
}
|
||||
|
||||
bool HasValue() const { return range.HasValue(); }
|
||||
QueryFileId FileId() const { return path; }
|
||||
|
||||
bool operator==(const QueryLocation& o) const {
|
||||
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.
|
||||
QueryFuncId id_;
|
||||
QueryLocation loc;
|
||||
bool is_implicit = false;
|
||||
|
||||
bool HasValue() const { return id_.HasValue(); }
|
||||
|
||||
QueryFuncRef() {} // Do not use, needed for reflect.
|
||||
QueryFuncRef(QueryFuncId id, QueryLocation loc, bool is_implicit)
|
||||
: id_(id), loc(loc), is_implicit(is_implicit) {}
|
||||
|
||||
std::tuple<QueryFuncId, QueryLocation, bool> ToTuple() const {
|
||||
return std::make_tuple(id_, loc, is_implicit);
|
||||
std::tuple<QueryFuncId, QueryLocation> ToTuple() const {
|
||||
return std::make_tuple(id_, loc);
|
||||
}
|
||||
bool operator==(const QueryFuncRef& o) const {
|
||||
return ToTuple() == o.ToTuple();
|
||||
@ -148,7 +114,7 @@ struct QueryFuncRef {
|
||||
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
|
||||
// symbol has changed, or one of many users of the symbol has changed.
|
||||
@ -251,7 +217,8 @@ MAKE_REFLECT_STRUCT(QueryFile::Def,
|
||||
dependencies);
|
||||
|
||||
struct QueryType {
|
||||
using Def = TypeDefDefinitionData<QueryTypeId,
|
||||
using Def = TypeDefDefinitionData<QueryFileId,
|
||||
QueryTypeId,
|
||||
QueryFuncId,
|
||||
QueryVarId,
|
||||
QueryLocation>;
|
||||
@ -261,18 +228,18 @@ struct QueryType {
|
||||
using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>;
|
||||
|
||||
Usr usr;
|
||||
Generation gen;
|
||||
Maybe<Id<void>> symbol_idx;
|
||||
optional<Def> def;
|
||||
std::vector<QueryTypeId> derived;
|
||||
std::vector<QueryVarId> instances;
|
||||
std::vector<QueryLocation> uses;
|
||||
|
||||
explicit QueryType(const Usr& usr) : usr(usr), gen(0) {}
|
||||
explicit QueryType(const Usr& usr) : usr(usr) {}
|
||||
};
|
||||
|
||||
struct QueryFunc {
|
||||
using Def = FuncDefDefinitionData<QueryTypeId,
|
||||
using Def = FuncDefDefinitionData<QueryFileId,
|
||||
QueryTypeId,
|
||||
QueryFuncId,
|
||||
QueryVarId,
|
||||
QueryFuncRef,
|
||||
@ -283,18 +250,18 @@ struct QueryFunc {
|
||||
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>;
|
||||
|
||||
Usr usr;
|
||||
Generation gen;
|
||||
Maybe<Id<void>> symbol_idx;
|
||||
optional<Def> def;
|
||||
std::vector<QueryLocation> declarations;
|
||||
std::vector<QueryFuncId> derived;
|
||||
std::vector<QueryFuncRef> callers;
|
||||
|
||||
explicit QueryFunc(const Usr& usr) : usr(usr), gen(0) {}
|
||||
explicit QueryFunc(const Usr& usr) : usr(usr) {}
|
||||
};
|
||||
|
||||
struct QueryVar {
|
||||
using Def = VarDefDefinitionData<QueryTypeId,
|
||||
using Def = VarDefDefinitionData<QueryFileId,
|
||||
QueryTypeId,
|
||||
QueryFuncId,
|
||||
QueryVarId,
|
||||
QueryLocation>;
|
||||
@ -303,13 +270,12 @@ struct QueryVar {
|
||||
using UsesUpdate = MergeableUpdate<QueryVarId, QueryLocation>;
|
||||
|
||||
Usr usr;
|
||||
Generation gen;
|
||||
Maybe<Id<void>> symbol_idx;
|
||||
optional<Def> def;
|
||||
std::vector<QueryLocation> declarations;
|
||||
std::vector<QueryLocation> uses;
|
||||
|
||||
explicit QueryVar(const Usr& usr) : usr(usr), gen(0) {}
|
||||
explicit QueryVar(const Usr& usr) : usr(usr) {}
|
||||
};
|
||||
|
||||
struct IndexUpdate {
|
||||
@ -428,6 +394,7 @@ template <typename I>
|
||||
struct IndexToQuery;
|
||||
|
||||
// clang-format off
|
||||
template <> struct IndexToQuery<IndexFileId> { using type = QueryFileId; };
|
||||
template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; };
|
||||
template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; };
|
||||
template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; };
|
||||
@ -450,7 +417,8 @@ struct IdMap {
|
||||
|
||||
// FIXME Too verbose
|
||||
// clang-format off
|
||||
QueryLocation ToQuery(Range range) const;
|
||||
QueryLocation ToQuery(Range range, SymbolRole role) const;
|
||||
QueryFileId ToQuery(IndexFileId) const;
|
||||
QueryTypeId ToQuery(IndexTypeId id) const;
|
||||
QueryFuncId ToQuery(IndexFuncId id) const;
|
||||
QueryVarId ToQuery(IndexVarId id) const;
|
||||
@ -463,12 +431,6 @@ struct IdMap {
|
||||
return ToQuery(*id);
|
||||
}
|
||||
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> ret;
|
||||
ret.reserve(a.size());
|
||||
@ -476,14 +438,7 @@ struct IdMap {
|
||||
ret.push_back(ToQuery(x));
|
||||
return ret;
|
||||
}
|
||||
template <typename I>
|
||||
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;
|
||||
}
|
||||
std::vector<QueryLocation> ToQuery(const std::vector<Range>& a) const;
|
||||
// clang-format on
|
||||
|
||||
SymbolIdx ToSymbol(IndexTypeId id) const;
|
||||
|
@ -106,8 +106,8 @@ optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
|
||||
break;
|
||||
}
|
||||
case SymbolKind::File: {
|
||||
return QueryLocation(QueryFileId(symbol.idx),
|
||||
Range(Position(1, 1), Position(1, 1)));
|
||||
return QueryLocation{Range(Position(0, 0), Position(0, 0)),
|
||||
QueryFileId(symbol.idx), SymbolRole::None};
|
||||
}
|
||||
case SymbolKind::Invalid: {
|
||||
assert(false && "unexpected");
|
||||
@ -123,21 +123,21 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
||||
case SymbolKind::Type: {
|
||||
QueryType& type = db->types[symbol.idx];
|
||||
if (type.def && type.def->definition_spelling)
|
||||
return type.def->definition_spelling->path;
|
||||
return type.def->definition_spelling->FileId();
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Func: {
|
||||
QueryFunc& func = db->funcs[symbol.idx];
|
||||
if (!func.declarations.empty())
|
||||
return func.declarations[0].path;
|
||||
return func.declarations[0].FileId();
|
||||
if (func.def && func.def->definition_spelling)
|
||||
return func.def->definition_spelling->path;
|
||||
return func.def->definition_spelling->FileId();
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
QueryVar& var = db->vars[symbol.idx];
|
||||
if (var.def && var.def->definition_spelling)
|
||||
return var.def->definition_spelling->path;
|
||||
return var.def->definition_spelling->FileId();
|
||||
break;
|
||||
}
|
||||
case SymbolKind::File: {
|
||||
@ -401,7 +401,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
|
||||
WorkingFiles* working_files,
|
||||
const QueryLocation& location) {
|
||||
std::string path;
|
||||
lsDocumentUri uri = GetLsDocumentUri(db, location.path, &path);
|
||||
lsDocumentUri uri = GetLsDocumentUri(db, location.FileId(), &path);
|
||||
optional<lsRange> range =
|
||||
GetLsRange(working_files->GetFileByFilename(path), location.range);
|
||||
if (!range)
|
||||
|
Loading…
Reference in New Issue
Block a user