struct QueryFuncRef : Reference {};

This commit is contained in:
Fangrui Song 2018-02-08 23:10:54 -08:00
parent 4bfb5a3586
commit 67e8132dbe
11 changed files with 74 additions and 59 deletions

View File

@ -84,6 +84,7 @@ struct Reference {
SymbolKind lex_parent_kind; SymbolKind lex_parent_kind;
SymbolRole role; SymbolRole role;
bool HasValue() const { return lex_parent_id.HasValue(); }
std::tuple<Range, Id<void>, SymbolKind, SymbolRole> ToTuple() const { std::tuple<Range, Id<void>, SymbolKind, SymbolRole> ToTuple() const {
return std::make_tuple(range, lex_parent_id, lex_parent_kind, role); return std::make_tuple(range, lex_parent_id, lex_parent_kind, role);
} }

View File

@ -36,17 +36,15 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
for (const SymbolRef& ref : refs) { for (const SymbolRef& ref : refs) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = db->types[ref.idx.idx];
if (!type.def) if (type.def)
continue; out.result = GetLsLocations(db, working_files,
std::vector<QueryLocation> locations = ToReference(db, type.def->parents));
ToQueryLocation(db, type.def->parents);
out.result = GetLsLocations(db, working_files, locations);
break; break;
} else if (ref.idx.kind == SymbolKind::Func) { } else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations = if (func.def)
ToQueryLocation(db, func.def->base); out.result =
out.result = GetLsLocations(db, working_files, locations); GetLsLocations(db, working_files, ToReference(db, func.def->base));
break; break;
} }
} }

View File

@ -84,7 +84,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
auto handle_caller = [&](QueryFuncRef caller, auto handle_caller = [&](QueryFuncRef caller,
Out_CqueryCallTree::CallType call_type) { Out_CqueryCallTree::CallType call_type) {
optional<lsLocation> call_location = optional<lsLocation> call_location =
GetLsLocation(db, working_files, caller.loc); GetLsLocation(db, working_files, caller);
if (!call_location) if (!call_location)
return; return;
@ -107,7 +107,10 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
//} //}
if (caller.HasValue()) { if (caller.HasValue()) {
QueryFunc& call_func = db->funcs[caller.id_.id]; QueryFuncId func_id = caller.FuncId();
if (!func_id.HasValue())
return;
QueryFunc& call_func = db->funcs[func_id.id];
if (!call_func.def) if (!call_func.def)
return; return;
@ -142,7 +145,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
handle_caller(caller, Out_CqueryCallTree::CallType::Direct); handle_caller(caller, Out_CqueryCallTree::CallType::Direct);
for (QueryFuncRef caller : base_callers) { for (QueryFuncRef caller : base_callers) {
// Do not show calls to the base function coming from this function. // Do not show calls to the base function coming from this function.
if (caller.id_ == root) if (caller.FuncId() == root)
continue; continue;
handle_caller(caller, Out_CqueryCallTree::CallType::Base); handle_caller(caller, Out_CqueryCallTree::CallType::Base);

View File

@ -27,14 +27,12 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Func) { if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations = std::vector<Reference> uses = ToReference(db, func.callers);
ToQueryLocation(db, func.callers);
for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func)) for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func))
locations.push_back(func_ref.loc); uses.push_back(func_ref);
for (QueryFuncRef func_ref : GetCallersForAllDerivedFunctions(db, func)) for (QueryFuncRef func_ref : GetCallersForAllDerivedFunctions(db, func))
locations.push_back(func_ref.loc); uses.push_back(func_ref);
out.result = GetLsLocations(db, working_files, uses);
out.result = GetLsLocations(db, working_files, locations);
} }
} }
QueueManager::WriteStdout(IpcId::CqueryCallers, out); QueueManager::WriteStdout(IpcId::CqueryCallers, out);

View File

@ -36,15 +36,13 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
for (const SymbolRef& ref : refs) { for (const SymbolRef& ref : refs) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = db->types[ref.idx.idx];
std::vector<QueryLocation> locations = out.result =
ToQueryLocation(db, type.derived); GetLsLocations(db, working_files, ToReference(db, type.derived));
out.result = GetLsLocations(db, working_files, locations);
break; break;
} else if (ref.idx.kind == SymbolKind::Func) { } else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations = out.result =
ToQueryLocation(db, func.derived); GetLsLocations(db, working_files, ToReference(db, func.derived));
out.result = GetLsLocations(db, working_files, locations);
break; break;
} }
} }

