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)); return ClangCursor(clang_getCursorDefinition(cx_cursor));
} }
ClangCursor ClangCursor::get_lexical_parent() const {
return ClangCursor(clang_getCursorLexicalParent(cx_cursor));
}
ClangCursor ClangCursor::get_semantic_parent() const { ClangCursor ClangCursor::get_semantic_parent() const {
return ClangCursor(clang_getCursorSemanticParent(cx_cursor)); return ClangCursor(clang_getCursorSemanticParent(cx_cursor));
} }

View File

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

View File

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

View File

@ -57,7 +57,16 @@ struct Id {
// Invalid id. // Invalid id.
Id() : id(-1) {} Id() : id(-1) {}
explicit Id(RawId id) : id(id) {} 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) {} explicit Id(Id<U> o) : id(o.id) {}
// Needed for google::dense_hash_map. // 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 SymbolIdx {
struct IndexFuncRef : Reference { RawId idx;
// Constructors are unnecessary in C++17 p0017 SymbolKind kind;
IndexFuncRef() = default;
IndexFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) 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} {} : 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(Reader& visitor, Reference& value);
void Reflect(Writer& visitor, Reference& value); void Reflect(Writer& visitor, Reference& value);
@ -126,7 +164,6 @@ struct IndexFamily {
using TypeId = Id<IndexType>; using TypeId = Id<IndexType>;
using VarId = Id<IndexVar>; using VarId = Id<IndexVar>;
using Range = ::Range; using Range = ::Range;
using FuncRef = IndexFuncRef;
}; };
template <typename F> template <typename F>
@ -218,7 +255,7 @@ struct IndexType {
// Every usage, useful for things like renames. // Every usage, useful for things like renames.
// NOTE: Do not insert directly! Use AddUsage instead. // NOTE: Do not insert directly! Use AddUsage instead.
std::vector<Reference> uses; std::vector<Use> uses;
IndexType() {} // For serialization. IndexType() {} // For serialization.
IndexType(IndexTypeId id, Usr usr); IndexType(IndexTypeId id, Usr usr);
@ -243,7 +280,7 @@ struct FuncDefDefinitionData {
std::vector<typename F::VarId> locals; std::vector<typename F::VarId> locals;
// Functions that this function calls. // Functions that this function calls.
std::vector<typename F::FuncRef> callees; std::vector<SymbolRef> callees;
typename F::FileId file; typename F::FileId file;
// Type which declares this one (ie, it is a method) // 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 // To get all usages, also include the ranges inside of declarations and
// def.definition_spelling. // def.definition_spelling.
std::vector<IndexFuncRef> callers; std::vector<Use> uses;
IndexFunc() {} // For serialization. IndexFunc() {} // For serialization.
IndexFunc(IndexFuncId id, Usr usr) : usr(usr), id(id) { IndexFunc(IndexFuncId id, Usr usr) : usr(usr), id(id) {
@ -416,7 +453,7 @@ struct IndexVar {
std::vector<Range> declarations; std::vector<Range> declarations;
// Usages. // Usages.
std::vector<Reference> uses; std::vector<Use> uses;
IndexVar() {} // For serialization. IndexVar() {} // For serialization.
IndexVar(IndexVarId id, Usr usr) : usr(usr), id(id) { 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); QueryType& type = db->GetType(sym);
if (type.def) if (type.def)
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files,
ToReference(db, type.def->parents)); ToUses(db, type.def->parents));
break; break;
} else if (sym.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
if (func.def) if (func.def)
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files,
ToReference(db, func.def->base)); ToUses(db, func.def->base));
break; break;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -285,7 +285,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
SymbolRole::Declaration); SymbolRole::Declaration);
add_outline(decl.spelling, id, SymbolKind::Func, 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 // Make ranges of implicit function calls larger (spanning one more column
// to the left/right). This is hacky but useful. e.g. // to the left/right). This is hacky but useful. e.g.
// textDocument/definition on the space/semicolon in `A a;` or `return // 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); *GetQueryVarIdFromUsr(query_db, entry.second, true);
} }
Reference IdMap::ToQuery(Range range, SymbolRole role) const { Use IdMap::ToQuery(Range range, SymbolRole role) const {
return Reference{range, Id<void>(primary_file), SymbolKind:: File, role}; return Use(range, 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;
} }
QueryTypeId IdMap::ToQuery(IndexTypeId id) const { QueryTypeId IdMap::ToQuery(IndexTypeId id) const {
assert(cached_type_ids_.find(id) != cached_type_ids_.end()); 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()); assert(cached_var_ids_.find(id) != cached_var_ids_.end());
return QueryVarId(cached_var_ids_.find(id)->second); 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) { switch (ref.kind) {
default: case SymbolKind::Invalid:
break; break;
case SymbolKind::File: case SymbolKind::File:
ret.id = Id<void>(primary_file); ref.id = primary_file;
break; break;
case SymbolKind::Func: case SymbolKind::Func:
ret.id = Id<void>(ToQuery(IndexFuncId(ref.id))); ref.id = ToQuery(IndexFuncId(ref.id));
break; break;
case SymbolKind::Type: case SymbolKind::Type:
ret.id = Id<void>(ToQuery(IndexTypeId(ref.id))); ref.id = ToQuery(IndexTypeId(ref.id));
break; 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. // 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<Use> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<Reference> ret; std::vector<Use> ret;
ret.reserve(a.size()); ret.reserve(a.size());
for (auto& x : a) for (auto& x : a)
ret.push_back(ToQuery(x, SymbolRole::Reference)); 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_derived, derived, QueryTypeId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances, PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances,
QueryVarId); QueryVarId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Reference); PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Use);
}); });
// Functions // Functions
@ -629,10 +620,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
funcs_derived.push_back(QueryFunc::DerivedUpdate( funcs_derived.push_back(QueryFunc::DerivedUpdate(
previous_id_map.ToQuery(func->id), {}, previous_id_map.ToQuery(func->id), {},
previous_id_map.ToQuery(func->derived))); previous_id_map.ToQuery(func->derived)));
if (!func->callers.empty()) if (!func->uses.empty())
funcs_callers.push_back(QueryFunc::CallersUpdate( funcs_uses.push_back(QueryFunc::UsesUpdate(
previous_id_map.ToQuery(func->id), {}, previous_id_map.ToQuery(func->id), {},
previous_id_map.ToQuery(func->callers))); previous_id_map.ToQuery(func->uses)));
} }
}, },
/*onAdded:*/ /*onAdded:*/
@ -650,10 +641,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
funcs_derived.push_back( funcs_derived.push_back(
QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id), QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id),
current_id_map.ToQuery(func->derived))); current_id_map.ToQuery(func->derived)));
if (!func->callers.empty()) if (!func->uses.empty())
funcs_callers.push_back( funcs_uses.push_back(
QueryFunc::CallersUpdate(current_id_map.ToQuery(func->id), QueryFunc::UsesUpdate(current_id_map.ToQuery(func->id),
current_id_map.ToQuery(func->callers))); current_id_map.ToQuery(func->uses)));
}, },
/*onFound:*/ /*onFound:*/
[this, &previous_id_map, &current_id_map](IndexFunc* previous, [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, PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations,
Reference); Use);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId); 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 // Variables
@ -721,9 +712,8 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
vars_def_update.push_back(QueryVar::DefUpdate( vars_def_update.push_back(QueryVar::DefUpdate(
current->usr, std::move(*current_remapped_def))); current->usr, std::move(*current_remapped_def)));
PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, Use);
Reference); PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Use);
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Reference);
}); });
#undef PROCESS_UPDATE_DIFF #undef PROCESS_UPDATE_DIFF
@ -747,7 +737,7 @@ void IndexUpdate::Merge(IndexUpdate&& update) {
INDEX_UPDATE_APPEND(funcs_def_update); INDEX_UPDATE_APPEND(funcs_def_update);
INDEX_UPDATE_MERGE(funcs_declarations); INDEX_UPDATE_MERGE(funcs_declarations);
INDEX_UPDATE_MERGE(funcs_derived); INDEX_UPDATE_MERGE(funcs_derived);
INDEX_UPDATE_MERGE(funcs_callers); INDEX_UPDATE_MERGE(funcs_uses);
INDEX_UPDATE_APPEND(vars_removed); INDEX_UPDATE_APPEND(vars_removed);
INDEX_UPDATE_APPEND(vars_def_update); INDEX_UPDATE_APPEND(vars_def_update);
@ -864,7 +854,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) {
ImportOrUpdate(std::move(update->funcs_def_update)); ImportOrUpdate(std::move(update->funcs_def_update));
HANDLE_MERGEABLE(funcs_declarations, declarations, funcs); HANDLE_MERGEABLE(funcs_declarations, declarations, funcs);
HANDLE_MERGEABLE(funcs_derived, derived, 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); RemoveUsrs(SymbolKind::Var, update->vars_removed);
ImportOrUpdate(std::move(update->vars_def_update)); ImportOrUpdate(std::move(update->vars_def_update));
@ -1053,7 +1043,7 @@ TEST_SUITE("query") {
previous.Resolve(previous.ToTypeId(HashUsr("usr1"))) previous.Resolve(previous.ToTypeId(HashUsr("usr1")))
->uses.push_back(Reference{Range(Position(1, 0))}); ->uses.push_back(Reference{Range(Position(1, 0))});
previous.Resolve(previous.ToFuncId(HashUsr("usr2"))) 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)); SymbolKind::Func, SymbolRole::None));
previous.Resolve(previous.ToVarId(HashUsr("usr3"))) previous.Resolve(previous.ToVarId(HashUsr("usr3")))
->uses.push_back(Reference{Range(Position(3, 0))}); ->uses.push_back(Reference{Range(Position(3, 0))});
@ -1072,21 +1062,21 @@ TEST_SUITE("query") {
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
IndexFunc* cf = current.Resolve(current.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)); 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)); SymbolKind::Func, SymbolRole::None));
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
REQUIRE(update.funcs_removed == std::vector<Usr>{}); REQUIRE(update.funcs_removed == std::vector<Usr>{});
REQUIRE(update.funcs_callers.size() == 1); REQUIRE(update.funcs_uses.size() == 1);
REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); REQUIRE(update.funcs_uses[0].id == QueryFuncId(0));
REQUIRE(update.funcs_callers[0].to_remove.size() == 1); REQUIRE(update.funcs_uses[0].to_remove.size() == 1);
REQUIRE(update.funcs_callers[0].to_remove[0].range == REQUIRE(update.funcs_uses[0].to_remove[0].range ==
Range(Position(1, 0))); Range(Position(1, 0)));
REQUIRE(update.funcs_callers[0].to_add.size() == 1); REQUIRE(update.funcs_uses[0].to_add.size() == 1);
REQUIRE(update.funcs_callers[0].to_add[0].range == REQUIRE(update.funcs_uses[0].to_add[0].range ==
Range(Position(2, 0))); Range(Position(2, 0)));
} }
@ -1117,14 +1107,14 @@ TEST_SUITE("query") {
IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr")));
IndexFunc* cf = current.Resolve(current.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)); SymbolKind::Func, SymbolRole::None));
pf->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0), pf->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None)); SymbolKind::Func, SymbolRole::None));
cf->callers.push_back(IndexFuncRef(Range(Position(4, 0)), Id<void>(0), cf->uses.push_back(Use(Range(Position(4, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None)); SymbolKind::Func, SymbolRole::None));
cf->callers.push_back(IndexFuncRef(Range(Position(5, 0)), Id<void>(0), cf->uses.push_back(Use(Range(Position(5, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None)); SymbolKind::Func, SymbolRole::None));
QueryDatabase db; QueryDatabase db;
IdMap previous_map(&db, previous.id_cache); IdMap previous_map(&db, previous.id_cache);
@ -1137,13 +1127,13 @@ TEST_SUITE("query") {
&previous_map, &current_map, &previous, &current); &previous_map, &current_map, &previous, &current);
db.ApplyIndexUpdate(&import_update); db.ApplyIndexUpdate(&import_update);
REQUIRE(db.funcs[0].callers.size() == 2); REQUIRE(db.funcs[0].uses.size() == 2);
REQUIRE(db.funcs[0].callers[0].range == Range(Position(1, 0))); REQUIRE(db.funcs[0].uses[0].range == Range(Position(1, 0)));
REQUIRE(db.funcs[0].callers[1].range == Range(Position(2, 0))); REQUIRE(db.funcs[0].uses[1].range == Range(Position(2, 0)));
db.ApplyIndexUpdate(&delta_update); db.ApplyIndexUpdate(&delta_update);
REQUIRE(db.funcs[0].callers.size() == 2); REQUIRE(db.funcs[0].uses.size() == 2);
REQUIRE(db.funcs[0].callers[0].range == Range(Position(4, 0))); REQUIRE(db.funcs[0].uses[0].range == Range(Position(4, 0)));
REQUIRE(db.funcs[0].callers[1].range == Range(Position(5, 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 IdMap;
struct SymbolIdx { using QueryFuncRef = Use;
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();
}
};
// There are two sources of reindex updates: the (single) definition of a // There are two sources of reindex updates: the (single) definition of a
// symbol has changed, or one of many users of the symbol has changed. // symbol has changed, or one of many users of the symbol has changed.
@ -132,7 +93,6 @@ struct QueryFamily {
using TypeId = Id<QueryType>; using TypeId = Id<QueryType>;
using VarId = Id<QueryVar>; using VarId = Id<QueryVar>;
using Range = Reference; using Range = Reference;
using FuncRef = QueryFuncRef;
}; };
struct QueryFile { struct QueryFile {
@ -175,14 +135,14 @@ struct QueryType {
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>; using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>;
using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>; using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>;
using UsesUpdate = MergeableUpdate<QueryTypeId, Reference>; using UsesUpdate = MergeableUpdate<QueryTypeId, Use>;
Usr usr; Usr usr;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<QueryTypeId> derived; std::vector<QueryTypeId> derived;
std::vector<QueryVarId> instances; std::vector<QueryVarId> instances;
std::vector<Reference> uses; std::vector<Use> uses;
explicit QueryType(const Usr& usr) : usr(usr) {} explicit QueryType(const Usr& usr) : usr(usr) {}
}; };
@ -190,16 +150,16 @@ struct QueryType {
struct QueryFunc { struct QueryFunc {
using Def = FuncDefDefinitionData<QueryFamily>; using Def = FuncDefDefinitionData<QueryFamily>;
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>; using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Use>;
using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>; using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>;
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>; using UsesUpdate = MergeableUpdate<QueryFuncId, Use>;
Usr usr; Usr usr;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<Reference> declarations; std::vector<Use> declarations;
std::vector<QueryFuncId> derived; std::vector<QueryFuncId> derived;
std::vector<QueryFuncRef> callers; std::vector<Use> uses;
explicit QueryFunc(const Usr& usr) : usr(usr) {} explicit QueryFunc(const Usr& usr) : usr(usr) {}
}; };
@ -207,14 +167,14 @@ struct QueryFunc {
struct QueryVar { struct QueryVar {
using Def = VarDefDefinitionData<QueryFamily>; using Def = VarDefDefinitionData<QueryFamily>;
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>; using DeclarationsUpdate = MergeableUpdate<QueryVarId, Use>;
using UsesUpdate = MergeableUpdate<QueryVarId, Reference>; using UsesUpdate = MergeableUpdate<QueryVarId, Use>;
Usr usr; Usr usr;
Maybe<Id<void>> symbol_idx; Maybe<Id<void>> symbol_idx;
optional<Def> def; optional<Def> def;
std::vector<Reference> declarations; std::vector<Use> declarations;
std::vector<Reference> uses; std::vector<Use> uses;
explicit QueryVar(const Usr& usr) : usr(usr) {} explicit QueryVar(const Usr& usr) : usr(usr) {}
}; };
@ -250,7 +210,7 @@ struct IndexUpdate {
std::vector<QueryFunc::DefUpdate> funcs_def_update; std::vector<QueryFunc::DefUpdate> funcs_def_update;
std::vector<QueryFunc::DeclarationsUpdate> funcs_declarations; std::vector<QueryFunc::DeclarationsUpdate> funcs_declarations;
std::vector<QueryFunc::DerivedUpdate> funcs_derived; std::vector<QueryFunc::DerivedUpdate> funcs_derived;
std::vector<QueryFunc::CallersUpdate> funcs_callers; std::vector<QueryFunc::UsesUpdate> funcs_uses;
// Variable updates. // Variable updates.
std::vector<Usr> vars_removed; std::vector<Usr> vars_removed;
@ -279,7 +239,7 @@ MAKE_REFLECT_STRUCT(IndexUpdate,
funcs_def_update, funcs_def_update,
funcs_declarations, funcs_declarations,
funcs_derived, funcs_derived,
funcs_callers, funcs_uses,
vars_removed, vars_removed,
vars_def_update, vars_def_update,
vars_declarations, vars_declarations,
@ -379,10 +339,10 @@ template <> struct IndexToQuery<IndexFileId> { using type = QueryFileId; };
template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; }; template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; };
template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; }; template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; };
template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; }; template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; };
template <> struct IndexToQuery<IndexFuncRef> { using type = QueryFuncRef; }; template <> struct IndexToQuery<Use> { using type = Use; };
template <> struct IndexToQuery<Range> { using type = Reference; }; template <> struct IndexToQuery<SymbolRef> { using type = SymbolRef; };
template <> struct IndexToQuery<Reference> { using type = Reference; }; template <> struct IndexToQuery<Range> { using type = Use; };
template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Reference; }; template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Use; };
template <typename I> struct IndexToQuery<optional<I>> { template <typename I> struct IndexToQuery<optional<I>> {
using type = optional<typename IndexToQuery<I>::type>; using type = optional<typename IndexToQuery<I>::type>;
}; };
@ -399,13 +359,14 @@ struct IdMap {
// FIXME Too verbose // FIXME Too verbose
// clang-format off // clang-format off
Reference ToQuery(Range range, SymbolRole role) const;
Reference ToQuery(Reference ref) const;
QueryTypeId ToQuery(IndexTypeId id) const; QueryTypeId ToQuery(IndexTypeId id) const;
QueryFuncId ToQuery(IndexFuncId id) const; QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const; QueryVarId ToQuery(IndexVarId id) const;
QueryFuncRef ToQuery(IndexFuncRef ref) const; SymbolRef ToQuery(SymbolRef ref) const;
Reference ToQuery(IndexFunc::Declaration decl) 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> template <typename I>
Maybe<typename IndexToQuery<I>::type> ToQuery(Maybe<I> id) const { Maybe<typename IndexToQuery<I>::type> ToQuery(Maybe<I> id) const {
if (!id) if (!id)
@ -420,7 +381,7 @@ struct IdMap {
ret.push_back(ToQuery(x)); ret.push_back(ToQuery(x));
return ret; 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 // clang-format on

View File

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

View File

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

View File

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