mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-31 09:50:26 +00:00
Derive SymbolRef,Use from Reference and add lexical container to func/var/type uses
This commit is contained in:
parent
a50bff0b24
commit
420e84329b
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
309
src/indexer.cc
309
src/indexer.cc
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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*/);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
152
src/query.cc
152
src/query.cc
@ -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, ¤t_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, ¤t_map, &previous, ¤t);
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
85
src/query.h
85
src/query.h
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user