View File

@ -38,9 +38,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
// fallthrough // fallthrough
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[id]; QueryType& type = db->types[id];
std::vector<QueryLocation> locations = out.result = GetLsLocations(db, working_files,
ToQueryLocation(db, type.instances); ToReference(db, type.instances));
out.result = GetLsLocations(db, working_files, locations);
break; break;
} }
} }

View File

@ -451,10 +451,21 @@ 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 {
if (ref.lex_parent_kind == SymbolKind::Func) QueryFuncRef ret(ref.range, ref.lex_parent_id, ref.lex_parent_kind, ref.role);
return QueryFuncRef{ToQuery(IndexFuncId(ref.lex_parent_id)), switch (ref.lex_parent_kind) {
ToQuery(ref.range, ref.role)}; default:
return QueryFuncRef{QueryFuncId(), ToQuery(ref.range, ref.role)}; break;
case SymbolKind::File:
ret.lex_parent_id = Id<void>(primary_file);
break;
case SymbolKind::Func:
ret.lex_parent_id = Id<void>(ToQuery(IndexFuncId(ref.lex_parent_id)));
break;
case SymbolKind::Type:
ret.lex_parent_id = Id<void>(ToQuery(IndexTypeId(ref.lex_parent_id)));
break;
}
return ret;
} }
Reference IdMap::ToQuery(IndexFunc::Declaration decl) const { Reference IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation. // TODO: expose more than just QueryLocation.
@ -1061,10 +1072,10 @@ TEST_SUITE("query") {
REQUIRE(update.funcs_callers.size() == 1); REQUIRE(update.funcs_callers.size() == 1);
REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); REQUIRE(update.funcs_callers[0].id == QueryFuncId(0));
REQUIRE(update.funcs_callers[0].to_remove.size() == 1); REQUIRE(update.funcs_callers[0].to_remove.size() == 1);
REQUIRE(update.funcs_callers[0].to_remove[0].loc.range == REQUIRE(update.funcs_callers[0].to_remove[0].range ==
Range(Position(1, 0))); Range(Position(1, 0)));
REQUIRE(update.funcs_callers[0].to_add.size() == 1); REQUIRE(update.funcs_callers[0].to_add.size() == 1);
REQUIRE(update.funcs_callers[0].to_add[0].loc.range == REQUIRE(update.funcs_callers[0].to_add[0].range ==
Range(Position(2, 0))); Range(Position(2, 0)));
} }
@ -1116,12 +1127,12 @@ TEST_SUITE("query") {
db.ApplyIndexUpdate(&import_update); db.ApplyIndexUpdate(&import_update);
REQUIRE(db.funcs[0].callers.size() == 2); REQUIRE(db.funcs[0].callers.size() == 2);
REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(1, 0))); REQUIRE(db.funcs[0].callers[0].range == Range(Position(1, 0)));
REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(2, 0))); REQUIRE(db.funcs[0].callers[1].range == Range(Position(2, 0)));
db.ApplyIndexUpdate(&delta_update); db.ApplyIndexUpdate(&delta_update);
REQUIRE(db.funcs[0].callers.size() == 2); REQUIRE(db.funcs[0].callers.size() == 2);
REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(4, 0))); REQUIRE(db.funcs[0].callers[0].range == Range(Position(4, 0)));
REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(5, 0))); REQUIRE(db.funcs[0].callers[1].range == Range(Position(5, 0)));
} }
} }

View File

