mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 12:42:34 +00:00 
			
		
		
		
	Derive SymbolRef,Use from Reference and add lexical container to func/var/type uses
This commit is contained in:
		
							parent
							
								
									a50bff0b24
								
							
						
					
					
						commit
						420e84329b
					
				| @ -194,6 +194,10 @@ ClangCursor ClangCursor::get_definition() const { | ||||
|   return ClangCursor(clang_getCursorDefinition(cx_cursor)); | ||||
| } | ||||
| 
 | ||||
| ClangCursor ClangCursor::get_lexical_parent() const { | ||||
|   return ClangCursor(clang_getCursorLexicalParent(cx_cursor)); | ||||
| } | ||||
| 
 | ||||
| ClangCursor ClangCursor::get_semantic_parent() const { | ||||
|   return ClangCursor(clang_getCursorSemanticParent(cx_cursor)); | ||||
| } | ||||
|  | ||||
| @ -73,6 +73,7 @@ class ClangCursor { | ||||
|   ClangCursor get_referenced() const; | ||||
|   ClangCursor get_canonical() const; | ||||
|   ClangCursor get_definition() const; | ||||
|   ClangCursor get_lexical_parent() const; | ||||
|   ClangCursor get_semantic_parent() const; | ||||
|   std::vector<ClangCursor> get_arguments() const; | ||||
|   bool is_valid_kind() const; | ||||
|  | ||||
							
								
								
									
										309
									
								
								src/indexer.cc
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								src/indexer.cc
									
									
									
									
									
								
							| @ -30,7 +30,7 @@ constexpr bool kIndexStdDeclarations = true; | ||||
| // display their declarations on hover.
 | ||||
| constexpr int kMaxLinesDisplayTypeAliasDeclarations = 3; | ||||
| 
 | ||||
| void AddFuncRef(std::vector<IndexFuncRef>* result, IndexFuncRef ref) { | ||||
| void AddFuncUse(std::vector<Use>* result, Use ref) { | ||||
|   if (!result->empty() && (*result)[result->size() - 1] == ref) | ||||
|     return; | ||||
|   result->push_back(ref); | ||||
| @ -53,6 +53,30 @@ bool IsScopeSemanticContainer(CXCursorKind kind) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| SymbolKind GetSymbolKind(CXCursorKind kind) { | ||||
|   switch (kind) { | ||||
|   default: | ||||
|     return SymbolKind::Invalid; | ||||
| 
 | ||||
|   case CXCursor_FunctionDecl: | ||||
|   case CXCursor_CXXMethod: | ||||
|   case CXCursor_Constructor: | ||||
|   case CXCursor_Destructor: | ||||
|   case CXCursor_ConversionFunction: | ||||
|   case CXCursor_FunctionTemplate: | ||||
|   case CXCursor_OverloadedDeclRef: | ||||
|   case CXCursor_LambdaExpr: | ||||
|     return SymbolKind::Func; | ||||
| 
 | ||||
|   case CXCursor_Namespace: | ||||
|   case CXCursor_EnumDecl: | ||||
|   case CXCursor_UnionDecl: | ||||
|   case CXCursor_StructDecl: | ||||
|   case CXCursor_ClassDecl: | ||||
|     return SymbolKind::Type; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // Inverse of libclang/CXIndexDataConsumer.cpp getEntityKindFromSymbolKind
 | ||||
| ClangSymbolKind GetSymbolKind(CXIdxEntityKind kind) { | ||||
|   switch (kind) { | ||||
| @ -410,26 +434,6 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| bool IsFunctionCallContext(CXCursorKind kind) { | ||||
|   switch (kind) { | ||||
|     case CXCursor_FunctionDecl: | ||||
|     case CXCursor_CXXMethod: | ||||
|     case CXCursor_Constructor: | ||||
|     case CXCursor_Destructor: | ||||
|     case CXCursor_ConversionFunction: | ||||
|     case CXCursor_FunctionTemplate: | ||||
|     case CXCursor_OverloadedDeclRef: | ||||
|     // TODO: we need to test lambdas
 | ||||
|     case CXCursor_LambdaExpr: | ||||
|       return true; | ||||
| 
 | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| void SetTypeName(IndexType* type, | ||||
|                  const ClangCursor& cursor, | ||||
|                  const CXIdxContainerInfo* container, | ||||
| @ -581,23 +585,30 @@ void SetVarDetail(IndexVar* var, | ||||
| 
 | ||||
| void OnIndexReference_Function(IndexFile* db, | ||||
|                                Range loc, | ||||
|                                ClangCursor caller_cursor, | ||||
|                                ClangCursor parent_cursor, | ||||
|                                IndexFuncId called_id, | ||||
|                                IndexFunc* called, | ||||
|                                SymbolRole role) { | ||||
|   if (IsFunctionCallContext(caller_cursor.get_kind())) { | ||||
|     IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor); | ||||
|     IndexFunc* caller = db->Resolve(caller_id); | ||||
|     // Calling db->ToFuncId invalidates the FuncDef* ptrs.
 | ||||
|     called = db->Resolve(called_id); | ||||
| 
 | ||||
|     AddFuncRef(&caller->def.callees, | ||||
|                IndexFuncRef(loc, Id<void>(called->id), SymbolKind::Func, role)); | ||||
|     AddFuncRef(&called->callers, | ||||
|                IndexFuncRef(loc, Id<void>(caller->id), SymbolKind::Func, role)); | ||||
|   } else { | ||||
|     AddFuncRef(&called->callers, | ||||
|                IndexFuncRef(loc, Id<void>(), SymbolKind::Invalid, role)); | ||||
|   switch (GetSymbolKind(parent_cursor.get_kind())) { | ||||
|     case SymbolKind::Func: { | ||||
|       IndexFunc* parent = db->Resolve(db->ToFuncId(parent_cursor.cx_cursor)); | ||||
|       IndexFunc* called = db->Resolve(called_id); | ||||
|       parent->def.callees.push_back( | ||||
|           SymbolRef(loc, called->id, SymbolKind::Func, role)); | ||||
|       AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Func, role)); | ||||
|       break; | ||||
|     } | ||||
|     case SymbolKind::Type: { | ||||
|       IndexType* parent = db->Resolve(db->ToTypeId(parent_cursor.cx_cursor)); | ||||
|       IndexFunc* called = db->Resolve(called_id); | ||||
|       called = db->Resolve(called_id); | ||||
|       AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Type, role)); | ||||
|       break; | ||||
|     } | ||||
|     default: { | ||||
|       IndexFunc* called = db->Resolve(called_id); | ||||
|       AddFuncUse(&called->uses, Use(loc, Id<void>(), SymbolKind::File, role)); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -686,17 +697,55 @@ void UniqueAdd(std::vector<T>& values, T value) { | ||||
| } | ||||
| 
 | ||||
| // FIXME Reference: set id in call sites and remove this
 | ||||
| void AddUse(std::vector<Reference>& values, Range value) { | ||||
|   values.push_back(Reference{value, Id<void>(), SymbolKind::Invalid, | ||||
|                              SymbolRole::Reference}); | ||||
| void AddUse(std::vector<Use>& values, Range value) { | ||||
|   values.push_back( | ||||
|       Use(value, Id<void>(), SymbolKind::File, SymbolRole::Reference)); | ||||
| } | ||||
| 
 | ||||
| // FIXME Reference: set id in call sites and remove this
 | ||||
| void UniqueAdd(std::vector<Reference>& values, Range value) { | ||||
|   if (std::find_if(values.begin(), values.end(), [&](const Reference& ref) { | ||||
|         return ref.range == value; | ||||
|       }) == values.end()) | ||||
|     AddUse(values, value); | ||||
| void AddUse(IndexFile* db, | ||||
|             std::vector<Use>& uses, | ||||
|             Range range, | ||||
|             ClangCursor parent, | ||||
|             SymbolRole role = SymbolRole::Reference) { | ||||
|   switch (GetSymbolKind(parent.get_kind())) { | ||||
|     default: | ||||
|       uses.push_back(Use(range, Id<void>(), SymbolKind::File, role)); | ||||
|       break; | ||||
|     case SymbolKind::Func: | ||||
|       uses.push_back( | ||||
|           Use(range, db->ToFuncId(parent.cx_cursor), SymbolKind::Func, role)); | ||||
|       break; | ||||
|     case SymbolKind::Type: | ||||
|       uses.push_back( | ||||
|           Use(range, db->ToTypeId(parent.cx_cursor), SymbolKind::Type, role)); | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| CXCursor fromContainer(const CXIdxContainerInfo* parent) { | ||||
|   return parent ? parent->cursor : clang_getNullCursor(); | ||||
| } | ||||
| 
 | ||||
| void AddUseSpell(IndexFile* db, | ||||
|                  std::vector<Use>& uses, | ||||
|                  ClangCursor cursor) { | ||||
|   AddUse(db, uses, cursor.get_spelling_range(), | ||||
|          cursor.get_lexical_parent().cx_cursor, SymbolRole::Reference); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
| void UniqueAddUse(IndexFile* db, std::vector<Use>& uses, Range range, Args&&... args) { | ||||
|   if (std::find_if(uses.begin(), uses.end(), | ||||
|                    [&](Use use) { return use.range == range; }) == uses.end()) | ||||
|     AddUse(db, uses, range, std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
| void UniqueAddUseSpell(IndexFile* db, std::vector<Use>& uses, ClangCursor cursor, Args&&... args) { | ||||
|   Range range = cursor.get_spelling_range(); | ||||
|   if (std::find_if(uses.begin(), uses.end(), | ||||
|                    [&](Use use) { return use.range == range; }) == uses.end()) | ||||
|     AddUse(db, uses, range, cursor.get_lexical_parent().cx_cursor, std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| IdCache::IdCache(const std::string& primary_file) | ||||
| @ -840,17 +889,7 @@ bool IsGlobalContainer(const CXIdxContainerInfo* container) { | ||||
| bool IsTypeDefinition(const CXIdxContainerInfo* container) { | ||||
|   if (!container) | ||||
|     return false; | ||||
| 
 | ||||
|   switch (container->cursor.kind) { | ||||
|     case CXCursor_Namespace: | ||||
|     case CXCursor_EnumDecl: | ||||
|     case CXCursor_UnionDecl: | ||||
|     case CXCursor_StructDecl: | ||||
|     case CXCursor_ClassDecl: | ||||
|       return true; | ||||
|     default: | ||||
|       return false; | ||||
|   } | ||||
|   return GetSymbolKind(container->cursor.kind) == SymbolKind::Type; | ||||
| } | ||||
| 
 | ||||
| struct VisitDeclForTypeUsageParam { | ||||
| @ -886,7 +925,7 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor, | ||||
|     IndexType* ref_type = db->Resolve(*param->toplevel_type); | ||||
|     std::string name = cursor.get_referenced().get_spelling(); | ||||
|     if (name == ref_type->def.ShortName()) { | ||||
|       UniqueAdd(ref_type->uses, cursor.get_spelling_range()); | ||||
|       UniqueAddUseSpell(db, ref_type->uses, cursor); | ||||
|       param->toplevel_type = nullopt; | ||||
|       return; | ||||
|     } | ||||
| @ -908,8 +947,7 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor, | ||||
|   IndexType* ref_type_def = db->Resolve(ref_type_id); | ||||
|   // TODO: Should we even be visiting this if the file is not from the main
 | ||||
|   // def? Try adding assert on |loc| later.
 | ||||
|   Range loc = cursor.get_spelling_range(); | ||||
|   UniqueAdd(ref_type_def->uses, loc); | ||||
|   UniqueAddUseSpell(db, ref_type_def->uses, cursor); | ||||
| } | ||||
| 
 | ||||
| ClangCursor::VisitResult VisitDeclForTypeUsageVisitor( | ||||
| @ -1128,10 +1166,8 @@ ClangCursor::VisitResult AddDeclInitializerUsagesVisitor(ClangCursor cursor, | ||||
|       if (ref_usr == "") | ||||
|         break; | ||||
| 
 | ||||
|       Range loc = cursor.get_spelling_range(); | ||||
|       IndexVarId ref_id = db->ToVarId(HashUsr(ref_usr)); | ||||
|       IndexVar* ref_def = db->Resolve(ref_id); | ||||
|       UniqueAdd(ref_def->uses, loc); | ||||
|       IndexVar* ref_var = db->Resolve(db->ToVarId(HashUsr(ref_usr))); | ||||
|       UniqueAddUseSpell(db, ref_var->uses, cursor); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
| @ -1195,7 +1231,7 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor, | ||||
|         var_def->def.definition_extent = | ||||
|             ResolveCXSourceRange(cx_extent, nullptr); | ||||
|       } else | ||||
|         UniqueAdd(var_def->uses, decl_loc_spelling); | ||||
|         UniqueAddUse(db, var_def->uses, decl_loc_spelling, parent); | ||||
| 
 | ||||
|       break; | ||||
|     } | ||||
| @ -1244,10 +1280,11 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, | ||||
|             // seems no way to extract the spelling range of `type` and we do
 | ||||
|             // not want to do subtraction here.
 | ||||
|             // See https://github.com/jacobdufault/cquery/issues/252
 | ||||
|             UniqueAdd(ref_type_index->uses, ref_cursor.get_extent()); | ||||
|             UniqueAddUse(db, ref_type_index->uses, ref_cursor.get_extent(), | ||||
|                          ref_cursor.get_lexical_parent()); | ||||
|           } | ||||
|         } | ||||
|         UniqueAdd(ref_index->uses, cursor.get_spelling_range()); | ||||
|         UniqueAddUseSpell(db, ref_index->uses, cursor); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| @ -1261,10 +1298,9 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, | ||||
|           case CXCursor_FunctionDecl: | ||||
|           case CXCursor_FunctionTemplate: { | ||||
|             IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash()); | ||||
|             IndexFunc* called = db->Resolve(called_id); | ||||
|             OnIndexReference_Function(db, cursor.get_spelling_range(), | ||||
|                                       data->container, called_id, called, | ||||
|                                       SymbolRole::None); | ||||
|                                       data->container, called_id, | ||||
|                                       SymbolRole::CalledBy); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
| @ -1293,7 +1329,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, | ||||
|           ref_index->def.short_name_size = ref_index->def.detailed_name.size(); | ||||
|           ref_index->def.kind = ClangSymbolKind::Parameter; | ||||
|         } | ||||
|         UniqueAdd(ref_index->uses, cursor.get_spelling_range()); | ||||
|         UniqueAddUseSpell(db, ref_index->uses, cursor); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| @ -1319,7 +1355,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, | ||||
|           ref_index->def.short_name_size = ref_index->def.detailed_name.size(); | ||||
|           ref_index->def.kind = ClangSymbolKind::Parameter; | ||||
|         } | ||||
|         UniqueAdd(ref_index->uses, cursor.get_spelling_range()); | ||||
|         UniqueAddUseSpell(db, ref_index->uses, cursor); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| @ -1502,17 +1538,24 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | ||||
|       // has already been seen.
 | ||||
| 
 | ||||
|       if (decl->isDefinition && decl->semanticContainer) { | ||||
|         if (IsFunctionCallContext(decl->semanticContainer->cursor.kind)) { | ||||
|           IndexFuncId parent_func_id = | ||||
|               db->ToFuncId(decl->semanticContainer->cursor); | ||||
|           var->def.parent_kind = SymbolKind::Func; | ||||
|           var->def.parent_id = Id<void>(parent_func_id); | ||||
|         } else if (IsTypeDefinition(decl->semanticContainer)) { | ||||
|           IndexTypeId parent_type_id = | ||||
|               db->ToTypeId(decl->semanticContainer->cursor); | ||||
|           var->def.parent_kind = SymbolKind::Type; | ||||
|           var->def.parent_id = Id<void>(parent_type_id); | ||||
|           db->Resolve(parent_type_id)->def.vars.push_back(var_id); | ||||
|         switch (GetSymbolKind(decl->semanticContainer->cursor.kind)) { | ||||
|           default: | ||||
|             break; | ||||
|           case SymbolKind::Func: { | ||||
|             IndexFuncId parent_func_id = | ||||
|                 db->ToFuncId(decl->semanticContainer->cursor); | ||||
|             var->def.parent_kind = SymbolKind::Func; | ||||
|             var->def.parent_id = Id<void>(parent_func_id); | ||||
|             break; | ||||
|           } | ||||
|           case SymbolKind::Type: { | ||||
|             IndexTypeId parent_type_id = | ||||
|                 db->ToTypeId(decl->semanticContainer->cursor); | ||||
|             var->def.parent_kind = SymbolKind::Type; | ||||
|             var->def.parent_id = Id<void>(parent_type_id); | ||||
|             db->Resolve(parent_type_id)->def.vars.push_back(var_id); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
| @ -1632,13 +1675,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | ||||
|           func->def.declaring_type = declaring_type_id; | ||||
| 
 | ||||
|           // Mark a type reference at the ctor/dtor location.
 | ||||
|           if (decl->entityInfo->kind == CXIdxEntity_CXXConstructor) | ||||
|             UniqueAdd(declaring_type_def->uses, decl_spelling); | ||||
|           if (decl->entityInfo->kind == CXIdxEntity_CXXDestructor) { | ||||
|             Range dtor_type_range = decl_spelling; | ||||
|             dtor_type_range.start.column += 1;  // Don't count the leading ~
 | ||||
|             UniqueAdd(declaring_type_def->uses, dtor_type_range); | ||||
|           } | ||||
|           if (decl->entityInfo->kind == CXIdxEntity_CXXConstructor | ||||
|               || decl->entityInfo->kind == CXIdxEntity_CXXDestructor) | ||||
|             UniqueAddUse(db, declaring_type_def->uses, decl_spelling, | ||||
|                          fromContainer(decl->lexicalContainer)); | ||||
| 
 | ||||
|           // Add function to declaring type.
 | ||||
|           UniqueAdd(declaring_type_def->def.funcs, func_id); | ||||
| @ -1714,7 +1754,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       UniqueAdd(type->uses, spell); | ||||
|       UniqueAddUse(db, type->uses, spell, fromContainer(decl->lexicalContainer)); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
| @ -1751,13 +1791,13 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | ||||
|           if (!enum_type.is_fundamental()) { | ||||
|             IndexType* int_type = | ||||
|                 db->Resolve(db->ToTypeId(enum_type.get_usr_hash())); | ||||
|             AddUse(int_type->uses, decl_spell); | ||||
|             AddUse(db, int_type->uses, decl_spell, fromContainer(decl->lexicalContainer)); | ||||
|             // type is invalidated.
 | ||||
|             type = db->Resolve(type_id); | ||||
|           } | ||||
|         } | ||||
|       } else | ||||
|         UniqueAdd(type->uses, decl_spell); | ||||
|         UniqueAddUse(db, type->uses, decl_spell, fromContainer(decl->lexicalContainer)); | ||||
| 
 | ||||
|       switch (decl->entityInfo->templateKind) { | ||||
|         default: | ||||
| @ -1905,7 +1945,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|     case CXIdxEntity_CXXNamespace: { | ||||
|       ClangCursor referenced = ref->referencedEntity->cursor; | ||||
|       IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash())); | ||||
|       AddUse(ns->uses, cursor.get_spelling_range()); | ||||
|       AddUse(db, ns->uses, cursor.get_spelling_range(), fromContainer(ref->container)); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
| @ -1943,7 +1983,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|           var->def.kind = ClangSymbolKind::Parameter; | ||||
|         } | ||||
|       } | ||||
|       UniqueAdd(var->uses, loc); | ||||
|       UniqueAddUse(db, var->uses, loc, fromContainer(ref->container), SymbolRole::Reference); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
| @ -1999,8 +2039,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|         CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db); | ||||
| 
 | ||||
|       OnIndexReference_Function( | ||||
|           db, loc, ref->container->cursor, called_id, called, | ||||
|           is_implicit ? SymbolRole::Implicit : SymbolRole::None); | ||||
|           db, loc, ref->container->cursor, called_id, | ||||
|           SymbolRole::CalledBy | | ||||
|               (is_implicit ? SymbolRole::Implicit : SymbolRole::None)); | ||||
| 
 | ||||
|       // Checks if |str| starts with |start|. Ignores case.
 | ||||
|       auto str_begin = [](const char* start, const char* str) { | ||||
| @ -2040,9 +2081,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|               param->ctors.TryFindConstructorUsr(ctor_type_usr, call_type_desc); | ||||
|           if (ctor_usr) { | ||||
|             IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr)); | ||||
|             AddFuncRef(&ctor->callers, | ||||
|                        IndexFuncRef(loc, Id<void>(), SymbolKind::Invalid, | ||||
|                                     SymbolRole::Implicit)); | ||||
|             AddFuncUse(&ctor->uses, | ||||
|                        Use(loc, Id<void>(), SymbolKind::File, | ||||
|                            SymbolRole::CalledBy | SymbolRole::Implicit)); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| @ -2078,7 +2119,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|       //    Foo f;
 | ||||
|       //  }
 | ||||
|       //
 | ||||
|       UniqueAdd(ref_type->uses, ClangCursor(ref->cursor).get_spelling_range()); | ||||
|       UniqueAddUseSpell(db, ref_type->uses, ref->cursor); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
| @ -2319,57 +2360,15 @@ std::string GetClangVersion() { | ||||
|   return ToString(clang_getClangVersion()); | ||||
| } | ||||
| 
 | ||||
| void Reflect(Reader& visitor, IndexFuncRef& value) { | ||||
|   if (visitor.Format() == SerializeFormat::Json) { | ||||
|     std::string s = visitor.GetString(); | ||||
|     const char* str_value = s.c_str(); | ||||
|     if (str_value[0] == '~') { | ||||
|       value.role = SymbolRole::Implicit; | ||||
|       ++str_value; | ||||
|     } else | ||||
|       value.role = SymbolRole::None; | ||||
|     RawId id = atol(str_value); | ||||
|     const char* loc_string = strchr(str_value, '@') + 1; | ||||
| 
 | ||||
|     value.id = Id<void>(id); | ||||
|     value.range = Range(loc_string); | ||||
|   } else { | ||||
|     Reflect(visitor, static_cast<Reference&>(value)); | ||||
|   } | ||||
| } | ||||
| void Reflect(Writer& visitor, IndexFuncRef& value) { | ||||
|   if (visitor.Format() == SerializeFormat::Json) { | ||||
|     std::string s; | ||||
|     if (value.role & SymbolRole::Implicit) | ||||
|       s += "~"; | ||||
| 
 | ||||
|     // id.id is unsigned, special case -1 value
 | ||||
|     if (value.id.HasValue()) | ||||
|       s += std::to_string(value.id.id); | ||||
|     else | ||||
|       s += "-1"; | ||||
| 
 | ||||
|     s += "@" + value.range.ToString(); | ||||
|     visitor.String(s.c_str()); | ||||
|   } else { | ||||
|     Reflect(visitor, static_cast<Reference&>(value)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void Reflect(Reader& visitor, Reference& value) { | ||||
|   if (visitor.Format() == SerializeFormat::Json) { | ||||
|     std::string s = visitor.GetString(); | ||||
|     value = Reference{}; | ||||
|     value.range = Range(s.c_str()); | ||||
|     auto sep = s.find('|'); | ||||
|     if (sep == std::string::npos) | ||||
|       value.role = SymbolRole::Reference; | ||||
|     else { | ||||
|       char* p = const_cast<char*>(s.c_str()) + sep; | ||||
|       value.role = SymbolRole(strtol(p + 1, &p, 10)); | ||||
|       value.kind = SymbolKind(strtol(p + 1, &p, 10)); | ||||
|       value.id = Id<void>(strtol(p + 1, &p, 10)); | ||||
|     } | ||||
|     std::string t = visitor.GetString(); | ||||
|     char* s = const_cast<char*>(t.c_str()); | ||||
|     value.range = Range(s); | ||||
|     s = strchr(s, '|'); | ||||
|     value.id.id = RawId(strtol(s + 1, &s, 10)); | ||||
|     value.kind = static_cast<SymbolKind>(strtol(s + 1, &s, 10)); | ||||
|     value.role = static_cast<SymbolRole>(strtol(s + 1, &s, 10)); | ||||
|   } else { | ||||
|     Reflect(visitor, value.range); | ||||
|     Reflect(visitor, value.id); | ||||
| @ -2380,13 +2379,11 @@ void Reflect(Reader& visitor, Reference& value) { | ||||
| void Reflect(Writer& visitor, Reference& value) { | ||||
|   if (visitor.Format() == SerializeFormat::Json) { | ||||
|     std::string s = value.range.ToString(); | ||||
|     if (value.role != SymbolRole::Reference || | ||||
|         value.kind != SymbolKind::Invalid) { | ||||
|       s += '|' + std::to_string(uint8_t(value.role)); | ||||
|       s += '|' + std::to_string(uint8_t(value.kind)); | ||||
|       s += '|' + std::to_string(RawId(value.id)); | ||||
|     } | ||||
|     visitor.String(s.c_str()); | ||||
|     // RawId(-1) -> "-1"
 | ||||
|     s += '|' + std::to_string(static_cast<std::make_signed<RawId>::type>(value.id.id)); | ||||
|     s += '|' + std::to_string(int(value.kind)); | ||||
|     s += '|' + std::to_string(int(value.role)); | ||||
|     Reflect(visitor, s); | ||||
|   } else { | ||||
|     Reflect(visitor, value.range); | ||||
|     Reflect(visitor, value.id); | ||||
|  | ||||
| @ -57,7 +57,16 @@ struct Id { | ||||
|   // Invalid id.
 | ||||
|   Id() : id(-1) {} | ||||
|   explicit Id(RawId id) : id(id) {} | ||||
|   template <typename U> | ||||
|   // Id<T> -> Id<void> or Id<T> -> Id<T> is allowed implicitly.
 | ||||
|   template <typename U, | ||||
|             typename std::enable_if<std::is_void<T>::value || | ||||
|                                         std::is_same<T, U>::value, | ||||
|                                     bool>::type = false> | ||||
|   Id(Id<U> o) : id(o.id) {} | ||||
|   template <typename U, | ||||
|             typename std::enable_if<!(std::is_void<T>::value || | ||||
|                                       std::is_same<T, U>::value), | ||||
|                                     bool>::type = false> | ||||
|   explicit Id(Id<U> o) : id(o.id) {} | ||||
| 
 | ||||
|   // Needed for google::dense_hash_map.
 | ||||
| @ -107,16 +116,45 @@ struct Reference { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // NOTE: id can be -1 if the function call is not coming from a function.
 | ||||
| struct IndexFuncRef : Reference { | ||||
|   // Constructors are unnecessary in C++17 p0017
 | ||||
|   IndexFuncRef() = default; | ||||
|   IndexFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) | ||||
| struct SymbolIdx { | ||||
|   RawId idx; | ||||
|   SymbolKind kind; | ||||
| 
 | ||||
|   bool operator==(const SymbolIdx& o) const { | ||||
|     return kind == o.kind && idx == o.idx; | ||||
|   } | ||||
|   bool operator!=(const SymbolIdx& o) const { return !(*this == o); } | ||||
|   bool operator<(const SymbolIdx& o) const { | ||||
|     if (kind != o.kind) | ||||
|       return kind < o.kind; | ||||
|     return idx < o.idx; | ||||
|   } | ||||
| }; | ||||
| MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx); | ||||
| MAKE_HASHABLE(SymbolIdx, t.kind, t.idx); | ||||
| 
 | ||||
| // |id,kind| refer to the referenced entity.
 | ||||
| struct SymbolRef : Reference { | ||||
|   SymbolRef() = default; | ||||
|   SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) | ||||
|     : Reference{range, id, kind, role} {} | ||||
|   SymbolRef(Reference ref) : Reference(ref) {} | ||||
|   SymbolRef(SymbolIdx si) | ||||
|     : Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {} | ||||
| 
 | ||||
|   RawId Idx() const { return RawId(id); } | ||||
|   operator SymbolIdx() const { return SymbolIdx{Idx(), kind}; } | ||||
| }; | ||||
| 
 | ||||
| // Represents an occurrence of a variable/type, |id,kind| refer to the lexical
 | ||||
| // parent.
 | ||||
| struct Use : Reference { | ||||
|   Use() = default; | ||||
|   Use(Reference ref) : Reference(ref) {} | ||||
|   Use(Range range, Id<void> id, SymbolKind kind, SymbolRole role) | ||||
|       : Reference{range, id, kind, role} {} | ||||
| }; | ||||
| 
 | ||||
| void Reflect(Reader& visitor, IndexFuncRef& value); | ||||
| void Reflect(Writer& visitor, IndexFuncRef& value); | ||||
| void Reflect(Reader& visitor, Reference& value); | ||||
| void Reflect(Writer& visitor, Reference& value); | ||||
| 
 | ||||
| @ -126,7 +164,6 @@ struct IndexFamily { | ||||
|   using TypeId = Id<IndexType>; | ||||
|   using VarId = Id<IndexVar>; | ||||
|   using Range = ::Range; | ||||
|   using FuncRef = IndexFuncRef; | ||||
| }; | ||||
| 
 | ||||
| template <typename F> | ||||
| @ -218,7 +255,7 @@ struct IndexType { | ||||
| 
 | ||||
|   // Every usage, useful for things like renames.
 | ||||
|   // NOTE: Do not insert directly! Use AddUsage instead.
 | ||||
|   std::vector<Reference> uses; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   IndexType() {}  // For serialization.
 | ||||
|   IndexType(IndexTypeId id, Usr usr); | ||||
| @ -243,7 +280,7 @@ struct FuncDefDefinitionData { | ||||
|   std::vector<typename F::VarId> locals; | ||||
| 
 | ||||
|   // Functions that this function calls.
 | ||||
|   std::vector<typename F::FuncRef> callees; | ||||
|   std::vector<SymbolRef> callees; | ||||
| 
 | ||||
|   typename F::FileId file; | ||||
|   // Type which declares this one (ie, it is a method)
 | ||||
| @ -321,7 +358,7 @@ struct IndexFunc { | ||||
|   //
 | ||||
|   // To get all usages, also include the ranges inside of declarations and
 | ||||
|   // def.definition_spelling.
 | ||||
|   std::vector<IndexFuncRef> callers; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   IndexFunc() {}  // For serialization.
 | ||||
|   IndexFunc(IndexFuncId id, Usr usr) : usr(usr), id(id) { | ||||
| @ -416,7 +453,7 @@ struct IndexVar { | ||||
| 
 | ||||
|   std::vector<Range> declarations; | ||||
|   // Usages.
 | ||||
|   std::vector<Reference> uses; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   IndexVar() {}  // For serialization.
 | ||||
|   IndexVar(IndexVarId id, Usr usr) : usr(usr), id(id) { | ||||
|  | ||||
| @ -38,13 +38,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> { | ||||
|         QueryType& type = db->GetType(sym); | ||||
|         if (type.def) | ||||
|           out.result = GetLsLocations(db, working_files, | ||||
|                                       ToReference(db, type.def->parents)); | ||||
|                                       ToUses(db, type.def->parents)); | ||||
|         break; | ||||
|       } else if (sym.kind == SymbolKind::Func) { | ||||
|         QueryFunc& func = db->GetFunc(sym); | ||||
|         if (func.def) | ||||
|           out.result = GetLsLocations(db, working_files, | ||||
|                                       ToReference(db, func.def->base)); | ||||
|                                       ToUses(db, func.def->base)); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @ -105,11 +105,8 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree( | ||||
|     //  std::endl; return;
 | ||||
|     //}
 | ||||
| 
 | ||||
|     if (caller.HasValue()) { | ||||
|       QueryFuncId func_id = caller.FuncId(); | ||||
|       if (!func_id.HasValue()) | ||||
|         return; | ||||
|       QueryFunc& call_func = db->funcs[func_id.id]; | ||||
|     if (caller.kind == SymbolKind::Func) { | ||||
|       QueryFunc& call_func = db->GetFunc(caller); | ||||
|       if (!call_func.def) | ||||
|         return; | ||||
| 
 | ||||
| @ -137,18 +134,16 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree( | ||||
|       GetCallersForAllBaseFunctions(db, root_func); | ||||
|   std::vector<QueryFuncRef> derived_callers = | ||||
|       GetCallersForAllDerivedFunctions(db, root_func); | ||||
|   result.reserve(root_func.callers.size() + base_callers.size() + | ||||
|   result.reserve(root_func.uses.size() + base_callers.size() + | ||||
|                  derived_callers.size()); | ||||
| 
 | ||||
|   for (QueryFuncRef caller : root_func.callers) | ||||
|   for (QueryFuncRef caller : root_func.uses) | ||||
|     handle_caller(caller, Out_CqueryCallTree::CallType::Direct); | ||||
|   for (QueryFuncRef caller : base_callers) { | ||||
|     // Do not show calls to the base function coming from this function.
 | ||||
|     if (caller.FuncId() == root) | ||||
|       continue; | ||||
| 
 | ||||
|     handle_caller(caller, Out_CqueryCallTree::CallType::Base); | ||||
|   } | ||||
|   for (QueryFuncRef caller : base_callers) | ||||
|     if (caller.kind == SymbolKind::Func && caller.id != Id<void>(root)) { | ||||
|       // Do not show calls to the base function coming from this function.
 | ||||
|       handle_caller(caller, Out_CqueryCallTree::CallType::Base); | ||||
|     } | ||||
|   for (QueryFuncRef caller : derived_callers) | ||||
|     handle_caller(caller, Out_CqueryCallTree::CallType::Derived); | ||||
| 
 | ||||
|  | ||||
| @ -27,10 +27,10 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> { | ||||
|          FindSymbolsAtLocation(working_file, file, request->params.position)) { | ||||
|       if (sym.kind == SymbolKind::Func) { | ||||
|         QueryFunc& func = db->GetFunc(sym); | ||||
|         std::vector<Reference> uses = ToReference(db, func.callers); | ||||
|         for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, func)) | ||||
|         std::vector<Use> uses = func.uses; | ||||
|         for (Use func_ref : GetCallersForAllBaseFunctions(db, func)) | ||||
|           uses.push_back(func_ref); | ||||
|         for (QueryFuncRef func_ref : GetCallersForAllDerivedFunctions(db, func)) | ||||
|         for (Use func_ref : GetCallersForAllDerivedFunctions(db, func)) | ||||
|           uses.push_back(func_ref); | ||||
|         out.result = GetLsLocations(db, working_files, uses); | ||||
|       } | ||||
|  | ||||
| @ -37,12 +37,12 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> { | ||||
|       if (sym.kind == SymbolKind::Type) { | ||||
|         QueryType& type = db->GetType(sym); | ||||
|         out.result = | ||||
|             GetLsLocations(db, working_files, ToReference(db, type.derived)); | ||||
|             GetLsLocations(db, working_files, ToUses(db, type.derived)); | ||||
|         break; | ||||
|       } else if (sym.kind == SymbolKind::Func) { | ||||
|         QueryFunc& func = db->GetFunc(sym); | ||||
|         out.result = | ||||
|             GetLsLocations(db, working_files, ToReference(db, func.derived)); | ||||
|             GetLsLocations(db, working_files, ToUses(db, func.derived)); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @ -38,8 +38,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> { | ||||
|         // fallthrough
 | ||||
|         case SymbolKind::Type: { | ||||
|           QueryType& type = db->types[idx]; | ||||
|           out.result = GetLsLocations(db, working_files, | ||||
|                                       ToReference(db, type.instances)); | ||||
|           out.result = | ||||
|               GetLsLocations(db, working_files, ToUses(db, type.instances)); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|  | ||||
| @ -85,7 +85,7 @@ void AddCodeLens(const char* singular, | ||||
|                  const char* plural, | ||||
|                  CommonCodeLensParams* common, | ||||
|                  SymbolRef loc, | ||||
|                  const std::vector<Reference>& uses, | ||||
|                  const std::vector<Use>& uses, | ||||
|                  bool force_display) { | ||||
|   TCodeLens code_lens; | ||||
|   optional<lsRange> range = GetLsRange(common->working_file, loc.range); | ||||
| @ -100,7 +100,7 @@ void AddCodeLens(const char* singular, | ||||
| 
 | ||||
|   // Add unique uses.
 | ||||
|   std::unordered_set<lsLocation> unique_uses; | ||||
|   for (const Reference& use : uses) { | ||||
|   for (Use use : uses) { | ||||
|     optional<lsLocation> location = | ||||
|         GetLsLocation(common->db, common->working_files, use); | ||||
|     if (!location) | ||||
| @ -159,9 +159,9 @@ struct TextDocumentCodeLensHandler | ||||
|           AddCodeLens("ref", "refs", &common, OffsetStartColumn(sym, 0), | ||||
|                       type.uses, true /*force_display*/); | ||||
|           AddCodeLens("derived", "derived", &common, OffsetStartColumn(sym, 1), | ||||
|                       ToReference(db, type.derived), false /*force_display*/); | ||||
|                       ToUses(db, type.derived), false /*force_display*/); | ||||
|           AddCodeLens("var", "vars", &common, OffsetStartColumn(sym, 2), | ||||
|                       ToReference(db, type.instances), false /*force_display*/); | ||||
|                       ToUses(db, type.instances), false /*force_display*/); | ||||
|           break; | ||||
|         } | ||||
|         case SymbolKind::Func: { | ||||
| @ -183,35 +183,33 @@ struct TextDocumentCodeLensHandler | ||||
|             return SymbolRef(*def); | ||||
|           }; | ||||
| 
 | ||||
|           std::vector<QueryFuncRef> base_callers = | ||||
|           std::vector<Use> base_callers = | ||||
|               GetCallersForAllBaseFunctions(db, func); | ||||
|           std::vector<QueryFuncRef> derived_callers = | ||||
|           std::vector<Use> derived_callers = | ||||
|               GetCallersForAllDerivedFunctions(db, func); | ||||
|           if (base_callers.empty() && derived_callers.empty()) { | ||||
|             SymbolRef loc = try_ensure_spelling(sym); | ||||
|             AddCodeLens("call", "calls", &common, | ||||
|                         OffsetStartColumn(loc, offset++), | ||||
|                         ToReference(db, func.callers), true /*force_display*/); | ||||
|                         OffsetStartColumn(loc, offset++), func.uses, | ||||
|                         true /*force_display*/); | ||||
|           } else { | ||||
|             SymbolRef loc = try_ensure_spelling(sym); | ||||
|             AddCodeLens("direct call", "direct calls", &common, | ||||
|                         OffsetStartColumn(loc, offset++), | ||||
|                         ToReference(db, func.callers), false /*force_display*/); | ||||
|                         OffsetStartColumn(loc, offset++), func.uses, | ||||
|                         false /*force_display*/); | ||||
|             if (!base_callers.empty()) | ||||
|               AddCodeLens("base call", "base calls", &common, | ||||
|                           OffsetStartColumn(loc, offset++), | ||||
|                           ToReference(db, base_callers), | ||||
|                           OffsetStartColumn(loc, offset++), base_callers, | ||||
|                           false /*force_display*/); | ||||
|             if (!derived_callers.empty()) | ||||
|               AddCodeLens("derived call", "derived calls", &common, | ||||
|                           OffsetStartColumn(loc, offset++), | ||||
|                           ToReference(db, derived_callers), | ||||
|                           OffsetStartColumn(loc, offset++), derived_callers, | ||||
|                           false /*force_display*/); | ||||
|           } | ||||
| 
 | ||||
|           AddCodeLens("derived", "derived", &common, | ||||
|                       OffsetStartColumn(sym, offset++), | ||||
|                       ToReference(db, func.derived), false /*force_display*/); | ||||
|                       ToUses(db, func.derived), false /*force_display*/); | ||||
| 
 | ||||
|           // "Base"
 | ||||
|           if (func.def->base.size() == 1) { | ||||
| @ -238,7 +236,7 @@ struct TextDocumentCodeLensHandler | ||||
|             } | ||||
|           } else { | ||||
|             AddCodeLens("base", "base", &common, OffsetStartColumn(sym, 1), | ||||
|                         ToReference(db, func.def->base), | ||||
|                         ToUses(db, func.def->base), | ||||
|                         false /*force_display*/); | ||||
|           } | ||||
| 
 | ||||
|  | ||||
| @ -23,17 +23,17 @@ struct Out_TextDocumentDefinition | ||||
| }; | ||||
| MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result); | ||||
| 
 | ||||
| std::vector<Reference> GetGotoDefinitionTargets(QueryDatabase* db, | ||||
|                                                 SymbolRef sym) { | ||||
| std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db, | ||||
|                                           SymbolRef sym) { | ||||
|   switch (sym.kind) { | ||||
|     // Returns GetDeclarationsOfSymbolForGotoDefinition and
 | ||||
|     // variable type definition.
 | ||||
|     case SymbolKind::Var: { | ||||
|       std::vector<Reference> ret = | ||||
|       std::vector<Use> ret = | ||||
|           GetDeclarationsOfSymbolForGotoDefinition(db, sym); | ||||
|       QueryVar& var = db->GetVar(sym); | ||||
|       if (var.def && var.def->variable_type) { | ||||
|         std::vector<Reference> types = GetDeclarationsOfSymbolForGotoDefinition( | ||||
|         std::vector<Use> types = GetDeclarationsOfSymbolForGotoDefinition( | ||||
|             db, SymbolRef(Range(), Id<void>(var.def->variable_type->id), | ||||
|                           SymbolKind::Type, SymbolRole::None)); | ||||
|         ret.insert(ret.end(), types.begin(), types.end()); | ||||
| @ -91,8 +91,8 @@ struct TextDocumentDefinitionHandler | ||||
|                        def_loc->range.Contains(target_line, target_column))) { | ||||
|         // Goto declaration.
 | ||||
| 
 | ||||
|         std::vector<Reference> targets = GetGotoDefinitionTargets(db, sym); | ||||
|         for (Reference target : targets) { | ||||
|         std::vector<Use> targets = GetGotoDefinitionTargets(db, sym); | ||||
|         for (Use target : targets) { | ||||
|           optional<lsLocation> ls_target = | ||||
|               GetLsLocation(db, working_files, target); | ||||
|           if (ls_target) | ||||
|  | ||||
| @ -38,9 +38,9 @@ struct TextDocumentDocumentHighlightHandler | ||||
|     for (SymbolRef sym : | ||||
|          FindSymbolsAtLocation(working_file, file, request->params.position)) { | ||||
|       // Found symbol. Return references to highlight.
 | ||||
|       std::vector<Reference> uses = GetUsesOfSymbol(db, sym, true); | ||||
|       std::vector<Use> uses = GetUsesOfSymbol(db, sym, true); | ||||
|       out.result.reserve(uses.size()); | ||||
|       for (Reference use : uses) { | ||||
|       for (Use use : uses) { | ||||
|         if (db->GetFileId(use) != file_id) | ||||
|           continue; | ||||
| 
 | ||||
|  | ||||
| @ -54,10 +54,10 @@ struct TextDocumentReferencesHandler | ||||
|     for (const SymbolRef& sym : | ||||
|          FindSymbolsAtLocation(working_file, file, request->params.position)) { | ||||
|       // Found symbol. Return references.
 | ||||
|       std::vector<Reference> uses = GetUsesOfSymbol( | ||||
|       std::vector<Use> uses = GetUsesOfSymbol( | ||||
|           db, sym, request->params.context.includeDeclaration); | ||||
|       out.result.reserve(uses.size()); | ||||
|       for (const Reference& use : uses) { | ||||
|       for (Use use : uses) { | ||||
|         optional<lsLocation> ls_location = | ||||
|             GetLsLocation(db, working_files, use); | ||||
|         if (ls_location) | ||||
|  | ||||
| @ -6,17 +6,17 @@ namespace { | ||||
| 
 | ||||
| lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, | ||||
|                                    WorkingFiles* working_files, | ||||
|                                    const std::vector<Reference>& refs, | ||||
|                                    const std::vector<Use>& uses, | ||||
|                                    const std::string& new_text) { | ||||
|   std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit; | ||||
| 
 | ||||
|   for (auto& ref : refs) { | ||||
|   for (Use use : uses) { | ||||
|     optional<lsLocation> ls_location = | ||||
|         GetLsLocation(db, working_files, ref); | ||||
|         GetLsLocation(db, working_files, use); | ||||
|     if (!ls_location) | ||||
|       continue; | ||||
| 
 | ||||
|     QueryFileId file_id = db->GetFileId(ref); | ||||
|     QueryFileId file_id = db->GetFileId(use); | ||||
|     if (path_to_edit.find(file_id) == path_to_edit.end()) { | ||||
|       path_to_edit[file_id] = lsTextDocumentEdit(); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										152
									
								
								src/query.cc
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								src/query.cc
									
									
									
									
									
								
							| @ -285,7 +285,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in | ||||
|                       SymbolRole::Declaration); | ||||
|       add_outline(decl.spelling, id, SymbolKind::Func, SymbolRole::Declaration); | ||||
|     } | ||||
|     for (const IndexFuncRef& caller : func.callers) { | ||||
|     for (Use caller : func.uses) { | ||||
|       // Make ranges of implicit function calls larger (spanning one more column
 | ||||
|       // to the left/right). This is hacky but useful. e.g.
 | ||||
|       // textDocument/definition on the space/semicolon in `A a;` or `return
 | ||||
| @ -432,30 +432,8 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) | ||||
|         *GetQueryVarIdFromUsr(query_db, entry.second, true); | ||||
| } | ||||
| 
 | ||||
| Reference IdMap::ToQuery(Range range, SymbolRole role) const { | ||||
|   return Reference{range, Id<void>(primary_file), SymbolKind:: File, role}; | ||||
| } | ||||
| Reference IdMap::ToQuery(Reference ref) const { | ||||
|   switch (ref.kind) { | ||||
|     case SymbolKind::Invalid: | ||||
|     case SymbolKind::File: | ||||
|       ref.kind = SymbolKind::File; | ||||
|       ref.id = Id<void>(primary_file); | ||||
|       break; | ||||
|     case SymbolKind::Func: | ||||
|       ref.id = Id<void>( | ||||
|           cached_func_ids_.find(IndexFuncId(ref.id))->second); | ||||
|       break; | ||||
|     case SymbolKind::Type: | ||||
|       ref.id = Id<void>( | ||||
|           cached_type_ids_.find(IndexTypeId(ref.id))->second); | ||||
|       break; | ||||
|     case SymbolKind::Var: | ||||
|       ref.id = | ||||
|           Id<void>(cached_var_ids_.find(IndexVarId(ref.id))->second); | ||||
|       break; | ||||
|   } | ||||
|   return ref; | ||||
| Use IdMap::ToQuery(Range range, SymbolRole role) const { | ||||
|   return Use(range, primary_file, SymbolKind:: File, role); | ||||
| } | ||||
| QueryTypeId IdMap::ToQuery(IndexTypeId id) const { | ||||
|   assert(cached_type_ids_.find(id) != cached_type_ids_.end()); | ||||
| @ -471,29 +449,42 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const { | ||||
|   assert(cached_var_ids_.find(id) != cached_var_ids_.end()); | ||||
|   return QueryVarId(cached_var_ids_.find(id)->second); | ||||
| } | ||||
| QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const { | ||||
|   QueryFuncRef ret(ref.range, ref.id, ref.kind, ref.role); | ||||
| 
 | ||||
| Use IdMap::ToQuery(Reference ref) const { | ||||
|   switch (ref.kind) { | ||||
|     default: | ||||
|       break; | ||||
|     case SymbolKind::File: | ||||
|       ret.id = Id<void>(primary_file); | ||||
|       break; | ||||
|     case SymbolKind::Func: | ||||
|       ret.id = Id<void>(ToQuery(IndexFuncId(ref.id))); | ||||
|       break; | ||||
|     case SymbolKind::Type: | ||||
|       ret.id = Id<void>(ToQuery(IndexTypeId(ref.id))); | ||||
|       break; | ||||
|   case SymbolKind::Invalid: | ||||
|     break; | ||||
|   case SymbolKind::File: | ||||
|     ref.id = primary_file; | ||||
|     break; | ||||
|   case SymbolKind::Func: | ||||
|     ref.id = ToQuery(IndexFuncId(ref.id)); | ||||
|     break; | ||||
|   case SymbolKind::Type: | ||||
|     ref.id = ToQuery(IndexTypeId(ref.id)); | ||||
|     break; | ||||
|   case SymbolKind::Var: | ||||
|     ref.id = ToQuery(IndexVarId(ref.id)); | ||||
|     break; | ||||
|   } | ||||
|   return ret; | ||||
|   return ref; | ||||
| } | ||||
| Reference IdMap::ToQuery(IndexFunc::Declaration decl) const { | ||||
| SymbolRef IdMap::ToQuery(SymbolRef ref) const { | ||||
|   ref.Reference::operator=(ToQuery(static_cast<Reference>(ref))); | ||||
|   return ref; | ||||
| } | ||||
| Use IdMap::ToQuery(Use use) const { | ||||
|   use.Reference::operator=(ToQuery(static_cast<Reference>(use))); | ||||
|   return use; | ||||
| } | ||||
| 
 | ||||
| Use IdMap::ToQuery(IndexFunc::Declaration decl) const { | ||||
|   // TODO: expose more than just QueryLocation.
 | ||||
|   return Reference{decl.spelling, Id<void>(primary_file), SymbolKind::File, SymbolRole::Declaration}; | ||||
|   return Use(decl.spelling, primary_file, SymbolKind::File, | ||||
|              SymbolRole::Declaration); | ||||
| } | ||||
| std::vector<Reference> IdMap::ToQuery(const std::vector<Range>& a) const { | ||||
|   std::vector<Reference> ret; | ||||
| std::vector<Use> IdMap::ToQuery(const std::vector<Range>& a) const { | ||||
|   std::vector<Use> ret; | ||||
|   ret.reserve(a.size()); | ||||
|   for (auto& x : a) | ||||
|     ret.push_back(ToQuery(x, SymbolRole::Reference)); | ||||
| @ -610,7 +601,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, | ||||
|         PROCESS_UPDATE_DIFF(QueryTypeId, types_derived, derived, QueryTypeId); | ||||
|         PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances, | ||||
|                             QueryVarId); | ||||
|         PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Reference); | ||||
|         PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, Use); | ||||
|       }); | ||||
| 
 | ||||
|   // Functions
 | ||||
| @ -629,10 +620,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, | ||||
|             funcs_derived.push_back(QueryFunc::DerivedUpdate( | ||||
|                 previous_id_map.ToQuery(func->id), {}, | ||||
|                 previous_id_map.ToQuery(func->derived))); | ||||
|           if (!func->callers.empty()) | ||||
|             funcs_callers.push_back(QueryFunc::CallersUpdate( | ||||
|           if (!func->uses.empty()) | ||||
|             funcs_uses.push_back(QueryFunc::UsesUpdate( | ||||
|                 previous_id_map.ToQuery(func->id), {}, | ||||
|                 previous_id_map.ToQuery(func->callers))); | ||||
|                 previous_id_map.ToQuery(func->uses))); | ||||
|         } | ||||
|       }, | ||||
|       /*onAdded:*/ | ||||
| @ -650,10 +641,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, | ||||
|           funcs_derived.push_back( | ||||
|               QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id), | ||||
|                                        current_id_map.ToQuery(func->derived))); | ||||
|         if (!func->callers.empty()) | ||||
|           funcs_callers.push_back( | ||||
|               QueryFunc::CallersUpdate(current_id_map.ToQuery(func->id), | ||||
|                                        current_id_map.ToQuery(func->callers))); | ||||
|         if (!func->uses.empty()) | ||||
|           funcs_uses.push_back( | ||||
|               QueryFunc::UsesUpdate(current_id_map.ToQuery(func->id), | ||||
|                                     current_id_map.ToQuery(func->uses))); | ||||
|       }, | ||||
|       /*onFound:*/ | ||||
|       [this, &previous_id_map, ¤t_id_map](IndexFunc* previous, | ||||
| @ -670,9 +661,9 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, | ||||
|         } | ||||
| 
 | ||||
|         PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations, | ||||
|                             Reference); | ||||
|                             Use); | ||||
|         PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId); | ||||
|         PROCESS_UPDATE_DIFF(QueryFuncId, funcs_callers, callers, QueryFuncRef); | ||||
|         PROCESS_UPDATE_DIFF(QueryFuncId, funcs_uses, uses, Use); | ||||
|       }); | ||||
| 
 | ||||
|   // Variables
 | ||||
| @ -721,9 +712,8 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, | ||||
|           vars_def_update.push_back(QueryVar::DefUpdate( | ||||
|               current->usr, std::move(*current_remapped_def))); | ||||
| 
 | ||||
|         PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, | ||||
|                             Reference); | ||||
|         PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Reference); | ||||
|         PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, Use); | ||||
|         PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Use); | ||||
|       }); | ||||
| 
 | ||||
| #undef PROCESS_UPDATE_DIFF | ||||
| @ -747,7 +737,7 @@ void IndexUpdate::Merge(IndexUpdate&& update) { | ||||
|   INDEX_UPDATE_APPEND(funcs_def_update); | ||||
|   INDEX_UPDATE_MERGE(funcs_declarations); | ||||
|   INDEX_UPDATE_MERGE(funcs_derived); | ||||
|   INDEX_UPDATE_MERGE(funcs_callers); | ||||
|   INDEX_UPDATE_MERGE(funcs_uses); | ||||
| 
 | ||||
|   INDEX_UPDATE_APPEND(vars_removed); | ||||
|   INDEX_UPDATE_APPEND(vars_def_update); | ||||
| @ -864,7 +854,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) { | ||||
|   ImportOrUpdate(std::move(update->funcs_def_update)); | ||||
|   HANDLE_MERGEABLE(funcs_declarations, declarations, funcs); | ||||
|   HANDLE_MERGEABLE(funcs_derived, derived, funcs); | ||||
|   HANDLE_MERGEABLE(funcs_callers, callers, funcs); | ||||
|   HANDLE_MERGEABLE(funcs_uses, uses, funcs); | ||||
| 
 | ||||
|   RemoveUsrs(SymbolKind::Var, update->vars_removed); | ||||
|   ImportOrUpdate(std::move(update->vars_def_update)); | ||||
| @ -1053,7 +1043,7 @@ TEST_SUITE("query") { | ||||
|     previous.Resolve(previous.ToTypeId(HashUsr("usr1"))) | ||||
|         ->uses.push_back(Reference{Range(Position(1, 0))}); | ||||
|     previous.Resolve(previous.ToFuncId(HashUsr("usr2"))) | ||||
|         ->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0), | ||||
|         ->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0), | ||||
|                                          SymbolKind::Func, SymbolRole::None)); | ||||
|     previous.Resolve(previous.ToVarId(HashUsr("usr3"))) | ||||
|         ->uses.push_back(Reference{Range(Position(3, 0))}); | ||||
| @ -1072,21 +1062,21 @@ TEST_SUITE("query") { | ||||
|     IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); | ||||
|     IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); | ||||
| 
 | ||||
|     pf->callers.push_back(IndexFuncRef(Range(Position(1, 0)), Id<void>(0), | ||||
|     pf->uses.push_back(Use(Range(Position(1, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
|     cf->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0), | ||||
|     cf->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|     REQUIRE(update.funcs_removed == std::vector<Usr>{}); | ||||
|     REQUIRE(update.funcs_callers.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); | ||||
|     REQUIRE(update.funcs_callers[0].to_remove.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].to_remove[0].range == | ||||
|     REQUIRE(update.funcs_uses.size() == 1); | ||||
|     REQUIRE(update.funcs_uses[0].id == QueryFuncId(0)); | ||||
|     REQUIRE(update.funcs_uses[0].to_remove.size() == 1); | ||||
|     REQUIRE(update.funcs_uses[0].to_remove[0].range == | ||||
|             Range(Position(1, 0))); | ||||
|     REQUIRE(update.funcs_callers[0].to_add.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].to_add[0].range == | ||||
|     REQUIRE(update.funcs_uses[0].to_add.size() == 1); | ||||
|     REQUIRE(update.funcs_uses[0].to_add[0].range == | ||||
|             Range(Position(2, 0))); | ||||
|   } | ||||
| 
 | ||||
| @ -1117,14 +1107,14 @@ TEST_SUITE("query") { | ||||
| 
 | ||||
|     IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); | ||||
|     IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); | ||||
|     pf->callers.push_back(IndexFuncRef(Range(Position(1, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
|     pf->callers.push_back(IndexFuncRef(Range(Position(2, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
|     cf->callers.push_back(IndexFuncRef(Range(Position(4, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
|     cf->callers.push_back(IndexFuncRef(Range(Position(5, 0)), Id<void>(0), | ||||
|                                        SymbolKind::Func, SymbolRole::None)); | ||||
|     pf->uses.push_back(Use(Range(Position(1, 0)), Id<void>(0), | ||||
|                               SymbolKind::Func, SymbolRole::None)); | ||||
|     pf->uses.push_back(Use(Range(Position(2, 0)), Id<void>(0), | ||||
|                               SymbolKind::Func, SymbolRole::None)); | ||||
|     cf->uses.push_back(Use(Range(Position(4, 0)), Id<void>(0), | ||||
|                               SymbolKind::Func, SymbolRole::None)); | ||||
|     cf->uses.push_back(Use(Range(Position(5, 0)), Id<void>(0), | ||||
|                               SymbolKind::Func, SymbolRole::None)); | ||||
| 
 | ||||
|     QueryDatabase db; | ||||
|     IdMap previous_map(&db, previous.id_cache); | ||||
| @ -1137,13 +1127,13 @@ TEST_SUITE("query") { | ||||
|         &previous_map, ¤t_map, &previous, ¤t); | ||||
| 
 | ||||
|     db.ApplyIndexUpdate(&import_update); | ||||
|     REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|     REQUIRE(db.funcs[0].callers[0].range == Range(Position(1, 0))); | ||||
|     REQUIRE(db.funcs[0].callers[1].range == Range(Position(2, 0))); | ||||
|     REQUIRE(db.funcs[0].uses.size() == 2); | ||||
|     REQUIRE(db.funcs[0].uses[0].range == Range(Position(1, 0))); | ||||
|     REQUIRE(db.funcs[0].uses[1].range == Range(Position(2, 0))); | ||||
| 
 | ||||
|     db.ApplyIndexUpdate(&delta_update); | ||||
|     REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|     REQUIRE(db.funcs[0].callers[0].range == Range(Position(4, 0))); | ||||
|     REQUIRE(db.funcs[0].callers[1].range == Range(Position(5, 0))); | ||||
|     REQUIRE(db.funcs[0].uses.size() == 2); | ||||
|     REQUIRE(db.funcs[0].uses[0].range == Range(Position(4, 0))); | ||||
|     REQUIRE(db.funcs[0].uses[1].range == Range(Position(5, 0))); | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										85
									
								
								src/query.h
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								src/query.h
									
									
									
									
									
								
							| @ -20,46 +20,7 @@ using QueryVarId = Id<QueryVar>; | ||||
| 
 | ||||
| struct IdMap; | ||||
| 
 | ||||
| struct SymbolIdx { | ||||
|   RawId idx; | ||||
|   SymbolKind kind; | ||||
| 
 | ||||
|   bool operator==(const SymbolIdx& o) const { | ||||
|     return kind == o.kind && idx == o.idx; | ||||
|   } | ||||
|   bool operator!=(const SymbolIdx& o) const { return !(*this == o); } | ||||
|   bool operator<(const SymbolIdx& o) const { | ||||
|     if (kind != o.kind) | ||||
|       return kind < o.kind; | ||||
|     return idx < o.idx; | ||||
|   } | ||||
| }; | ||||
| MAKE_REFLECT_STRUCT(SymbolIdx, kind, idx); | ||||
| MAKE_HASHABLE(SymbolIdx, t.kind, t.idx); | ||||
| 
 | ||||
| struct SymbolRef : Reference { | ||||
|   SymbolRef() = default; | ||||
|   SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) | ||||
|       : Reference{range, id, kind, role} {} | ||||
|   SymbolRef(Reference ref) : Reference(ref) {} | ||||
|   SymbolRef(SymbolIdx si) | ||||
|       : Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {} | ||||
| 
 | ||||
|   RawId Idx() const { return RawId(id); } | ||||
|   operator SymbolIdx() const { return SymbolIdx{Idx(), kind, }; } | ||||
| }; | ||||
| 
 | ||||
| struct QueryFuncRef : Reference { | ||||
|   QueryFuncRef() = default; | ||||
|   QueryFuncRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) | ||||
|     : Reference{range, id, kind, role} {} | ||||
| 
 | ||||
|   QueryFuncId FuncId() const { | ||||
|     if (kind == SymbolKind::Func) | ||||
|       return QueryFuncId(id); | ||||
|     return QueryFuncId(); | ||||
|   } | ||||
| }; | ||||
| using QueryFuncRef = Use; | ||||
| 
 | ||||
| // There are two sources of reindex updates: the (single) definition of a
 | ||||
| // symbol has changed, or one of many users of the symbol has changed.
 | ||||
| @ -132,7 +93,6 @@ struct QueryFamily { | ||||
|   using TypeId = Id<QueryType>; | ||||
|   using VarId = Id<QueryVar>; | ||||
|   using Range = Reference; | ||||
|   using FuncRef = QueryFuncRef; | ||||
| }; | ||||
| 
 | ||||
| struct QueryFile { | ||||
| @ -175,14 +135,14 @@ struct QueryType { | ||||
|   using DefUpdate = WithUsr<Def>; | ||||
|   using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>; | ||||
|   using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>; | ||||
|   using UsesUpdate = MergeableUpdate<QueryTypeId, Reference>; | ||||
|   using UsesUpdate = MergeableUpdate<QueryTypeId, Use>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<QueryTypeId> derived; | ||||
|   std::vector<QueryVarId> instances; | ||||
|   std::vector<Reference> uses; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   explicit QueryType(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| @ -190,16 +150,16 @@ struct QueryType { | ||||
| struct QueryFunc { | ||||
|   using Def = FuncDefDefinitionData<QueryFamily>; | ||||
|   using DefUpdate = WithUsr<Def>; | ||||
|   using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>; | ||||
|   using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Use>; | ||||
|   using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>; | ||||
|   using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>; | ||||
|   using UsesUpdate = MergeableUpdate<QueryFuncId, Use>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<Reference> declarations; | ||||
|   std::vector<Use> declarations; | ||||
|   std::vector<QueryFuncId> derived; | ||||
|   std::vector<QueryFuncRef> callers; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   explicit QueryFunc(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| @ -207,14 +167,14 @@ struct QueryFunc { | ||||
| struct QueryVar { | ||||
|   using Def = VarDefDefinitionData<QueryFamily>; | ||||
|   using DefUpdate = WithUsr<Def>; | ||||
|   using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>; | ||||
|   using UsesUpdate = MergeableUpdate<QueryVarId, Reference>; | ||||
|   using DeclarationsUpdate = MergeableUpdate<QueryVarId, Use>; | ||||
|   using UsesUpdate = MergeableUpdate<QueryVarId, Use>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<Reference> declarations; | ||||
|   std::vector<Reference> uses; | ||||
|   std::vector<Use> declarations; | ||||
|   std::vector<Use> uses; | ||||
| 
 | ||||
|   explicit QueryVar(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| @ -250,7 +210,7 @@ struct IndexUpdate { | ||||
|   std::vector<QueryFunc::DefUpdate> funcs_def_update; | ||||
|   std::vector<QueryFunc::DeclarationsUpdate> funcs_declarations; | ||||
|   std::vector<QueryFunc::DerivedUpdate> funcs_derived; | ||||
|   std::vector<QueryFunc::CallersUpdate> funcs_callers; | ||||
|   std::vector<QueryFunc::UsesUpdate> funcs_uses; | ||||
| 
 | ||||
|   // Variable updates.
 | ||||
|   std::vector<Usr> vars_removed; | ||||
| @ -279,7 +239,7 @@ MAKE_REFLECT_STRUCT(IndexUpdate, | ||||
|                     funcs_def_update, | ||||
|                     funcs_declarations, | ||||
|                     funcs_derived, | ||||
|                     funcs_callers, | ||||
|                     funcs_uses, | ||||
|                     vars_removed, | ||||
|                     vars_def_update, | ||||
|                     vars_declarations, | ||||
| @ -379,10 +339,10 @@ template <> struct IndexToQuery<IndexFileId> { using type = QueryFileId; }; | ||||
| template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; }; | ||||
| template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; }; | ||||
| template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; }; | ||||
| template <> struct IndexToQuery<IndexFuncRef> { using type = QueryFuncRef; }; | ||||
| template <> struct IndexToQuery<Range> { using type = Reference; }; | ||||
| template <> struct IndexToQuery<Reference> { using type = Reference; }; | ||||
| template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Reference; }; | ||||
| template <> struct IndexToQuery<Use> { using type = Use; }; | ||||
| template <> struct IndexToQuery<SymbolRef> { using type = SymbolRef; }; | ||||
| template <> struct IndexToQuery<Range> { using type = Use; }; | ||||
| template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Use; }; | ||||
| template <typename I> struct IndexToQuery<optional<I>> { | ||||
|   using type = optional<typename IndexToQuery<I>::type>; | ||||
| }; | ||||
| @ -399,13 +359,14 @@ struct IdMap { | ||||
| 
 | ||||
|   // FIXME Too verbose
 | ||||
|   // clang-format off
 | ||||
|   Reference ToQuery(Range range, SymbolRole role) const; | ||||
|   Reference ToQuery(Reference ref) const; | ||||
|   QueryTypeId ToQuery(IndexTypeId id) const; | ||||
|   QueryFuncId ToQuery(IndexFuncId id) const; | ||||
|   QueryVarId ToQuery(IndexVarId id) const; | ||||
|   QueryFuncRef ToQuery(IndexFuncRef ref) const; | ||||
|   Reference ToQuery(IndexFunc::Declaration decl) const; | ||||
|   SymbolRef ToQuery(SymbolRef ref) const; | ||||
|   Use ToQuery(Range range, SymbolRole role) const; | ||||
|   Use ToQuery(Reference ref) const; | ||||
|   Use ToQuery(Use ref) const; | ||||
|   Use ToQuery(IndexFunc::Declaration decl) const; | ||||
|   template <typename I> | ||||
|   Maybe<typename IndexToQuery<I>::type> ToQuery(Maybe<I> id) const { | ||||
|     if (!id) | ||||
| @ -420,7 +381,7 @@ struct IdMap { | ||||
|       ret.push_back(ToQuery(x)); | ||||
|     return ret; | ||||
|   } | ||||
|   std::vector<Reference> ToQuery(const std::vector<Range>& a) const; | ||||
|   std::vector<Use> ToQuery(const std::vector<Range>& a) const; | ||||
|   // clang-format on
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -119,18 +119,9 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, | ||||
|   return nullopt; | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryFuncRef>& refs) { | ||||
|   std::vector<Reference> ret; | ||||
|   ret.reserve(refs.size()); | ||||
|   for (auto& ref : refs) | ||||
|     ret.push_back(ref); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryFuncId>& ids) { | ||||
|   std::vector<Reference> ret; | ||||
| std::vector<Use> ToUses(QueryDatabase* db, | ||||
|                         const std::vector<QueryFuncId>& ids) { | ||||
|   std::vector<Use> ret; | ||||
|   ret.reserve(ids.size()); | ||||
|   for (auto id : ids) { | ||||
|     QueryFunc& func = db->funcs[id.id]; | ||||
| @ -142,9 +133,9 @@ std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryTypeId>& ids) { | ||||
|   std::vector<Reference> ret; | ||||
| std::vector<Use> ToUses(QueryDatabase* db, | ||||
|                         const std::vector<QueryTypeId>& ids) { | ||||
|   std::vector<Use> ret; | ||||
|   ret.reserve(ids.size()); | ||||
|   for (auto id : ids) { | ||||
|     QueryType& type = db->types[id.id]; | ||||
| @ -154,9 +145,8 @@ std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryVarId>& ids) { | ||||
|   std::vector<Reference> ret; | ||||
| std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) { | ||||
|   std::vector<Use> ret; | ||||
|   ret.reserve(ids.size()); | ||||
|   for (auto id : ids) { | ||||
|     QueryVar& var = db->vars[id.id]; | ||||
| @ -168,13 +158,13 @@ std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, | ||||
|                                        SymbolRef sym, | ||||
|                                        bool include_decl) { | ||||
| std::vector<Use> GetUsesOfSymbol(QueryDatabase* db, | ||||
|                                  SymbolRef sym, | ||||
|                                  bool include_decl) { | ||||
|   switch (sym.kind) { | ||||
|     case SymbolKind::Type: { | ||||
|       QueryType& type = db->types[sym.Idx()]; | ||||
|       std::vector<Reference> ret = type.uses; | ||||
|       std::vector<Use> ret = type.uses; | ||||
|       if (include_decl && type.def && type.def->definition_spelling) | ||||
|         ret.push_back(*type.def->definition_spelling); | ||||
|       return ret; | ||||
| @ -182,7 +172,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, | ||||
|     case SymbolKind::Func: { | ||||
|       // TODO: the vector allocation could be avoided.
 | ||||
|       QueryFunc& func = db->funcs[sym.Idx()]; | ||||
|       std::vector<Reference> ret = ToReference(db, func.callers); | ||||
|       std::vector<Use> ret = func.uses; | ||||
|       if (include_decl) { | ||||
|         AddRange(&ret, func.declarations); | ||||
|         if (func.def && func.def->definition_spelling) | ||||
| @ -192,7 +182,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, | ||||
|     } | ||||
|     case SymbolKind::Var: { | ||||
|       QueryVar& var = db->vars[sym.Idx()]; | ||||
|       std::vector<Reference> ret = var.uses; | ||||
|       std::vector<Use> ret = var.uses; | ||||
|       if (include_decl) { | ||||
|         if (var.def && var.def->definition_spelling) | ||||
|           ret.push_back(*var.def->definition_spelling); | ||||
| @ -208,7 +198,7 @@ std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition( | ||||
| std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition( | ||||
|     QueryDatabase* db, | ||||
|     SymbolRef sym) { | ||||
|   switch (sym.kind) { | ||||
| @ -238,7 +228,7 @@ std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition( | ||||
| 
 | ||||
| bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { | ||||
|   // Check self.
 | ||||
|   if (!root.callers.empty()) | ||||
|   if (!root.uses.empty()) | ||||
|     return true; | ||||
| 
 | ||||
|   // Check for base calls.
 | ||||
| @ -249,7 +239,7 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { | ||||
|   while (!queue.empty()) { | ||||
|     QueryFunc& func = *queue.front(); | ||||
|     queue.pop(); | ||||
|     if (!func.callers.empty()) | ||||
|     if (!func.uses.empty()) | ||||
|       return true; | ||||
|     if (func.def) | ||||
|       EachWithGen<QueryFunc>(db->funcs, func.def->base, [&](QueryFunc& func1) { | ||||
| @ -264,7 +254,7 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { | ||||
|   while (!queue.empty()) { | ||||
|     QueryFunc& func = *queue.front(); | ||||
|     queue.pop(); | ||||
|     if (!func.callers.empty()) | ||||
|     if (!func.uses.empty()) | ||||
|       return true; | ||||
|     EachWithGen<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) { | ||||
|       queue.push(&func1); | ||||
| @ -274,9 +264,9 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|                                                         QueryFunc& root) { | ||||
|   std::vector<QueryFuncRef> callers; | ||||
| std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|                                                QueryFunc& root) { | ||||
|   std::vector<Use> callers; | ||||
|   if (!root.def) | ||||
|     return callers; | ||||
| 
 | ||||
| @ -288,7 +278,7 @@ std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|     QueryFunc& func = *queue.front(); | ||||
|     queue.pop(); | ||||
| 
 | ||||
|     AddRange(&callers, func.callers); | ||||
|     AddRange(&callers, func.uses); | ||||
|     if (func.def) | ||||
|       EachWithGen<QueryFunc>(db->funcs, func.def->base, [&](QueryFunc& func1) { | ||||
|         queue.push(&func1); | ||||
| @ -298,9 +288,9 @@ std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|   return callers; | ||||
| } | ||||
| 
 | ||||
| std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db, | ||||
|                                                            QueryFunc& root) { | ||||
|   std::vector<QueryFuncRef> callers; | ||||
| std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db, | ||||
|                                                   QueryFunc& root) { | ||||
|   std::vector<Use> callers; | ||||
| 
 | ||||
|   std::queue<QueryFunc*> queue; | ||||
|   EachWithGen<QueryFunc>(db->funcs, root.derived, [&](QueryFunc& func) { | ||||
| @ -314,7 +304,7 @@ std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db, | ||||
|     EachWithGen<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) { | ||||
|       queue.push(&func1); | ||||
|     }); | ||||
|     AddRange(&callers, func.callers); | ||||
|     AddRange(&callers, func.uses); | ||||
|   } | ||||
| 
 | ||||
|   return callers; | ||||
| @ -403,11 +393,11 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db, | ||||
| std::vector<lsLocation> GetLsLocations( | ||||
|     QueryDatabase* db, | ||||
|     WorkingFiles* working_files, | ||||
|     const std::vector<Reference>& refs) { | ||||
|     const std::vector<Use>& uses) { | ||||
|   std::unordered_set<lsLocation> unique_locations; | ||||
|   for (Reference ref : refs) { | ||||
|   for (Use use : uses) { | ||||
|     optional<lsLocation> location = | ||||
|         GetLsLocation(db, working_files, ref); | ||||
|         GetLsLocation(db, working_files, use); | ||||
|     if (!location) | ||||
|       continue; | ||||
|     unique_locations.insert(*location); | ||||
|  | ||||
| @ -15,27 +15,25 @@ Maybe<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolRef sym); | ||||
| Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, | ||||
|                                                SymbolRef sym); | ||||
| 
 | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryFuncRef>& refs); | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryFuncId>& ids); | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryTypeId>& ids); | ||||
| std::vector<Reference> ToReference(QueryDatabase* db, | ||||
|                                    const std::vector<QueryVarId>& ids); | ||||
| std::vector<Use> ToUses(QueryDatabase* db, | ||||
|                         const std::vector<QueryFuncId>& ids); | ||||
| std::vector<Use> ToUses(QueryDatabase* db, | ||||
|                         const std::vector<QueryTypeId>& ids); | ||||
| std::vector<Use> ToUses(QueryDatabase* db, | ||||
|                         const std::vector<QueryVarId>& ids); | ||||
| 
 | ||||
| std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db, | ||||
|                                        SymbolRef sym, | ||||
|                                        bool include_decl); | ||||
| std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition( | ||||
| std::vector<Use> GetUsesOfSymbol(QueryDatabase* db, | ||||
|                                  SymbolRef sym, | ||||
|                                  bool include_decl); | ||||
| std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition( | ||||
|     QueryDatabase* db, | ||||
|     SymbolRef sym); | ||||
| 
 | ||||
| bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root); | ||||
| std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|                                                         QueryFunc& root); | ||||
| std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryDatabase* db, | ||||
|                                                            QueryFunc& root); | ||||
| std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db, | ||||
|                                                QueryFunc& root); | ||||
| std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db, | ||||
|                                                   QueryFunc& root); | ||||
| optional<lsPosition> GetLsPosition(WorkingFile* working_file, | ||||
|                                    const Position& position); | ||||
| optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location); | ||||
| @ -50,7 +48,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db, | ||||
| std::vector<lsLocation> GetLsLocations( | ||||
|     QueryDatabase* db, | ||||
|     WorkingFiles* working_files, | ||||
|     const std::vector<Reference>& refs); | ||||
|     const std::vector<Use>& refs); | ||||
| // Returns a symbol. The symbol will have *NOT* have a location assigned.
 | ||||
| optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, | ||||
|                                             WorkingFiles* working_files, | ||||
|  | ||||
| @ -240,7 +240,7 @@ void Reflect(TVisitor& visitor, IndexFunc& value) { | ||||
|   REFLECT_MEMBER2("base", value.def.base); | ||||
|   REFLECT_MEMBER2("derived", value.derived); | ||||
|   REFLECT_MEMBER2("locals", value.def.locals); | ||||
|   REFLECT_MEMBER2("callers", value.callers); | ||||
|   REFLECT_MEMBER2("uses", value.uses); | ||||
|   REFLECT_MEMBER2("callees", value.def.callees); | ||||
|   REFLECT_MEMBER_END(); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user