Derive SymbolRef,Use from Reference and add lexical container to func/var/type uses

This commit is contained in:
Fangrui Song 2018-02-10 12:53:18 -08:00
parent a50bff0b24
commit 420e84329b
19 changed files with 393 additions and 422 deletions

View File

@ -194,6 +194,10 @@ ClangCursor ClangCursor::get_definition() const {
return ClangCursor(clang_getCursorDefinition(cx_cursor));
}
ClangCursor ClangCursor::get_lexical_parent() const {
return ClangCursor(clang_getCursorLexicalParent(cx_cursor));
}
ClangCursor ClangCursor::get_semantic_parent() const {
return ClangCursor(clang_getCursorSemanticParent(cx_cursor));
}

View File

@ -73,6 +73,7 @@ class ClangCursor {
ClangCursor get_referenced() const;
ClangCursor get_canonical() const;
ClangCursor get_definition() const;
ClangCursor get_lexical_parent() const;
ClangCursor get_semantic_parent() const;
std::vector<ClangCursor> get_arguments() const;
bool is_valid_kind() const;

View File

@ -30,7 +30,7 @@ constexpr bool kIndexStdDeclarations = true;
// display their declarations on hover.
constexpr int kMaxLinesDisplayTypeAliasDeclarations = 3;
void AddFuncRef(std::vector<IndexFuncRef>* result, IndexFuncRef ref) {
void AddFuncUse(std::vector<Use>* result, Use ref) {
if (!result->empty() && (*result)[result->size() - 1] == ref)
return;
result->push_back(ref);
@ -53,6 +53,30 @@ bool IsScopeSemanticContainer(CXCursorKind kind) {
}
}
SymbolKind GetSymbolKind(CXCursorKind kind) {
switch (kind) {
default:
return SymbolKind::Invalid;
case CXCursor_FunctionDecl:
case CXCursor_CXXMethod:
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_ConversionFunction:
case CXCursor_FunctionTemplate:
case CXCursor_OverloadedDeclRef:
case CXCursor_LambdaExpr:
return SymbolKind::Func;
case CXCursor_Namespace:
case CXCursor_EnumDecl:
case CXCursor_UnionDecl:
case CXCursor_StructDecl:
case CXCursor_ClassDecl:
return SymbolKind::Type;
}
}
// Inverse of libclang/CXIndexDataConsumer.cpp getEntityKindFromSymbolKind
ClangSymbolKind GetSymbolKind(CXIdxEntityKind kind) {
switch (kind) {
@ -410,26 +434,6 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu,
return result;
}
bool IsFunctionCallContext(CXCursorKind kind) {
switch (kind) {
case CXCursor_FunctionDecl:
case CXCursor_CXXMethod:
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_ConversionFunction:
case CXCursor_FunctionTemplate:
case CXCursor_OverloadedDeclRef:
// TODO: we need to test lambdas
case CXCursor_LambdaExpr:
return true;
default:
break;
}
return false;
}
void SetTypeName(IndexType* type,
const ClangCursor& cursor,
const CXIdxContainerInfo* container,
@ -581,23 +585,30 @@ void SetVarDetail(IndexVar* var,
void OnIndexReference_Function(IndexFile* db,
Range loc,
ClangCursor caller_cursor,
ClangCursor parent_cursor,
IndexFuncId called_id,
IndexFunc* called,
SymbolRole role) {
if (IsFunctionCallContext(caller_cursor.get_kind())) {
IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor);
IndexFunc* caller = db->Resolve(caller_id);
// Calling db->ToFuncId invalidates the FuncDef* ptrs.
called = db->Resolve(called_id);
AddFuncRef(&caller->def.callees,
IndexFuncRef(loc, Id<void>(called->id), SymbolKind::Func, role));
AddFuncRef(&called->callers,
IndexFuncRef(loc, Id<void>(caller->id), SymbolKind::Func, role));
} else {
AddFuncRef(&called->callers,
IndexFuncRef(loc, Id<void>(), SymbolKind::Invalid, role));
switch (GetSymbolKind(parent_cursor.get_kind())) {
case SymbolKind::Func: {
IndexFunc* parent = db->Resolve(db->ToFuncId(parent_cursor.cx_cursor));
IndexFunc* called = db->Resolve(called_id);
parent->def.callees.push_back(
SymbolRef(loc, called->id, SymbolKind::Func, role));
AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Func, role));
break;
}
case SymbolKind::Type: {
IndexType* parent = db->Resolve(db->ToTypeId(parent_cursor.cx_cursor));
IndexFunc* called = db->Resolve(called_id);
called = db->Resolve(called_id);
AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Type, role));
break;
}
default: {
IndexFunc* called = db->Resolve(called_id);
AddFuncUse(&called->uses, Use(loc, Id<void>(), SymbolKind::File, role));
break;
}
}
}
@ -686,17 +697,55 @@ void UniqueAdd(std::vector<T>& values, T value) {
}
// FIXME Reference: set id in call sites and remove this
void AddUse(std::vector<Reference>& values, Range value) {
values.push_back(Reference{value, Id<void>(), SymbolKind::Invalid,
SymbolRole::Reference});
void AddUse(std::vector<Use>& values, Range value) {
values.push_back(
Use(value, Id<void>(), SymbolKind::File, SymbolRole::Reference));
}
// FIXME Reference: set id in call sites and remove this
void UniqueAdd(std::vector<Reference>& values, Range value) {
if (std::find_if(values.begin(), values.end(), [&](const Reference& ref) {
return ref.range == value;
}) == values.end())
AddUse(values, value);
void AddUse(IndexFile* db,
std::vector<Use>& uses,
Range range,
ClangCursor parent,
SymbolRole role = SymbolRole::Reference) {
switch (GetSymbolKind(parent.get_kind())) {
default:
uses.push_back(Use(range, Id<void>(), SymbolKind::File, role));
break;
case SymbolKind::Func:
uses.push_back(
Use(range, db->ToFuncId(parent.cx_cursor), SymbolKind::Func, role));
break;
case SymbolKind::Type:
uses.push_back(
Use(range, db->ToTypeId(parent.cx_cursor), SymbolKind::Type, role));
break;
}
}
CXCursor fromContainer(const CXIdxContainerInfo* parent) {
return parent ? parent->cursor : clang_getNullCursor();
}
void AddUseSpell(IndexFile* db,
std::vector<Use>& uses,
ClangCursor cursor) {
AddUse(db, uses, cursor.get_spelling_range(),
cursor.get_lexical_parent().cx_cursor, SymbolRole::Reference);
}
template <typename... Args>
void UniqueAddUse(IndexFile* db, std::vector<Use>& uses, Range range, Args&&... args) {
if (std::find_if(uses.begin(), uses.end(),
[&](Use use) { return use.range == range; }) == uses.end())
AddUse(db, uses, range, std::forward<Args>(args)...);
}
template <typename... Args>
void UniqueAddUseSpell(IndexFile* db, std::vector<Use>& uses, ClangCursor cursor, Args&&... args) {
Range range = cursor.get_spelling_range();
if (std::find_if(uses.begin(), uses.end(),
[&](Use use) { return use.range == range; }) == uses.end())
AddUse(db, uses, range, cursor.get_lexical_parent().cx_cursor, std::forward<Args>(args)...);
}
IdCache::IdCache(const std::string& primary_file)
@ -840,17 +889,7 @@ bool IsGlobalContainer(const CXIdxContainerInfo* container) {
bool IsTypeDefinition(const CXIdxContainerInfo* container) {
if (!container)
return false;
switch (container->cursor.kind) {
case CXCursor_Namespace:
case CXCursor_EnumDecl:
case CXCursor_UnionDecl:
case CXCursor_StructDecl:
case CXCursor_ClassDecl:
return true;
default:
return false;
}
return GetSymbolKind(container->cursor.kind) == SymbolKind::Type;
}
struct VisitDeclForTypeUsageParam {
@ -886,7 +925,7 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
IndexType* ref_type = db->Resolve(*param->toplevel_type);
std::string name = cursor.get_referenced().get_spelling();
if (name == ref_type->def.ShortName()) {
UniqueAdd(ref_type->uses, cursor.get_spelling_range());
UniqueAddUseSpell(db, ref_type->uses, cursor);
param->toplevel_type = nullopt;
return;
}
@ -908,8 +947,7 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
IndexType* ref_type_def = db->Resolve(ref_type_id);
// TODO: Should we even be visiting this if the file is not from the main
// def? Try adding assert on |loc| later.
Range loc = cursor.get_spelling_range();
UniqueAdd(ref_type_def->uses, loc);
UniqueAddUseSpell(db, ref_type_def->uses, cursor);
}
ClangCursor::VisitResult VisitDeclForTypeUsageVisitor(
@ -1128,10 +1166,8 @@ ClangCursor::VisitResult AddDeclInitializerUsagesVisitor(ClangCursor cursor,
if (ref_usr == "")
break;
Range loc = cursor.get_spelling_range();
IndexVarId ref_id = db->ToVarId(HashUsr(ref_usr));
IndexVar* ref_def = db->Resolve(ref_id);
UniqueAdd(ref_def->uses, loc);
IndexVar* ref_var = db->Resolve(db->ToVarId(HashUsr(ref_usr)));
UniqueAddUseSpell(db, ref_var->uses, cursor);
break;
}
@ -1195,7 +1231,7 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
var_def->def.definition_extent =
ResolveCXSourceRange(cx_extent, nullptr);
} else
UniqueAdd(var_def->uses, decl_loc_spelling);
UniqueAddUse(db, var_def->uses, decl_loc_spelling, parent);
break;
}
@ -1244,10 +1280,11 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
// seems no way to extract the spelling range of `type` and we do
// not want to do subtraction here.
// See https://github.com/jacobdufault/cquery/issues/252
UniqueAdd(ref_type_index->uses, ref_cursor.get_extent());
UniqueAddUse(db, ref_type_index->uses, ref_cursor.get_extent(),
ref_cursor.get_lexical_parent());
}
}
UniqueAdd(ref_index->uses, cursor.get_spelling_range());
UniqueAddUseSpell(db, ref_index->uses, cursor);
}
break;
}
@ -1261,10 +1298,9 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
case CXCursor_FunctionDecl:
case CXCursor_FunctionTemplate: {
IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash());
IndexFunc* called = db->Resolve(called_id);
OnIndexReference_Function(db, cursor.get_spelling_range(),
data->container, called_id, called,
SymbolRole::None);
data->container, called_id,
SymbolRole::CalledBy);
break;
}
}
@ -1293,7 +1329,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
ref_index->def.short_name_size = ref_index->def.detailed_name.size();
ref_index->def.kind = ClangSymbolKind::Parameter;
}
UniqueAdd(ref_index->uses, cursor.get_spelling_range());
UniqueAddUseSpell(db, ref_index->uses, cursor);
}
break;
}
@ -1319,7 +1355,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
ref_index->def.short_name_size = ref_index->def.detailed_name.size();
ref_index->def.kind = ClangSymbolKind::Parameter;
}
UniqueAdd(ref_index->uses, cursor.get_spelling_range());
UniqueAddUseSpell(db, ref_index->uses, cursor);
}
break;
}
@ -1502,17 +1538,24 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// has already been seen.
if (decl->isDefinition && decl->semanticContainer) {
if (IsFunctionCallContext(decl->semanticContainer->cursor.kind)) {
IndexFuncId parent_func_id =
db->ToFuncId(decl->semanticContainer->cursor);
var->def.parent_kind = SymbolKind::Func;
var->def.parent_id = Id<void>(parent_func_id);
} else if (IsTypeDefinition(decl->semanticContainer)) {
IndexTypeId parent_type_id =
db->ToTypeId(decl->semanticContainer->cursor);
var->def.parent_kind = SymbolKind::Type;
var->def.parent_id = Id<void>(parent_type_id);
db->Resolve(parent_type_id)->def.vars.push_back(var_id);
switch (GetSymbolKind(decl->semanticContainer->cursor.kind)) {
default:
break;
case SymbolKind::Func: {
IndexFuncId parent_func_id =
db->ToFuncId(decl->semanticContainer->cursor);
var->def.parent_kind = SymbolKind::Func;
var->def.parent_id = Id<void>(parent_func_id);
break;
}
case SymbolKind::Type: {
IndexTypeId parent_type_id =
db->ToTypeId(decl->semanticContainer->cursor);
var->def.parent_kind = SymbolKind::Type;
var->def.parent_id = Id<void>(parent_type_id);
db->Resolve(parent_type_id)->def.vars.push_back(var_id);
break;
}
}
}
@ -1632,13 +1675,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
func->def.declaring_type = declaring_type_id;
// Mark a type reference at the ctor/dtor location.
if (decl->entityInfo->kind == CXIdxEntity_CXXConstructor)
UniqueAdd(declaring_type_def->uses, decl_spelling);
if (decl->entityInfo->kind == CXIdxEntity_CXXDestructor) {
Range dtor_type_range = decl_spelling;
dtor_type_range.start.column += 1; // Don't count the leading ~
UniqueAdd(declaring_type_def->uses, dtor_type_range);
}
if (decl->entityInfo->kind == CXIdxEntity_CXXConstructor
|| decl->entityInfo->kind == CXIdxEntity_CXXDestructor)
UniqueAddUse(db, declaring_type_def->uses, decl_spelling,
fromContainer(decl->lexicalContainer));
// Add function to declaring type.
UniqueAdd(declaring_type_def->def.funcs, func_id);
@ -1714,7 +1754,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
}
}
UniqueAdd(type->uses, spell);
UniqueAddUse(db, type->uses, spell, fromContainer(decl->lexicalContainer));
break;
}
@ -1751,13 +1791,13 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
if (!enum_type.is_fundamental()) {
IndexType* int_type =
db->Resolve(db->ToTypeId(enum_type.get_usr_hash()));
AddUse(int_type->uses, decl_spell);
AddUse(db, int_type->uses, decl_spell, fromContainer(decl->lexicalContainer));
// type is invalidated.
type = db->Resolve(type_id);
}
}
} else
UniqueAdd(type->uses, decl_spell);
UniqueAddUse(db, type->uses, decl_spell, fromContainer(decl->lexicalContainer));
switch (decl->entityInfo->templateKind) {
default:
@ -1905,7 +1945,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
case CXIdxEntity_CXXNamespace: {
ClangCursor referenced = ref->referencedEntity->cursor;
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
AddUse(ns->uses, cursor.get_spelling_range());
AddUse(db, ns->uses, cursor.get_spelling_range(), fromContainer(ref->container));
break;
}
@ -1943,7 +1983,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
var->def.kind = ClangSymbolKind::Parameter;
}
}
UniqueAdd(var->uses, loc);
UniqueAddUse(db, var->uses, loc, fromContainer(ref->container), SymbolRole::Reference);
break;
}
@ -1999,8 +2039,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db);
OnIndexReference_Function(
db, loc, ref->container->cursor, called_id, called,
is_implicit ? SymbolRole::Implicit : SymbolRole::None);
db, loc, ref->container->cursor, called_id,
SymbolRole::CalledBy |
(is_implicit ? SymbolRole::Implicit : SymbolRole::None));
// Checks if |str| starts with |start|. Ignores case.
auto str_begin = [](const char* start, const char* str) {
@ -2040,9 +2081,9 @@ 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, Id<void>(), SymbolKind::Invalid,
SymbolRole::Implicit));
AddFuncUse(&ctor->uses,
Use(loc, Id<void>(), SymbolKind::File,
SymbolRole::CalledBy | SymbolRole::Implicit));
}
}
}
@ -2078,7 +2119,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
// Foo f;
// }
//
UniqueAdd(ref_type->uses, ClangCursor(ref->cursor).get_spelling_range());
UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
break;
}
@ -2319,57 +2360,15 @@ std::string GetClangVersion() {
return ToString(clang_getClangVersion());
}
void Reflect(Reader& visitor, IndexFuncRef& value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string s = visitor.GetString();
const char* str_value = s.c_str();
if (str_value[0] == '~') {
value.role = SymbolRole::Implicit;
++str_value;
} else
value.role = SymbolRole::None;
RawId id = atol(str_value);
const char* loc_string = strchr(str_value, '@') + 1;
value.id = Id<void>(id);
value.range = Range(loc_string);
} else {
Reflect(visitor, static_cast<Reference&>(value));
}
}
void Reflect(Writer& visitor, IndexFuncRef& value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string s;
if (value.role & SymbolRole::Implicit)
s += "~";
// id.id is unsigned, special case -1 value
if (value.id.HasValue())
s += std::to_string(value.id.id);
else
s += "-1";
s += "@" + value.range.ToString();
visitor.String(s.c_str());
} else {
Reflect(visitor, static_cast<Reference&>(value));
}
}
void Reflect(Reader& visitor, Reference& value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string s = visitor.GetString();
value = Reference{};
value.range = Range(s.c_str());
auto sep = s.find('|');
if (sep == std::string::npos)
value.role = SymbolRole::Reference;
else {
char* p = const_cast<char*>(s.c_str()) + sep;
value.role = SymbolRole(strtol(p + 1, &p, 10));
value.kind = SymbolKind(strtol(p + 1, &p, 10));
value.id = Id<void>(strtol(p + 1, &p, 10));
}
std::string t = visitor.GetString();
char* s = const_cast<char*>(t.c_str());
value.range = Range(s);
s = strchr(s, '|');
value.id.id = RawId(strtol(s + 1, &s, 10));
value.kind = static_cast<SymbolKind>(strtol(s + 1, &s, 10));
value.role = static_cast<SymbolRole>(strtol(s + 1, &s, 10));
} else {
Reflect(visitor, value.range);
Reflect(visitor, value.id);
@ -2380,13 +2379,11 @@ void Reflect(Reader& visitor, Reference& value) {
void Reflect(Writer& visitor, Reference& value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string s = value.range.ToString();
if (value.role != SymbolRole::Reference ||
value.kind != SymbolKind::Invalid) {
s += '|' + std::to_string(uint8_t(value.role));
s += '|' + std::to_string(uint8_t(value.kind));
s += '|' + std::to_string(RawId(value.id));
}
visitor.String(s.c_str());
// RawId(-1) -> "-1"
s += '|' + std::to_string(static_cast<std::make_signed<RawId>::type>(value.id.id));
s += '|' + std::to_string(int(value.kind));
s += '|' + std::to_string(int(value.role));
Reflect(visitor, s);
} else {
Reflect(visitor, value.range);
Reflect(visitor, value.id);

View File

@ -57,7 +57,16 @@ struct Id {
// Invalid id.
Id() : id(-1) {}
explicit Id(RawId id) : id(id) {}
template <typename U>
// Id<T> -> Id<void> or Id<T> -> Id<T> is allowed implicitly.
template <typename U,
typename std::enable_if<std::is_void<T>::value ||
std::is_same<T, U>::value,
bool>::type = false>
Id(Id<U> o) : id(o.id) {}
template <typename U,
typename std::enable_if<!(std::is_void<T>::value ||
std::is_same<T, U>::value),
bool>::type = false>
explicit Id(Id<U> o) : id(o.id) {}
// Needed for google::dense_hash_map.
@ -107,16 +116,45 @@ struct Reference {
}
};
// NOTE: id can be -1 if the function call is not coming from a function.
struct IndexFuncRef : Reference {
// Constructors are unnecessary in C++17 p0017
IndexFuncRef() = default;
IndexFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
struct SymbolIdx {
RawId idx;
SymbolKind kind;
bool operator==(const SymbolIdx& o) const {
return kind == o.kind && idx == o.idx;
}
bool operator!=(const SymbolIdx& o) const { return !(*this == o); }
bool operator<(const SymbolIdx& o) const {
if (kind != o.kind)
return kind < o.kind;
return idx < o.idx;
}
};
MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx);
MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
// |id,kind| refer to the referenced entity.
struct SymbolRef : Reference {
SymbolRef() = default;
SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {}
SymbolRef(Reference ref) : Reference(ref) {}
SymbolRef(SymbolIdx si)
: Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {}
RawId Idx() const { return RawId(id); }
operator SymbolIdx() const { return SymbolIdx{Idx(), kind}; }
};
// Represents an occurrence of a variable/type, |id,kind| refer to the lexical
// parent.
struct Use : Reference {
Use() = default;
Use(Reference ref) : Reference(ref) {}
Use(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {}
};
void Reflect(Reader& visitor, IndexFuncRef& value);
void Reflect(Writer& visitor, IndexFuncRef& value);
void Reflect(Reader& visitor, Reference& value);
void Reflect(Writer& visitor, Reference& value);
@ -126,7 +164,6 @@ struct IndexFamily {
using TypeId = Id<IndexType>;
using VarId = Id<IndexVar>;
using Range = ::Range;
using FuncRef = IndexFuncRef;
};
template <typename F>
@ -218,7 +255,7 @@ struct IndexType {
// Every usage, useful for things like renames.
// NOTE: Do not insert directly! Use AddUsage instead.
std::vector<Reference> uses;
std::vector<Use> uses;
IndexType() {} // For serialization.
IndexType(IndexTypeId id, Usr usr);
@ -243,7 +280,7 @@ struct FuncDefDefinitionData {
std::vector<typename F::VarId> locals;
// Functions that this function calls.
std::vector<typename F::FuncRef> callees;
std::vector<SymbolRef> callees;
typename F::FileId file;
// Type which declares this one (ie, it is a method)
@ -321,7 +358,7 @@ struct IndexFunc {
//
// To get all usages, also include the ranges inside of declarations and
// def.definition_spelling.
std::vector<IndexFuncRef> callers;
std::vector<Use> uses;
IndexFunc() {} // For serialization.
IndexFunc(IndexFuncId id, Usr usr) : usr(usr), id(id) {
@ -416,7 +453,7 @@ struct IndexVar {
std::vector<Range> declarations;
// Usages.
std::vector<Reference> uses;
std::vector<Use> uses;
IndexVar() {} // For serialization.
IndexVar(IndexVarId id, Usr usr) : usr(usr), id(id) {

View File

@ -38,13 +38,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
QueryType& type = db->GetType(sym);
if (type.def)
out.result = GetLsLocations(db, working_files,
ToReference(db, type.def->parents));
ToUses(db, type.def->parents));
break;
} else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
if (func.def)
out.result = GetLsLocations(db, working_files,
ToReference(db, func.def->base));
ToUses(db, func.def->base));
break;
}
}

View File

@ -105,11 +105,8 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
// std::endl; return;
//}
if (caller.HasValue()) {
QueryFuncId func_id = caller.FuncId();
if (!func_id.HasValue())
return;
QueryFunc& call_func = db->funcs[func_id.id];
if (caller.kind == SymbolKind::Func) {
QueryFunc& call_func = db->GetFunc(caller);
if (!call_func.def)
return;
@ -137,18 +134,16 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
GetCallersForAllBaseFunctions(db, root_func);
std::vector<QueryFuncRef> derived_callers =
GetCallersForAllDerivedFunctions(db, root_func);
result.reserve(root_func.callers.size() + base_callers.size() +
result.reserve(root_func.uses.size() + base_callers.size() +
derived_callers.size());
for (QueryFuncRef caller : root_func.callers)
for (QueryFuncRef caller : root_func.uses)
handle_caller(caller, Out_CqueryCallTree::CallType::Direct);
for (QueryFuncRef caller : base_callers) {
// Do not show calls to the base function coming from this function.
if (caller.FuncId() == root)
continue;
handle_caller(caller, Out_CqueryCallTree::CallType::Base);
}
for (QueryFuncRef 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)
handle_caller(caller, Out_CqueryCallTree::CallType::Derived);

View File

@ -27,10 +27,10 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
std::vector<Reference> uses = ToReference(db, func.callers);
for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func))
std::vector<Use> uses = func.uses;
for (Use func_ref : GetCallersForAllBaseFunctions(db, func))
uses.push_back(func_ref);
for (QueryFuncRef func_ref : GetCallersForAllDerivedFunctions(db, func))
for (Use func_ref : GetCallersForAllDerivedFunctions(db, func))
uses.push_back(func_ref);
out.result = GetLsLocations(db, working_files, uses);
}

View File

@ -37,12 +37,12 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
if (sym.kind == SymbolKind::Type) {
QueryType& type = db->GetType(sym);
out.result =
GetLsLocations(db, working_files, ToReference(db, type.derived));
GetLsLocations(db, working_files, ToUses(db, type.derived));
break;
} else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
out.result =
GetLsLocations(db, working_files, ToReference(db, func.derived));
GetLsLocations(db, working_files, ToUses(db, func.derived));
break;
}
}

View File

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

View File

@ -85,7 +85,7 @@ void AddCodeLens(const char* singular,
const char* plural,
CommonCodeLensParams* common,
SymbolRef loc,
const std::vector<Reference>& uses,
const std::vector<Use>& uses,
bool force_display) {
TCodeLens code_lens;
optional<lsRange> range = GetLsRange(common->working_file, loc.range);
@ -100,7 +100,7 @@ void AddCodeLens(const char* singular,
// Add unique uses.
std::unordered_set<lsLocation> unique_uses;
for (const Reference& use : uses) {
for (Use use : uses) {
optional<lsLocation> location =
GetLsLocation(common->db, common->working_files, use);
if (!location)
@ -159,9 +159,9 @@ struct TextDocumentCodeLensHandler
AddCodeLens("ref", "refs", &common, OffsetStartColumn(sym, 0),
type.uses, true /*force_display*/);
AddCodeLens("derived", "derived", &common, OffsetStartColumn(sym, 1),
ToReference(db, type.derived), false /*force_display*/);
ToUses(db, type.derived), false /*force_display*/);
AddCodeLens("var", "vars", &common, OffsetStartColumn(sym, 2),
ToReference(db, type.instances), false /*force_display*/);
ToUses(db, type.instances), false /*force_display*/);
break;
}
case SymbolKind::Func: {
@ -183,35 +183,33 @@ struct TextDocumentCodeLensHandler
return SymbolRef(*def);
};
std::vector<QueryFuncRef> base_callers =
std::vector<Use> base_callers =
GetCallersForAllBaseFunctions(db, func);
std::vector<QueryFuncRef> derived_callers =
std::vector<Use> derived_callers =
GetCallersForAllDerivedFunctions(db, func);
if (base_callers.empty() && derived_callers.empty()) {
SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("call", "calls", &common,
OffsetStartColumn(loc, offset++),
ToReference(db, func.callers), true /*force_display*/);
OffsetStartColumn(loc, offset++), func.uses,
true /*force_display*/);
} else {
SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("direct call", "direct calls", &common,
OffsetStartColumn(loc, offset++),
ToReference(db, func.callers), false /*force_display*/);
OffsetStartColumn(loc, offset++), func.uses,
false /*force_display*/);
if (!base_callers.empty())
AddCodeLens("base call", "base calls", &common,
OffsetStartColumn(loc, offset++),
ToReference(db, base_callers),
OffsetStartColumn(loc, offset++), base_callers,
false /*force_display*/);
if (!derived_callers.empty())
AddCodeLens("derived call", "derived calls", &common,
OffsetStartColumn(loc, offset++),
ToReference(db, derived_callers),
OffsetStartColumn(loc, offset++), derived_callers,
false /*force_display*/);
}
AddCodeLens("derived", "derived", &common,
OffsetStartColumn(sym, offset++),
ToReference(db, func.derived), false /*force_display*/);
ToUses(db, func.derived), false /*force_display*/);
// "Base"
if (func.def->base.size() == 1) {
@ -238,7 +236,7 @@ struct TextDocumentCodeLensHandler
}
} else {
AddCodeLens("base", "base", &common, OffsetStartColumn(sym, 1),
ToReference(db, func.def->base),
ToUses(db, func.def->base),
false /*force_display*/);
}