@ -101,25 +101,17 @@ struct SymbolRef {
}; };
MAKE_REFLECT_STRUCT(SymbolRef, idx, loc); MAKE_REFLECT_STRUCT(SymbolRef, idx, loc);
struct QueryFuncRef { struct QueryFuncRef : Reference {
// NOTE: id_ can be -1 if the function call is not coming from a function. QueryFuncRef() = default;
QueryFuncId id_; QueryFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
QueryLocation loc; : Reference{range, id, kind, role} {}
bool HasValue() const { return id_.HasValue(); } QueryFuncId FuncId() const {
if (lex_parent_kind == SymbolKind::Func)
std::tuple<QueryFuncId, QueryLocation> ToTuple() const { return QueryFuncId(lex_parent_id);
return std::make_tuple(id_, loc); return QueryFuncId();
}
bool operator==(const QueryFuncRef& o) const {
return ToTuple() == o.ToTuple();
}
bool operator!=(const QueryFuncRef& o) const { return !(*this == o); }
bool operator<(const QueryFuncRef& o) const {
return ToTuple() < o.ToTuple();
} }
}; };
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.

View File

@ -188,8 +188,7 @@ std::vector<Reference> ToReference(QueryDatabase* db,
std::vector<Reference> ret; std::vector<Reference> ret;
ret.reserve(refs.size()); ret.reserve(refs.size());
for (auto& ref : refs) for (auto& ref : refs)
ret.push_back(Reference{ref.loc.range, Id<void>(ref.id_), SymbolKind::Func, ret.push_back(ref);
ref.loc.role});
return ret; return ret;
} }
@ -199,7 +198,7 @@ std::vector<QueryLocation> ToQueryLocation(
std::vector<QueryLocation> locs; std::vector<QueryLocation> locs;
locs.reserve(refs.size()); locs.reserve(refs.size());
for (const QueryFuncRef& ref : refs) for (const QueryFuncRef& ref : refs)
locs.push_back(ref.loc); locs.push_back(QueryLocation{ref.range, GetFileId(db, ref), ref.role});
return locs; return locs;
} }
std::vector<QueryLocation> ToQueryLocation( std::vector<QueryLocation> ToQueryLocation(
@ -450,11 +449,11 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
std::vector<lsLocation> GetLsLocations( std::vector<lsLocation> GetLsLocations(
QueryDatabase* db, QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
const std::vector<QueryLocation>& locations) { const std::vector<Reference>& refs) {
std::unordered_set<lsLocation> unique_locations; std::unordered_set<lsLocation> unique_locations;
for (const QueryLocation& query_location : locations) { for (Reference ref : refs) {
optional<lsLocation> location = optional<lsLocation> location =
GetLsLocation(db, working_files, query_location); GetLsLocation(db, working_files, ref);
if (!location) if (!location)
continue; continue;
unique_locations.insert(*location); unique_locations.insert(*location);

View File

@ -25,6 +25,20 @@ QueryFileId GetFileId(QueryDatabase* db, Reference ref);
std::vector<Reference> ToReference(QueryDatabase* db, std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs); const std::vector<QueryFuncRef>& refs);
template <typename Q>
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<Id<Q>>& ids) {
std::vector<Reference> ret;
ret.reserve(ids.size());
for (auto id : ids) {
optional<QueryLocation> loc = GetDefinitionSpellingOfSymbol(db, id);
if (loc)
ret.push_back(*loc);
}
return ret;
}
std::vector<QueryLocation> ToQueryLocation( std::vector<QueryLocation> ToQueryLocation(
QueryDatabase* db, QueryDatabase* db,
const std::vector<QueryFuncRef>& refs); const std::vector<QueryFuncRef>& refs);
@ -62,7 +76,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
std::vector<lsLocation> GetLsLocations( std::vector<lsLocation> GetLsLocations(
QueryDatabase* db, QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
const std::vector<QueryLocation>& locations); const std::vector<Reference>& refs);
// Returns a symbol. The symbol will have *NOT* have a location assigned. // Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,

View File

@ -166,6 +166,8 @@ def configure(ctx):
cxxflags = ctx.env.CXXFLAGS cxxflags = ctx.env.CXXFLAGS
else: else:
cxxflags = ['-g', '-Wall', '-Wno-sign-compare', '-Werror'] cxxflags = ['-g', '-Wall', '-Wno-sign-compare', '-Werror']
if 'g++' in ctx.env.CXX_NAME:
cxxflags.append('-Wno-return-type')
if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS): if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS):
cxxflags.append('-std=c++11') cxxflags.append('-std=c++11')