diff --git a/src/command_line.cc b/src/command_line.cc index 842c7b69..0dc0b43f 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -30,8 +30,16 @@ const int kQueueSizeBytes = 1024 * 8; } struct IndexTranslationUnitRequest { + enum class Type { + Import, + Update + }; + std::string path; std::vector args; + Type type; + + IndexTranslationUnitRequest(Type type) : type(type) {} }; struct IndexTranslationUnitResponse { @@ -152,23 +160,39 @@ void RegisterMessageTypes() { MessageRegistry::instance()->Register(); } -void WriteToCache(std::string filename, IndexedFile& file) { +std::string GetCachedFileName(std::string source_file) { // TODO/FIXME const char* kCacheDirectory = "C:/Users/jacob/Desktop/superindex/indexer/CACHE/"; - - - std::replace(filename.begin(), filename.end(), '\\', '_'); - std::replace(filename.begin(), filename.end(), '/', '_'); - std::replace(filename.begin(), filename.end(), ':', '_'); - std::replace(filename.begin(), filename.end(), '.', '_'); - std::string cache_file = kCacheDirectory + filename + ".json"; + std::replace(source_file.begin(), source_file.end(), '\\', '_'); + std::replace(source_file.begin(), source_file.end(), '/', '_'); + std::replace(source_file.begin(), source_file.end(), ':', '_'); + std::replace(source_file.begin(), source_file.end(), '.', '_'); + return kCacheDirectory + source_file + ".json"; +} +optional LoadCachedFile(std::string filename) { + // TODO FIXME FIXME FIXME + return nullopt; + + std::string cache_file = GetCachedFileName(filename); + + std::ifstream cache; + cache.open(GetCachedFileName(filename)); + if (!cache.good()) + return nullopt; + + std::string file_content = std::string( + std::istreambuf_iterator(cache), + std::istreambuf_iterator()); + + return Deserialize(filename, file_content); +} + +void WriteToCache(std::string filename, IndexedFile& file) { std::string indexed_content = Serialize(file); - - std::cerr << "Caching to " << cache_file << std::endl; std::ofstream cache; - cache.open(cache_file); + cache.open(GetCachedFileName(filename)); assert(cache.good()); cache << indexed_content; cache.close(); @@ -184,24 +208,60 @@ void IndexMain(IndexRequestQueue* requests, IndexResponseQueue* responses) { continue; } + + Timer time; + + // If the index update is an import, then we will load the previous index + // into memory if we have a previous index. After that, we dispatch an + // update request to get the latest version. + if (request->type == IndexTranslationUnitRequest::Type::Import) { + request->type = IndexTranslationUnitRequest::Type::Update; + + // TODO: we're not serializing out the files cache. We only ever want to import references + // from the primary file though, so that should be ok. We need to cleanup indexer output. + optional old_index = LoadCachedFile(request->path); + if (old_index.has_value()) { + IndexUpdate update(old_index.value()); + IndexTranslationUnitResponse response(update); + responses->Enqueue(response); + time.ResetAndPrint("Loading cached index"); + requests->Enqueue(request.value()); + continue; + } + } + + assert(request->type == IndexTranslationUnitRequest::Type::Update); + // Parse request and send a response. std::cerr << "Parsing file " << request->path << " with args " << Join(request->args, ", ") << std::endl; - Timer time; - IndexedFile file = Parse(request->path, request->args); + IndexedFile new_index = Parse(request->path, request->args); time.ResetAndPrint("Parsing/indexing"); - // TODO: Check cache for existing index; compute diff if there is one. - IndexUpdate update(file); - IndexTranslationUnitResponse response(update); - time.ResetAndPrint("Creating index update/response"); - - responses->Enqueue(response); - time.ResetAndPrint("Sending update to server"); + // If we have a cached index, that means it is already imported, which + // means we want to apply a delta update. + optional old_index = LoadCachedFile(request->path); + time.ResetAndPrint("Loading previous index"); + if (old_index) { + // Apply delta update. + IndexUpdate update(old_index.value(), new_index); + IndexTranslationUnitResponse response(update); + time.ResetAndPrint("Creating delta index update/response"); + responses->Enqueue(response); + time.ResetAndPrint("Sending update to server"); + } + else { + // Apply full update. + IndexUpdate update(new_index); + IndexTranslationUnitResponse response(update); + time.ResetAndPrint("Creating index update/response"); + responses->Enqueue(response); + time.ResetAndPrint("Sending update to server"); + } // Cache file so we can diff it later. - WriteToCache(request->path, file); + WriteToCache(request->path, new_index); time.ResetAndPrint("Cache index update to disk"); } } @@ -230,6 +290,7 @@ lsLocation GetLsLocation(const QueryableLocation& location) { void AddCodeLens(std::vector* result, QueryableLocation loc, const std::vector& uses, + bool exclude_loc, bool only_interesting, const char* singular, const char* plural) { @@ -248,6 +309,8 @@ void AddCodeLens(std::vector* result, // Add unique uses. std::unordered_set unique_uses; for (const QueryableLocation& use : uses) { + if (exclude_loc && use == loc) + continue; if (only_interesting && !use.interesting) continue; unique_uses.insert(GetLsLocation(use)); @@ -263,13 +326,14 @@ void AddCodeLens(std::vector* result, else code_lens.command->title += plural; - if (unique_uses.size() > 0) + if (exclude_loc || unique_uses.size() > 0) result->push_back(code_lens); } void AddCodeLens(std::vector* result, QueryableLocation loc, const std::vector& uses, + bool exclude_loc, bool only_interesting, const char* singular, const char* plural) { @@ -277,13 +341,14 @@ void AddCodeLens(std::vector* result, uses0.reserve(uses.size()); for (const UsrRef& use : uses) uses0.push_back(use.loc); - AddCodeLens(result, loc, uses0, only_interesting, singular, plural); + AddCodeLens(result, loc, uses0, exclude_loc, only_interesting, singular, plural); } void AddCodeLens(std::vector* result, QueryableDatabase* db, QueryableLocation loc, const std::vector& usrs, + bool exclude_loc, bool only_interesting, const char* singular, const char* plural) { @@ -317,7 +382,7 @@ void AddCodeLens(std::vector* result, } } } - AddCodeLens(result, loc, uses0, only_interesting, singular, plural); + AddCodeLens(result, loc, uses0, exclude_loc, only_interesting, singular, plural); } void QueryDbMainLoop( @@ -362,7 +427,7 @@ void QueryDbMainLoop( << "] Dispatching index request for file " << filepath << std::endl; - IndexTranslationUnitRequest request; + IndexTranslationUnitRequest request(IndexTranslationUnitRequest::Type::Import); request.path = filepath; request.args = entry.args; index_requests->Enqueue(request); @@ -488,34 +553,39 @@ void QueryDbMainLoop( } for (UsrRef ref : file->outline) { + // NOTE: We OffsetColumn so that the code lens always show up in a + // predictable order. Otherwise, the client may randomize it. + SymbolIdx symbol = db->usr_to_symbol[ref.usr]; switch (symbol.kind) { case SymbolKind::Type: { QueryableTypeDef& def = db->types[symbol.idx]; - AddCodeLens(&response.result, ref.loc, def.uses, - true /*only_interesting*/, "reference", + AddCodeLens(&response.result, ref.loc.OffsetColumn(0), def.uses, + false /*exclude_loc*/, true /*only_interesting*/, "reference", "references"); - AddCodeLens(&response.result, db, ref.loc, def.derived, - false /*only_interesting*/, "derived", "derived"); + AddCodeLens(&response.result, db, ref.loc.OffsetColumn(1), def.derived, + false /*exclude_loc*/, false /*only_interesting*/, "derived", "derived"); + AddCodeLens(&response.result, db, ref.loc.OffsetColumn(2), def.instantiations, + false /*exclude_loc*/, false /*only_interesting*/, "instantiation", "instantiations"); break; } case SymbolKind::Func: { QueryableFuncDef& def = db->funcs[symbol.idx]; - AddCodeLens(&response.result, ref.loc, def.uses, - false /*only_interesting*/, "reference", - "references"); - AddCodeLens(&response.result, ref.loc, def.callers, - false /*only_interesting*/, "caller", "callers"); - AddCodeLens(&response.result, ref.loc, def.def.callees, - false /*only_interesting*/, "callee", "callees"); - AddCodeLens(&response.result, db, ref.loc, def.derived, - false /*only_interesting*/, "derived", "derived"); + //AddCodeLens(&response.result, ref.loc.OffsetColumn(0), def.uses, + // false /*exclude_loc*/, false /*only_interesting*/, "reference", + // "references"); + AddCodeLens(&response.result, ref.loc.OffsetColumn(1), def.callers, + false /*exclude_loc*/, false /*only_interesting*/, "caller", "callers"); + AddCodeLens(&response.result, ref.loc.OffsetColumn(2), def.def.callees, + false /*exclude_loc*/, false /*only_interesting*/, "callee", "callees"); + AddCodeLens(&response.result, db, ref.loc.OffsetColumn(3), def.derived, + false /*exclude_loc*/, false /*only_interesting*/, "derived", "derived"); break; } case SymbolKind::Var: { QueryableVarDef& def = db->vars[symbol.idx]; - AddCodeLens(&response.result, ref.loc, def.uses, - false /*only_interesting*/, "reference", + AddCodeLens(&response.result, ref.loc.OffsetColumn(0), def.uses, + true /*exclude_loc*/, false /*only_interesting*/, "reference", "references"); break; } @@ -830,9 +900,10 @@ void LanguageServerMain(std::string process_name) { } int main(int argc, char** argv) { - bool loop = false; - while (loop) - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + //bool loop = true; + //while (loop) + // std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::seconds(3)); PlatformInit(); RegisterMessageTypes(); diff --git a/src/indexer.cpp b/src/indexer.cpp index 869a9e59..f20ce594 100644 --- a/src/indexer.cpp +++ b/src/indexer.cpp @@ -5,7 +5,7 @@ #include "serializer.h" -IndexedFile::IndexedFile(const std::string& path) : path(path) { +IndexedFile::IndexedFile(const std::string& path) : id_cache(path), path(path) { // TODO: Reconsider if we should still be reusing the same id_cache. // Preallocate any existing resolved ids. for (const auto& entry : id_cache.usr_to_type_id) @@ -119,13 +119,13 @@ std::string Location::ToPrettyString(IdCache* id_cache) { return result; } -IdCache::IdCache() { +IdCache::IdCache(const std::string& primary_file) : primary_file(primary_file) { // Reserve id 0 for unfound. file_path_to_file_id[""] = FileId(0); file_id_to_file_path[FileId(0)] = ""; } -Location IdCache::Resolve(const CXSourceLocation& cx_loc, bool interesting) { +Location IdCache::ForceResolve(const CXSourceLocation& cx_loc, bool interesting) { CXFile file; unsigned int line, column, offset; clang_getSpellingLocation(cx_loc, &file, &line, &column, &offset); @@ -137,7 +137,8 @@ Location IdCache::Resolve(const CXSourceLocation& cx_loc, bool interesting) { auto it = file_path_to_file_id.find(path); if (it != file_path_to_file_id.end()) { file_id = it->second; - } else { + } + else { file_id = FileId(file_path_to_file_id.size()); file_path_to_file_id[path] = file_id; file_id_to_file_path[file_id] = path; @@ -147,16 +148,32 @@ Location IdCache::Resolve(const CXSourceLocation& cx_loc, bool interesting) { return Location(interesting, file_id, line, column); } -Location IdCache::Resolve(const CXIdxLoc& cx_idx_loc, bool interesting) { +Location IdCache::ForceResolve(const CXIdxLoc& cx_idx_loc, bool interesting) { + CXSourceLocation cx_loc = clang_indexLoc_getCXSourceLocation(cx_idx_loc); + return ForceResolve(cx_loc, interesting); +} + +Location IdCache::ForceResolve(const CXCursor& cx_cursor, bool interesting) { + return ForceResolve(clang_getCursorLocation(cx_cursor), interesting); +} + + +optional IdCache::Resolve(const CXSourceLocation& cx_loc, bool interesting) { + if (!clang_Location_isFromMainFile(cx_loc)) + return nullopt; + return ForceResolve(cx_loc, interesting); +} + +optional IdCache::Resolve(const CXIdxLoc& cx_idx_loc, bool interesting) { CXSourceLocation cx_loc = clang_indexLoc_getCXSourceLocation(cx_idx_loc); return Resolve(cx_loc, interesting); } -Location IdCache::Resolve(const CXCursor& cx_cursor, bool interesting) { +optional IdCache::Resolve(const CXCursor& cx_cursor, bool interesting) { return Resolve(clang_getCursorLocation(cx_cursor), interesting); } -Location IdCache::Resolve(const clang::Cursor& cursor, bool interesting) { +optional IdCache::Resolve(const clang::Cursor& cursor, bool interesting) { return Resolve(cursor.cx_cursor, interesting); } @@ -236,7 +253,7 @@ void diagnostic(CXClientData client_data, std::string spelling = clang::ToString(clang_getDiagnosticSpelling(diagnostic)); - Location location = param->db->id_cache.Resolve( + Location location = param->db->id_cache.ForceResolve( clang_getDiagnosticLocation(diagnostic), false /*interesting*/); std::cerr << location.ToPrettyString(¶m->db->id_cache) << ": " @@ -386,8 +403,11 @@ void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor, if (param->is_interesting) { IndexedTypeDef* ref_type_def = db->Resolve(ref_type_id); - Location loc = db->id_cache.Resolve(cursor, true /*interesting*/); - AddUsage(ref_type_def->uses, loc); + // TODO: Should we even be visiting this if the file is not from the main + // def? Try adding assert on |loc| later. + optional loc = db->id_cache.Resolve(cursor, true /*interesting*/); + if (loc) + AddUsage(ref_type_def->uses, loc.value()); } } @@ -451,13 +471,10 @@ optional ResolveToDeclarationType(IndexedFile* db, } // Add usages to any seen TypeRef or TemplateRef under the given |decl_cursor|. -// This -// returns the first seen TypeRef or TemplateRef value, which can be useful if -// trying -// to figure out ie, what a using statement refers to. If trying to generally -// resolve -// a cursor to a type, use ResolveToDeclarationType, which works in more -// scenarios. +// This returns the first seen TypeRef or TemplateRef value, which can be +// useful if trying to figure out ie, what a using statement refers to. If +// trying to generally resolve a cursor to a type, use +// ResolveToDeclarationType, which works in more scenarios. optional AddDeclTypeUsages( IndexedFile* db, clang::Cursor decl_cursor, @@ -638,12 +655,14 @@ clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor, if (ref_usr == "") break; - VarId ref_id = db->ToVarId(ref_usr); - IndexedVarDef* ref_def = db->Resolve(ref_id); - Location loc = db->id_cache.Resolve(cursor, false /*interesting*/); + optional loc = db->id_cache.Resolve(cursor, false /*interesting*/); // std::cerr << "Adding usage to id=" << ref_id.id << " usr=" << ref_usr // << " at " << loc.ToString() << std::endl; - AddUsage(ref_def->uses, loc); + if (loc) { + VarId ref_id = db->ToVarId(ref_usr); + IndexedVarDef* ref_def = db->Resolve(ref_id); + AddUsage(ref_def->uses, loc.value()); + } break; } @@ -680,6 +699,11 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_Field: case CXIdxEntity_Variable: case CXIdxEntity_CXXStaticVariable: { + optional decl_loc = + db->id_cache.Resolve(decl->loc, false /*interesting*/); + if (!decl_loc) + break; + clang::Cursor decl_cursor = decl->cursor; // Do not index implicit template instantiations. @@ -692,8 +716,6 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { VarId var_id = db->ToVarId(decl->entityInfo->USR); IndexedVarDef* var_def = db->Resolve(var_id); - var_def->is_bad_def = is_system_def; - // TODO: Eventually run with this if. Right now I want to iron out bugs // this may shadow. // TODO: Verify this gets called multiple times @@ -703,13 +725,11 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { ns->QualifiedName(decl->semanticContainer, var_def->def.short_name); //} - Location decl_loc = - db->id_cache.Resolve(decl->loc, false /*interesting*/); if (decl->isDefinition) - var_def->def.definition = decl_loc; + var_def->def.definition = decl_loc.value(); else - var_def->def.declaration = decl_loc; - AddUsage(var_def->uses, decl_loc); + var_def->def.declaration = decl_loc.value(); + AddUsage(var_def->uses, decl_loc.value()); // std::cerr << std::endl << "Visiting declaration" << std::endl; // Dump(decl_cursor); @@ -725,13 +745,25 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { db, decl_cursor, decl_cursor.get_kind() != CXCursor_ParmDecl /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); - optional var_type = ResolveToDeclarationType(db, decl_cursor); - if (var_type.has_value()) - var_def->def.variable_type = var_type.value(); + // We don't need to assign declaring type multiple times if this variable + // has already been seen. + if (!decl->isRedeclaration) { + optional var_type = ResolveToDeclarationType(db, decl_cursor); + if (var_type.has_value()) { + // Don't treat enum definition variables as instantiations. + bool is_enum_member = decl->semanticContainer && decl->semanticContainer->cursor.kind == CXCursor_EnumDecl; + if (!is_enum_member) + db->Resolve(var_type.value())->instantiations.push_back(var_id.id); + + var_def->def.variable_type = var_type.value(); + } + } + + // TODO: Refactor handlers so more things are under 'if (!decl->isRedeclaration)' if (decl->isDefinition && IsTypeDefinition(decl->semanticContainer)) { TypeId declaring_type_id = - db->ToTypeId(decl->semanticContainer->cursor); + db->ToTypeId(decl->semanticContainer->cursor); IndexedTypeDef* declaring_type_def = db->Resolve(declaring_type_id); var_def->def.declaring_type = declaring_type_id; declaring_type_def->def.vars.push_back(var_id); @@ -746,6 +778,11 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_CXXInstanceMethod: case CXIdxEntity_CXXStaticMethod: case CXIdxEntity_CXXConversionFunction: { + optional decl_loc = + db->id_cache.Resolve(decl->loc, false /*interesting*/); + if (!decl_loc) + break; + clang::Cursor decl_cursor = decl->cursor; clang::Cursor resolved = decl_cursor.template_specialization_to_template_definition(); @@ -753,10 +790,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { FuncId func_id = db->ToFuncId(resolved.cx_cursor); IndexedFuncDef* func_def = db->Resolve(func_id); - Location decl_loc = - db->id_cache.Resolve(decl->loc, false /*interesting*/); - - AddUsage(func_def->uses, decl_loc); + AddUsage(func_def->uses, decl_loc.value()); // We don't actually need to know the return type, but we need to mark it // as an interesting usage. AddDeclTypeUsages(db, decl_cursor, true /*is_interesting*/, @@ -766,9 +800,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // hacking the 'declarations' field by // adding a definition when we really don't have one. if (decl->isDefinition && !func_def->def.definition.has_value()) - func_def->def.definition = decl_loc; + func_def->def.definition = decl_loc.value(); else - func_def->declarations.push_back(decl_loc); + func_def->declarations.push_back(decl_loc.value()); // If decl_cursor != resolved, then decl_cursor is a template // specialization. We @@ -776,8 +810,6 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // that // scenario. if (decl_cursor == resolved) { - func_def->is_bad_def = is_system_def; - // TODO: Eventually run with this if. Right now I want to iron out bugs // this may shadow. // if (!decl->isRedeclaration) { @@ -805,7 +837,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // Mark a type reference at the ctor/dtor location. // TODO: Should it be interesting? if (is_ctor_or_dtor) { - Location type_usage_loc = decl_loc; + Location type_usage_loc = decl_loc.value(); AddUsage(declaring_type_def->uses, type_usage_loc); } @@ -895,6 +927,10 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_Typedef: case CXIdxEntity_CXXTypeAlias: { + optional decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); + if (!decl_loc) + break; + // Note we want to fetch the first TypeRef. Running // ResolveCursorType(decl->cursor) would return // the type of the typedef/using, not the type of the referenced type. @@ -905,8 +941,6 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { TypeId type_id = db->ToTypeId(decl->entityInfo->USR); IndexedTypeDef* type_def = db->Resolve(type_id); - type_def->is_bad_def = is_system_def; - if (alias_of) type_def->def.alias_of = alias_of.value(); @@ -914,9 +948,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { type_def->def.qualified_name = ns->QualifiedName(decl->semanticContainer, type_def->def.short_name); - Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); - type_def->def.definition = decl_loc.WithInteresting(false); - AddUsage(type_def->uses, decl_loc); + type_def->def.definition = decl_loc.value().WithInteresting(false); + AddUsage(type_def->uses, decl_loc.value()); break; } @@ -924,11 +957,13 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_Union: case CXIdxEntity_Struct: case CXIdxEntity_CXXClass: { + optional decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); + if (!decl_loc) + break; + TypeId type_id = db->ToTypeId(decl->entityInfo->USR); IndexedTypeDef* type_def = db->Resolve(type_id); - type_def->is_bad_def = is_system_def; - // TODO: Eventually run with this if. Right now I want to iron out bugs // this may shadow. // TODO: For type section, verify if this ever runs for non definitions? @@ -951,9 +986,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // } assert(decl->isDefinition); - Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); - type_def->def.definition = decl_loc.WithInteresting(false); - AddUsage(type_def->uses, decl_loc); + type_def->def.definition = decl_loc.value().WithInteresting(false); + AddUsage(type_def->uses, decl_loc.value()); // type_def->alias_of // type_def->funcs @@ -972,9 +1006,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { decl->semanticContainer, decl->lexicalContainer); optional parent_type_id = ResolveToDeclarationType(db, base_class->cursor); - IndexedTypeDef* type_def = - db->Resolve(type_id); // type_def ptr could be invalidated by - // ResolveDeclToType. + // type_def ptr could be invalidated by ResolveToDeclarationType. + IndexedTypeDef* type_def = db->Resolve(type_id); if (parent_type_id) { IndexedTypeDef* parent_type_def = db->Resolve(parent_type_id.value()); @@ -990,7 +1023,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { std::cerr << "!! Unhandled indexDeclaration: " << clang::Cursor(decl->cursor).ToString() << " at " - << db->id_cache.Resolve(decl->loc, false /*interesting*/).ToString() + << db->id_cache.ForceResolve(decl->loc, false /*interesting*/).ToString() << std::endl; std::cerr << " entityInfo->kind = " << decl->entityInfo->kind << std::endl; @@ -1024,9 +1057,16 @@ bool IsFunction(CXCursorKind kind) { void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { - if (clang_Location_isInSystemHeader(clang_getCursorLocation(ref->cursor)) || - clang_Location_isInSystemHeader( - clang_getCursorLocation(ref->referencedEntity->cursor))) +// if (clang_Location_isInSystemHeader(clang_getCursorLocation(ref->cursor)) || +// clang_Location_isInSystemHeader( +// clang_getCursorLocation(ref->referencedEntity->cursor))) +// return; + + // Don't index references that are not from the main file. + if (!clang_Location_isFromMainFile(clang_getCursorLocation(ref->cursor))) + return; + // Don't index references to system headers. + if (clang_Location_isInSystemHeader(clang_getCursorLocation(ref->referencedEntity->cursor))) return; IndexParam* param = static_cast(client_data); @@ -1047,13 +1087,16 @@ void indexEntityReference(CXClientData client_data, case CXIdxEntity_CXXStaticVariable: case CXIdxEntity_Variable: case CXIdxEntity_Field: { + optional loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); + if (!loc) + break; + clang::Cursor referenced = ref->referencedEntity->cursor; referenced = referenced.template_specialization_to_template_definition(); VarId var_id = db->ToVarId(referenced.get_usr()); IndexedVarDef* var_def = db->Resolve(var_id); - Location loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); - AddUsage(var_def->uses, loc); + AddUsage(var_def->uses, loc.value()); break; } @@ -1074,10 +1117,14 @@ void indexEntityReference(CXClientData client_data, // Don't report duplicate usages. // TODO: search full history? - Location loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); - if (param->last_func_usage_location == loc) + optional loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); + if (!loc) break; - param->last_func_usage_location = loc; + + // TODO: cleanup/remove this + if (param->last_func_usage_location == loc.value()) + break; + param->last_func_usage_location = loc.value(); // Note: be careful, calling db->ToFuncId invalidates the FuncDef* ptrs. FuncId called_id = db->ToFuncId(ref->referencedEntity->USR); @@ -1086,12 +1133,12 @@ void indexEntityReference(CXClientData client_data, IndexedFuncDef* caller_def = db->Resolve(caller_id); IndexedFuncDef* called_def = db->Resolve(called_id); - caller_def->def.callees.push_back(FuncRef(called_id, loc)); - called_def->callers.push_back(FuncRef(caller_id, loc)); - AddUsage(called_def->uses, loc); + caller_def->def.callees.push_back(FuncRef(called_id, loc.value())); + called_def->callers.push_back(FuncRef(caller_id, loc.value())); + AddUsage(called_def->uses, loc.value()); } else { IndexedFuncDef* called_def = db->Resolve(called_id); - AddUsage(called_def->uses, loc); + AddUsage(called_def->uses, loc.value()); } // For constructor/destructor, also add a usage against the type. Clang @@ -1101,11 +1148,9 @@ void indexEntityReference(CXClientData client_data, clang::Cursor ref_cursor = ref->cursor; if (ref->referencedEntity->kind == CXIdxEntity_CXXConstructor || ref->referencedEntity->kind == CXIdxEntity_CXXDestructor) { - Location parent_loc = db->id_cache.Resolve(ref->parentEntity->cursor, + Location parent_loc = db->id_cache.ForceResolve(ref->parentEntity->cursor, true /*interesting*/); - Location our_loc = - db->id_cache.Resolve(ref->loc, true /*is_interesting*/); - if (!parent_loc.IsEqualTo(our_loc)) { + if (!parent_loc.IsEqualTo(loc.value())) { IndexedFuncDef* called_def = db->Resolve(called_id); // I suspect it is possible for the declaring type to be null // when the class is invalid. @@ -1113,7 +1158,7 @@ void indexEntityReference(CXClientData client_data, // assert(called_def->def.declaring_type.has_value()); IndexedTypeDef* type_def = db->Resolve(called_def->def.declaring_type.value()); - AddUsage(type_def->uses, our_loc); + AddUsage(type_def->uses, loc.value().WithInteresting(true)); } } } @@ -1126,23 +1171,16 @@ void indexEntityReference(CXClientData client_data, case CXIdxEntity_Union: case CXIdxEntity_Struct: case CXIdxEntity_CXXClass: { + optional loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); + if (!loc) + break; + clang::Cursor referenced = ref->referencedEntity->cursor; referenced = referenced.template_specialization_to_template_definition(); TypeId referenced_id = db->ToTypeId(referenced.get_usr()); IndexedTypeDef* referenced_def = db->Resolve(referenced_id); - // We will not get a declaration visit for forward declared types. Try to - // mark them as non-bad - // defs here so we will output usages/etc. - if (referenced_def->is_bad_def) { - bool is_system_def = clang_Location_isInSystemHeader( - clang_getCursorLocation(ref->referencedEntity->cursor)); - Location loc = db->id_cache.Resolve(ref->referencedEntity->cursor, - false /*interesting*/); - if (!is_system_def && loc.raw_file_id != -1) - referenced_def->is_bad_def = false; - } // // The following will generate two TypeRefs to Foo, both located at the // same spot (line 3, column 3). One of the parents will be set to @@ -1159,8 +1197,7 @@ void indexEntityReference(CXClientData client_data, // Foo f; // } // - AddUsage(referenced_def->uses, - db->id_cache.Resolve(ref->loc, false /*interesting*/)); + AddUsage(referenced_def->uses, loc.value()); break; } @@ -1168,7 +1205,7 @@ void indexEntityReference(CXClientData client_data, std::cerr << "!! Unhandled indexEntityReference: " << cursor.ToString() << " at " - << db->id_cache.Resolve(ref->loc, false /*interesting*/).ToString() + << db->id_cache.ForceResolve(ref->loc, false /*interesting*/).ToString() << std::endl; std::cerr << " ref->referencedEntity->kind = " << ref->referencedEntity->kind << std::endl; @@ -1177,7 +1214,7 @@ void indexEntityReference(CXClientData client_data, << ref->parentEntity->kind << std::endl; std::cerr << " ref->loc = " - << db->id_cache.Resolve(ref->loc, false /*interesting*/).ToString() + << db->id_cache.ForceResolve(ref->loc, false /*interesting*/).ToString() << std::endl; std::cerr << " ref->kind = " << ref->kind << std::endl; if (ref->parentEntity) @@ -1239,8 +1276,7 @@ IndexedFile Parse(std::string filename, std::cerr << "!! [START] Indexing " << filename << std::endl; clang_indexTranslationUnit(index_action, ¶m, callbacks, sizeof(callbacks), - CXIndexOpt_IndexFunctionLocalSymbols | - CXIndexOpt_SkipParsedBodiesInSession, + CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations, tu.cx_tu); std::cerr << "!! [END] Indexing " << filename << std::endl; clang_IndexAction_dispose(index_action); diff --git a/src/indexer.h b/src/indexer.h index e6c86b65..c71756f0 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -323,16 +323,27 @@ struct IndexedTypeDef { // Immediate derived types. std::vector derived; + // Declared variables of this type. + // TODO: this needs a lot more work and lots of tests. + // TODO: add instantiation on ctor / dtor, do not add instantiation if type is ptr + std::vector instantiations; + // Every usage, useful for things like renames. // NOTE: Do not insert directly! Use AddUsage instead. std::vector uses; - bool is_bad_def = true; - IndexedTypeDef() : def("") {} // For serialization IndexedTypeDef(TypeId id, const std::string& usr); + bool HasInterestingState() const { + return + def.definition || + !derived.empty() || + !instantiations.empty() || + !uses.empty(); + } + bool operator<(const IndexedTypeDef& other) const { return def.usr < other.def.usr; } @@ -428,13 +439,21 @@ struct IndexedFuncDef { // All usages. For interesting usages, see callees. std::vector uses; - bool is_bad_def = true; - IndexedFuncDef() {} // For reflection. IndexedFuncDef(FuncId id, const std::string& usr) : def(usr), id(id) { // assert(usr.size() > 0); } + bool HasInterestingState() const { + return + def.definition || + !def.callees.empty() || + !declarations.empty() || + !derived.empty() || + !callers.empty() || + !uses.empty(); + } + bool operator<(const IndexedFuncDef& other) const { return def.usr < other.def.usr; } @@ -503,14 +522,18 @@ struct IndexedVarDef { // Usages. std::vector uses; - bool is_bad_def = true; - IndexedVarDef() : def("") {} // For serialization IndexedVarDef(VarId id, const std::string& usr) : def(usr), id(id) { // assert(usr.size() > 0); } + bool HasInterestingState() const { + return + def.definition || + !uses.empty(); + } + bool operator<(const IndexedVarDef& other) const { return def.usr < other.def.usr; } @@ -518,6 +541,7 @@ struct IndexedVarDef { MAKE_HASHABLE(IndexedVarDef, t.def.usr); struct IdCache { + std::string primary_file; std::unordered_map file_path_to_file_id; std::unordered_map usr_to_type_id; std::unordered_map usr_to_func_id; @@ -527,11 +551,14 @@ struct IdCache { std::unordered_map func_id_to_usr; std::unordered_map var_id_to_usr; - IdCache(); - Location Resolve(const CXSourceLocation& cx_loc, bool interesting); - Location Resolve(const CXIdxLoc& cx_idx_loc, bool interesting); - Location Resolve(const CXCursor& cx_cursor, bool interesting); - Location Resolve(const clang::Cursor& cursor, bool interesting); + IdCache(const std::string& primary_file); + Location ForceResolve(const CXSourceLocation& cx_loc, bool interesting); + Location ForceResolve(const CXIdxLoc& cx_idx_loc, bool interesting); + Location ForceResolve(const CXCursor& cx_cursor, bool interesting); + optional Resolve(const CXSourceLocation& cx_loc, bool interesting); + optional Resolve(const CXIdxLoc& cx_idx_loc, bool interesting); + optional Resolve(const CXCursor& cx_cursor, bool interesting); + optional Resolve(const clang::Cursor& cursor, bool interesting); }; struct IndexedFile { diff --git a/src/libclangmm/TranslationUnit.cc b/src/libclangmm/TranslationUnit.cc index c6c65397..14f5d3e3 100644 --- a/src/libclangmm/TranslationUnit.cc +++ b/src/libclangmm/TranslationUnit.cc @@ -24,6 +24,11 @@ TranslationUnit::TranslationUnit( for (const auto& arg : platform_args) args.push_back(arg.c_str()); + std::cerr << "Parsing " << filepath << " with args "; + for (const auto& arg : args) + std::cerr << arg << " "; + std::cerr << std::endl; + CXErrorCode error_code = clang_parseTranslationUnit2( index.cx_index, filepath.c_str(), diff --git a/src/query.cc b/src/query.cc index 9911cb96..dc1fc78e 100644 --- a/src/query.cc +++ b/src/query.cc @@ -46,8 +46,10 @@ Usr MapIdToUsr(const IdCache& id_cache, const VarId& id) { return id_cache.var_id_to_usr.find(id)->second; } QueryableLocation MapIdToUsr(const IdCache& id_cache, const Location& id) { - assert(id_cache.file_id_to_file_path.find(id.file_id()) != id_cache.file_id_to_file_path.end()); - return QueryableLocation(id_cache.file_id_to_file_path.find(id.file_id())->second, id.line, id.column, id.interesting); + assert(id.raw_file_id == 1); + return QueryableLocation(id_cache.primary_file, id.line, id.column, id.interesting); + //assert(id_cache.file_id_to_file_path.find(id.file_id()) != id_cache.file_id_to_file_path.end()); + //return QueryableLocation(id_cache.file_id_to_file_path.find(id.file_id())->second, id.line, id.column, id.interesting); } std::vector MapIdToUsr(const IdCache& id_cache, const std::vector& ids) { @@ -173,6 +175,7 @@ QueryableFile::QueryableFile(const IndexedFile& indexed) QueryableTypeDef::QueryableTypeDef(IdCache& id_cache, const IndexedTypeDef& indexed) : def(MapIdToUsr(id_cache, indexed.def)) { derived = MapIdToUsr(id_cache, indexed.derived); + instantiations = MapIdToUsr(id_cache, indexed.instantiations); uses = MapIdToUsr(id_cache, indexed.uses); } @@ -314,12 +317,12 @@ void CompareGroups( while (prev_it != previous_data.end() && curr_it != current_data.end()) { // same id if (prev_it->def.usr == curr_it->def.usr) { - if (!prev_it->is_bad_def && !curr_it->is_bad_def) + //if (!prev_it->is_bad_def && !curr_it->is_bad_def) on_found(&*prev_it, &*curr_it); - else if (prev_it->is_bad_def) - on_added(&*curr_it); - else if (curr_it->is_bad_def) - on_removed(&*curr_it); + //else if (prev_it->is_bad_def) + // on_added(&*curr_it); + //else if (curr_it->is_bad_def) + // on_removed(&*curr_it); ++prev_it; ++curr_it; @@ -368,17 +371,16 @@ void CompareGroups( IndexUpdate::IndexUpdate(IndexedFile& file) { + // TODO: Do not add empty data (ie, def has nothing but USR) + files_added.push_back(QueryableFile(file)); for (const IndexedTypeDef& def : file.types) { - if (def.is_bad_def) continue; types_added.push_back(QueryableTypeDef(file.id_cache, def)); } for (const IndexedFuncDef& def : file.funcs) { - if (def.is_bad_def) continue; funcs_added.push_back(QueryableFuncDef(file.id_cache, def)); } for (const IndexedVarDef& def : file.vars) { - if (def.is_bad_def) continue; vars_added.push_back(QueryableVarDef(file.id_cache, def)); } } @@ -491,6 +493,7 @@ void IndexUpdate::Merge(const IndexUpdate& update) { INDEX_UPDATE_MERGE(types_added); INDEX_UPDATE_MERGE(types_def_changed); INDEX_UPDATE_MERGE(types_derived); + INDEX_UPDATE_MERGE(types_instantiations); INDEX_UPDATE_MERGE(types_uses); INDEX_UPDATE_MERGE(funcs_removed); diff --git a/src/query.h b/src/query.h index 84e9fe85..517d3576 100644 --- a/src/query.h +++ b/src/query.h @@ -22,6 +22,10 @@ struct QueryableLocation { QueryableLocation(Usr path, int line, int column, bool interesting) : path(path), line(line), column(column), interesting(interesting) {} + QueryableLocation OffsetColumn(int offset) const { + return QueryableLocation(path, line, column + offset, interesting); + } + bool operator==(const QueryableLocation& other) const { // Note: We ignore |is_interesting|. return @@ -104,16 +108,18 @@ MAKE_REFLECT_STRUCT(QueryableFile, file_id, outline); struct QueryableTypeDef { using DefUpdate = TypeDefDefinitionData; using DerivedUpdate = MergeableUpdate; + using InstantiationsUpdate = MergeableUpdate; using UsesUpdate = MergeableUpdate; DefUpdate def; std::vector derived; + std::vector instantiations; std::vector uses; QueryableTypeDef() : def("") {} // For serialization. QueryableTypeDef(IdCache& id_cache, const IndexedTypeDef& indexed); }; -MAKE_REFLECT_STRUCT(QueryableTypeDef, def, derived, uses); +MAKE_REFLECT_STRUCT(QueryableTypeDef, def, derived, instantiations, uses); struct QueryableFuncDef { using DefUpdate = FuncDefDefinitionData; @@ -186,6 +192,7 @@ struct IndexUpdate { std::vector types_added; std::vector types_def_changed; std::vector types_derived; + std::vector types_instantiations; std::vector types_uses; // Function updates. diff --git a/src/serializer.cc b/src/serializer.cc index d6ee1680..65a4663f 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -40,6 +40,9 @@ void Reflect(Reader& visitor, Location& value) { value = Location(visitor.GetString()); } void Reflect(Writer& visitor, Location& value) { + // We only ever want to emit id=1 files. + assert(value.raw_file_id == 1); + std::string output = value.ToString(); visitor.String(output.c_str(), output.size()); } @@ -76,15 +79,22 @@ void Reflect(Writer& visitor, Ref& value) { +// TODO: Move this to indexer.cpp +// TODO: Rename indexer.cpp to indexer.cc +// TODO: Do not serialize a USR if it has no usages/etc outside of USR info. // IndexedTypeDef bool ReflectMemberStart(Reader& reader, IndexedTypeDef& value) { - value.is_bad_def = false; + //value.is_bad_def = false; return true; } bool ReflectMemberStart(Writer& writer, IndexedTypeDef& value) { - if (value.is_bad_def) - return false; + if (!value.HasInterestingState()) + std::cerr << "bad"; + assert(value.HasInterestingState()); + + //if (value.is_bad_def) + // return false; DefaultReflectMemberStart(writer); return true; } @@ -102,6 +112,7 @@ void Reflect(TVisitor& visitor, IndexedTypeDef& value) { REFLECT_MEMBER2("types", value.def.types); REFLECT_MEMBER2("funcs", value.def.funcs); REFLECT_MEMBER2("vars", value.def.vars); + REFLECT_MEMBER2("instantiations", value.instantiations); REFLECT_MEMBER2("uses", value.uses); REFLECT_MEMBER_END(); } @@ -109,12 +120,16 @@ void Reflect(TVisitor& visitor, IndexedTypeDef& value) { // IndexedFuncDef bool ReflectMemberStart(Reader& reader, IndexedFuncDef& value) { - value.is_bad_def = false; + //value.is_bad_def = false; return true; } bool ReflectMemberStart(Writer& writer, IndexedFuncDef& value) { - if (value.is_bad_def) - return false; + if (!value.HasInterestingState()) + std::cerr << "bad"; + assert(value.HasInterestingState()); + + //if (value.is_bad_def) + // return false; DefaultReflectMemberStart(writer); return true; } @@ -140,12 +155,16 @@ void Reflect(TVisitor& visitor, IndexedFuncDef& value) { // IndexedVarDef bool ReflectMemberStart(Reader& reader, IndexedVarDef& value) { - value.is_bad_def = false; + //value.is_bad_def = false; return true; } bool ReflectMemberStart(Writer& writer, IndexedVarDef& value) { - if (value.is_bad_def) - return false; + if (!value.HasInterestingState()) + std::cerr << "bad"; + assert(value.HasInterestingState()); + + //if (value.is_bad_def) + // return false; DefaultReflectMemberStart(writer); return true; } @@ -204,9 +223,11 @@ std::string Serialize(IndexedFile& file) { return output.GetString(); } -IndexedFile Deserialize(std::string path, std::string serialized) { +optional Deserialize(std::string path, std::string serialized) { rapidjson::Document reader; reader.Parse(serialized.c_str()); + if (reader.HasParseError()) + return nullopt; IndexedFile file(path); Reflect(reader, file); diff --git a/src/serializer.h b/src/serializer.h index 4627e19b..0c568a32 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -204,4 +204,4 @@ void ReflectMember(Reader& visitor, const char* name, T& value) { } std::string Serialize(IndexedFile& file); -IndexedFile Deserialize(std::string path, std::string serialized); +optional Deserialize(std::string path, std::string serialized); diff --git a/src/test.cc b/src/test.cc index 69f4cc9c..2e5f82cc 100644 --- a/src/test.cc +++ b/src/test.cc @@ -22,7 +22,7 @@ std::string ToString(const rapidjson::Document& document) { return buffer.GetString(); } -std::vector split_string(const std::string& str, const std::string& delimiter) { +std::vector SplitString(const std::string& str, const std::string& delimiter) { // http://stackoverflow.com/a/13172514 std::vector strings; @@ -40,22 +40,30 @@ std::vector split_string(const std::string& str, const std::string& } -void DiffDocuments(rapidjson::Document& expected, rapidjson::Document& actual) { - std::vector actual_output; - { - std::string buffer = ToString(actual); - actual_output = split_string(buffer, "\n"); - } +void DiffDocuments(std::string path, rapidjson::Document& expected, rapidjson::Document& actual) { + std::string joined_actual_output = ToString(actual); + std::vector actual_output = SplitString(joined_actual_output, "\n"); + std::string joined_expected_output = ToString(expected); + std::vector expected_output = SplitString(joined_expected_output, "\n"); - std::vector expected_output; - { - std::string buffer = ToString(expected); - expected_output = split_string(buffer, "\n"); - } + + std::cout << "[FAILED] " << path << std::endl; + std::cout << "Expected output for " << path << ":" << std::endl; + std::cout << joined_expected_output << std::endl; + std::cout << "Actual output for " << path << ":" << std::endl; + std::cout << joined_actual_output << std::endl; + std::cout << std::endl; + + int max_diff = 5; int len = std::min(actual_output.size(), expected_output.size()); for (int i = 0; i < len; ++i) { if (actual_output[i] != expected_output[i]) { + if (--max_diff < 0) { + std::cout << "(... more lines may differ ...)" << std::endl; + break; + } + std::cout << "Line " << i << " differs:" << std::endl; std::cout << " expected: " << expected_output[i] << std::endl; std::cout << " actual: " << actual_output[i] << std::endl; @@ -78,7 +86,7 @@ void DiffDocuments(rapidjson::Document& expected, rapidjson::Document& actual) { void VerifySerializeToFrom(IndexedFile& file) { return; // TODO: reenable std::string expected = file.ToString(); - std::string actual = Deserialize("foo.cc", Serialize(file)).ToString(); + std::string actual = Deserialize("foo.cc", Serialize(file)).value().ToString(); if (expected != actual) { std::cerr << "Serialization failure" << std::endl;; assert(false); @@ -99,9 +107,11 @@ void RunTests() { for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { //if (path != "tests/templates/specialized_func_definition.cc") continue; //if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue; - //if (path != "tests/foo2.cc") continue; - //if (path != "tests/namespaces/namespace_reference.cc") continue; + //if (path != "tests/multi_file/header.h") continue; + //if (path != "tests/multi_file/impl.cc") continue; + //if (path != "tests/inheritance/class_inherit_templated_parent.cc") continue; //if (path != "tests/templates/implicit_variable_instantiation.cc") continue; + //if (path != "tests/_empty_test.cc") continue; //if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue; //path = "C:/Users/jacob/Desktop/superindex/indexer/" + path; @@ -114,7 +124,14 @@ void RunTests() { // Run test. std::cout << "[START] " << path << std::endl; - IndexedFile db = Parse(path, {}, false /*dump_ast*/); + IndexedFile db = Parse(path, { + "-xc++", + "-std=c++11", + "-IC:/Users/jacob/Desktop/superindex/indexer/third_party/", + "-IC:/Users/jacob/Desktop/superindex/indexer/third_party/doctest/", + "-IC:/Users/jacob/Desktop/superindex/indexer/third_party/rapidjson/include", + "-IC:/Users/jacob/Desktop/superindex/indexer/src" + }, false /*dump_ast*/); VerifySerializeToFrom(db); std::string actual_output = db.ToString(); @@ -125,14 +142,7 @@ void RunTests() { std::cout << "[PASSED] " << path << std::endl; } else { - std::cout << "[FAILED] " << path << std::endl; - std::cout << "Expected output for " << path << ":" << std::endl; - std::cout << expected_output; - std::cout << "Actual output for " << path << ":" << std::endl; - std::cout << actual_output; - std::cout << std::endl; - std::cout << std::endl; - DiffDocuments(expected, actual); + DiffDocuments(path, expected, actual); break; } } diff --git a/tests/constructors/constructor.cc b/tests/constructors/constructor.cc index 31b40464..517f3aeb 100644 --- a/tests/constructors/constructor.cc +++ b/tests/constructors/constructor.cc @@ -18,6 +18,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "funcs": [0], + "instantiations": [0, 1], "uses": ["*1:1:7", "1:3:3", "*1:7:3", "*1:8:3", "*1:8:17"] }], "funcs": [{ diff --git a/tests/constructors/destructor.cc b/tests/constructors/destructor.cc index dd11dfd4..c576f9b9 100644 --- a/tests/constructors/destructor.cc +++ b/tests/constructors/destructor.cc @@ -23,6 +23,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "funcs": [0, 1], + "instantiations": [0], "uses": ["*1:1:7", "1:3:3", "1:4:3", "*1:8:3"] }], "funcs": [{ diff --git a/tests/enums/enum_usage.cc b/tests/enums/enum_usage.cc index 7ec97e94..ed8a7ded 100644 --- a/tests/enums/enum_usage.cc +++ b/tests/enums/enum_usage.cc @@ -15,6 +15,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:12", "vars": [0, 1], + "instantiations": [2], "uses": ["*1:1:12", "*1:6:1", "1:6:9"] }], "vars": [{ diff --git a/tests/foobar.cc b/tests/foobar.cc index 24992523..c83cadd7 100644 --- a/tests/foobar.cc +++ b/tests/foobar.cc @@ -31,6 +31,7 @@ OUTPUT: "short_name": "Foo", "qualified_name": "Foo", "definition": "1:5:8", + "instantiations": [1], "uses": ["*1:5:8", "*1:9:1", "*1:10:1"] }, { "id": 3, @@ -38,6 +39,7 @@ OUTPUT: "short_name": "Inner", "qualified_name": "Foo::Inner", "definition": "1:6:10", + "instantiations": [0], "uses": ["*1:6:10", "*1:9:9"] }], "vars": [{ diff --git a/tests/inheritance/class_inherit_templated_parent.cc b/tests/inheritance/class_inherit_templated_parent.cc index 4976c913..fcd8cc4f 100644 --- a/tests/inheritance/class_inherit_templated_parent.cc +++ b/tests/inheritance/class_inherit_templated_parent.cc @@ -49,6 +49,10 @@ OUTPUT: "parents": [1], "derived": [5], "uses": ["*1:11:7", "*1:13:56"] + }, { + "id": 4, + "usr": "c:class_inherit_templated_parent.cc@154", + "uses": ["*1:11:24"] }, { "id": 5, "usr": "c:@S@Derived", diff --git a/tests/multi_file/header.h b/tests/multi_file/header.h new file mode 100644 index 00000000..25dc0146 --- /dev/null +++ b/tests/multi_file/header.h @@ -0,0 +1,121 @@ +#pragma once + +#include "../../third_party/doctest/doctest/doctest.h" +#include "../../third_party/macro_map.h" +#include "../../third_party/optional.h" +#include +#include +#include + +struct Base {}; + +struct SameFileDerived : Base {}; + +using Foo0 = SameFileDerived; + +template +void Foo1() {} + +template +struct Foo2 {}; + +enum Foo3 { A, B, C }; + +int Foo4; +static int Foo5; + +/* +OUTPUT: +{ + "types": [{ + "id": 0, + "usr": "c:@S@Base", + "short_name": "Base", + "qualified_name": "Base", + "definition": "1:10:8", + "derived": [1], + "uses": ["*1:10:8", "*1:12:26"] + }, { + "id": 1, + "usr": "c:@S@SameFileDerived", + "short_name": "SameFileDerived", + "qualified_name": "SameFileDerived", + "definition": "1:12:8", + "parents": [0], + "uses": ["*1:12:8", "*1:14:14"] + }, { + "id": 2, + "usr": "c:@Foo0", + "short_name": "Foo0", + "qualified_name": "Foo0", + "definition": "1:14:7", + "alias_of": 1, + "uses": ["*1:14:7"] + }, { + "id": 3, + "usr": "c:@ST>1#T@Foo2", + "short_name": "Foo2", + "qualified_name": "Foo2", + "definition": "1:20:8", + "uses": ["*1:20:8"] + }, { + "id": 4, + "usr": "c:@E@Foo3", + "short_name": "Foo3", + "qualified_name": "Foo3", + "definition": "1:22:6", + "vars": [0, 1, 2], + "uses": ["*1:22:6"] + }], + "funcs": [{ + "id": 0, + "usr": "c:@FT@>1#TFoo1#v#", + "short_name": "Foo1", + "qualified_name": "Foo1", + "definition": "1:17:6", + "uses": ["1:17:6"] + }], + "vars": [{ + "id": 0, + "usr": "c:@E@Foo3@A", + "short_name": "A", + "qualified_name": "Foo3::A", + "definition": "1:22:13", + "variable_type": 4, + "declaring_type": 4, + "uses": ["1:22:13"] + }, { + "id": 1, + "usr": "c:@E@Foo3@B", + "short_name": "B", + "qualified_name": "Foo3::B", + "definition": "1:22:16", + "variable_type": 4, + "declaring_type": 4, + "uses": ["1:22:16"] + }, { + "id": 2, + "usr": "c:@E@Foo3@C", + "short_name": "C", + "qualified_name": "Foo3::C", + "definition": "1:22:19", + "variable_type": 4, + "declaring_type": 4, + "uses": ["1:22:19"] + }, { + "id": 3, + "usr": "c:@Foo4", + "short_name": "Foo4", + "qualified_name": "Foo4", + "definition": "1:24:5", + "uses": ["1:24:5"] + }, { + "id": 4, + "usr": "c:header.h@Foo5", + "short_name": "Foo5", + "qualified_name": "Foo5", + "definition": "1:25:12", + "uses": ["1:25:12"] + }] +} +*/ diff --git a/tests/multi_file/impl.cc b/tests/multi_file/impl.cc new file mode 100644 index 00000000..9c068d29 --- /dev/null +++ b/tests/multi_file/impl.cc @@ -0,0 +1,1053 @@ +#include "serializer.h" +#include "indexer.h" + +// int +void Reflect(Reader& visitor, int& value) { + value = visitor.GetInt(); +} +void Reflect(Writer& visitor, int& value) { + visitor.Int(value); +} +// bool +void Reflect(Reader& visitor, bool& value) { + value = visitor.GetBool(); +} +void Reflect(Writer& visitor, bool& value) { + visitor.Bool(value); +} +// std::string +void Reflect(Reader& visitor, std::string& value) { + value = visitor.GetString(); +} +void Reflect(Writer& visitor, std::string& value) { + visitor.String(value.c_str(), value.size()); +} + + +// ReflectMember +void ReflectMember(Writer& visitor, const char* name, std::string& value) { + if (value.empty()) + return; + visitor.Key(name); + Reflect(visitor, value); +} + + +// Location +void Reflect(Reader& visitor, Location& value) { + value = Location(visitor.GetString()); +} +void Reflect(Writer& visitor, Location& value) { + // We only ever want to emit id=1 files. + assert(value.raw_file_id == 1); + + std::string output = value.ToString(); + visitor.String(output.c_str(), output.size()); +} + + +// Id +template +void Reflect(Reader& visitor, Id& id) { + id.id = visitor.GetUint64(); +} +template +void Reflect(Writer& visitor, Id& value) { + visitor.Uint64(value.id); +} + + +// Ref +void Reflect(Reader& visitor, Ref& value) { + const char* str_value = visitor.GetString(); + uint64_t id = atoi(str_value); + const char* loc_string = strchr(str_value, '@') + 1; + + value.id = Id(id); + value.loc = Location(loc_string); +} +void Reflect(Writer& visitor, Ref& value) { + std::string s = std::to_string(value.id.id) + "@" + value.loc.ToString(); + visitor.String(s.c_str()); +} + + + + + + + +// TODO: Move this to indexer.cpp +// TODO: Rename indexer.cpp to indexer.cc +// TODO: Do not serialize a USR if it has no usages/etc outside of USR info. + +// IndexedTypeDef +bool ReflectMemberStart(Reader& reader, IndexedTypeDef& value) { + //value.is_bad_def = false; + return true; +} +bool ReflectMemberStart(Writer& writer, IndexedTypeDef& value) { + //if (value.is_bad_def) + // return false; + DefaultReflectMemberStart(writer); + return true; +} +template +void Reflect(TVisitor& visitor, IndexedTypeDef& value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER2("id", value.id); + REFLECT_MEMBER2("usr", value.def.usr); + REFLECT_MEMBER2("short_name", value.def.short_name); + REFLECT_MEMBER2("qualified_name", value.def.qualified_name); + REFLECT_MEMBER2("definition", value.def.definition); + REFLECT_MEMBER2("alias_of", value.def.alias_of); + REFLECT_MEMBER2("parents", value.def.parents); + REFLECT_MEMBER2("derived", value.derived); + REFLECT_MEMBER2("types", value.def.types); + REFLECT_MEMBER2("funcs", value.def.funcs); + REFLECT_MEMBER2("vars", value.def.vars); + REFLECT_MEMBER2("uses", value.uses); + REFLECT_MEMBER_END(); +} + + +// IndexedFuncDef +bool ReflectMemberStart(Reader& reader, IndexedFuncDef& value) { + //value.is_bad_def = false; + return true; +} +bool ReflectMemberStart(Writer& writer, IndexedFuncDef& value) { + //if (value.is_bad_def) + // return false; + DefaultReflectMemberStart(writer); + return true; +} +template +void Reflect(TVisitor& visitor, IndexedFuncDef& value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER2("id", value.id); + REFLECT_MEMBER2("usr", value.def.usr); + REFLECT_MEMBER2("short_name", value.def.short_name); + REFLECT_MEMBER2("qualified_name", value.def.qualified_name); + REFLECT_MEMBER2("declarations", value.declarations); + REFLECT_MEMBER2("definition", value.def.definition); + REFLECT_MEMBER2("declaring_type", value.def.declaring_type); + REFLECT_MEMBER2("base", value.def.base); + REFLECT_MEMBER2("derived", value.derived); + REFLECT_MEMBER2("locals", value.def.locals); + REFLECT_MEMBER2("callers", value.callers); + REFLECT_MEMBER2("callees", value.def.callees); + REFLECT_MEMBER2("uses", value.uses); + REFLECT_MEMBER_END(); +} + + +// IndexedVarDef +bool ReflectMemberStart(Reader& reader, IndexedVarDef& value) { + //value.is_bad_def = false; + return true; +} +bool ReflectMemberStart(Writer& writer, IndexedVarDef& value) { + //if (value.is_bad_def) + // return false; + DefaultReflectMemberStart(writer); + return true; +} +template +void Reflect(TVisitor& visitor, IndexedVarDef& value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER2("id", value.id); + REFLECT_MEMBER2("usr", value.def.usr); + REFLECT_MEMBER2("short_name", value.def.short_name); + REFLECT_MEMBER2("qualified_name", value.def.qualified_name); + REFLECT_MEMBER2("declaration", value.def.declaration); + REFLECT_MEMBER2("definition", value.def.definition); + REFLECT_MEMBER2("variable_type", value.def.variable_type); + REFLECT_MEMBER2("declaring_type", value.def.declaring_type); + REFLECT_MEMBER2("uses", value.uses); + REFLECT_MEMBER_END(); +} + + +// IndexedFile +bool ReflectMemberStart(Writer& visitor, IndexedFile& value) { + auto it = value.id_cache.usr_to_type_id.find(""); + if (it != value.id_cache.usr_to_type_id.end()) { + value.Resolve(it->second)->def.short_name = ""; + assert(value.Resolve(it->second)->uses.size() == 0); + } + + DefaultReflectMemberStart(visitor); + return true; +} +template +void Reflect(TVisitor& visitor, IndexedFile& value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER(types); + REFLECT_MEMBER(funcs); + REFLECT_MEMBER(vars); + REFLECT_MEMBER_END(); +} + + + + + + + +std::string Serialize(IndexedFile& file) { + rapidjson::StringBuffer output; + rapidjson::PrettyWriter writer(output); + //Writer writer(output); + writer.SetFormatOptions( + rapidjson::PrettyFormatOptions::kFormatSingleLineArray); + writer.SetIndent(' ', 2); + + Reflect(writer, file); + + return output.GetString(); +} + +optional Deserialize(std::string path, std::string serialized) { + rapidjson::Document reader; + reader.Parse(serialized.c_str()); + if (reader.HasParseError()) + return nullopt; + + IndexedFile file(path); + Reflect(reader, file); + + return file; +} + +#if false +#include "header.h" +#include "serializer.h" + + +struct SeparateFileDerived : Base {}; + +void f() { + rapidjson::StringBuffer output; + rapidjson::PrettyWriter writer(output); + //Writer writer(output); + writer.SetFormatOptions( + rapidjson::PrettyFormatOptions::kFormatSingleLineArray); + writer.SetIndent(' ', 2); + + Foo2 a; +} +#endif + +/* +OUTPUT: +{ + "types": [{ + "id": 0, + "usr": "c:@Reader", + "instantiations": [0, 4, 8, 15, 20, 24, 32, 38, 44], + "uses": ["*1:5:14", "*1:12:14", "*1:19:14", "*1:37:14", "*1:51:14", "*1:61:14", "*1:85:25", "*1:115:25", "*1:146:25"] + }, { + "id": 1, + "usr": "c:@Writer", + "instantiations": [2, 6, 10, 12, 17, 22, 29, 34, 40, 46, 50], + "uses": ["*1:8:14", "*1:15:14", "*1:22:14", "*1:28:20", "*1:40:14", "*1:55:14", "*1:69:14", "*1:89:25", "*1:119:25", "*1:150:25", "*1:173:25"] + }, { + "id": 2, + "usr": "c:@N@std@T@string", + "instantiations": [9, 11, 14, 19, 31, 58, 59], + "uses": ["*1:19:36", "*1:22:36", "*1:28:60", "*1:44:8", "*1:70:8", "*1:198:6", "*1:211:40", "*1:211:58"] + }, { + "id": 3, + "usr": "c:@S@Location", + "instantiations": [16, 18], + "uses": ["*1:37:31", "*1:40:31"] + }, { + "id": 4, + "usr": "c:@ST>1#T@Id", + "instantiations": [21, 23], + "uses": ["*1:51:31", "*1:55:31"] + }, { + "id": 5, + "usr": "c:impl.cc@1122", + "uses": ["*1:51:34"] + }, { + "id": 6, + "usr": "c:impl.cc@1223", + "uses": ["*1:55:34"] + }, { + "id": 7, + "usr": "c:@ST>1#T@Ref", + "instantiations": [25, 30], + "uses": ["*1:61:31", "*1:69:31"] + }, { + "id": 8, + "usr": "c:@S@IndexedFuncDef", + "instantiations": [39, 41, 43], + "uses": ["*1:61:35", "*1:69:35", "*1:115:41", "*1:119:41", "*1:126:33"] + }, { + "id": 9, + "usr": "c:@T@uint64_t", + "instantiations": [27], + "uses": ["*1:63:3"] + }, { + "id": 10, + "usr": "c:@S@IndexedTypeDef", + "instantiations": [33, 35, 37], + "uses": ["*1:85:41", "*1:89:41", "*1:96:33"] + }, { + "id": 11, + "usr": "c:impl.cc@2280", + "uses": ["*1:96:14"] + }, { + "id": 12, + "usr": "c:impl.cc@3310", + "uses": ["*1:126:14"] + }, { + "id": 13, + "usr": "c:@S@IndexedVarDef", + "instantiations": [45, 47, 49], + "uses": ["*1:146:41", "*1:150:41", "*1:157:33"] + }, { + "id": 14, + "usr": "c:impl.cc@4407", + "uses": ["*1:157:14"] + }, { + "id": 15, + "usr": "c:@S@IndexedFile", + "instantiations": [51, 54, 55, 61], + "uses": ["*1:173:42", "*1:184:33", "*1:198:23", "*1:211:10", "*1:217:3"] + }, { + "id": 16, + "usr": "c:impl.cc@5404", + "uses": ["*1:184:14"] + }, { + "id": 17, + "usr": "c:stringbuffer.h@N@rapidjson@T@StringBuffer", + "instantiations": [56], + "uses": ["*1:199:14"] + }, { + "id": 18, + "usr": "c:@N@std@N@experimental@ST>1#T@optional", + "uses": ["*1:211:1"] + }, { + "id": 19, + "usr": "c:document.h@N@rapidjson@T@Document", + "instantiations": [60], + "uses": ["*1:212:14"] + }], + "funcs": [{ + "id": 0, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&I#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:5:6", + "uses": ["1:5:6"] + }, { + "id": 1, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&I#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:8:6", + "callees": ["2@1:9:11"], + "uses": ["1:8:6"] + }, { + "id": 2, + "usr": "c:@N@rapidjson@ST>5#T#T#T#T#Ni@Writer@F@Int#I#", + "callers": ["1@1:9:11"], + "uses": ["1:9:11"] + }, { + "id": 3, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&b#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:12:6", + "uses": ["1:12:6"] + }, { + "id": 4, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&b#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:15:6", + "callees": ["5@1:16:11"], + "uses": ["1:15:6"] + }, { + "id": 5, + "usr": "c:@N@rapidjson@ST>5#T#T#T#T#Ni@Writer@F@Bool#b#", + "callers": ["4@1:16:11"], + "uses": ["1:16:11"] + }, { + "id": 6, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:19:6", + "uses": ["1:19:6"] + }, { + "id": 7, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:22:6", + "callers": ["8@1:32:3"], + "uses": ["1:22:6", "1:32:3"] + }, { + "id": 8, + "usr": "c:@F@ReflectMember#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#*1C#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#", + "short_name": "ReflectMember", + "qualified_name": "ReflectMember", + "definition": "1:28:6", + "callees": ["9@1:31:11", "7@1:32:3"], + "uses": ["1:28:6"] + }, { + "id": 9, + "usr": "c:@N@rapidjson@ST>5#T#T#T#T#Ni@Writer@F@Key#*1^type-parameter-0-1:::Ch#", + "callers": ["8@1:31:11"], + "uses": ["1:31:11"] + }, { + "id": 10, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Location#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:37:6", + "uses": ["1:37:6"] + }, { + "id": 11, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Location#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:40:6", + "callees": ["12@1:44:30"], + "uses": ["1:40:6"] + }, { + "id": 12, + "usr": "c:@S@Location@F@ToString#", + "callers": ["11@1:44:30"], + "uses": ["1:44:30"] + }, { + "id": 13, + "usr": "c:@FT@>1#TReflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&>@ST>1#T@Id1t0.0#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:51:6", + "uses": ["1:51:6"] + }, { + "id": 14, + "usr": "c:@FT@>1#TReflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&>@ST>1#T@Id1t0.0#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:55:6", + "uses": ["1:55:6"] + }, { + "id": 15, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:61:6", + "uses": ["1:61:6"] + }, { + "id": 16, + "usr": "c:@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Ref>#$@S@IndexedFuncDef#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:69:6", + "callees": ["17@1:71:11"], + "uses": ["1:69:6"] + }, { + "id": 17, + "usr": "c:@N@rapidjson@ST>5#T#T#T#T#Ni@Writer@F@String#*1^type-parameter-0-1:::Ch#", + "callers": ["16@1:71:11"], + "uses": ["1:71:11"] + }, { + "id": 18, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedTypeDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:85:6", + "uses": ["1:85:6"] + }, { + "id": 19, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedTypeDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:89:6", + "callees": ["20@1:92:3"], + "uses": ["1:89:6"] + }, { + "id": 20, + "usr": "c:@F@DefaultReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#", + "callers": ["19@1:92:3", "23@1:122:3", "26@1:153:3", "28@1:180:3"], + "uses": ["1:92:3", "1:122:3", "1:153:3", "1:180:3"] + }, { + "id": 21, + "usr": "c:@FT@>1#TReflect#&t0.0#&$@S@IndexedTypeDef#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:96:6", + "uses": ["1:96:6"] + }, { + "id": 22, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedFuncDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:115:6", + "uses": ["1:115:6"] + }, { + "id": 23, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFuncDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:119:6", + "callees": ["20@1:122:3"], + "uses": ["1:119:6"] + }, { + "id": 24, + "usr": "c:@FT@>1#TReflect#&t0.0#&$@S@IndexedFuncDef#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:126:6", + "uses": ["1:126:6"] + }, { + "id": 25, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedVarDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:146:6", + "uses": ["1:146:6"] + }, { + "id": 26, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedVarDef#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:150:6", + "callees": ["20@1:153:3"], + "uses": ["1:150:6"] + }, { + "id": 27, + "usr": "c:@FT@>1#TReflect#&t0.0#&$@S@IndexedVarDef#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:157:6", + "uses": ["1:157:6"] + }, { + "id": 28, + "usr": "c:@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFile#", + "short_name": "ReflectMemberStart", + "qualified_name": "ReflectMemberStart", + "definition": "1:173:6", + "callees": ["20@1:180:3"], + "uses": ["1:173:6"] + }, { + "id": 29, + "usr": "c:@FT@>1#TReflect#&t0.0#&$@S@IndexedFile#v#", + "short_name": "Reflect", + "qualified_name": "Reflect", + "definition": "1:184:6", + "uses": ["1:184:6"] + }, { + "id": 30, + "usr": "c:@F@Serialize#&$@S@IndexedFile#", + "short_name": "Serialize", + "qualified_name": "Serialize", + "definition": "1:198:13", + "uses": ["1:198:13"] + }, { + "id": 31, + "usr": "c:@F@Deserialize#$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#S0_#", + "short_name": "Deserialize", + "qualified_name": "Deserialize", + "definition": "1:211:23", + "callees": ["32@1:217:15"], + "uses": ["1:211:23"] + }, { + "id": 32, + "usr": "c:@S@IndexedFile@F@IndexedFile#&1$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#", + "callers": ["31@1:217:15"], + "uses": ["1:217:15"] + }], + "vars": [{ + "id": 0, + "usr": "c:impl.cc@70@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&I#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:5:22", + "variable_type": 0, + "uses": ["1:5:22"] + }, { + "id": 1, + "usr": "c:impl.cc@87@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&I#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:5:36", + "uses": ["1:5:36"] + }, { + "id": 2, + "usr": "c:impl.cc@147@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&I#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:8:22", + "variable_type": 1, + "uses": ["1:8:22", "1:9:3"] + }, { + "id": 3, + "usr": "c:impl.cc@164@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&I#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:8:36", + "uses": ["1:8:36", "1:9:15"] + }, { + "id": 4, + "usr": "c:impl.cc@227@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&b#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:12:22", + "variable_type": 0, + "uses": ["1:12:22"] + }, { + "id": 5, + "usr": "c:impl.cc@244@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&b#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:12:37", + "uses": ["1:12:37"] + }, { + "id": 6, + "usr": "c:impl.cc@306@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&b#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:15:22", + "variable_type": 1, + "uses": ["1:15:22", "1:16:3"] + }, { + "id": 7, + "usr": "c:impl.cc@323@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&b#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:15:37", + "uses": ["1:15:37", "1:16:16"] + }, { + "id": 8, + "usr": "c:impl.cc@395@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:19:22", + "variable_type": 0, + "uses": ["1:19:22"] + }, { + "id": 9, + "usr": "c:impl.cc@412@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:19:44", + "variable_type": 2, + "uses": ["1:19:44"] + }, { + "id": 10, + "usr": "c:impl.cc@483@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:22:22", + "variable_type": 1, + "uses": ["1:22:22"] + }, { + "id": 11, + "usr": "c:impl.cc@500@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:22:44", + "variable_type": 2, + "uses": ["1:22:44"] + }, { + "id": 12, + "usr": "c:impl.cc@615@F@ReflectMember#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#*1C#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:28:28", + "variable_type": 1, + "uses": ["1:28:28", "1:31:3", "1:32:11"] + }, { + "id": 13, + "usr": "c:impl.cc@632@F@ReflectMember#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#*1C#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@name", + "short_name": "name", + "qualified_name": "name", + "definition": "1:28:49", + "uses": ["1:28:49", "1:31:15"] + }, { + "id": 14, + "usr": "c:impl.cc@650@F@ReflectMember#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#*1C#&$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:28:68", + "variable_type": 2, + "uses": ["1:28:68", "1:29:7", "1:32:20"] + }, { + "id": 15, + "usr": "c:impl.cc@791@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Location#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:37:22", + "variable_type": 0, + "uses": ["1:37:22"] + }, { + "id": 16, + "usr": "c:impl.cc@808@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Location#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:37:41", + "variable_type": 3, + "uses": ["1:37:41"] + }, { + "id": 17, + "usr": "c:impl.cc@886@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Location#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:40:22", + "variable_type": 1, + "uses": ["1:40:22"] + }, { + "id": 18, + "usr": "c:impl.cc@903@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Location#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:40:41", + "variable_type": 3, + "uses": ["1:40:41", "1:44:24"] + }, { + "id": 19, + "usr": "c:impl.cc@1006@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Location#@output", + "short_name": "output", + "qualified_name": "output", + "definition": "1:44:15", + "variable_type": 2, + "uses": ["1:44:15"] + }, { + "id": 20, + "usr": "c:impl.cc@1148@FT@>1#TReflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&>@ST>1#T@Id1t0.0#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:51:22", + "variable_type": 0, + "uses": ["1:51:22"] + }, { + "id": 21, + "usr": "c:impl.cc@1165@FT@>1#TReflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&>@ST>1#T@Id1t0.0#v#@id", + "short_name": "id", + "qualified_name": "id", + "definition": "1:51:38", + "variable_type": 4, + "uses": ["1:51:38"] + }, { + "id": 22, + "usr": "c:impl.cc@1249@FT@>1#TReflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&>@ST>1#T@Id1t0.0#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:55:22", + "variable_type": 1, + "uses": ["1:55:22"] + }, { + "id": 23, + "usr": "c:impl.cc@1266@FT@>1#TReflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&>@ST>1#T@Id1t0.0#v#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:55:38", + "variable_type": 4, + "uses": ["1:55:38"] + }, { + "id": 24, + "usr": "c:impl.cc@1356@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:61:22", + "variable_type": 0, + "uses": ["1:61:22"] + }, { + "id": 25, + "usr": "c:impl.cc@1373@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:61:52", + "variable_type": 7, + "uses": ["1:61:52"] + }, { + "id": 26, + "usr": "c:impl.cc@1406@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#@str_value", + "short_name": "str_value", + "qualified_name": "str_value", + "definition": "1:62:15", + "uses": ["1:62:15", "1:63:22", "1:64:35"] + }, { + "id": 27, + "usr": "c:impl.cc@1454@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#@id", + "short_name": "id", + "qualified_name": "id", + "definition": "1:63:12", + "variable_type": 9, + "uses": ["1:63:12"] + }, { + "id": 28, + "usr": "c:impl.cc@1488@F@Reflect#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@Ref>#$@S@IndexedFuncDef#@loc_string", + "short_name": "loc_string", + "qualified_name": "loc_string", + "definition": "1:64:15", + "uses": ["1:64:15"] + }, { + "id": 29, + "usr": "c:impl.cc@1635@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Ref>#$@S@IndexedFuncDef#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:69:22", + "variable_type": 1, + "uses": ["1:69:22", "1:71:3"] + }, { + "id": 30, + "usr": "c:impl.cc@1652@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Ref>#$@S@IndexedFuncDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:69:52", + "variable_type": 7, + "uses": ["1:69:52"] + }, { + "id": 31, + "usr": "c:impl.cc@1685@F@Reflect#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@Ref>#$@S@IndexedFuncDef#@s", + "short_name": "s", + "qualified_name": "s", + "definition": "1:70:15", + "variable_type": 2, + "uses": ["1:70:15", "1:71:18"] + }, { + "id": 32, + "usr": "c:impl.cc@2008@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedTypeDef#@reader", + "short_name": "reader", + "qualified_name": "reader", + "definition": "1:85:33", + "variable_type": 0, + "uses": ["1:85:33"] + }, { + "id": 33, + "usr": "c:impl.cc@2024@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedTypeDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:85:57", + "variable_type": 10, + "uses": ["1:85:57"] + }, { + "id": 34, + "usr": "c:impl.cc@2124@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedTypeDef#@writer", + "short_name": "writer", + "qualified_name": "writer", + "definition": "1:89:33", + "variable_type": 1, + "uses": ["1:89:33", "1:92:29"] + }, { + "id": 35, + "usr": "c:impl.cc@2140@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedTypeDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:89:57", + "variable_type": 10, + "uses": ["1:89:57"] + }, { + "id": 36, + "usr": "c:impl.cc@2313@FT@>1#TReflect#&t0.0#&$@S@IndexedTypeDef#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:96:24", + "uses": ["1:96:24"] + }, { + "id": 37, + "usr": "c:impl.cc@2332@FT@>1#TReflect#&t0.0#&$@S@IndexedTypeDef#v#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:96:49", + "variable_type": 10, + "uses": ["1:96:49"] + }, { + "id": 38, + "usr": "c:impl.cc@3038@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedFuncDef#@reader", + "short_name": "reader", + "qualified_name": "reader", + "definition": "1:115:33", + "variable_type": 0, + "uses": ["1:115:33"] + }, { + "id": 39, + "usr": "c:impl.cc@3054@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedFuncDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:115:57", + "variable_type": 8, + "uses": ["1:115:57"] + }, { + "id": 40, + "usr": "c:impl.cc@3154@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFuncDef#@writer", + "short_name": "writer", + "qualified_name": "writer", + "definition": "1:119:33", + "variable_type": 1, + "uses": ["1:119:33", "1:122:29"] + }, { + "id": 41, + "usr": "c:impl.cc@3170@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFuncDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:119:57", + "variable_type": 8, + "uses": ["1:119:57"] + }, { + "id": 42, + "usr": "c:impl.cc@3343@FT@>1#TReflect#&t0.0#&$@S@IndexedFuncDef#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:126:24", + "uses": ["1:126:24"] + }, { + "id": 43, + "usr": "c:impl.cc@3362@FT@>1#TReflect#&t0.0#&$@S@IndexedFuncDef#v#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:126:49", + "variable_type": 8, + "uses": ["1:126:49"] + }, { + "id": 44, + "usr": "c:impl.cc@4137@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedVarDef#@reader", + "short_name": "reader", + "qualified_name": "reader", + "definition": "1:146:33", + "variable_type": 0, + "uses": ["1:146:33"] + }, { + "id": 45, + "usr": "c:impl.cc@4153@F@ReflectMemberStart#&$@N@rapidjson@S@GenericValue>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@MemoryPoolAllocator>#$@N@rapidjson@S@CrtAllocator#&$@S@IndexedVarDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:146:56", + "variable_type": 13, + "uses": ["1:146:56"] + }, { + "id": 46, + "usr": "c:impl.cc@4252@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedVarDef#@writer", + "short_name": "writer", + "qualified_name": "writer", + "definition": "1:150:33", + "variable_type": 1, + "uses": ["1:150:33", "1:153:29"] + }, { + "id": 47, + "usr": "c:impl.cc@4268@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedVarDef#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:150:56", + "variable_type": 13, + "uses": ["1:150:56"] + }, { + "id": 48, + "usr": "c:impl.cc@4440@FT@>1#TReflect#&t0.0#&$@S@IndexedVarDef#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:157:24", + "uses": ["1:157:24"] + }, { + "id": 49, + "usr": "c:impl.cc@4459@FT@>1#TReflect#&t0.0#&$@S@IndexedVarDef#v#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:157:48", + "variable_type": 13, + "uses": ["1:157:48"] + }, { + "id": 50, + "usr": "c:impl.cc@5061@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFile#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:173:33", + "variable_type": 1, + "uses": ["1:173:33", "1:180:29"] + }, { + "id": 51, + "usr": "c:impl.cc@5078@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFile#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:173:55", + "variable_type": 15, + "uses": ["1:173:55"] + }, { + "id": 52, + "usr": "c:impl.cc@5103@F@ReflectMemberStart#&$@N@rapidjson@S@Writer>#$@N@rapidjson@S@GenericStringBuffer>#$@N@rapidjson@S@UTF8>#C#$@N@rapidjson@S@CrtAllocator#S3_#S3_#S4_#Vi0#&$@S@IndexedFile#@it", + "short_name": "it", + "qualified_name": "it", + "definition": "1:174:8", + "uses": ["1:174:8"] + }, { + "id": 53, + "usr": "c:impl.cc@5437@FT@>1#TReflect#&t0.0#&$@S@IndexedFile#v#@visitor", + "short_name": "visitor", + "qualified_name": "visitor", + "definition": "1:184:24", + "uses": ["1:184:24"] + }, { + "id": 54, + "usr": "c:impl.cc@5456@FT@>1#TReflect#&t0.0#&$@S@IndexedFile#v#@value", + "short_name": "value", + "qualified_name": "value", + "definition": "1:184:46", + "variable_type": 15, + "uses": ["1:184:46"] + }, { + "id": 55, + "usr": "c:impl.cc@5647@F@Serialize#&$@S@IndexedFile#@file", + "short_name": "file", + "qualified_name": "file", + "definition": "1:198:36", + "variable_type": 15, + "uses": ["1:198:36"] + }, { + "id": 56, + "usr": "c:impl.cc@5671@F@Serialize#&$@S@IndexedFile#@output", + "short_name": "output", + "qualified_name": "output", + "definition": "1:199:27", + "variable_type": 17, + "uses": ["1:199:27"] + }, { + "id": 57, + "usr": "c:impl.cc@5706@F@Serialize#&$@S@IndexedFile#@writer", + "short_name": "writer", + "qualified_name": "writer", + "definition": "1:200:52", + "uses": ["1:200:52"] + }, { + "id": 58, + "usr": "c:impl.cc@6018@F@Deserialize#$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#S0_#@path", + "short_name": "path", + "qualified_name": "path", + "definition": "1:211:47", + "variable_type": 2, + "uses": ["1:211:47", "1:217:20"] + }, { + "id": 59, + "usr": "c:impl.cc@6036@F@Deserialize#$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#S0_#@serialized", + "short_name": "serialized", + "qualified_name": "serialized", + "definition": "1:211:65", + "variable_type": 2, + "uses": ["1:211:65"] + }, { + "id": 60, + "usr": "c:impl.cc@6065@F@Deserialize#$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#S0_#@reader", + "short_name": "reader", + "qualified_name": "reader", + "definition": "1:212:23", + "variable_type": 19, + "uses": ["1:212:23"] + }, { + "id": 61, + "usr": "c:impl.cc@6187@F@Deserialize#$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#S0_#@file", + "short_name": "file", + "qualified_name": "file", + "definition": "1:217:15", + "variable_type": 15, + "uses": ["1:217:15"] + }] +} +*/ diff --git a/tests/outline/outline.cc b/tests/outline/outline.cc index 96a06714..572505a7 100644 --- a/tests/outline/outline.cc +++ b/tests/outline/outline.cc @@ -17,6 +17,11 @@ OUTPUT: "definition": "1:3:8", "vars": [0, 1, 2], "uses": ["*1:3:8"] + }, { + "id": 1, + "usr": "c:@N@std@ST>2#T#T@vector", + "instantiations": [2], + "uses": ["*1:6:8"] }], "vars": [{ "id": 0, diff --git a/tests/outline/outline2.cc b/tests/outline/outline2.cc index ed3f7d9e..9c8919df 100644 --- a/tests/outline/outline2.cc +++ b/tests/outline/outline2.cc @@ -22,6 +22,16 @@ OUTPUT: "definition": "1:6:8", "vars": [0, 1, 2], "uses": ["*1:6:8", "*1:12:13"] + }, { + "id": 1, + "usr": "c:@N@std@T@string", + "instantiations": [0, 1], + "uses": ["*1:7:8", "*1:8:8", "*1:9:20"] + }, { + "id": 2, + "usr": "c:@N@std@ST>2#T#T@vector", + "instantiations": [2], + "uses": ["*1:9:8", "*1:12:6"] }], "funcs": [{ "id": 0, diff --git a/tests/templates/implicit_variable_instantiation.cc b/tests/templates/implicit_variable_instantiation.cc index 7133fa95..614e4934 100644 --- a/tests/templates/implicit_variable_instantiation.cc +++ b/tests/templates/implicit_variable_instantiation.cc @@ -23,6 +23,7 @@ OUTPUT: "short_name": "VarType", "qualified_name": "ns::VarType", "definition": "1:2:8", + "instantiations": [0], "uses": ["*1:2:8", "*1:6:22", "*1:6:44", "*1:10:18"] }, { "id": 1, diff --git a/tests/templates/namespace_template_type_usage_folded_into_one.cc b/tests/templates/namespace_template_type_usage_folded_into_one.cc index 0fd1f743..dbe20248 100644 --- a/tests/templates/namespace_template_type_usage_folded_into_one.cc +++ b/tests/templates/namespace_template_type_usage_folded_into_one.cc @@ -15,6 +15,7 @@ OUTPUT: "short_name": "Foo", "qualified_name": "ns::Foo", "definition": "1:3:9", + "instantiations": [0, 1], "uses": ["*1:3:9", "*1:5:3", "*1:6:3"] }], "vars": [{ diff --git a/tests/templates/template_class_type_usage_folded_into_one.cc b/tests/templates/template_class_type_usage_folded_into_one.cc index ff43598c..baa6e1c6 100644 --- a/tests/templates/template_class_type_usage_folded_into_one.cc +++ b/tests/templates/template_class_type_usage_folded_into_one.cc @@ -57,6 +57,7 @@ OUTPUT: "short_name": "Inner", "qualified_name": "Foo::Inner", "definition": "1:6:10", + "instantiations": [0, 1], "uses": ["*1:6:10", "*1:9:9", "*1:10:9"] }], "vars": [{ diff --git a/tests/templates/template_type_usage_folded_into_one.cc b/tests/templates/template_type_usage_folded_into_one.cc index e0fdeba3..f316d7b2 100644 --- a/tests/templates/template_type_usage_folded_into_one.cc +++ b/tests/templates/template_type_usage_folded_into_one.cc @@ -13,6 +13,7 @@ OUTPUT: "short_name": "Foo", "qualified_name": "Foo", "definition": "1:2:7", + "instantiations": [0, 1], "uses": ["*1:2:7", "*1:4:1", "*1:5:1"] }], "vars": [{ diff --git a/tests/templates/template_var_usage_folded_into_one.cc b/tests/templates/template_var_usage_folded_into_one.cc index 8c877891..a4201229 100644 --- a/tests/templates/template_var_usage_folded_into_one.cc +++ b/tests/templates/template_var_usage_folded_into_one.cc @@ -44,6 +44,10 @@ OUTPUT: "qualified_name": "B", "definition": "1:2:6", "uses": ["*1:2:6", "1:8:13"] + }, { + "id": 2, + "usr": "c:template_var_usage_folded_into_one.cc@35", + "uses": ["*1:5:1"] }], "vars": [{ "id": 0, diff --git a/tests/unions/union_usage.cc b/tests/unions/union_usage.cc index 40b15a85..22bf07f6 100644 --- a/tests/unions/union_usage.cc +++ b/tests/unions/union_usage.cc @@ -10,6 +10,8 @@ void act(Foo*) { } /* +// TODO: instantiations on Foo should include parameter? + OUTPUT: { "types": [{ @@ -19,6 +21,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "vars": [0, 1], + "instantiations": [2], "uses": ["*1:1:7", "*1:6:1", "*1:8:10"] }], "funcs": [{ diff --git a/tests/usage/func_usage_call_method.cc b/tests/usage/func_usage_call_method.cc index 39b62784..991468f3 100644 --- a/tests/usage/func_usage_call_method.cc +++ b/tests/usage/func_usage_call_method.cc @@ -17,6 +17,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:8", "funcs": [0], + "instantiations": [0], "uses": ["*1:1:8", "*1:6:3"] }], "funcs": [{ diff --git a/tests/usage/func_usage_forward_decl_method.cc b/tests/usage/func_usage_forward_decl_method.cc index 0b685be0..41dc6266 100644 --- a/tests/usage/func_usage_forward_decl_method.cc +++ b/tests/usage/func_usage_forward_decl_method.cc @@ -16,6 +16,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:8", "funcs": [0], + "instantiations": [0], "uses": ["*1:1:8", "*1:6:3"] }], "funcs": [{ diff --git a/tests/usage/type_usage_as_template_parameter.cc b/tests/usage/type_usage_as_template_parameter.cc index b05277d4..60c20389 100644 --- a/tests/usage/type_usage_as_template_parameter.cc +++ b/tests/usage/type_usage_as_template_parameter.cc @@ -16,6 +16,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@ST>1#T@unique_ptr", + "instantiations": [0, 1, 2], "uses": ["1:2:7", "*1:6:8", "*1:7:8", "*1:9:1", "*1:10:3"] }, { "id": 1, diff --git a/tests/usage/type_usage_as_template_parameter_complex.cc b/tests/usage/type_usage_as_template_parameter_complex.cc index 2c5e4b1d..170b8e07 100644 --- a/tests/usage/type_usage_as_template_parameter_complex.cc +++ b/tests/usage/type_usage_as_template_parameter_complex.cc @@ -84,6 +84,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@ST>2#T#T@unique_ptr", + "instantiations": [0, 1], "uses": ["1:2:7", "*1:15:8", "*1:15:19", "*1:33:1", "*1:33:12", "*1:33:52", "*1:54:3", "*1:54:14", "*1:65:3", "*1:79:1"] }, { "id": 1, diff --git a/tests/usage/type_usage_as_template_parameter_simple.cc b/tests/usage/type_usage_as_template_parameter_simple.cc index 9e7239de..428c0c58 100644 --- a/tests/usage/type_usage_as_template_parameter_simple.cc +++ b/tests/usage/type_usage_as_template_parameter_simple.cc @@ -14,6 +14,7 @@ OUTPUT: "short_name": "unique_ptr", "qualified_name": "unique_ptr", "definition": "1:2:7", + "instantiations": [0], "uses": ["*1:2:7", "*1:6:8"] }, { "id": 1, diff --git a/tests/usage/type_usage_declare_extern.cc b/tests/usage/type_usage_declare_extern.cc index f708874f..71530a44 100644 --- a/tests/usage/type_usage_declare_extern.cc +++ b/tests/usage/type_usage_declare_extern.cc @@ -10,6 +10,7 @@ OUTPUT: "short_name": "T", "qualified_name": "T", "definition": "1:1:8", + "instantiations": [0], "uses": ["*1:1:8", "*1:3:8"] }], "vars": [{ diff --git a/tests/usage/type_usage_declare_field.cc b/tests/usage/type_usage_declare_field.cc index 652f0a51..eb60b02b 100644 --- a/tests/usage/type_usage_declare_field.cc +++ b/tests/usage/type_usage_declare_field.cc @@ -12,6 +12,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@ForwardType", + "instantiations": [0], "uses": ["1:1:8", "*1:5:3"] }, { "id": 1, @@ -19,6 +20,7 @@ OUTPUT: "short_name": "ImplementedType", "qualified_name": "ImplementedType", "definition": "1:2:8", + "instantiations": [1], "uses": ["*1:2:8", "*1:6:3"] }, { "id": 2, diff --git a/tests/usage/type_usage_declare_local.cc b/tests/usage/type_usage_declare_local.cc index 36d6648f..93148bdc 100644 --- a/tests/usage/type_usage_declare_local.cc +++ b/tests/usage/type_usage_declare_local.cc @@ -12,6 +12,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@ForwardType", + "instantiations": [0], "uses": ["1:1:8", "*1:5:3"] }, { "id": 1, @@ -19,6 +20,7 @@ OUTPUT: "short_name": "ImplementedType", "qualified_name": "ImplementedType", "definition": "1:2:8", + "instantiations": [1], "uses": ["*1:2:8", "*1:6:3"] }], "funcs": [{ diff --git a/tests/usage/type_usage_declare_param.cc b/tests/usage/type_usage_declare_param.cc index 140652ef..33bd1e33 100644 --- a/tests/usage/type_usage_declare_param.cc +++ b/tests/usage/type_usage_declare_param.cc @@ -9,6 +9,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@ForwardType", + "instantiations": [0], "uses": ["1:1:8", "*1:4:10"] }, { "id": 1, @@ -16,6 +17,7 @@ OUTPUT: "short_name": "ImplementedType", "qualified_name": "ImplementedType", "definition": "1:2:8", + "instantiations": [1], "uses": ["*1:2:8", "*1:4:26"] }], "funcs": [{ diff --git a/tests/usage/type_usage_declare_param_prototype.cc b/tests/usage/type_usage_declare_param_prototype.cc index 8b90d165..1a969b51 100644 --- a/tests/usage/type_usage_declare_param_prototype.cc +++ b/tests/usage/type_usage_declare_param_prototype.cc @@ -14,6 +14,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@Foo", + "instantiations": [0], "uses": ["1:1:8", "1:3:10", "1:3:18", "*1:4:10", "*1:4:18"] }], "funcs": [{ diff --git a/tests/usage/type_usage_declare_qualifiers.cc b/tests/usage/type_usage_declare_qualifiers.cc index ada65cf7..84d2c1de 100644 --- a/tests/usage/type_usage_declare_qualifiers.cc +++ b/tests/usage/type_usage_declare_qualifiers.cc @@ -15,6 +15,7 @@ OUTPUT: "short_name": "Type", "qualified_name": "Type", "definition": "1:1:8", + "instantiations": [0, 1, 2, 3, 4, 5], "uses": ["*1:1:8", "*1:3:10", "*1:3:26", "*1:4:3", "*1:5:3", "*1:6:9", "*1:7:9"] }], "funcs": [{ diff --git a/tests/usage/type_usage_declare_static.cc b/tests/usage/type_usage_declare_static.cc index 120d7d0e..1ed74b08 100644 --- a/tests/usage/type_usage_declare_static.cc +++ b/tests/usage/type_usage_declare_static.cc @@ -6,6 +6,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@Type", + "instantiations": [0], "uses": ["1:1:8", "*1:2:8"] }], "vars": [{ diff --git a/tests/usage/type_usage_various.cc b/tests/usage/type_usage_various.cc index b702ad40..fcd6ab56 100644 --- a/tests/usage/type_usage_various.cc +++ b/tests/usage/type_usage_various.cc @@ -19,6 +19,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "funcs": [0], + "instantiations": [0, 1], "uses": ["*1:1:7", "*1:2:3", "*1:5:1", "1:5:6", "*1:6:3", "*1:10:8"] }], "funcs": [{ diff --git a/tests/usage/var_usage_class_member.cc b/tests/usage/var_usage_class_member.cc index faa03f0b..867858f8 100644 --- a/tests/usage/var_usage_class_member.cc +++ b/tests/usage/var_usage_class_member.cc @@ -27,6 +27,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "vars": [0, 1], + "instantiations": [2], "uses": ["*1:1:7", "*1:11:3"] }], "funcs": [{ diff --git a/tests/usage/var_usage_cstyle_cast.cc b/tests/usage/var_usage_cstyle_cast.cc index 9c45791e..ecad894e 100644 --- a/tests/usage/var_usage_cstyle_cast.cc +++ b/tests/usage/var_usage_cstyle_cast.cc @@ -16,6 +16,7 @@ OUTPUT: "short_name": "VarType", "qualified_name": "VarType", "definition": "1:1:6", + "instantiations": [0], "uses": ["*1:1:6", "*1:4:20", "*1:4:42", "*1:7:7"] }, { "id": 1, diff --git a/tests/vars/class_member.cc b/tests/vars/class_member.cc index f474ccfd..e5456e3e 100644 --- a/tests/vars/class_member.cc +++ b/tests/vars/class_member.cc @@ -11,6 +11,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "vars": [0], + "instantiations": [0], "uses": ["*1:1:7", "*1:2:3"] }], "vars": [{ diff --git a/tests/vars/class_static_member.cc b/tests/vars/class_static_member.cc index 9458ef55..652cdf44 100644 --- a/tests/vars/class_static_member.cc +++ b/tests/vars/class_static_member.cc @@ -13,6 +13,7 @@ OUTPUT: "qualified_name": "Foo", "definition": "1:1:7", "vars": [0], + "instantiations": [0], "uses": ["*1:1:7", "*1:2:10", "*1:4:1", "1:4:6"] }], "vars": [{ diff --git a/tests/vars/function_local.cc b/tests/vars/function_local.cc index b55979dc..21f5378c 100644 --- a/tests/vars/function_local.cc +++ b/tests/vars/function_local.cc @@ -10,6 +10,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@Foo", + "instantiations": [0], "uses": ["1:1:8", "*1:4:3"] }], "funcs": [{ diff --git a/tests/vars/function_param.cc b/tests/vars/function_param.cc index 4090c98b..8dee749b 100644 --- a/tests/vars/function_param.cc +++ b/tests/vars/function_param.cc @@ -8,6 +8,7 @@ OUTPUT: "types": [{ "id": 0, "usr": "c:@S@Foo", + "instantiations": [0, 1], "uses": ["1:1:8", "*1:3:10", "*1:3:19"] }], "funcs": [{