View File

@ -23,17 +23,17 @@ struct Out_TextDocumentDefinition
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<Reference> GetGotoDefinitionTargets(QueryDatabase* db,
SymbolRef sym) {
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
SymbolRef sym) {
switch (sym.kind) {
// Returns GetDeclarationsOfSymbolForGotoDefinition and
// variable type definition.
case SymbolKind::Var: {
std::vector<Reference> ret =
std::vector<Use> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
QueryVar& var = db->GetVar(sym);
if (var.def && var.def->variable_type) {
std::vector<Reference> types = GetDeclarationsOfSymbolForGotoDefinition(
std::vector<Use> types = GetDeclarationsOfSymbolForGotoDefinition(
db, SymbolRef(Range(), Id<void>(var.def->variable_type->id),
SymbolKind::Type, SymbolRole::None));
ret.insert(ret.end(), types.begin(), types.end());
@ -91,8 +91,8 @@ struct TextDocumentDefinitionHandler
def_loc->range.Contains(target_line, target_column))) {
// Goto declaration.
std::vector<Reference> targets = GetGotoDefinitionTargets(db, sym);
for (Reference target : targets) {
std::vector<Use> targets = GetGotoDefinitionTargets(db, sym);
for (Use target : targets) {
optional<lsLocation> ls_target =
GetLsLocation(db, working_files, target);
if (ls_target)

View File

@ -38,9 +38,9 @@ struct TextDocumentDocumentHighlightHandler
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to highlight.
std::vector<Reference> uses = GetUsesOfSymbol(db, sym, true);
std::vector<Use> uses = GetUsesOfSymbol(db, sym, true);
out.result.reserve(uses.size());
for (Reference use : uses) {
for (Use use : uses) {
if (db->GetFileId(use) != file_id)
continue;

View File

@ -54,10 +54,10 @@ struct TextDocumentReferencesHandler
for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references.
std::vector<Reference> uses = GetUsesOfSymbol(
std::vector<Use> uses = GetUsesOfSymbol(
db, sym, request->params.context.includeDeclaration);
out.result.reserve(uses.size());
for (const Reference& use : uses) {
for (Use use : uses) {
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, use);
if (ls_location)

View File

@ -6,17 +6,17 @@ namespace {
lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Reference>& refs,
const std::vector<Use>& uses,
const std::string& new_text) {
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
for (auto& ref : refs) {
for (Use use : uses) {
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, ref);
GetLsLocation(db, working_files, use);
if (!ls_location)
continue;
QueryFileId file_id = db->GetFileId(ref);
QueryFileId file_id = db->GetFileId(use);
if (path_to_edit.find(file_id) == path_to_edit.end()) {
path_to_edit[file_id] = lsTextDocumentEdit();

View File

@ -285,7 +285,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
SymbolRole::Declaration);
add_outline(decl.spelling, id, SymbolKind::Func, SymbolRole::Declaration);
}
for (const IndexFuncRef& caller : func.callers) {
for (Use caller : 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
@ -432,30 +432,8 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
*GetQueryVarIdFromUsr(query_db, entry.second, true);
}
Reference IdMap::ToQuery(Range range, SymbolRole role) const {
return Reference{range, Id<void>(primary_file), SymbolKind:: File, role};
}
Reference IdMap::ToQuery(Reference ref) const {
switch (ref.kind) {
case SymbolKind::Invalid:
case SymbolKind::File:
ref.kind = SymbolKind::File;
ref.id = Id<void>(primary_file);
break;
case SymbolKind::Func:
ref.id = Id<void>(
cached_func_ids_.find(IndexFuncId(ref.id))->second);
break;
case SymbolKind::Type:
ref.id = Id<void>(
cached_type_ids_.find(IndexTypeId(ref.id))->second);
break;
case SymbolKind::Var:
ref.id =
Id<void>(cached_var_ids_.find(IndexVarId(ref.id))->second);
break;
}
return ref;
Use IdMap::ToQuery(Range range, SymbolRole 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());
@ -471,29 +449,42 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const {
assert(cached_var_ids_.find(id) != cached_var_ids_.end());
return QueryVarId(cached_var_ids_.find(id)->second);
}
QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const {
QueryFuncRef ret(ref.range, ref.id, ref.kind, ref.role);
Use IdMap::ToQuery(Reference ref) const {
switch (ref.kind) {
default:
break;
case SymbolKind::File:
ret.id = Id<void>(primary_file);
break;
case SymbolKind::Func:
ret.id = Id<void>(ToQuery(IndexFuncId(ref.id)));
break;
case SymbolKind::Type:
ret.id = Id<void>(ToQuery(IndexTypeId(ref.id)));
break;
case SymbolKind::Invalid:
break;
case SymbolKind::File:
ref.id = primary_file;
break;
case SymbolKind::Func:
ref.id = ToQuery(IndexFuncId(ref.id));
break;
case SymbolKind::Type:
ref.id = ToQuery(IndexTypeId(ref.id));
break;
case SymbolKind::Var:
ref.id = ToQuery(IndexVarId(ref.id));
break;
}
return ret;
return ref;
}
Reference IdMap::ToQuery(IndexFunc::Declaration decl) const {
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;
}
Use IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation.
return Reference{decl.spelling, Id<void>(primary_file), SymbolKind::File, SymbolRole::Declaration};
return Use(decl.spelling, primary_file, SymbolKind::File,
SymbolRole::Declaration);
}
std::vector<Reference> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<Reference> ret;
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, SymbolRole::Reference));
@ -610,7 +601,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
PROCESS_UPDATE_DIFF(QueryTypeId, types_derived, derived, QueryTypeId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances,
QueryVarId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Reference);
PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Use);
});
// Functions
@ -629,10 +620,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
funcs_derived.push_back(QueryFunc::DerivedUpdate(
previous_id_map.ToQuery(func->id), {},
previous_id_map.ToQuery(func->derived)));
if (!func->callers.empty())
funcs_callers.push_back(QueryFunc::CallersUpdate(
if (!func->uses.empty())
funcs_uses.push_back(QueryFunc::UsesUpdate(
previous_id_map.ToQuery(func->id), {},
previous_id_map.ToQuery(func->callers)));
previous_id_map.ToQuery(func->uses)));
}
},
/*onAdded:*/
@ -650,10 +641,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
funcs_derived.push_back(
QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id),
current_id_map.ToQuery(func->derived)));
if (!func->callers.empty())
funcs_callers.push_back(
QueryFunc::CallersUpdate(current_id_map.ToQuery(func->id),
current_id_map.ToQuery(func->callers)));
if (!func->uses.empty())
funcs_uses.push_back(
QueryFunc::UsesUpdate(current_id_map.ToQuery(func->id),
current_id_map.ToQuery(func->uses)));
},
/*onFound:*/
[this, &previous_id_map, &current_id_map](IndexFunc* previous,
@ -670,9 +661,9 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
}
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations,
Reference);
Use);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_callers, callers, QueryFuncRef);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_uses, uses, Use);
});
// Variables
@ -721,9 +712,8 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
vars_def_update.push_back(QueryVar::DefUpdate(
current->usr, std::move(*current_remapped_def)));
PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations,
Reference);
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Reference);
PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, Use);
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Use);
});
#undef PROCESS_UPDATE_DIFF
@ -747,7 +737,7 @@ void IndexUpdate::Merge(IndexUpdate&& update) {
INDEX_UPDATE_APPEND(funcs_def_update);
INDEX_UPDATE_MERGE(funcs_declarations);
INDEX_UPDATE_MERGE(funcs_derived);
INDEX_UPDATE_MERGE(funcs_callers);
INDEX_UPDATE_MERGE(funcs_uses);
INDEX_UPDATE_APPEND(vars_removed);
INDEX_UPDATE_APPEND(vars_def_update);
@ -864,7 +854,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) {
ImportOrUpdate(std::move(update->funcs_def_update));
HANDLE_MERGEABLE(funcs_declarations, declarations, funcs);
HANDLE_MERGEABLE(funcs_derived, derived, funcs);
HANDLE_MERGEABLE(funcs_callers, callers, funcs);
HANDLE_MERGEABLE(funcs_uses, uses, funcs);
RemoveUsrs(SymbolKind::Var, update->vars_removed);
ImportOrUpdate(std::move(update->vars_def_update));
@ -1053,7 +1043,7 @@ TEST_SUITE("query") {
previous.Resolve(previous.ToTypeId(HashUsr("usr1")))
->uses.push_back(Reference{Range(Position(1, 0))});
previous.Resolve(previous.ToFuncId(HashUsr("usr2")))
->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0),
->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
previous.Resolve(previous.ToVarId(HashUsr("usr3")))
->uses.push_back(Reference{Range(Position(3, 0))});
@ -1072,21 +1062,21 @@ TEST_SUITE("query") {
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
pf->callers.push_back(IndexFuncRef(Range(Position(1, 0)), Id<void>(0),
pf->uses.push_back(Use(Range(Position(1, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
cf->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0),
cf->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
IndexUpdate update = GetDelta(previous, current);
REQUIRE(update.funcs_removed == std::vector<Usr>{});
REQUIRE(update.funcs_callers.size() == 1);
REQUIRE(update.funcs_callers[0].id == QueryFuncId(0));
REQUIRE(update.funcs_callers[0].to_remove.size() == 1);
REQUIRE(update.funcs_callers[0].to_remove[0].range ==
REQUIRE(update.funcs_uses.size() == 1);
REQUIRE(update.funcs_uses[0].id == QueryFuncId(0));
REQUIRE(update.funcs_uses[0].to_remove.size() == 1);
REQUIRE(update.funcs_uses[0].to_remove[0].range ==
Range(Position(1, 0)));
REQUIRE(update.funcs_callers[0].to_add.size() == 1);
REQUIRE(update.funcs_callers[0].to_add[0].range ==
REQUIRE(update.funcs_uses[0].to_add.size() == 1);
REQUIRE(update.funcs_uses[0].to_add[0].range ==
Range(Position(2, 0)));
}
@ -1117,14 +1107,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(Range(Position(1, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
pf->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
cf->callers.push_back(IndexFuncRef(Range(Position(4, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
cf->callers.push_back(IndexFuncRef(Range(Position(5, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
pf->uses.push_back(Use(Range(Position(1, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
pf->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
cf->uses.push_back(Use(Range(Position(4, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
cf->uses.push_back(Use(Range(Position(5, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None));
QueryDatabase db;
IdMap previous_map(&db, previous.id_cache);
@ -1137,13 +1127,13 @@ TEST_SUITE("query") {
&previous_map, &current_map, &previous, &current);
db.ApplyIndexUpdate(&import_update);
REQUIRE(db.funcs[0].callers.size() == 2);
REQUIRE(db.funcs[0].callers[0].range == Range(Position(1, 0)));
REQUIRE(db.funcs[0].callers[1].range == Range(Position(2, 0)));
REQUIRE(db.funcs[0].uses.size() == 2);
REQUIRE(db.funcs[0].uses[0].range == Range(Position(1, 0)));
REQUIRE(db.funcs[0].uses[1].range == Range(Position(2, 0)));
db.ApplyIndexUpdate(&delta_update);
REQUIRE(db.funcs[0].callers.size() == 2);
REQUIRE(db.funcs[0].callers[0].range == Range(Position(4, 0)));
REQUIRE(db.funcs[0].callers[1].range == Range(Position(5, 0)));
REQUIRE(db.funcs[0].uses.size() == 2);
REQUIRE(db.funcs[0].uses[0].range == Range(Position(4, 0)));
REQUIRE(db.funcs[0].uses[1].range == Range(Position(5, 0)));
}
}

View File

@ -20,46 +20,7 @@ using QueryVarId = Id<QueryVar>;
struct IdMap;
struct SymbolIdx {
RawId idx;
SymbolKind kind;
bool operator==(const SymbolIdx& o) const {
return kind == o.kind && idx == o.idx;
}
bool operator!=(const SymbolIdx& o) const { return !(*this == o); }
bool operator<(const SymbolIdx& o) const {
if (kind != o.kind)
return kind < o.kind;
return idx < o.idx;
}
};
MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx);
MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
struct SymbolRef : Reference {
SymbolRef() = default;
SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {}
SymbolRef(Reference ref) : Reference(ref) {}
SymbolRef(SymbolIdx si)
: Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {}
RawId Idx() const { return RawId(id); }
operator SymbolIdx() const { return SymbolIdx{Idx(), kind, }; }
};
struct QueryFuncRef : Reference {
QueryFuncRef() = default;
QueryFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {}
QueryFuncId FuncId() const {
if (kind == SymbolKind::Func)
return QueryFuncId(id);
return QueryFuncId();
}
};
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.
@ -132,7 +93,6 @@ struct QueryFamily {
using TypeId = Id<QueryType>;
using VarId = Id<QueryVar>;
using Range = Reference;
using FuncRef = QueryFuncRef;
};
struct QueryFile {
@ -175,14 +135,14 @@ struct QueryType {
using DefUpdate = WithUsr<Def>;
using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>;
using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>;
using UsesUpdate = MergeableUpdate<QueryTypeId, Reference>;
using UsesUpdate = MergeableUpdate<QueryTypeId, Use>;
Usr usr;
Maybe<Id<void>> symbol_idx;
optional<Def> def;
std::vector<QueryTypeId> derived;
std::vector<QueryVarId> instances;
std::vector<Reference> uses;
std::vector<Use> uses;
explicit QueryType(const Usr& usr) : usr(usr) {}
};
@ -190,16 +150,16 @@ struct QueryType {
struct QueryFunc {
using Def = FuncDefDefinitionData<QueryFamily>;
using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Use>;
using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>;
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>;
using UsesUpdate = MergeableUpdate<QueryFuncId, Use>;
Usr usr;
Maybe<Id<void>> symbol_idx;
optional<Def> def;
std::vector<Reference> declarations;
std::vector<Use> declarations;
std::vector<QueryFuncId> derived;
std::vector<QueryFuncRef> callers;
std::vector<Use> uses;
explicit QueryFunc(const Usr& usr) : usr(usr) {}
};
@ -207,14 +167,14 @@ struct QueryFunc {
struct QueryVar {
using Def = VarDefDefinitionData<QueryFamily>;
using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>;
using UsesUpdate = MergeableUpdate<QueryVarId, Reference>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, Use>;
using UsesUpdate = MergeableUpdate<QueryVarId, Use>;
Usr usr;
Maybe<Id<void>> symbol_idx;
optional<Def> def;
std::vector<Reference> declarations;
std::vector<Reference> uses;
std::vector<Use> declarations;
std::vector<Use> uses;
explicit QueryVar(const Usr& usr) : usr(usr) {}
};
@ -250,7 +210,7 @@ struct IndexUpdate {
std::vector<QueryFunc::DefUpdate> funcs_def_update;
std::vector<QueryFunc::DeclarationsUpdate> funcs_declarations;
std::vector<QueryFunc::DerivedUpdate> funcs_derived;
std::vector<QueryFunc::CallersUpdate> funcs_callers;
std::vector<QueryFunc::UsesUpdate> funcs_uses;
// Variable updates.
std::vector<Usr> vars_removed;
@ -279,7 +239,7 @@ MAKE_REFLECT_STRUCT(IndexUpdate,
funcs_def_update,
funcs_declarations,
funcs_derived,
funcs_callers,
funcs_uses,
vars_removed,
vars_def_update,
vars_declarations,
@ -379,10 +339,10 @@ 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; };
template <> struct IndexToQuery<IndexFuncRef> { using type = QueryFuncRef; };
template <> struct IndexToQuery<Range> { using type = Reference; };
template <> struct IndexToQuery<Reference> { using type = Reference; };
template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Reference; };
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>;
};
@ -399,13 +359,14 @@ struct IdMap {
// FIXME Too verbose
// clang-format off
Reference ToQuery(Range range, SymbolRole role) const;
Reference ToQuery(Reference ref) const;
QueryTypeId ToQuery(IndexTypeId id) const;
QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const;
QueryFuncRef ToQuery(IndexFuncRef ref) const;
Reference ToQuery(IndexFunc::Declaration decl) const;
SymbolRef ToQuery(SymbolRef ref) const;
Use ToQuery(Range range, SymbolRole role) const;
Use ToQuery(Reference ref) const;
Use ToQuery(Use ref) const;
Use ToQuery(IndexFunc::Declaration decl) const;
template <typename I>
Maybe<typename IndexToQuery<I>::type> ToQuery(Maybe<I> id) const {
if (!id)
@ -420,7 +381,7 @@ struct IdMap {
ret.push_back(ToQuery(x));
return ret;
}
std::vector<Reference> ToQuery(const std::vector<Range>& a) const;
std::vector<Use> ToQuery(const std::vector<Range>& a) const;
// clang-format on

View File

@ -119,18 +119,9 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
return nullopt;
}
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs) {
std::vector<Reference> ret;
ret.reserve(refs.size());
for (auto& ref : refs)
ret.push_back(ref);
return ret;
}
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncId>& ids) {
std::vector<Reference> ret;
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryFuncId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryFunc& func = db->funcs[id.id];
@ -142,9 +133,9 @@ std::vector<Reference> ToReference(QueryDatabase* db,
return ret;
}
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryTypeId>& ids) {
std::vector<Reference> ret;
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryTypeId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryType& type = db->types[id.id];
@ -154,9 +145,8 @@ std::vector<Reference> ToReference(QueryDatabase* db,
return ret;
}
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryVarId>& ids) {
std::vector<Reference> ret;
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryVar& var = db->vars[id.id];
@ -168,13 +158,13 @@ std::vector<Reference> ToReference(QueryDatabase* db,
return ret;
}
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
SymbolRef sym,
bool include_decl) {
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
SymbolRef sym,
bool include_decl) {
switch (sym.kind) {
case SymbolKind::Type: {
QueryType& type = db->types[sym.Idx()];
std::vector<Reference> ret = type.uses;
std::vector<Use> ret = type.uses;
if (include_decl && type.def && type.def->definition_spelling)
ret.push_back(*type.def->definition_spelling);
return ret;
@ -182,7 +172,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
case SymbolKind::Func: {
// TODO: the vector allocation could be avoided.
QueryFunc& func = db->funcs[sym.Idx()];
std::vector<Reference> ret = ToReference(db, func.callers);
std::vector<Use> ret = func.uses;
if (include_decl) {
AddRange(&ret, func.declarations);
if (func.def && func.def->definition_spelling)
@ -192,7 +182,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
}
case SymbolKind::Var: {
QueryVar& var = db->vars[sym.Idx()];
std::vector<Reference> ret = var.uses;
std::vector<Use> ret = var.uses;
if (include_decl) {
if (var.def && var.def->definition_spelling)
ret.push_back(*var.def->definition_spelling);
@ -208,7 +198,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
}
}
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
SymbolRef sym) {
switch (sym.kind) {
@ -238,7 +228,7 @@ std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
// Check self.
if (!root.callers.empty())
if (!root.uses.empty())
return true;
// Check for base calls.
@ -249,7 +239,7 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
while (!queue.empty()) {
QueryFunc& func = *queue.front();
queue.pop();
if (!func.callers.empty())
if (!func.uses.empty())
return true;
if (func.def)
EachWithGen<QueryFunc>(db->funcs, func.def->base, [&](QueryFunc& func1) {
@ -264,7 +254,7 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
while (!queue.empty()) {
QueryFunc& func = *queue.front();
queue.pop();
if (!func.callers.empty())
if (!func.uses.empty())
return true;
EachWithGen<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) {
queue.push(&func1);
@ -274,9 +264,9 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
return false;
}
std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<QueryFuncRef> callers;
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<Use> callers;
if (!root.def)
return callers;
@ -288,7 +278,7 @@ std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& func = *queue.front();
queue.pop();
AddRange(&callers, func.callers);
AddRange(&callers, func.uses);
if (func.def)
EachWithGen<QueryFunc>(db->funcs, func.def->base, [&](QueryFunc& func1) {
queue.push(&func1);
@ -298,9 +288,9 @@ std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
return callers;
}
std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<QueryFuncRef> callers;
std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<Use> callers;
std::queue<QueryFunc*> queue;
EachWithGen<QueryFunc>(db->funcs, root.derived, [&](QueryFunc& func) {
@ -314,7 +304,7 @@ std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db,
EachWithGen<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) {
queue.push(&func1);
});
AddRange(&callers, func.callers);
AddRange(&callers, func.uses);
}
return callers;
@ -403,11 +393,11 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
std::vector<lsLocation> GetLsLocations(
QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Reference>& refs) {
const std::vector<Use>& uses) {
std::unordered_set<lsLocation> unique_locations;
for (Reference ref : refs) {
for (Use use : uses) {
optional<lsLocation> location =
GetLsLocation(db, working_files, ref);
GetLsLocation(db, working_files, use);
if (!location)
continue;
unique_locations.insert(*location);

View File

@ -15,27 +15,25 @@ Maybe<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym);
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
SymbolRef sym);
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs);
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncId>& ids);
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryTypeId>& ids);
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryVarId>& ids);
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryFuncId>& ids);
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryTypeId>& ids);
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryVarId>& ids);
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
SymbolRef sym,
bool include_decl);
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
SymbolRef sym,
bool include_decl);
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
SymbolRef sym);
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& root);
std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& root);
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& root);
std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& root);
optional<lsPosition> GetLsPosition(WorkingFile* working_file,
const Position& position);
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location);
@ -50,7 +48,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
std::vector<lsLocation> GetLsLocations(
QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Reference>& refs);
const std::vector<Use>& refs);
// Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files,

View File

@ -240,7 +240,7 @@ void Reflect(TVisitor& visitor, IndexFunc& value) {
REFLECT_MEMBER2("base", value.def.base);
REFLECT_MEMBER2("derived", value.derived);
REFLECT_MEMBER2("locals", value.def.locals);
REFLECT_MEMBER2("callers", value.callers);
REFLECT_MEMBER2("uses", value.uses);
REFLECT_MEMBER2("callees", value.def.callees);
REFLECT_MEMBER_END();
}