Add Id<QueryFile> file; to Use and simplify query.cc

This commit is contained in:
Fangrui Song 2018-02-11 20:22:47 -08:00
parent 2d6fd4e240
commit afd38cbce9
12 changed files with 76 additions and 97 deletions

View File

@ -657,8 +657,8 @@ void OnIndexReference_Function(IndexFile* db,
} // namespace
// static
const int IndexFile::kMajorVersion = 12;
const int IndexFile::kMinorVersion = 1;
const int IndexFile::kMajorVersion = 13;
const int IndexFile::kMinorVersion = 0;
IndexFile::IndexFile(const std::string& path, const std::string& contents)
: id_cache(path), path(path), file_contents(contents) {}
@ -1542,7 +1542,9 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
SetUse(db, &var->def.spell, decl_spell, lex_parent, Role::Definition);
SetUse(db, &var->def.extent, decl_cursor.get_extent(), lex_parent, Role::None);
} else {
var->declarations.push_back(decl_spell);
Maybe<Use> use;
SetUse(db, &use, decl_spell, lex_parent, Role::Declaration);
var->declarations.push_back(*use);
}
AddDeclInitializerUsages(db, decl_cursor);
@ -2374,6 +2376,9 @@ std::string GetClangVersion() {
return ToString(clang_getClangVersion());
}
// |SymbolRef| is serialized this way.
// |Use| also uses this though it has an extra field |file|,
// which is not used by Index* so it does not need to be serialized.
void Reflect(Reader& visitor, Reference& value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string t = visitor.GetString();

View File

@ -136,13 +136,19 @@ struct SymbolRef : Reference {
: Reference{Range(), si.id, si.kind, Role::None} {}
};
struct QueryFile;
// Represents an occurrence of a variable/type, |id,kind| refer to the lexical
// parent.
struct Use : Reference {
// |file| is used in Query* but not in Index*
Id<QueryFile> file;
Use() = default;
Use(Reference ref) : Reference(ref) {}
Use(Range range, Id<void> id, SymbolKind kind, Role role)
: Reference{range, id, kind, role} {}
Use(Range range, Id<void> id, SymbolKind kind, Role role, Id<QueryFile> file)
: Reference{range, id, kind, role}, file(file) {}
};
void Reflect(Reader& visitor, Reference& value);
@ -433,7 +439,7 @@ struct IndexVar {
Def def;
std::vector<Range> declarations;
std::vector<Use> declarations;
// Usages.
std::vector<Use> uses;

View File

@ -80,7 +80,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
std::vector<Out_CqueryCallTree::CallEntry> result;
auto handle_caller = [&](QueryFuncRef caller,
auto handle_caller = [&](Use caller,
Out_CqueryCallTree::CallType call_type) {
optional<lsLocation> call_location =
GetLsLocation(db, working_files, caller);
@ -130,21 +130,21 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
}
};
std::vector<QueryFuncRef> base_callers =
std::vector<Use> base_callers =
GetCallersForAllBaseFunctions(db, root_func);
std::vector<QueryFuncRef> derived_callers =
std::vector<Use> derived_callers =
GetCallersForAllDerivedFunctions(db, root_func);
result.reserve(root_func.uses.size() + base_callers.size() +
derived_callers.size());
for (QueryFuncRef caller : root_func.uses)
for (Use caller : root_func.uses)
handle_caller(caller, Out_CqueryCallTree::CallType::Direct);
for (QueryFuncRef caller : base_callers)
for (Use caller : base_callers)
if (caller.kind == SymbolKind::Func && caller.id != Id<void>(root)) {
// Do not show calls to the base function coming from this function.
handle_caller(caller, Out_CqueryCallTree::CallType::Base);
}
for (QueryFuncRef caller : derived_callers)
for (Use caller : derived_callers)
handle_caller(caller, Out_CqueryCallTree::CallType::Derived);
return result;

View File

@ -73,7 +73,7 @@ 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->extent) {
Maybe<QueryFileId> t = db->GetFileId(*func.def->extent);
QueryFileId t = func.def->extent->file;
if (t != file_id)
return t;
}
@ -84,7 +84,7 @@ 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->extent) {
Maybe<QueryFileId> t = db->GetFileId(*var.def->extent);
QueryFileId t = var.def->extent->file;
if (t != file_id)
return t;
}
@ -150,8 +150,8 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
QueryFileId impl_file_id,
QueryFunc& func) {
assert(func.def);
for (const Reference& decl : func.declarations) {
if (db->GetFileId(decl) != decl_file_id)
for (Use decl : func.declarations) {
if (decl.file != decl_file_id)
continue;
optional<lsRange> ls_decl = GetLsRange(working_file, decl.range);
@ -204,8 +204,8 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
if (!sym_func.def || !sym_func.def->extent)
break;
for (const Reference& func_decl : sym_func.declarations) {
if (db->GetFileId(func_decl) == decl_file_id) {
for (Use func_decl : sym_func.declarations) {
if (func_decl.file == 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

@ -91,6 +91,7 @@ void AddCodeLens(const char* singular,
optional<lsRange> range = GetLsRange(common->working_file, loc.range);
if (!range)
return;
// FIXME SymbolRef loc -> Use loc
Maybe<QueryFileId> file_id = common->db->GetFileId(loc);
if (!file_id)
return;
@ -178,7 +179,7 @@ struct TextDocumentCodeLensHandler
// extent location to the spelling location.
auto try_ensure_spelling = [&](SymbolRef sym) {
Maybe<Use> def = GetDefinitionSpellingOfSymbol(db, sym);
if (!def || db->GetFileId(*def) != db->GetFileId(sym) ||
if (!def || def->file != *db->GetFileId(sym) ||
def->range.start.line != sym.range.start.line) {
return sym;
}

View File

@ -86,7 +86,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 || (db->GetFileId(*def_loc) == file_id &&
if (!def_loc || (def_loc->file == file_id &&
def_loc->range.Contains(target_line, target_column))) {
// Goto declaration.

View File

@ -41,7 +41,7 @@ struct TextDocumentDocumentHighlightHandler
std::vector<Use> uses = GetUsesOfSymbol(db, sym, true);
out.result.reserve(uses.size());
for (Use use : uses) {
if (db->GetFileId(use) != file_id)
if (use.file != file_id)
continue;
optional<lsLocation> ls_location =

View File

@ -16,23 +16,21 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
if (!ls_location)
continue;
Maybe<QueryFileId> file_id = db->GetFileId(use);
if (!file_id)
continue;
if (path_to_edit.find(*file_id) == path_to_edit.end()) {
path_to_edit[*file_id] = lsTextDocumentEdit();
QueryFileId file_id = use.file;
if (path_to_edit.find(file_id) == path_to_edit.end()) {
path_to_edit[file_id] = lsTextDocumentEdit();
QueryFile& file = db->files[file_id->id];
QueryFile& file = db->files[file_id.id];
if (!file.def)
continue;
const std::string& path = file.def->path;
path_to_edit[*file_id].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[*file_id].textDocument.version =
path_to_edit[file_id].textDocument.version =
working_file->version;
}
@ -41,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
edit.newText = new_text;
// vscode complains if we submit overlapping text edits.
auto& edits = path_to_edit[*file_id].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

@ -233,10 +233,6 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
Role role) {
def.outline.push_back(SymbolRef(range, id, kind, role));
};
auto add_all_symbols = [&](Range range, Id<void> id, SymbolKind kind,
Role role) {
def.all_symbols.push_back(SymbolRef(range, id, kind, role));
};
auto add_all_symbols_use = [&](Use use, Id<void> id, SymbolKind kind) {
def.all_symbols.push_back(
SymbolRef(use.range, id, kind, use.role));
@ -252,7 +248,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
if (type.def.extent)
add_outline_use(*type.def.extent, id, SymbolKind::Type);
for (Use use : type.uses)
add_all_symbols(use.range, id, SymbolKind::Type, use.role);
add_all_symbols_use(use, id, SymbolKind::Type);
}
for (const IndexFunc& func : indexed.funcs) {
QueryFuncId id = id_map.ToQuery(func.id);
@ -261,23 +257,21 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
if (func.def.extent)
add_outline_use(*func.def.extent, id, SymbolKind::Func);
for (const IndexFunc::Declaration& decl : func.declarations) {
add_all_symbols(decl.spelling, id, SymbolKind::Func,
Role::Declaration);
def.all_symbols.push_back(
SymbolRef(decl.spelling, id, SymbolKind::Func, Role::Declaration));
add_outline(decl.spelling, id, SymbolKind::Func, Role::Declaration);
}
for (Use caller : func.uses) {
for (Use use : func.uses) {
// Make ranges of implicit function calls larger (spanning one more column
// to the left/right). This is hacky but useful. e.g.
// textDocument/definition on the space/semicolon in `A a;` or `return
// 42;` will take you to the constructor.
Range range = caller.range;
if (caller.role & Role::Implicit) {
if (range.start.column > 0)
range.start.column--;
range.end.column++;
if (use.role & Role::Implicit) {
if (use.range.start.column > 0)
use.range.start.column--;
use.range.end.column++;
}
add_all_symbols(range, id, SymbolKind::Func,
caller.role | Role::Call);
add_all_symbols_use(use, id, SymbolKind::Func);
}
}
for (const IndexVar& var : indexed.vars) {
@ -286,15 +280,12 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
add_all_symbols_use(*var.def.spell, id, SymbolKind::Var);
if (var.def.extent)
add_outline_use(*var.def.extent, id, SymbolKind::Var);
for (const Range& decl : var.declarations) {
add_all_symbols(decl, id_map.ToQuery(var.id), SymbolKind::Var,
Role::Definition);
add_outline(decl, id_map.ToQuery(var.id), SymbolKind::Var,
Role::Declaration);
for (Use decl : var.declarations) {
add_all_symbols_use(decl, id, SymbolKind::Var);
add_outline_use(decl, id, SymbolKind::Var);
}
for (Use use : var.uses)
add_all_symbols(use.range, id_map.ToQuery(var.id), SymbolKind::Var,
use.role);
add_all_symbols_use(use, id, SymbolKind::Var);
}
std::sort(def.outline.begin(), def.outline.end(),
@ -411,14 +402,12 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
*GetQueryVarIdFromUsr(query_db, entry.second, true);
}
Use IdMap::ToQuery(Range range, Role role) const {
return Use(range, primary_file, SymbolKind:: File, role);
}
QueryTypeId IdMap::ToQuery(IndexTypeId id) const {
assert(cached_type_ids_.find(id) != cached_type_ids_.end());
return QueryTypeId(cached_type_ids_.find(id)->second);
}
QueryFuncId IdMap::ToQuery(IndexFuncId id) const {
// FIXME id shouldn't be invalid
if (id == IndexFuncId())
return QueryFuncId();
assert(cached_func_ids_.find(id) != cached_func_ids_.end());
@ -430,44 +419,38 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const {
}
Use IdMap::ToQuery(Reference ref) const {
Use ret(ref);
ret.file = primary_file;
switch (ref.kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File:
ref.id = primary_file;
ret.id = primary_file;
break;
case SymbolKind::Func:
ref.id = ToQuery(IndexFuncId(ref.id));
ret.id = ToQuery(IndexFuncId(ref.id));
break;
case SymbolKind::Type:
ref.id = ToQuery(IndexTypeId(ref.id));
ret.id = ToQuery(IndexTypeId(ref.id));
break;
case SymbolKind::Var:
ref.id = ToQuery(IndexVarId(ref.id));
ret.id = ToQuery(IndexVarId(ref.id));
break;
}
return ref;
return ret;
}
SymbolRef IdMap::ToQuery(SymbolRef ref) const {
ref.Reference::operator=(ToQuery(static_cast<Reference>(ref)));
return ref;
}
Use IdMap::ToQuery(Use use) const {
use.Reference::operator=(ToQuery(static_cast<Reference>(use)));
return use;
return ToQuery(static_cast<Reference>(use));
}
Use IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation.
return Use(decl.spelling, primary_file, SymbolKind::File,
Role::Declaration);
}
std::vector<Use> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<Use> ret;
ret.reserve(a.size());
for (auto& x : a)
ret.push_back(ToQuery(x, Role::Reference));
return ret;
return {decl.spelling, primary_file, SymbolKind::File, Role::Declaration,
primary_file};
}
// ----------------------

View File

@ -20,8 +20,6 @@ using QueryVarId = Id<QueryVar>;
struct IdMap;
using QueryFuncRef = Use;
// 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.
//
@ -341,7 +339,6 @@ template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; };
template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; };
template <> struct IndexToQuery<Use> { using type = Use; };
template <> struct IndexToQuery<SymbolRef> { using type = SymbolRef; };
template <> struct IndexToQuery<Range> { using type = Use; };
template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Use; };
template <typename I> struct IndexToQuery<optional<I>> {
using type = optional<typename IndexToQuery<I>::type>;
@ -363,7 +360,6 @@ struct IdMap {
QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const;
SymbolRef ToQuery(SymbolRef ref) const;
Use ToQuery(Range range, Role role) const;
Use ToQuery(Reference ref) const;
Use ToQuery(Use ref) const;
Use ToQuery(IndexFunc::Declaration decl) const;
@ -381,7 +377,6 @@ struct IdMap {
ret.push_back(ToQuery(x));
return ret;
}
std::vector<Use> ToQuery(const std::vector<Range>& a) const;
// clang-format on

View File

@ -16,19 +16,13 @@ int ComputeRangeSize(const Range& range) {
return range.end.column - range.start.column;
}
Maybe<Use> UseWithFileId(Maybe<Use> use, QueryFileId file_id) {
if (!use)
return nullopt;
return Use(use->range, file_id, SymbolKind::File, use->role);
}
} // namespace
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
QueryFuncId id) {
QueryFunc& func = db->funcs[id.id];
if (func.def)
return UseWithFileId(func.def->spell, func.def->file);
return func.def->spell;
return nullopt;
}
@ -38,19 +32,19 @@ Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
case SymbolKind::Type: {
QueryType& type = db->GetType(sym);
if (type.def)
return UseWithFileId(type.def->spell, type.def->file);
return type.def->spell;
break;
}
case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym);
if (func.def)
return UseWithFileId(func.def->spell, func.def->file);
return func.def->spell;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym);
if (var.def)
return UseWithFileId(var.def->spell, var.def->file);
return var.def->spell;
break;
}
case SymbolKind::File:
@ -67,24 +61,24 @@ Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) {
case SymbolKind::Type: {
QueryType& type = db->GetType(sym);
if (type.def)
return UseWithFileId(type.def->extent, type.def->file);
return type.def->extent;
break;
}
case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym);
if (func.def)
return UseWithFileId(func.def->extent, func.def->file);
return func.def->extent;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym);
if (var.def)
return UseWithFileId(var.def->extent, var.def->file);
return var.def->extent;
break;
}
case SymbolKind::File:
return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind,
Role::None);
Role::None, QueryFileId(sym.id));
case SymbolKind::Invalid: {
assert(false && "unexpected");
break;
@ -105,7 +99,7 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym);
if (!func.declarations.empty())
return db->GetFileId(func.declarations[0]);
return func.declarations[0].file;
if (func.def)
return func.def->file;
break;
@ -383,14 +377,11 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id) {
optional<lsLocation> GetLsLocation(QueryDatabase* db,
WorkingFiles* working_files,
Reference ref) {
Use use) {
std::string path;
Maybe<QueryFileId> file_id = db->GetFileId(ref);
if (!file_id)
return nullopt;
lsDocumentUri uri = GetLsDocumentUri(db, *file_id, &path);
lsDocumentUri uri = GetLsDocumentUri(db, use.file, &path);
optional<lsRange> range =
GetLsRange(working_files->GetFileByFilename(path), ref.range);
GetLsRange(working_files->GetFileByFilename(path), use.range);
if (!range)
return nullopt;
return lsLocation(uri, *range);

View File

@ -44,7 +44,7 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id);
optional<lsLocation> GetLsLocation(QueryDatabase* db,
WorkingFiles* working_files,
Reference location);
Use use);
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
WorkingFiles* working_files,
Use use,