Add lexical parent to Type/Var and definition_spelling->spell, definition_extent->extent

This commit is contained in:
Fangrui Song 2018-02-10 20:01:10 -08:00
parent 3ba9209eea
commit 9a6cbafa04
17 changed files with 253 additions and 227 deletions

View File

@ -66,7 +66,7 @@ enum class StorageClass : uint8_t {
}; };
MAKE_REFLECT_TYPE_PROXY(StorageClass); MAKE_REFLECT_TYPE_PROXY(StorageClass);
enum class SymbolRole : uint8_t { enum class Role : uint8_t {
None = 0, None = 0,
Declaration = 1 << 0, Declaration = 1 << 0,
Definition = 1 << 1, Definition = 1 << 1,
@ -75,15 +75,15 @@ enum class SymbolRole : uint8_t {
ChildOf = 1 << 4, ChildOf = 1 << 4,
BaseOf = 1 << 5, BaseOf = 1 << 5,
CalledBy = 1 << 6, Call = 1 << 6,
}; };
MAKE_REFLECT_TYPE_PROXY(SymbolRole); MAKE_REFLECT_TYPE_PROXY(Role);
MAKE_ENUM_HASHABLE(SymbolRole); MAKE_ENUM_HASHABLE(Role);
inline uint8_t operator&(SymbolRole lhs, SymbolRole rhs) { inline uint8_t operator&(Role lhs, Role rhs) {
return uint8_t(lhs) & uint8_t(rhs); return uint8_t(lhs) & uint8_t(rhs);
} }
inline SymbolRole operator|(SymbolRole lhs, SymbolRole rhs) { inline Role operator|(Role lhs, Role rhs) {
return SymbolRole(uint8_t(lhs) | uint8_t(rhs)); return Role(uint8_t(lhs) | uint8_t(rhs));
} }

View File

@ -434,6 +434,29 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu,
return result; return result;
} }
void SetUse(IndexFile* db, Maybe<Use>* def, Range range, ClangCursor lex_parent, Role role) {
switch (GetSymbolKind(lex_parent.get_kind())) {
default:
*def = Use(range, Id<void>(), SymbolKind::File, role);
break;
case SymbolKind::Func: {
IndexFuncId id = db->ToFuncId(lex_parent.cx_cursor);
*def = Use(range, id, SymbolKind::Func, Role::Definition);
break;
}
case SymbolKind::Type: {
IndexTypeId id = db->ToTypeId(lex_parent.cx_cursor);
*def = Use(range, id, SymbolKind::Type, Role::Definition);
break;
}
case SymbolKind::Var: {
IndexVarId id = db->ToVarId(lex_parent.cx_cursor);
*def = Use(range, id, SymbolKind::Var, Role::Definition);
break;
}
}
}
void SetTypeName(IndexType* type, void SetTypeName(IndexType* type,
const ClangCursor& cursor, const ClangCursor& cursor,
const CXIdxContainerInfo* container, const CXIdxContainerInfo* container,
@ -587,7 +610,7 @@ void OnIndexReference_Function(IndexFile* db,
Range loc, Range loc,
ClangCursor parent_cursor, ClangCursor parent_cursor,
IndexFuncId called_id, IndexFuncId called_id,
SymbolRole role) { Role role) {
switch (GetSymbolKind(parent_cursor.get_kind())) { switch (GetSymbolKind(parent_cursor.get_kind())) {
case SymbolKind::Func: { case SymbolKind::Func: {
IndexFunc* parent = db->Resolve(db->ToFuncId(parent_cursor.cx_cursor)); IndexFunc* parent = db->Resolve(db->ToFuncId(parent_cursor.cx_cursor));
@ -615,8 +638,8 @@ void OnIndexReference_Function(IndexFile* db,
} // namespace } // namespace
// static // static
const int IndexFile::kMajorVersion = 11; const int IndexFile::kMajorVersion = 12;
const int IndexFile::kMinorVersion = 3; const int IndexFile::kMinorVersion = 0;
IndexFile::IndexFile(const std::string& path, const std::string& contents) IndexFile::IndexFile(const std::string& path, const std::string& contents)
: id_cache(path), path(path), file_contents(contents) {} : id_cache(path), path(path), file_contents(contents) {}
@ -699,14 +722,14 @@ 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<Use>& values, Range value) { void AddUse(std::vector<Use>& values, Range value) {
values.push_back( values.push_back(
Use(value, Id<void>(), SymbolKind::File, SymbolRole::Reference)); Use(value, Id<void>(), SymbolKind::File, Role::Reference));
} }
void AddUse(IndexFile* db, void AddUse(IndexFile* db,
std::vector<Use>& uses, std::vector<Use>& uses,
Range range, Range range,
ClangCursor parent, ClangCursor parent,
SymbolRole role = SymbolRole::Reference) { Role role = Role::Reference) {
switch (GetSymbolKind(parent.get_kind())) { switch (GetSymbolKind(parent.get_kind())) {
default: default:
uses.push_back(Use(range, Id<void>(), SymbolKind::File, role)); uses.push_back(Use(range, Id<void>(), SymbolKind::File, role));
@ -730,7 +753,7 @@ void AddUseSpell(IndexFile* db,
std::vector<Use>& uses, std::vector<Use>& uses,
ClangCursor cursor) { ClangCursor cursor) {
AddUse(db, uses, cursor.get_spelling_range(), AddUse(db, uses, cursor.get_spelling_range(),
cursor.get_lexical_parent().cx_cursor, SymbolRole::Reference); cursor.get_lexical_parent().cx_cursor, Role::Reference);
} }
template <typename... Args> template <typename... Args>
@ -1197,9 +1220,11 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
"#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent); "#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent);
var_def->def.kind = ClangSymbolKind::Macro; var_def->def.kind = ClangSymbolKind::Macro;
var_def->def.comments = cursor.get_comments(); var_def->def.comments = cursor.get_comments();
var_def->def.definition_spelling = decl_loc_spelling; ClangCursor lex_parent;
var_def->def.definition_extent = SetUse(db, &var_def->def.spell, decl_loc_spelling, lex_parent,
ResolveCXSourceRange(cx_extent, nullptr); Role::Definition);
SetUse(db, &var_def->def.extent,
ResolveCXSourceRange(cx_extent, nullptr), lex_parent, Role::None);
} else } else
UniqueAddUse(db, var_def->uses, decl_loc_spelling, parent); UniqueAddUse(db, var_def->uses, decl_loc_spelling, parent);
@ -1232,13 +1257,13 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
case CXCursor_DeclRefExpr: { case CXCursor_DeclRefExpr: {
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor); ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) { if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) {
IndexVar* ref_index = IndexVar* ref_var =
db->Resolve(db->ToVarId(ref_cursor.get_usr_hash())); db->Resolve(db->ToVarId(ref_cursor.get_usr_hash()));
if (ref_index->def.detailed_name.empty()) { if (ref_var->def.detailed_name.empty()) {
ref_index->def.definition_spelling = ref_cursor.get_spelling_range(); SetUse(db, &ref_var->def.spell, ref_cursor.get_spelling_range(), parent, Role::Definition);
ref_index->def.definition_extent = ref_cursor.get_extent(); SetUse(db, &ref_var->def.extent, ref_cursor.get_extent(), parent, Role::None);
ref_index->def.kind = ClangSymbolKind::Parameter; ref_var->def.kind = ClangSymbolKind::Parameter;
SetVarDetail(ref_index, ref_cursor.get_spelling(), ref_cursor, SetVarDetail(ref_var, ref_cursor.get_spelling(), ref_cursor,
nullptr, true, db, param); nullptr, true, db, param);
ClangType ref_type = clang_getCursorType(ref_cursor.cx_cursor); ClangType ref_type = clang_getCursorType(ref_cursor.cx_cursor);
@ -1254,7 +1279,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
ref_cursor.get_lexical_parent()); ref_cursor.get_lexical_parent());
} }
} }
UniqueAddUseSpell(db, ref_index->uses, cursor); UniqueAddUseSpell(db, ref_var->uses, cursor);
} }
break; break;
} }
@ -1270,7 +1295,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash()); IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash());
OnIndexReference_Function(db, cursor.get_spelling_range(), OnIndexReference_Function(db, cursor.get_spelling_range(),
data->container, called_id, data->container, called_id,
SymbolRole::CalledBy); Role::Call);
break; break;
} }
} }
@ -1288,8 +1313,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
// CXCursor_TranslationUnit, but not (confirm this) by visiting // CXCursor_TranslationUnit, but not (confirm this) by visiting
// {Class,Function}Template. Thus we need to initialize it here. // {Class,Function}Template. Thus we need to initialize it here.
if (ref_index->def.detailed_name.empty()) { if (ref_index->def.detailed_name.empty()) {
ref_index->def.definition_spelling = ref_cursor.get_spelling_range(); SetUse(db, &ref_index->def.spell, ref_cursor.get_spelling_range(), parent, Role::Definition);
ref_index->def.definition_extent = ref_cursor.get_extent(); SetUse(db, &ref_index->def.extent, ref_cursor.get_extent(), parent, Role::None);
#if CINDEX_HAVE_PRETTY #if CINDEX_HAVE_PRETTY
ref_index->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor); ref_index->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor);
#else #else
@ -1314,8 +1339,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
// CXCursor_TranslationUnit, but not (confirm this) by visiting // CXCursor_TranslationUnit, but not (confirm this) by visiting
// {Class,Function}Template. Thus we need to initialize it here. // {Class,Function}Template. Thus we need to initialize it here.
if (ref_index->def.detailed_name.empty()) { if (ref_index->def.detailed_name.empty()) {
ref_index->def.definition_spelling = ref_cursor.get_spelling_range(); SetUse(db, &ref_index->def.spell, ref_cursor.get_spelling_range(), parent, Role::Definition);
ref_index->def.definition_extent = ref_cursor.get_extent(); SetUse(db, &ref_index->def.extent, ref_cursor.get_extent(), parent, Role::None);
#if CINDEX_HAVE_PRETTY #if CINDEX_HAVE_PRETTY
ref_index->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor); ref_index->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor);
#else #else
@ -1410,7 +1435,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
return; return;
// The language of this declaration // The language of this declaration
LanguageId decl_lang = [decl]() { LanguageId decl_lang = [&decl]() {
switch (clang_getCursorLanguage(decl->cursor)) { switch (clang_getCursorLanguage(decl->cursor)) {
case CXLanguage_C: case CXLanguage_C:
return LanguageId::C; return LanguageId::C;
@ -1429,6 +1454,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
} }
NamespaceHelper* ns = &param->ns; NamespaceHelper* ns = &param->ns;
ClangCursor lex_parent(fromContainer(decl->lexicalContainer));
switch (decl->entityInfo->kind) { switch (decl->entityInfo->kind) {
case CXIdxEntity_CXXNamespace: { case CXIdxEntity_CXXNamespace: {
@ -1440,8 +1466,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
if (ns->def.detailed_name.empty()) { if (ns->def.detailed_name.empty()) {
SetTypeName(ns, decl_cursor, decl->semanticContainer, SetTypeName(ns, decl_cursor, decl->semanticContainer,
decl->entityInfo->name, param); decl->entityInfo->name, param);
ns->def.definition_spelling = decl_spell; SetUse(db, &ns->def.spell, decl_spell, lex_parent, Role::Definition);
ns->def.definition_extent = decl_cursor.get_extent(); SetUse(db, &ns->def.extent, decl_cursor.get_extent(), lex_parent, Role::None);
if (decl->semanticContainer) { if (decl->semanticContainer) {
IndexTypeId parent_id = db->ToTypeId( IndexTypeId parent_id = db->ToTypeId(
ClangCursor(decl->semanticContainer->cursor).get_usr_hash()); ClangCursor(decl->semanticContainer->cursor).get_usr_hash());
@ -1487,8 +1513,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
//} //}
if (decl->isDefinition) { if (decl->isDefinition) {
var->def.definition_spelling = decl_spell; SetUse(db, &var->def.spell, decl_spell, lex_parent, Role::Definition);
var->def.definition_extent = decl_cursor.get_extent(); SetUse(db, &var->def.extent, decl_cursor.get_extent(), lex_parent, Role::None);
} else { } else {
var->declarations.push_back(decl_spell); var->declarations.push_back(decl_spell);
} }
@ -1566,10 +1592,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// TODO: Support multiple function definitions, which is common for // TODO: Support multiple function definitions, which is common for
// template specializations. // template specializations.
if (decl->isDefinition && !is_template_specialization) { if (decl->isDefinition && !is_template_specialization) {
// assert(!func->def.definition_spelling); // assert(!func->def.spell);
// assert(!func->def.definition_extent); // assert(!func->def.extent);
func->def.definition_spelling = decl_spelling; func->def.spell = decl_spelling;
func->def.definition_extent = decl_extent; func->def.extent = decl_extent;
} else { } else {
IndexFunc::Declaration declaration; IndexFunc::Declaration declaration;
declaration.spelling = decl_spelling; declaration.spelling = decl_spelling;
@ -1697,8 +1723,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
ClangCursor decl_cursor = decl->cursor; ClangCursor decl_cursor = decl->cursor;
Range spell = decl_cursor.get_spelling_range(); Range spell = decl_cursor.get_spelling_range();
Range extent = decl_cursor.get_extent(); Range extent = decl_cursor.get_extent();
type->def.definition_spelling = spell; SetUse(db, &type->def.spell, spell, lex_parent, Role::Definition);
type->def.definition_extent = extent; SetUse(db, &type->def.extent, extent, lex_parent, Role::None);
SetTypeName(type, decl_cursor, decl->semanticContainer, SetTypeName(type, decl_cursor, decl->semanticContainer,
decl->entityInfo->name, param); decl->entityInfo->name, param);
@ -1753,8 +1779,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// } // }
if (decl->isDefinition) { if (decl->isDefinition) {
type->def.definition_spelling = decl_spell; SetUse(db, &type->def.spell, decl_spell, lex_parent, Role::Definition);
type->def.definition_extent = decl_cursor.get_extent(); SetUse(db, &type->def.extent, decl_cursor.get_extent(), lex_parent, Role::None);
if (decl_cursor.get_kind() == CXCursor_EnumDecl) { if (decl_cursor.get_kind() == CXCursor_EnumDecl) {
ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor); ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor);
@ -1790,11 +1816,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
origin->def.kind = type->def.kind; origin->def.kind = type->def.kind;
} }
// TODO The name may be assigned in |ResolveToDeclarationType| but // TODO The name may be assigned in |ResolveToDeclarationType| but
// |definition_spelling| is nullopt. // |spell| is nullopt.
if (!origin->def.definition_spelling) { if (!origin->def.spell) {
origin->def.definition_spelling = SetUse(db, &origin->def.spell, origin_cursor.get_spelling_range(), lex_parent, Role::Definition);
origin_cursor.get_spelling_range(); SetUse(db, &origin->def.extent, origin_cursor.get_extent(), lex_parent, Role::None);
origin->def.definition_extent = origin_cursor.get_extent();
} }
origin->derived.push_back(type_id); origin->derived.push_back(type_id);
type->def.parents.push_back(origin_id); type->def.parents.push_back(origin_id);
@ -1909,6 +1934,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
return; return;
ClangCursor cursor(ref->cursor); ClangCursor cursor(ref->cursor);
ClangCursor lex_parent(fromContainer(ref->container));
switch (ref->referencedEntity->kind) { switch (ref->referencedEntity->kind) {
case CXIdxEntity_CXXNamespaceAlias: case CXIdxEntity_CXXNamespaceAlias:
@ -1942,8 +1968,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
CXFile referenced_file; CXFile referenced_file;
Range spelling = referenced.get_spelling_range(&referenced_file); Range spelling = referenced.get_spelling_range(&referenced_file);
if (file == referenced_file) { if (file == referenced_file) {
var->def.definition_spelling = spelling; SetUse(db, &var->def.spell, spelling, lex_parent, Role::Definition);
var->def.definition_extent = referenced.get_extent(); SetUse(db, &var->def.extent, referenced.get_extent(), lex_parent, Role::None);
// TODO Some of the logic here duplicates CXIdxEntity_Variable branch // TODO Some of the logic here duplicates CXIdxEntity_Variable branch
// of OnIndexDeclaration. But there `decl` is of type CXIdxDeclInfo // of OnIndexDeclaration. But there `decl` is of type CXIdxDeclInfo
@ -1953,7 +1979,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
var->def.kind = ClangSymbolKind::Parameter; var->def.kind = ClangSymbolKind::Parameter;
} }
} }
UniqueAddUse(db, var->uses, loc, fromContainer(ref->container), SymbolRole::Reference); UniqueAddUse(db, var->uses, loc, fromContainer(ref->container), Role::Reference);
break; break;
} }
@ -2010,8 +2036,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
OnIndexReference_Function( OnIndexReference_Function(
db, loc, ref->container->cursor, called_id, db, loc, ref->container->cursor, called_id,
SymbolRole::CalledBy | Role::Call |
(is_implicit ? SymbolRole::Implicit : SymbolRole::None)); (is_implicit ? Role::Implicit : Role::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) {
@ -2053,7 +2079,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr)); IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr));
AddFuncUse(&ctor->uses, AddFuncUse(&ctor->uses,
Use(loc, Id<void>(), SymbolKind::File, Use(loc, Id<void>(), SymbolKind::File,
SymbolRole::CalledBy | SymbolRole::Implicit)); Role::Call | Role::Implicit));
} }
} }
} }
@ -2338,7 +2364,7 @@ void Reflect(Reader& visitor, Reference& value) {
s = strchr(s, '|'); s = strchr(s, '|');
value.id.id = RawId(strtol(s + 1, &s, 10)); value.id.id = RawId(strtol(s + 1, &s, 10));
value.kind = static_cast<SymbolKind>(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)); value.role = static_cast<Role>(strtol(s + 1, &s, 10));
} else { } else {
Reflect(visitor, value.range); Reflect(visitor, value.range);
Reflect(visitor, value.id); Reflect(visitor, value.id);

View File

@ -92,10 +92,10 @@ struct Reference {
Range range; Range range;
Id<void> id; Id<void> id;
SymbolKind kind; SymbolKind kind;
SymbolRole role; Role role;
bool HasValue() const { return id.HasValue(); } bool HasValue() const { return range.HasValue(); }
std::tuple<Range, Id<void>, SymbolKind, SymbolRole> ToTuple() const { std::tuple<Range, Id<void>, SymbolKind, Role> ToTuple() const {
return std::make_tuple(range, id, kind, role); return std::make_tuple(range, id, kind, role);
} }
bool operator==(const Reference& o) const { bool operator==(const Reference& o) const {
@ -126,11 +126,11 @@ MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
// |id,kind| refer to the referenced entity. // |id,kind| refer to the referenced entity.
struct SymbolRef : Reference { struct SymbolRef : Reference {
SymbolRef() = default; SymbolRef() = default;
SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) SymbolRef(Range range, Id<void> id, SymbolKind kind, Role role)
: Reference{range, id, kind, role} {} : Reference{range, id, kind, role} {}
SymbolRef(Reference ref) : Reference(ref) {} SymbolRef(Reference ref) : Reference(ref) {}
SymbolRef(SymbolIdx si) SymbolRef(SymbolIdx si)
: Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {} : Reference{Range(), Id<void>(si.idx), si.kind, Role::None} {}
RawId Idx() const { return RawId(id); } RawId Idx() const { return RawId(id); }
operator SymbolIdx() const { return SymbolIdx{Idx(), kind}; } operator SymbolIdx() const { return SymbolIdx{Idx(), kind}; }
@ -141,7 +141,7 @@ struct SymbolRef : Reference {
struct Use : Reference { struct Use : Reference {
Use() = default; Use() = default;
Use(Reference ref) : Reference(ref) {} Use(Reference ref) : Reference(ref) {}
Use(Range range, Id<void> id, SymbolKind kind, SymbolRole role) Use(Range range, Id<void> id, SymbolKind kind, Role role)
: Reference{range, id, kind, role} {} : Reference{range, id, kind, role} {}
}; };
@ -172,8 +172,8 @@ struct TypeDefDefinitionData {
// It's also difficult to identify a `class Foo;` statement with the clang // It's also difficult to identify a `class Foo;` statement with the clang
// indexer API (it's doable using cursor AST traversal), so we don't bother // indexer API (it's doable using cursor AST traversal), so we don't bother
// supporting the feature. // supporting the feature.
Maybe<typename F::Range> definition_spelling; Maybe<Use> spell;
Maybe<typename F::Range> definition_extent; Maybe<Use> extent;
// Immediate parent types. // Immediate parent types.
std::vector<typename F::TypeId> parents; std::vector<typename F::TypeId> parents;
@ -194,8 +194,8 @@ struct TypeDefDefinitionData {
bool operator==(const TypeDefDefinitionData& o) const { bool operator==(const TypeDefDefinitionData& o) const {
return detailed_name == o.detailed_name && return detailed_name == o.detailed_name &&
definition_spelling == o.definition_spelling && spell == o.spell &&
definition_extent == o.definition_extent && alias_of == o.alias_of && extent == o.extent && alias_of == o.alias_of &&
parents == o.parents && types == o.types && funcs == o.funcs && parents == o.parents && types == o.types && funcs == o.funcs &&
vars == o.vars && kind == o.kind && hover == o.hover && vars == o.vars && kind == o.kind && hover == o.hover &&
comments == o.comments; comments == o.comments;
@ -218,8 +218,8 @@ void Reflect(TVisitor& visitor, TypeDefDefinitionData<Family>& value) {
REFLECT_MEMBER(kind); REFLECT_MEMBER(kind);
REFLECT_MEMBER(hover); REFLECT_MEMBER(hover);
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(spell);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(extent);
REFLECT_MEMBER(file); REFLECT_MEMBER(file);
REFLECT_MEMBER(alias_of); REFLECT_MEMBER(alias_of);
REFLECT_MEMBER(parents); REFLECT_MEMBER(parents);
@ -260,8 +260,8 @@ struct FuncDefDefinitionData {
std::string detailed_name; std::string detailed_name;
std::string hover; std::string hover;
std::string comments; std::string comments;
Maybe<typename F::Range> definition_spelling; Maybe<typename F::Range> spell;
Maybe<typename F::Range> definition_extent; Maybe<typename F::Range> extent;
// Method this method overrides. // Method this method overrides.
std::vector<typename F::FuncId> base; std::vector<typename F::FuncId> base;
@ -282,8 +282,8 @@ struct FuncDefDefinitionData {
bool operator==(const FuncDefDefinitionData& o) const { bool operator==(const FuncDefDefinitionData& o) const {
return detailed_name == o.detailed_name && return detailed_name == o.detailed_name &&
definition_spelling == o.definition_spelling && spell == o.spell &&
definition_extent == o.definition_extent && extent == o.extent &&
declaring_type == o.declaring_type && base == o.base && declaring_type == o.declaring_type && base == o.base &&
locals == o.locals && callees == o.callees && kind == o.kind && locals == o.locals && callees == o.callees && kind == o.kind &&
storage == o.storage && hover == o.hover && comments == o.comments; storage == o.storage && hover == o.hover && comments == o.comments;
@ -308,8 +308,8 @@ void Reflect(TVisitor& visitor, FuncDefDefinitionData<Family>& value) {
REFLECT_MEMBER(storage); REFLECT_MEMBER(storage);
REFLECT_MEMBER(hover); REFLECT_MEMBER(hover);
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(spell);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(extent);
REFLECT_MEMBER(file); REFLECT_MEMBER(file);
REFLECT_MEMBER(declaring_type); REFLECT_MEMBER(declaring_type);
REFLECT_MEMBER(base); REFLECT_MEMBER(base);
@ -347,7 +347,7 @@ struct IndexFunc {
// function context then the FuncRef will not have an associated id. // function context then the FuncRef will not have an associated id.
// //
// 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.spell.
std::vector<Use> uses; std::vector<Use> uses;
IndexFunc() {} // For serialization. IndexFunc() {} // For serialization.
@ -372,8 +372,8 @@ struct VarDefDefinitionData {
std::string comments; std::string comments;
// TODO: definitions should be a list of ranges, since there can be more // TODO: definitions should be a list of ranges, since there can be more
// than one - when?? // than one - when??
Maybe<typename F::Range> definition_spelling; Maybe<Use> spell;
Maybe<typename F::Range> definition_extent; Maybe<Use> extent;
typename F::FileId file; typename F::FileId file;
// Type of the variable. // Type of the variable.
@ -398,8 +398,8 @@ struct VarDefDefinitionData {
bool operator==(const VarDefDefinitionData& o) const { bool operator==(const VarDefDefinitionData& o) const {
return detailed_name == o.detailed_name && return detailed_name == o.detailed_name &&
definition_spelling == o.definition_spelling && spell == o.spell &&
definition_extent == o.definition_extent && extent == o.extent &&
variable_type == o.variable_type && parent_id == o.parent_id && variable_type == o.variable_type && parent_id == o.parent_id &&
parent_kind == o.parent_kind && kind == o.kind && parent_kind == o.parent_kind && kind == o.kind &&
storage == o.storage && hover == o.hover && comments == o.comments; storage == o.storage && hover == o.hover && comments == o.comments;
@ -422,8 +422,8 @@ void Reflect(TVisitor& visitor, VarDefDefinitionData<Family>& value) {
REFLECT_MEMBER(short_name_offset); REFLECT_MEMBER(short_name_offset);
REFLECT_MEMBER(hover); REFLECT_MEMBER(hover);
REFLECT_MEMBER(comments); REFLECT_MEMBER(comments);
REFLECT_MEMBER(definition_spelling); REFLECT_MEMBER(spell);
REFLECT_MEMBER(definition_extent); REFLECT_MEMBER(extent);
REFLECT_MEMBER(file); REFLECT_MEMBER(file);
REFLECT_MEMBER(variable_type); REFLECT_MEMBER(variable_type);
REFLECT_MEMBER(parent_id); REFLECT_MEMBER(parent_id);

View File

@ -30,8 +30,8 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
// Order by |Definition| DESC, range size ASC. // Order by |Definition| DESC, range size ASC.
std::stable_sort(syms.begin(), syms.end(), std::stable_sort(syms.begin(), syms.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return (a.role & SymbolRole::Definition) > return (a.role & Role::Definition) >
(b.role & SymbolRole::Definition); (b.role & Role::Definition);
}); });
for (SymbolRef sym : syms) { for (SymbolRef sym : syms) {
if (sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {

View File

@ -53,10 +53,10 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildInitialCallTree(
WorkingFiles* working_files, WorkingFiles* working_files,
QueryFuncId root) { QueryFuncId root) {
QueryFunc& root_func = db->funcs[root.id]; QueryFunc& root_func = db->funcs[root.id];
if (!root_func.def || !root_func.def->definition_spelling) if (!root_func.def || !root_func.def->spell)
return {}; return {};
optional<lsLocation> def_loc = optional<lsLocation> def_loc =
GetLsLocation(db, working_files, *root_func.def->definition_spelling); GetLsLocation(db, working_files, *root_func.def->spell);
if (!def_loc) if (!def_loc)
return {}; return {};

View File

@ -30,8 +30,8 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
// Order by |Definition| DESC, range size ASC. // Order by |Definition| DESC, range size ASC.
std::stable_sort(syms.begin(), syms.end(), std::stable_sort(syms.begin(), syms.end(),
[](const SymbolRef& a, const SymbolRef& b) { [](const SymbolRef& a, const SymbolRef& b) {
return (a.role & SymbolRole::Definition) > return (a.role & Role::Definition) >
(b.role & SymbolRole::Definition); (b.role & Role::Definition);
}); });
for (const SymbolRef& sym : syms) { for (const SymbolRef& sym : syms) {
if (sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {

View File

@ -40,10 +40,10 @@ MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy, jsonrpc, id, result);
std::vector<Out_CqueryMemberHierarchy::Entry> std::vector<Out_CqueryMemberHierarchy::Entry>
BuildInitial(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) { BuildInitial(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
QueryType& root_type = db->types[root.id]; QueryType& root_type = db->types[root.id];
if (!root_type.def || !root_type.def->definition_spelling) if (!root_type.def || !root_type.def->spell)
return {}; return {};
optional<lsLocation> def_loc = optional<lsLocation> def_loc =
GetLsLocation(db, working_files, *root_type.def->definition_spelling); GetLsLocation(db, working_files, *root_type.def->spell);
if (!def_loc) if (!def_loc)
return {}; return {};
@ -67,9 +67,9 @@ ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
// FIXME WithGen // FIXME WithGen
entry.type_id = entry.type_id =
var.def->variable_type ? var.def->variable_type->id : RawId(-1); var.def->variable_type ? var.def->variable_type->id : RawId(-1);
if (var.def->definition_spelling) { if (var.def->spell) {
optional<lsLocation> loc = optional<lsLocation> loc =
GetLsLocation(db, working_files, *var.def->definition_spelling); GetLsLocation(db, working_files, *var.def->spell);
// TODO invalid location // TODO invalid location
if (loc) if (loc)
entry.location = *loc; entry.location = *loc;

View File

@ -37,9 +37,9 @@ BuildParentInheritanceHierarchyForType(QueryDatabase* db,
EachWithGen(db->types, root_type.def->parents, [&](QueryType& parent_type) { EachWithGen(db->types, root_type.def->parents, [&](QueryType& parent_type) {
Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; Out_CqueryTypeHierarchyTree::TypeEntry parent_entry;
parent_entry.name = parent_type.def->detailed_name; parent_entry.name = parent_type.def->detailed_name;
if (parent_type.def->definition_spelling) if (parent_type.def->spell)
parent_entry.location = GetLsLocation( parent_entry.location = GetLsLocation(
db, working_files, *parent_type.def->definition_spelling); db, working_files, *parent_type.def->spell);
parent_entry.children = parent_entry.children =
BuildParentInheritanceHierarchyForType(db, working_files, parent_type); BuildParentInheritanceHierarchyForType(db, working_files, parent_type);
@ -57,9 +57,9 @@ BuildInheritanceHierarchyForType(QueryDatabase* db,
// Name and location. // Name and location.
entry.name = root_type.def->detailed_name; entry.name = root_type.def->detailed_name;
if (root_type.def->definition_spelling) if (root_type.def->spell)
entry.location = entry.location =
GetLsLocation(db, working_files, *root_type.def->definition_spelling); GetLsLocation(db, working_files, *root_type.def->spell);
entry.children.reserve(root_type.derived.size()); entry.children.reserve(root_type.derived.size());
@ -101,9 +101,9 @@ BuildParentInheritanceHierarchyForFunc(QueryDatabase* db,
Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; Out_CqueryTypeHierarchyTree::TypeEntry parent_entry;
parent_entry.name = parent_func.def->detailed_name; parent_entry.name = parent_func.def->detailed_name;
if (parent_func.def->definition_spelling) if (parent_func.def->spell)
parent_entry.location = GetLsLocation( parent_entry.location = GetLsLocation(
db, working_files, *parent_func.def->definition_spelling); db, working_files, *parent_func.def->spell);
parent_entry.children = parent_entry.children =
BuildParentInheritanceHierarchyForFunc(db, working_files, parent_id); BuildParentInheritanceHierarchyForFunc(db, working_files, parent_id);
@ -125,9 +125,9 @@ BuildInheritanceHierarchyForFunc(QueryDatabase* db,
// Name and location. // Name and location.
entry.name = root_func.def->detailed_name; entry.name = root_func.def->detailed_name;
if (root_func.def->definition_spelling) if (root_func.def->spell)
entry.location = entry.location =
GetLsLocation(db, working_files, *root_func.def->definition_spelling); GetLsLocation(db, working_files, *root_func.def->spell);
entry.children.reserve(root_func.derived.size()); entry.children.reserve(root_func.derived.size());

View File

@ -72,8 +72,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (func.def && func.def->definition_extent) { if (func.def && func.def->extent) {
QueryFileId t = db->GetFileId(*func.def->definition_extent); QueryFileId t = db->GetFileId(*func.def->extent);
if (t != file_id) if (t != file_id)
return t; return t;
} }
@ -83,8 +83,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
QueryVar& var = db->GetVar(sym); QueryVar& var = db->GetVar(sym);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (var.def && var.def->definition_extent) { if (var.def && var.def->extent) {
QueryFileId t = db->GetFileId(*var.def->definition_extent); QueryFileId t = db->GetFileId(*var.def->extent);
if (t != file_id) if (t != file_id)
return t; return t;
} }
@ -164,10 +164,10 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
QueryType& declaring_type = db->types[func.def->declaring_type->id]; QueryType& declaring_type = db->types[func.def->declaring_type->id];
if (declaring_type.def) { if (declaring_type.def) {
type_name = std::string(declaring_type.def->ShortName()); type_name = std::string(declaring_type.def->ShortName());
optional<lsRange> ls_type_def_extent = GetLsRange( optional<lsRange> ls_type_extent = GetLsRange(
working_file, declaring_type.def->definition_extent->range); working_file, declaring_type.def->extent->range);
if (ls_type_def_extent) { if (ls_type_extent) {
same_file_insert_end = ls_type_def_extent->end; same_file_insert_end = ls_type_extent->end;
same_file_insert_end->character += 1; // move past semicolon. same_file_insert_end->character += 1; // move past semicolon.
} }
} }
@ -201,7 +201,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& sym_func = db->GetFunc(sym); QueryFunc& sym_func = db->GetFunc(sym);
if (!sym_func.def || !sym_func.def->definition_extent) if (!sym_func.def || !sym_func.def->extent)
break; break;
for (const Reference& func_decl : sym_func.declarations) { for (const Reference& func_decl : sym_func.declarations) {
@ -209,7 +209,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
int dist = func_decl.range.start.line - decl.range.start.line; int dist = func_decl.range.start.line - decl.range.start.line;
if (abs(dist) < abs(best_dist)) { if (abs(dist) < abs(best_dist)) {
optional<lsLocation> def_loc = GetLsLocation( optional<lsLocation> def_loc = GetLsLocation(
db, working_files, *sym_func.def->definition_extent); db, working_files, *sym_func.def->extent);
if (!def_loc) if (!def_loc)
continue; continue;
@ -356,7 +356,7 @@ struct TextDocumentCodeActionHandler
Out_TextDocumentCodeAction::Command command; Out_TextDocumentCodeAction::Command command;
EachWithGen(db->funcs, type.def->funcs, [&](QueryFunc& func_def) { EachWithGen(db->funcs, type.def->funcs, [&](QueryFunc& func_def) {
if (func_def.def->definition_extent) if (func_def.def->extent)
return; return;
EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/); EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/);
optional<lsTextEdit> edit = BuildAutoImplementForFunction( optional<lsTextEdit> edit = BuildAutoImplementForFunction(
@ -398,7 +398,7 @@ struct TextDocumentCodeActionHandler
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
if (!func.def || func.def->definition_extent) if (!func.def || func.def->extent)
break; break;
EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/); EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/);

View File

@ -35,7 +35,7 @@ std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
if (var.def && var.def->variable_type) { if (var.def && var.def->variable_type) {
std::vector<Use> 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, Role::None));
ret.insert(ret.end(), types.begin(), types.end()); ret.insert(ret.end(), types.begin(), types.end());
} }
return ret; return ret;
@ -79,9 +79,9 @@ struct TextDocumentDefinitionHandler
// We use spelling start and extent end because this causes vscode to // We use spelling start and extent end because this causes vscode to
// highlight the entire definition when previewing / hoving with the // highlight the entire definition when previewing / hoving with the
// mouse. // mouse.
Maybe<Reference> def_extent = GetDefinitionExtentOfSymbol(db, sym); Maybe<Use> extent = GetDefinitionExtentOfSymbol(db, sym);
if (def_loc && def_extent) if (def_loc && extent)
def_loc->range.end = def_extent->range.end; def_loc->range.end = extent->range.end;
// If the cursor is currently at or in the definition we should goto // If the cursor is currently at or in the definition we should goto
// the declaration if possible. We also want to use declarations if // the declaration if possible. We also want to use declarations if

View File

@ -17,6 +17,8 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
continue; continue;
QueryFileId file_id = db->GetFileId(use); QueryFileId file_id = db->GetFileId(use);
if (!file_id.HasValue())
continue;
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

@ -22,8 +22,8 @@ bool InsertSymbolIntoResult(QueryDatabase* db,
if (!info) if (!info)
return false; return false;
Maybe<Reference> location = GetDefinitionExtentOfSymbol(db, symbol); Maybe<Use> location = GetDefinitionExtentOfSymbol(db, symbol);
Reference loc; Use loc;
if (location) if (location)
loc = *location; loc = *location;
else { else {

View File

@ -43,12 +43,8 @@ optional<QueryType::Def> ToQuery(const IdMap& id_map,
result.hover = type.hover; result.hover = type.hover;
result.comments = type.comments; result.comments = type.comments;
result.file = id_map.primary_file; result.file = id_map.primary_file;
if (type.definition_spelling) result.spell = id_map.ToQuery(type.spell);
result.definition_spelling = result.extent = id_map.ToQuery(type.extent);
id_map.ToQuery(*type.definition_spelling, SymbolRole::Definition);
if (type.definition_extent)
result.definition_extent =
id_map.ToQuery(*type.definition_extent, SymbolRole::None);
result.alias_of = id_map.ToQuery(type.alias_of); result.alias_of = id_map.ToQuery(type.alias_of);
result.parents = id_map.ToQuery(type.parents); result.parents = id_map.ToQuery(type.parents);
result.types = id_map.ToQuery(type.types); result.types = id_map.ToQuery(type.types);
@ -71,12 +67,12 @@ optional<QueryFunc::Def> ToQuery(const IdMap& id_map,
result.hover = func.hover; result.hover = func.hover;
result.comments = func.comments; result.comments = func.comments;
result.file = id_map.primary_file; result.file = id_map.primary_file;
if (func.definition_spelling) if (func.spell)
result.definition_spelling = result.spell =
id_map.ToQuery(*func.definition_spelling, SymbolRole::Definition); id_map.ToQuery(*func.spell, Role::Definition);
if (func.definition_extent) if (func.extent)
result.definition_extent = result.extent =
id_map.ToQuery(*func.definition_extent, SymbolRole::None); id_map.ToQuery(*func.extent, Role::None);
result.declaring_type = id_map.ToQuery(func.declaring_type); result.declaring_type = id_map.ToQuery(func.declaring_type);
result.base = id_map.ToQuery(func.base); result.base = id_map.ToQuery(func.base);
result.locals = id_map.ToQuery(func.locals); result.locals = id_map.ToQuery(func.locals);
@ -95,12 +91,10 @@ optional<QueryVar::Def> ToQuery(const IdMap& id_map, const IndexVar::Def& var) {
result.hover = var.hover; result.hover = var.hover;
result.comments = var.comments; result.comments = var.comments;
result.file = id_map.primary_file; result.file = id_map.primary_file;
if (var.definition_spelling) if (var.spell)
result.definition_spelling = result.spell = id_map.ToQuery(*var.spell);
id_map.ToQuery(*var.definition_spelling, SymbolRole::Definition); if (var.extent)
if (var.definition_extent) result.extent = id_map.ToQuery(*var.extent);
result.definition_extent =
id_map.ToQuery(*var.definition_extent, SymbolRole::None);
result.variable_type = id_map.ToQuery(var.variable_type); result.variable_type = id_map.ToQuery(var.variable_type);
if (result.parent_id) if (result.parent_id)
switch (var.parent_kind) { switch (var.parent_kind) {
@ -252,38 +246,43 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
} }
}(); }();
auto add_outline = [&](Range range, RawId id, SymbolKind kind, auto add_outline = [&](Range range, Id<void> id, SymbolKind kind,
SymbolRole role) { Role role) {
def.outline.push_back(SymbolRef(range, Id<void>(id), kind, role)); def.outline.push_back(SymbolRef(range, id, kind, role));
}; };
auto add_all_symbols = [&](Range range, RawId id, SymbolKind kind, auto add_all_symbols = [&](Range range, Id<void> id, SymbolKind kind,
SymbolRole role) { Role role) {
def.all_symbols.push_back(SymbolRef(range, Id<void>(id), kind, role)); def.all_symbols.push_back(SymbolRef(range, id, kind, role));
};
auto add_all_symbols_use = [&](Use use, Id<void> id, SymbolKind kind) {
def.all_symbols.push_back(
SymbolRef(use.range, id, kind, use.role));
};
auto add_outline_use = [&](Use use, Id<void> id, SymbolKind kind) {
def.outline.push_back(SymbolRef(use.range, id, kind, use.role));
}; };
for (const IndexType& type : indexed.types) { for (const IndexType& type : indexed.types) {
RawId id = id_map.ToQuery(type.id).id; QueryTypeId id = id_map.ToQuery(type.id);
if (type.def.definition_spelling.has_value()) if (type.def.spell)
add_all_symbols(*type.def.definition_spelling, id, SymbolKind::Type, add_all_symbols_use(*type.def.spell, id, SymbolKind::Type);
SymbolRole::Definition); if (type.def.extent)
if (type.def.definition_extent) add_outline_use(*type.def.extent, id, SymbolKind::Type);
add_outline(*type.def.definition_extent, id, SymbolKind::Type, for (Use use : type.uses)
SymbolRole::None);
for (const Reference& use : type.uses)
add_all_symbols(use.range, id, SymbolKind::Type, use.role); add_all_symbols(use.range, id, SymbolKind::Type, use.role);
} }
for (const IndexFunc& func : indexed.funcs) { for (const IndexFunc& func : indexed.funcs) {
RawId id = id_map.ToQuery(func.id).id; QueryFuncId id = id_map.ToQuery(func.id);
if (func.def.definition_spelling.has_value()) if (func.def.spell.has_value())
add_all_symbols(*func.def.definition_spelling, id, SymbolKind::Func, add_all_symbols(*func.def.spell, id, SymbolKind::Func,
SymbolRole::Definition); Role::Definition);
if (func.def.definition_extent.has_value()) if (func.def.extent.has_value())
add_outline(*func.def.definition_extent, id, add_outline(*func.def.extent, id,
SymbolKind::Func, SymbolRole::None); SymbolKind::Func, Role::None);
for (const IndexFunc::Declaration& decl : func.declarations) { for (const IndexFunc::Declaration& decl : func.declarations) {
add_all_symbols(decl.spelling, id, SymbolKind::Func, add_all_symbols(decl.spelling, id, SymbolKind::Func,
SymbolRole::Declaration); Role::Declaration);
add_outline(decl.spelling, id, SymbolKind::Func, SymbolRole::Declaration); add_outline(decl.spelling, id, SymbolKind::Func, Role::Declaration);
} }
for (Use caller : func.uses) { 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
@ -291,30 +290,29 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
// textDocument/definition on the space/semicolon in `A a;` or `return // textDocument/definition on the space/semicolon in `A a;` or `return
// 42;` will take you to the constructor. // 42;` will take you to the constructor.
Range range = caller.range; Range range = caller.range;
if (caller.role & SymbolRole::Implicit) { if (caller.role & Role::Implicit) {
if (range.start.column > 0) if (range.start.column > 0)
range.start.column--; range.start.column--;
range.end.column++; range.end.column++;
} }
add_all_symbols(range, id, SymbolKind::Func, add_all_symbols(range, id, SymbolKind::Func,
caller.role | SymbolRole::CalledBy); caller.role | Role::Call);
} }
} }
for (const IndexVar& var : indexed.vars) { for (const IndexVar& var : indexed.vars) {
if (var.def.definition_spelling) QueryVarId id = id_map.ToQuery(var.id);
add_all_symbols(*var.def.definition_spelling, id_map.ToQuery(var.id).id, if (var.def.spell)
SymbolKind::Var, SymbolRole::Definition); add_all_symbols_use(*var.def.spell, id, SymbolKind::Var);
if (var.def.definition_extent.has_value()) if (var.def.extent)
add_outline(*var.def.definition_extent, id_map.ToQuery(var.id).id, add_outline_use(*var.def.extent, id, SymbolKind::Var);
SymbolKind::Var, SymbolRole::None);
for (const Range& decl : var.declarations) { for (const Range& decl : var.declarations) {
add_all_symbols(decl, id_map.ToQuery(var.id).id, SymbolKind::Var, add_all_symbols(decl, id_map.ToQuery(var.id), SymbolKind::Var,
SymbolRole::Definition); Role::Definition);
add_outline(decl, id_map.ToQuery(var.id).id, SymbolKind::Var, add_outline(decl, id_map.ToQuery(var.id), SymbolKind::Var,
SymbolRole::Declaration); Role::Declaration);
} }
for (auto& use : var.uses) for (Use use : var.uses)
add_all_symbols(use.range, id_map.ToQuery(var.id).id, SymbolKind::Var, add_all_symbols(use.range, id_map.ToQuery(var.id), SymbolKind::Var,
use.role); use.role);
} }
@ -432,7 +430,7 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
*GetQueryVarIdFromUsr(query_db, entry.second, true); *GetQueryVarIdFromUsr(query_db, entry.second, true);
} }
Use IdMap::ToQuery(Range range, SymbolRole role) const { Use IdMap::ToQuery(Range range, Role role) const {
return Use(range, primary_file, SymbolKind:: File, role); return Use(range, primary_file, SymbolKind:: File, role);
} }
QueryTypeId IdMap::ToQuery(IndexTypeId id) const { QueryTypeId IdMap::ToQuery(IndexTypeId id) const {
@ -481,13 +479,13 @@ Use IdMap::ToQuery(Use use) const {
Use IdMap::ToQuery(IndexFunc::Declaration decl) const { Use IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation. // TODO: expose more than just QueryLocation.
return Use(decl.spelling, primary_file, SymbolKind::File, return Use(decl.spelling, primary_file, SymbolKind::File,
SymbolRole::Declaration); Role::Declaration);
} }
std::vector<Use> IdMap::ToQuery(const std::vector<Range>& a) const { std::vector<Use> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<Use> 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, Role::Reference));
return ret; return ret;
} }
@ -547,7 +545,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
previous_file.types, current_file.types, previous_file.types, current_file.types,
/*onRemoved:*/ /*onRemoved:*/
[this, &previous_id_map](IndexType* type) { [this, &previous_id_map](IndexType* type) {
if (type->def.definition_spelling) if (type->def.spell)
types_removed.push_back(type->usr); types_removed.push_back(type->usr);
else { else {
if (!type->derived.empty()) if (!type->derived.empty())
@ -609,7 +607,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
previous_file.funcs, current_file.funcs, previous_file.funcs, current_file.funcs,
/*onRemoved:*/ /*onRemoved:*/
[this, &previous_id_map](IndexFunc* func) { [this, &previous_id_map](IndexFunc* func) {
if (func->def.definition_spelling) { if (func->def.spell) {
funcs_removed.push_back(func->usr); funcs_removed.push_back(func->usr);
} else { } else {
if (!func->declarations.empty()) if (!func->declarations.empty())
@ -671,7 +669,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
previous_file.vars, current_file.vars, previous_file.vars, current_file.vars,
/*onRemoved:*/ /*onRemoved:*/
[this, &previous_id_map](IndexVar* var) { [this, &previous_id_map](IndexVar* var) {
if (var->def.definition_spelling) { if (var->def.spell) {
vars_removed.push_back(var->usr); vars_removed.push_back(var->usr);
} else { } else {
if (!var->declarations.empty()) if (!var->declarations.empty())
@ -894,8 +892,8 @@ void QueryDatabase::ImportOrUpdate(
QueryType& existing = types[it->second.id]; QueryType& existing = types[it->second.id];
// Keep the existing definition if it is higher quality. // Keep the existing definition if it is higher quality.
if (!(existing.def && existing.def->definition_spelling && if (!(existing.def && existing.def->spell &&
!def.value.definition_spelling)) { !def.value.spell)) {
existing.def = std::move(def.value); existing.def = std::move(def.value);
UpdateSymbols(&existing.symbol_idx, SymbolKind::Type, UpdateSymbols(&existing.symbol_idx, SymbolKind::Type,
it->second.id); it->second.id);
@ -917,8 +915,8 @@ void QueryDatabase::ImportOrUpdate(
QueryFunc& existing = funcs[it->second.id]; QueryFunc& existing = funcs[it->second.id];
// Keep the existing definition if it is higher quality. // Keep the existing definition if it is higher quality.
if (!(existing.def && existing.def->definition_spelling && if (!(existing.def && existing.def->spell &&
!def.value.definition_spelling)) { !def.value.spell)) {
existing.def = std::move(def.value); existing.def = std::move(def.value);
UpdateSymbols(&existing.symbol_idx, SymbolKind::Func, UpdateSymbols(&existing.symbol_idx, SymbolKind::Func,
it->second.id); it->second.id);
@ -939,8 +937,8 @@ void QueryDatabase::ImportOrUpdate(std::vector<QueryVar::DefUpdate>&& updates) {
QueryVar& existing = vars[it->second.id]; QueryVar& existing = vars[it->second.id];
// Keep the existing definition if it is higher quality. // Keep the existing definition if it is higher quality.
if (!(existing.def && existing.def->definition_spelling && if (!(existing.def && existing.def->spell &&
!def.value.definition_spelling)) { !def.value.spell)) {
existing.def = std::move(def.value); existing.def = std::move(def.value);
if (!def.value.is_local()) if (!def.value.is_local())
UpdateSymbols(&existing.symbol_idx, SymbolKind::Var, UpdateSymbols(&existing.symbol_idx, SymbolKind::Var,
@ -1023,11 +1021,11 @@ TEST_SUITE("query") {
IndexFile current("foo.cc", "<empty>"); IndexFile current("foo.cc", "<empty>");
previous.Resolve(previous.ToTypeId(HashUsr("usr1"))) previous.Resolve(previous.ToTypeId(HashUsr("usr1")))
->def.definition_spelling = Range(Position(1, 0)); ->def.spell = Use(Range(Position(1, 0)), Id<void>(), SymbolKind::File, Role::None);
previous.Resolve(previous.ToFuncId(HashUsr("usr2"))) previous.Resolve(previous.ToFuncId(HashUsr("usr2")))
->def.definition_spelling = Range(Position(2, 0)); ->def.spell = Range(Position(2, 0));
previous.Resolve(previous.ToVarId(HashUsr("usr3"))) previous.Resolve(previous.ToVarId(HashUsr("usr3")))
->def.definition_spelling = Range(Position(3, 0)); ->def.spell = Use(Range(Position(3, 0)), Id<void>(), SymbolKind::File, Role::None);
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
@ -1044,7 +1042,7 @@ TEST_SUITE("query") {
->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")))
->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0), ->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0),
SymbolKind::Func, SymbolRole::None)); SymbolKind::Func, Role::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))});
@ -1063,9 +1061,9 @@ TEST_SUITE("query") {
IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr")));
pf->uses.push_back(Use(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, Role::None));
cf->uses.push_back(Use(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, Role::None));
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
@ -1108,13 +1106,13 @@ 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->uses.push_back(Use(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, Role::None));
pf->uses.push_back(Use(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, Role::None));
cf->uses.push_back(Use(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, Role::None));
cf->uses.push_back(Use(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, Role::None));
QueryDatabase db; QueryDatabase db;
IdMap previous_map(&db, previous.id_cache); IdMap previous_map(&db, previous.id_cache);

View File

@ -363,7 +363,7 @@ struct IdMap {
QueryFuncId ToQuery(IndexFuncId id) const; QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const; QueryVarId ToQuery(IndexVarId id) const;
SymbolRef ToQuery(SymbolRef ref) const; SymbolRef ToQuery(SymbolRef ref) const;
Use ToQuery(Range range, SymbolRole role) const; Use ToQuery(Range range, Role role) const;
Use ToQuery(Reference ref) const; Use ToQuery(Reference ref) const;
Use ToQuery(Use ref) const; Use ToQuery(Use ref) const;
Use ToQuery(IndexFunc::Declaration decl) const; Use ToQuery(IndexFunc::Declaration decl) const;

View File

@ -22,7 +22,7 @@ Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
QueryFuncId id) { QueryFuncId id) {
QueryFunc& func = db->funcs[id.id]; QueryFunc& func = db->funcs[id.id];
if (func.def) if (func.def)
return func.def->definition_spelling; return func.def->spell;
return nullopt; return nullopt;
} }
@ -32,19 +32,19 @@ Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->GetType(sym); QueryType& type = db->GetType(sym);
if (type.def) if (type.def)
return *type.def->definition_spelling; return *type.def->spell;
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
if (func.def) if (func.def)
return func.def->definition_spelling; return func.def->spell;
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym); QueryVar& var = db->GetVar(sym);
if (var.def) if (var.def)
return var.def->definition_spelling; return *var.def->spell;
break; break;
} }
case SymbolKind::File: case SymbolKind::File:
@ -56,28 +56,28 @@ Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
return nullopt; return nullopt;
} }
Maybe<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym) { Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym) {
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->GetType(sym); QueryType& type = db->GetType(sym);
if (type.def) if (type.def)
return type.def->definition_extent; return type.def->extent;
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
if (func.def) if (func.def)
return func.def->definition_extent; return Use(*func.def->extent);
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym); QueryVar& var = db->GetVar(sym);
if (var.def) if (var.def)
return var.def->definition_extent; return var.def->extent;
break; break;
} }
case SymbolKind::File: case SymbolKind::File:
return sym; return Use(Reference(sym));
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
break; break;
@ -91,22 +91,22 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->GetType(sym); QueryType& type = db->GetType(sym);
if (type.def && type.def->definition_spelling) if (type.def && type.def->spell)
return db->GetFileId(*type.def->definition_spelling); return db->GetFileId(*type.def->spell);
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
if (!func.declarations.empty()) if (!func.declarations.empty())
return db->GetFileId(func.declarations[0]); return db->GetFileId(func.declarations[0]);
if (func.def && func.def->definition_spelling) if (func.def && func.def->spell)
return db->GetFileId(*func.def->definition_spelling); return db->GetFileId(*func.def->spell);
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym); QueryVar& var = db->GetVar(sym);
if (var.def && var.def->definition_spelling) if (var.def && var.def->spell)
return db->GetFileId(*var.def->definition_spelling); return db->GetFileId(*var.def->spell);
break; break;
} }
case SymbolKind::File: case SymbolKind::File:
@ -125,8 +125,8 @@ std::vector<Use> ToUses(QueryDatabase* db,
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];
if (func.def && func.def->definition_spelling) if (func.def && func.def->spell)
ret.push_back(*func.def->definition_spelling); ret.push_back(*func.def->spell);
else if (func.declarations.size()) else if (func.declarations.size())
ret.push_back(func.declarations[0]); ret.push_back(func.declarations[0]);
} }
@ -139,8 +139,8 @@ std::vector<Use> ToUses(QueryDatabase* db,
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];
if (type.def && type.def->definition_spelling) if (type.def && type.def->spell)
ret.push_back(*type.def->definition_spelling); ret.push_back(*type.def->spell);
} }
return ret; return ret;
} }
@ -150,8 +150,8 @@ std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
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];
if (var.def && var.def->definition_spelling) if (var.def && var.def->spell)
ret.push_back(*var.def->definition_spelling); ret.push_back(*var.def->spell);
else if (var.declarations.size()) else if (var.declarations.size())
ret.push_back(var.declarations[0]); ret.push_back(var.declarations[0]);
} }
@ -165,8 +165,8 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[sym.Idx()]; QueryType& type = db->types[sym.Idx()];
std::vector<Use> 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->spell)
ret.push_back(*type.def->definition_spelling); ret.push_back(*type.def->spell);
return ret; return ret;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
@ -175,8 +175,8 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
std::vector<Use> ret = func.uses; 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->spell)
ret.push_back(*func.def->definition_spelling); ret.push_back(*func.def->spell);
} }
return ret; return ret;
} }
@ -184,8 +184,8 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
QueryVar& var = db->vars[sym.Idx()]; QueryVar& var = db->vars[sym.Idx()];
std::vector<Use> 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->spell)
ret.push_back(*var.def->definition_spelling); ret.push_back(*var.def->spell);
ret.insert(ret.end(), var.declarations.begin(), var.declarations.end()); ret.insert(ret.end(), var.declarations.begin(), var.declarations.end());
} }
return ret; return ret;
@ -209,7 +209,7 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
// type from within the type definition. // type from within the type definition.
QueryType& type = db->GetType(sym); QueryType& type = db->GetType(sym);
if (type.def) { if (type.def) {
Maybe<Reference> def = type.def->definition_spelling; Maybe<Use> def = type.def->spell;
if (def) if (def)
return {*def}; return {*def};
} }

View File

@ -11,7 +11,7 @@ Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
QueryFuncId id); QueryFuncId id);
Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db, Maybe<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
SymbolRef sym); SymbolRef sym);
Maybe<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym); Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym);
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
SymbolRef sym); SymbolRef sym);

View File

@ -210,8 +210,8 @@ void Reflect(TVisitor& visitor, IndexType& value) {
ReflectShortName(visitor, value.def); ReflectShortName(visitor, value.def);
REFLECT_MEMBER2("kind", value.def.kind); REFLECT_MEMBER2("kind", value.def.kind);
ReflectHoverAndComments(visitor, value.def); ReflectHoverAndComments(visitor, value.def);
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling); REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("definition_extent", value.def.definition_extent); REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("alias_of", value.def.alias_of); REFLECT_MEMBER2("alias_of", value.def.alias_of);
REFLECT_MEMBER2("parents", value.def.parents); REFLECT_MEMBER2("parents", value.def.parents);
REFLECT_MEMBER2("derived", value.derived); REFLECT_MEMBER2("derived", value.derived);
@ -234,8 +234,8 @@ void Reflect(TVisitor& visitor, IndexFunc& value) {
REFLECT_MEMBER2("storage", value.def.storage); REFLECT_MEMBER2("storage", value.def.storage);
ReflectHoverAndComments(visitor, value.def); ReflectHoverAndComments(visitor, value.def);
REFLECT_MEMBER2("declarations", value.declarations); REFLECT_MEMBER2("declarations", value.declarations);
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling); REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("definition_extent", value.def.definition_extent); REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("declaring_type", value.def.declaring_type); REFLECT_MEMBER2("declaring_type", value.def.declaring_type);
REFLECT_MEMBER2("base", value.def.base); REFLECT_MEMBER2("base", value.def.base);
REFLECT_MEMBER2("derived", value.derived); REFLECT_MEMBER2("derived", value.derived);
@ -254,8 +254,8 @@ void Reflect(TVisitor& visitor, IndexVar& value) {
ReflectShortName(visitor, value.def); ReflectShortName(visitor, value.def);
ReflectHoverAndComments(visitor, value.def); ReflectHoverAndComments(visitor, value.def);
REFLECT_MEMBER2("declarations", value.declarations); REFLECT_MEMBER2("declarations", value.declarations);
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling); REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("definition_extent", value.def.definition_extent); REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("variable_type", value.def.variable_type); REFLECT_MEMBER2("variable_type", value.def.variable_type);
REFLECT_MEMBER2("uses", value.uses); REFLECT_MEMBER2("uses", value.uses);
REFLECT_MEMBER2("parent_id", value.def.parent_id); REFLECT_MEMBER2("parent_id", value.def.parent_id);