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,
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);
}
}

View File

@ -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;

View File

@ -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(

View File

@ -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;
}

View File

@ -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.

View File

@ -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 =

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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)