mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 04:32:33 +00:00 
			
		
		
		
	Change is_implicit to role in {Index,Query}FuncRef
Add `FileId file` to *DefDefinitionData::Def
This commit is contained in:
		
							parent
							
								
									10c2843846
								
							
						
					
					
						commit
						dbdab02ff4
					
				| @ -584,7 +584,7 @@ void OnIndexReference_Function(IndexFile* db, | ||||
|                                ClangCursor caller_cursor, | ||||
|                                IndexFuncId called_id, | ||||
|                                IndexFunc* called, | ||||
|                                bool is_implicit) { | ||||
|                                SymbolRole role) { | ||||
|   if (IsFunctionCallContext(caller_cursor.get_kind())) { | ||||
|     IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor); | ||||
|     IndexFunc* caller = db->Resolve(caller_id); | ||||
| @ -592,10 +592,10 @@ void OnIndexReference_Function(IndexFile* db, | ||||
|     called = db->Resolve(called_id); | ||||
| 
 | ||||
|     AddFuncRef(&caller->def.callees, | ||||
|                IndexFuncRef(called->id, loc, is_implicit)); | ||||
|     AddFuncRef(&called->callers, IndexFuncRef(caller->id, loc, is_implicit)); | ||||
|                IndexFuncRef{loc, called->id, role}); | ||||
|     AddFuncRef(&called->callers, IndexFuncRef{loc, caller->id, role}); | ||||
|   } else { | ||||
|     AddFuncRef(&called->callers, IndexFuncRef(loc, is_implicit)); | ||||
|     AddFuncRef(&called->callers, IndexFuncRef{loc, IndexFuncId(), role}); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -603,7 +603,7 @@ void OnIndexReference_Function(IndexFile* db, | ||||
| 
 | ||||
| // static
 | ||||
| const int IndexFile::kMajorVersion = 11; | ||||
| const int IndexFile::kMinorVersion = 1; | ||||
| const int IndexFile::kMinorVersion = 2; | ||||
| 
 | ||||
| IndexFile::IndexFile(const std::string& path, | ||||
|                      const std::string& contents) | ||||
| @ -1258,7 +1258,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, | ||||
|             IndexFunc* called = db->Resolve(called_id); | ||||
|             OnIndexReference_Function(db, cursor.get_spelling_range(), | ||||
|                                       data->container, called_id, called, | ||||
|                                       /*implicit=*/false); | ||||
|                                       SymbolRole::None); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
| @ -1992,8 +1992,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { | ||||
|       else | ||||
|         CheckTypeDependentMemberRefExpr(&loc, ref_cursor, param, db); | ||||
| 
 | ||||
|       OnIndexReference_Function(db, loc, ref->container->cursor, called_id, | ||||
|                                 called, is_implicit); | ||||
|       OnIndexReference_Function( | ||||
|           db, loc, ref->container->cursor, called_id, called, | ||||
|           is_implicit ? SymbolRole::Implicit : SymbolRole::None); | ||||
| 
 | ||||
|       // Checks if |str| starts with |start|. Ignores case.
 | ||||
|       auto str_begin = [](const char* start, const char* str) { | ||||
| @ -2033,7 +2034,8 @@ 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, true /*is_implicit*/)); | ||||
|             AddFuncRef(&ctor->callers, | ||||
|                        IndexFuncRef{loc, IndexFuncId(), SymbolRole::Implicit}); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| @ -2315,7 +2317,7 @@ void Reflect(Reader& visitor, IndexFuncRef& value) { | ||||
|     std::string s = visitor.GetString(); | ||||
|     const char* str_value = s.c_str(); | ||||
|     if (str_value[0] == '~') { | ||||
|       value.is_implicit = true; | ||||
|       value.role = SymbolRole::Implicit; | ||||
|       ++str_value; | ||||
|     } | ||||
|     RawId id = atol(str_value); | ||||
| @ -2324,15 +2326,15 @@ void Reflect(Reader& visitor, IndexFuncRef& value) { | ||||
|     value.id = IndexFuncId(id); | ||||
|     value.loc = Range(loc_string); | ||||
|   } else { | ||||
|     Reflect(visitor, value.id); | ||||
|     Reflect(visitor, value.loc); | ||||
|     Reflect(visitor, value.is_implicit); | ||||
|     Reflect(visitor, value.id); | ||||
|     Reflect(visitor, value.role); | ||||
|   } | ||||
| } | ||||
| void Reflect(Writer& visitor, IndexFuncRef& value) { | ||||
|   if (visitor.Format() == SerializeFormat::Json) { | ||||
|     std::string s; | ||||
|     if (value.is_implicit) | ||||
|     if (value.role & SymbolRole::Implicit) | ||||
|       s += "~"; | ||||
| 
 | ||||
|     // id.id is unsigned, special case -1 value
 | ||||
| @ -2344,8 +2346,8 @@ void Reflect(Writer& visitor, IndexFuncRef& value) { | ||||
|     s += "@" + value.loc.ToString(); | ||||
|     visitor.String(s.c_str()); | ||||
|   } else { | ||||
|     Reflect(visitor, value.id); | ||||
|     Reflect(visitor, value.loc); | ||||
|     Reflect(visitor, value.is_implicit); | ||||
|     Reflect(visitor, value.id); | ||||
|     Reflect(visitor, value.role); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -27,6 +27,7 @@ | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| 
 | ||||
| struct IndexFile; | ||||
| struct IndexType; | ||||
| struct IndexFunc; | ||||
| struct IndexVar; | ||||
| @ -61,7 +62,7 @@ struct Id { | ||||
| namespace std { | ||||
| template <typename T> | ||||
| struct hash<Id<T>> { | ||||
|   size_t operator()(const Id<T>& k) const { return hash<size_t>()(k.id); } | ||||
|   size_t operator()(const Id<T>& k) const { return hash<RawId>()(k.id); } | ||||
| }; | ||||
| }  // namespace std
 | ||||
| 
 | ||||
| @ -70,6 +71,7 @@ void Reflect(TVisitor& visitor, Id<T>& id) { | ||||
|   Reflect(visitor, id.id); | ||||
| } | ||||
| 
 | ||||
| using IndexFileId = Id<IndexFile>; | ||||
| using IndexTypeId = Id<IndexType>; | ||||
| using IndexFuncId = Id<IndexFunc>; | ||||
| using IndexVarId = Id<IndexVar>; | ||||
| @ -88,18 +90,10 @@ struct IndexFuncRef { | ||||
|   // NOTE: id can be -1 if the function call is not coming from a function.
 | ||||
|   Range loc; | ||||
|   IndexFuncId id; | ||||
|   SymbolRole role = SymbolRole::None; | ||||
|   bool is_implicit = false; | ||||
|   SymbolRole role; | ||||
| 
 | ||||
|   IndexFuncRef() {}  // For serialization.
 | ||||
| 
 | ||||
|   IndexFuncRef(IndexFuncId id, Range loc, bool is_implicit) | ||||
|       : loc(loc), id(id), is_implicit(is_implicit) {} | ||||
|   IndexFuncRef(Range loc, bool is_implicit) | ||||
|       : loc(loc), is_implicit(is_implicit) {} | ||||
| 
 | ||||
|   std::tuple<IndexFuncId, Range, bool> ToTuple() const { | ||||
|     return std::make_tuple(id, loc, is_implicit); | ||||
|   std::tuple<IndexFuncId, Range, SymbolRole> ToTuple() const { | ||||
|     return std::make_tuple(id, loc, role); | ||||
|   } | ||||
|   bool operator==(const IndexFuncRef& o) { return ToTuple() == o.ToTuple(); } | ||||
|   bool operator!=(const IndexFuncRef& o) { return !(*this == o); } | ||||
| @ -111,7 +105,11 @@ struct IndexFuncRef { | ||||
| void Reflect(Reader& visitor, IndexFuncRef& value); | ||||
| void Reflect(Writer& visitor, IndexFuncRef& value); | ||||
| 
 | ||||
| template <typename TypeId, typename FuncId, typename VarId, typename Range> | ||||
| template <typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
|           typename Range> | ||||
| struct TypeDefDefinitionData { | ||||
|   // General metadata.
 | ||||
|   std::string detailed_name; | ||||
| @ -130,10 +128,6 @@ struct TypeDefDefinitionData { | ||||
|   Maybe<Range> definition_spelling; | ||||
|   Maybe<Range> definition_extent; | ||||
| 
 | ||||
|   // If set, then this is the same underlying type as the given value (ie, this
 | ||||
|   // type comes from a using or typedef statement).
 | ||||
|   Maybe<TypeId> alias_of; | ||||
| 
 | ||||
|   // Immediate parent types.
 | ||||
|   std::vector<TypeId> parents; | ||||
| 
 | ||||
| @ -142,6 +136,11 @@ struct TypeDefDefinitionData { | ||||
|   std::vector<FuncId> funcs; | ||||
|   std::vector<VarId> vars; | ||||
| 
 | ||||
|   FileId file; | ||||
|   // If set, then this is the same underlying type as the given value (ie, this
 | ||||
|   // type comes from a using or typedef statement).
 | ||||
|   Maybe<TypeId> alias_of; | ||||
| 
 | ||||
|   int16_t short_name_offset = 0; | ||||
|   int16_t short_name_size = 0; | ||||
|   ClangSymbolKind kind = ClangSymbolKind::Unknown; | ||||
| @ -164,12 +163,14 @@ struct TypeDefDefinitionData { | ||||
|   } | ||||
| }; | ||||
| template <typename TVisitor, | ||||
|           typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
|           typename Range> | ||||
| void Reflect(TVisitor& visitor, | ||||
|              TypeDefDefinitionData<TypeId, FuncId, VarId, Range>& value) { | ||||
| void Reflect( | ||||
|     TVisitor& visitor, | ||||
|     TypeDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) { | ||||
|   REFLECT_MEMBER_START(); | ||||
|   REFLECT_MEMBER(detailed_name); | ||||
|   REFLECT_MEMBER(short_name_offset); | ||||
| @ -179,6 +180,7 @@ void Reflect(TVisitor& visitor, | ||||
|   REFLECT_MEMBER(comments); | ||||
|   REFLECT_MEMBER(definition_spelling); | ||||
|   REFLECT_MEMBER(definition_extent); | ||||
|   REFLECT_MEMBER(file); | ||||
|   REFLECT_MEMBER(alias_of); | ||||
|   REFLECT_MEMBER(parents); | ||||
|   REFLECT_MEMBER(types); | ||||
| @ -188,8 +190,11 @@ void Reflect(TVisitor& visitor, | ||||
| } | ||||
| 
 | ||||
| struct IndexType { | ||||
|   using Def = | ||||
|       TypeDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; | ||||
|   using Def = TypeDefDefinitionData<IndexFileId, | ||||
|                                     IndexTypeId, | ||||
|                                     IndexFuncId, | ||||
|                                     IndexVarId, | ||||
|                                     Range>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   IndexTypeId id; | ||||
| @ -213,7 +218,8 @@ struct IndexType { | ||||
| }; | ||||
| MAKE_HASHABLE(IndexType, t.id); | ||||
| 
 | ||||
| template <typename TypeId, | ||||
| template <typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
|           typename FuncRef, | ||||
| @ -226,9 +232,6 @@ struct FuncDefDefinitionData { | ||||
|   Maybe<Range> definition_spelling; | ||||
|   Maybe<Range> definition_extent; | ||||
| 
 | ||||
|   // Type which declares this one (ie, it is a method)
 | ||||
|   Maybe<TypeId> declaring_type; | ||||
| 
 | ||||
|   // Method this method overrides.
 | ||||
|   std::vector<FuncId> base; | ||||
| 
 | ||||
| @ -238,6 +241,9 @@ struct FuncDefDefinitionData { | ||||
|   // Functions that this function calls.
 | ||||
|   std::vector<FuncRef> callees; | ||||
| 
 | ||||
|   FileId file; | ||||
|   // Type which declares this one (ie, it is a method)
 | ||||
|   Maybe<TypeId> declaring_type; | ||||
|   int16_t short_name_offset = 0; | ||||
|   int16_t short_name_size = 0; | ||||
|   ClangSymbolKind kind = ClangSymbolKind::Unknown; | ||||
| @ -262,6 +268,7 @@ struct FuncDefDefinitionData { | ||||
| }; | ||||
| 
 | ||||
| template <typename TVisitor, | ||||
|           typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
| @ -269,7 +276,8 @@ template <typename TVisitor, | ||||
|           typename Range> | ||||
| void Reflect( | ||||
|     TVisitor& visitor, | ||||
|     FuncDefDefinitionData<TypeId, FuncId, VarId, FuncRef, Range>& value) { | ||||
|     FuncDefDefinitionData<FileId, TypeId, FuncId, VarId, FuncRef, Range>& | ||||
|         value) { | ||||
|   REFLECT_MEMBER_START(); | ||||
|   REFLECT_MEMBER(detailed_name); | ||||
|   REFLECT_MEMBER(short_name_offset); | ||||
| @ -280,6 +288,7 @@ void Reflect( | ||||
|   REFLECT_MEMBER(comments); | ||||
|   REFLECT_MEMBER(definition_spelling); | ||||
|   REFLECT_MEMBER(definition_extent); | ||||
|   REFLECT_MEMBER(file); | ||||
|   REFLECT_MEMBER(declaring_type); | ||||
|   REFLECT_MEMBER(base); | ||||
|   REFLECT_MEMBER(locals); | ||||
| @ -288,7 +297,8 @@ void Reflect( | ||||
| } | ||||
| 
 | ||||
| struct IndexFunc { | ||||
|   using Def = FuncDefDefinitionData<IndexTypeId, | ||||
|   using Def = FuncDefDefinitionData<IndexFileId, | ||||
|                                     IndexTypeId, | ||||
|                                     IndexFuncId, | ||||
|                                     IndexVarId, | ||||
|                                     IndexFuncRef, | ||||
| @ -337,7 +347,11 @@ MAKE_REFLECT_STRUCT(IndexFunc::Declaration, | ||||
|                     content, | ||||
|                     param_spellings); | ||||
| 
 | ||||
| template <typename TypeId, typename FuncId, typename VarId, typename Range> | ||||
| template <typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
|           typename Range> | ||||
| struct VarDefDefinitionData { | ||||
|   // General metadata.
 | ||||
|   std::string detailed_name; | ||||
| @ -348,6 +362,7 @@ struct VarDefDefinitionData { | ||||
|   Maybe<Range> definition_spelling; | ||||
|   Maybe<Range> definition_extent; | ||||
| 
 | ||||
|   FileId file; | ||||
|   // Type of the variable.
 | ||||
|   Maybe<TypeId> variable_type; | ||||
| 
 | ||||
| @ -376,8 +391,7 @@ struct VarDefDefinitionData { | ||||
|            parent_kind == o.parent_kind && kind == o.kind && | ||||
|            storage == o.storage && hover == o.hover && comments == o.comments; | ||||
|   } | ||||
|   bool operator!=( | ||||
|       const VarDefDefinitionData<TypeId, FuncId, VarId, Range>& other) const { | ||||
|   bool operator!=(const VarDefDefinitionData& other) const { | ||||
|     return !(*this == other); | ||||
|   } | ||||
| 
 | ||||
| @ -388,12 +402,14 @@ struct VarDefDefinitionData { | ||||
| }; | ||||
| 
 | ||||
| template <typename TVisitor, | ||||
|           typename FileId, | ||||
|           typename TypeId, | ||||
|           typename FuncId, | ||||
|           typename VarId, | ||||
|           typename Range> | ||||
| void Reflect(TVisitor& visitor, | ||||
|              VarDefDefinitionData<TypeId, FuncId, VarId, Range>& value) { | ||||
| void Reflect( | ||||
|     TVisitor& visitor, | ||||
|     VarDefDefinitionData<FileId, TypeId, FuncId, VarId, Range>& value) { | ||||
|   REFLECT_MEMBER_START(); | ||||
|   REFLECT_MEMBER(detailed_name); | ||||
|   REFLECT_MEMBER(short_name_size); | ||||
| @ -402,6 +418,7 @@ void Reflect(TVisitor& visitor, | ||||
|   REFLECT_MEMBER(comments); | ||||
|   REFLECT_MEMBER(definition_spelling); | ||||
|   REFLECT_MEMBER(definition_extent); | ||||
|   REFLECT_MEMBER(file); | ||||
|   REFLECT_MEMBER(variable_type); | ||||
|   REFLECT_MEMBER(parent_id); | ||||
|   REFLECT_MEMBER(parent_kind); | ||||
| @ -411,7 +428,11 @@ void Reflect(TVisitor& visitor, | ||||
| } | ||||
| 
 | ||||
| struct IndexVar { | ||||
|   using Def = VarDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; | ||||
|   using Def = VarDefDefinitionData<IndexFileId, | ||||
|                                    IndexTypeId, | ||||
|                                    IndexFuncId, | ||||
|                                    IndexVarId, | ||||
|                                    Range>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   IndexVarId id; | ||||
|  | ||||
| @ -73,8 +73,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db, | ||||
|         // Note: we ignore the definition if it is in the same file (ie,
 | ||||
|         // possibly a header).
 | ||||
|         if (func.def && func.def->definition_extent && | ||||
|             func.def->definition_extent->path != file_id) { | ||||
|           return func.def->definition_extent->path; | ||||
|             func.def->definition_extent->FileId() != file_id) { | ||||
|           return func.def->definition_extent->FileId(); | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
| @ -83,8 +83,8 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db, | ||||
|         // Note: we ignore the definition if it is in the same file (ie,
 | ||||
|         // possibly a header).
 | ||||
|         if (var.def && var.def->definition_extent && | ||||
|             var.def->definition_extent->path != file_id) { | ||||
|           return db->vars[sym.idx.idx].def->definition_extent->path; | ||||
|             var.def->definition_extent->FileId() != file_id) { | ||||
|           return db->vars[sym.idx.idx].def->definition_extent->FileId(); | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
| @ -149,7 +149,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db, | ||||
|                                                    QueryFunc& func) { | ||||
|   assert(func.def); | ||||
|   for (const QueryLocation& decl : func.declarations) { | ||||
|     if (decl.path != decl_file_id) | ||||
|     if (decl.FileId() != decl_file_id) | ||||
|       continue; | ||||
| 
 | ||||
|     optional<lsRange> ls_decl = GetLsRange(working_file, decl.range); | ||||
| @ -203,7 +203,7 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db, | ||||
|               break; | ||||
| 
 | ||||
|             for (QueryLocation& func_decl : sym_func.declarations) { | ||||
|               if (func_decl.path == decl_file_id) { | ||||
|               if (func_decl.FileId() == decl_file_id) { | ||||
|                 int dist = func_decl.range.start.line - decl.range.start.line; | ||||
|                 if (abs(dist) < abs(best_dist)) { | ||||
|                   optional<lsLocation> def_loc = GetLsLocation( | ||||
|  | ||||
| @ -90,7 +90,7 @@ void AddCodeLens(const char* singular, | ||||
|   code_lens.range = *range; | ||||
|   code_lens.command = lsCommand<lsCodeLensCommandArguments>(); | ||||
|   code_lens.command->command = "cquery.showReferences"; | ||||
|   code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.path); | ||||
|   code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.FileId()); | ||||
|   code_lens.command->arguments.position = code_lens.range.start; | ||||
| 
 | ||||
|   // Add unique uses.
 | ||||
| @ -179,7 +179,7 @@ struct TextDocumentCodeLensHandler | ||||
|           auto try_ensure_spelling = [&](SymbolRef sym) { | ||||
|             optional<QueryLocation> def = | ||||
|                 GetDefinitionSpellingOfSymbol(db, sym.idx); | ||||
|             if (!def || def->path != sym.loc.path || | ||||
|             if (!def || def->FileId() != sym.loc.FileId() || | ||||
|                 def->range.start.line != sym.loc.range.start.line) { | ||||
|               return sym.loc; | ||||
|             } | ||||
|  | ||||
| @ -90,7 +90,7 @@ struct TextDocumentDefinitionHandler | ||||
|       // the declaration if possible. We also want to use declarations if
 | ||||
|       // we're pointing to, ie, a pure virtual function which has no
 | ||||
|       // definition.
 | ||||
|       if (!def_loc || (def_loc->path == file_id && | ||||
|       if (!def_loc || (def_loc->FileId() == file_id && | ||||
|                        def_loc->range.Contains(target_line, target_column))) { | ||||
|         // Goto declaration.
 | ||||
| 
 | ||||
|  | ||||
| @ -41,7 +41,7 @@ struct TextDocumentDocumentHighlightHandler | ||||
|       std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true); | ||||
|       out.result.reserve(uses.size()); | ||||
|       for (const QueryLocation& use : uses) { | ||||
|         if (use.path != file_id) | ||||
|         if (use.FileId() != file_id) | ||||
|           continue; | ||||
| 
 | ||||
|         optional<lsLocation> ls_location = | ||||
|  | ||||
| @ -16,20 +16,21 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, | ||||
|     if (!ls_location) | ||||
|       continue; | ||||
| 
 | ||||
|     if (path_to_edit.find(location.path) == path_to_edit.end()) { | ||||
|       path_to_edit[location.path] = lsTextDocumentEdit(); | ||||
|     QueryFileId file_id = location.FileId(); | ||||
|     if (path_to_edit.find(file_id) == path_to_edit.end()) { | ||||
|       path_to_edit[file_id] = lsTextDocumentEdit(); | ||||
| 
 | ||||
|       QueryFile& file = db->files[location.path.id]; | ||||
|       QueryFile& file = db->files[file_id.id]; | ||||
|       if (!file.def) | ||||
|         continue; | ||||
| 
 | ||||
|       const std::string& path = file.def->path; | ||||
|       path_to_edit[location.path].textDocument.uri = | ||||
|       path_to_edit[file_id].textDocument.uri = | ||||
|           lsDocumentUri::FromPath(path); | ||||
| 
 | ||||
|       WorkingFile* working_file = working_files->GetFileByFilename(path); | ||||
|       if (working_file) | ||||
|         path_to_edit[location.path].textDocument.version = | ||||
|         path_to_edit[file_id].textDocument.version = | ||||
|             working_file->version; | ||||
|     } | ||||
| 
 | ||||
| @ -38,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, | ||||
|     edit.newText = new_text; | ||||
| 
 | ||||
|     // vscode complains if we submit overlapping text edits.
 | ||||
|     auto& edits = path_to_edit[location.path].edits; | ||||
|     auto& edits = path_to_edit[file_id].edits; | ||||
|     if (std::find(edits.begin(), edits.end(), edit) == edits.end()) | ||||
|       edits.push_back(edit); | ||||
|   } | ||||
|  | ||||
							
								
								
									
										86
									
								
								src/query.cc
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								src/query.cc
									
									
									
									
									
								
							| @ -42,8 +42,12 @@ optional<QueryType::Def> ToQuery(const IdMap& id_map, | ||||
|   result.kind = type.kind; | ||||
|   result.hover = type.hover; | ||||
|   result.comments = type.comments; | ||||
|   result.definition_spelling = id_map.ToQuery(type.definition_spelling); | ||||
|   result.definition_extent = id_map.ToQuery(type.definition_extent); | ||||
|   if (type.definition_spelling) | ||||
|     result.definition_spelling = | ||||
|         id_map.ToQuery(*type.definition_spelling, SymbolRole::Definition); | ||||
|   if (type.definition_extent) | ||||
|     result.definition_extent = | ||||
|         id_map.ToQuery(*type.definition_extent, SymbolRole::None); | ||||
|   result.alias_of = id_map.ToQuery(type.alias_of); | ||||
|   result.parents = id_map.ToQuery(type.parents); | ||||
|   result.types = id_map.ToQuery(type.types); | ||||
| @ -65,8 +69,12 @@ optional<QueryFunc::Def> ToQuery(const IdMap& id_map, | ||||
|   result.storage = func.storage; | ||||
|   result.hover = func.hover; | ||||
|   result.comments = func.comments; | ||||
|   result.definition_spelling = id_map.ToQuery(func.definition_spelling); | ||||
|   result.definition_extent = id_map.ToQuery(func.definition_extent); | ||||
|   if (func.definition_spelling) | ||||
|     result.definition_spelling = | ||||
|         id_map.ToQuery(*func.definition_spelling, SymbolRole::Definition); | ||||
|   if (func.definition_extent) | ||||
|     result.definition_extent = | ||||
|         id_map.ToQuery(*func.definition_extent, SymbolRole::None); | ||||
|   result.declaring_type = id_map.ToQuery(func.declaring_type); | ||||
|   result.base = id_map.ToQuery(func.base); | ||||
|   result.locals = id_map.ToQuery(func.locals); | ||||
| @ -84,8 +92,12 @@ optional<QueryVar::Def> ToQuery(const IdMap& id_map, const IndexVar::Def& var) { | ||||
|   result.short_name_size = var.short_name_size; | ||||
|   result.hover = var.hover; | ||||
|   result.comments = var.comments; | ||||
|   result.definition_spelling = id_map.ToQuery(var.definition_spelling); | ||||
|   result.definition_extent = id_map.ToQuery(var.definition_extent); | ||||
|   if (var.definition_spelling) | ||||
|     result.definition_spelling = | ||||
|       id_map.ToQuery(*var.definition_spelling, SymbolRole::Definition); | ||||
|   if (var.definition_extent) | ||||
|     result.definition_extent = | ||||
|       id_map.ToQuery(*var.definition_extent, SymbolRole::None); | ||||
|   result.variable_type = id_map.ToQuery(var.variable_type); | ||||
|   result.parent_id = var.parent_id; | ||||
|   result.parent_kind = var.parent_kind; | ||||
| @ -223,11 +235,13 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in | ||||
| 
 | ||||
|   auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) { | ||||
|     def.outline.push_back( | ||||
|         SymbolRef(idx, SymbolRole::Declaration, id_map.ToQuery(range))); | ||||
|         SymbolRef(idx, SymbolRole::Declaration, | ||||
|                   id_map.ToQuery(range, SymbolRole::Declaration))); | ||||
|   }; | ||||
|   auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role, | ||||
|                                          Range range) { | ||||
|     def.all_symbols.push_back(SymbolRef(idx, role, id_map.ToQuery(range))); | ||||
|     def.all_symbols.push_back( | ||||
|         SymbolRef(idx, role, id_map.ToQuery(range, role))); | ||||
|   }; | ||||
| 
 | ||||
|   for (const IndexType& type : indexed.types) { | ||||
| @ -256,16 +270,13 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in | ||||
|       // textDocument/definition on the space/semicolon in `A a;` or `return
 | ||||
|       // 42;` will take you to the constructor.
 | ||||
|       Range range = caller.loc; | ||||
|       if (caller.is_implicit) { | ||||
|       if (caller.role & SymbolRole::Implicit) { | ||||
|         if (range.start.column > 0) | ||||
|           range.start.column--; | ||||
|         range.end.column++; | ||||
|       } | ||||
|       add_all_symbols(id_map.ToSymbol(func.id), | ||||
|                       caller.is_implicit | ||||
|                           ? SymbolRole::Implicit | SymbolRole::CalledBy | ||||
|                           : SymbolRole::CalledBy, | ||||
|                       range); | ||||
|                       caller.role | SymbolRole::CalledBy, range); | ||||
|     } | ||||
|   } | ||||
|   for (const IndexVar& var : indexed.vars) { | ||||
| @ -396,8 +407,11 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) | ||||
|         *GetQueryVarIdFromUsr(query_db, entry.second, true); | ||||
| } | ||||
| 
 | ||||
| QueryLocation IdMap::ToQuery(Range range) const { | ||||
|   return QueryLocation(primary_file, range); | ||||
| QueryLocation IdMap::ToQuery(Range range, SymbolRole role) const { | ||||
|   return QueryLocation{range, primary_file, role}; | ||||
| } | ||||
| QueryFileId IdMap::ToQuery(IndexFileId) const { | ||||
|   return primary_file; | ||||
| } | ||||
| QueryTypeId IdMap::ToQuery(IndexTypeId id) const { | ||||
|   assert(cached_type_ids_.find(id) != cached_type_ids_.end()); | ||||
| @ -414,11 +428,18 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const { | ||||
|   return QueryVarId(cached_var_ids_.find(id)->second); | ||||
| } | ||||
| QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const { | ||||
|   return QueryFuncRef(ToQuery(ref.id), ToQuery(ref.loc), ref.is_implicit); | ||||
|   return QueryFuncRef{ToQuery(ref.id), ToQuery(ref.loc, ref.role)}; | ||||
| } | ||||
| QueryLocation IdMap::ToQuery(IndexFunc::Declaration decl) const { | ||||
|   // TODO: expose more than just QueryLocation.
 | ||||
|   return QueryLocation(primary_file, decl.spelling); | ||||
|   return QueryLocation{decl.spelling, primary_file, SymbolRole::Declaration}; | ||||
| } | ||||
| std::vector<QueryLocation> IdMap::ToQuery(const std::vector<Range>& a) const { | ||||
|   std::vector<QueryLocation> ret; | ||||
|   ret.reserve(a.size()); | ||||
|   for (auto& x : a) | ||||
|     ret.push_back(ToQuery(x, SymbolRole::Reference)); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| SymbolIdx IdMap::ToSymbol(IndexTypeId id) const { | ||||
| @ -734,7 +755,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, | ||||
|         QueryType& type = types[usr_to_type[usr].id]; | ||||
|         if (type.symbol_idx) | ||||
|           symbols[type.symbol_idx->id].kind = SymbolKind::Invalid; | ||||
|         type.gen++; | ||||
|         //type.def = QueryType::Def();
 | ||||
|         type.def = nullopt; | ||||
|       } | ||||
| @ -745,7 +765,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, | ||||
|         QueryFunc& func = funcs[usr_to_func[usr].id]; | ||||
|         if (func.symbol_idx) | ||||
|           symbols[func.symbol_idx->id].kind = SymbolKind::Invalid; | ||||
|         func.gen++; | ||||
|         //func.def = QueryFunc::Def();
 | ||||
|         func.def = nullopt; | ||||
|       } | ||||
| @ -756,7 +775,6 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, | ||||
|         QueryVar& var = vars[usr_to_var[usr].id]; | ||||
|         if (var.symbol_idx) | ||||
|           symbols[var.symbol_idx->id].kind = SymbolKind::Invalid; | ||||
|         var.gen++; | ||||
|         //var.def = QueryVar::Def();
 | ||||
|         var.def = nullopt; | ||||
|       } | ||||
| @ -987,8 +1005,8 @@ TEST_SUITE("query") { | ||||
|     previous.Resolve(previous.ToTypeId(HashUsr("usr1"))) | ||||
|         ->uses.push_back(Range(Position(1, 0))); | ||||
|     previous.Resolve(previous.ToFuncId(HashUsr("usr2"))) | ||||
|         ->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                          false /*is_implicit*/)); | ||||
|         ->callers.push_back(IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), | ||||
|                                          SymbolRole::None}); | ||||
|     previous.Resolve(previous.ToVarId(HashUsr("usr3"))) | ||||
|         ->uses.push_back(Range(Position(3, 0))); | ||||
| 
 | ||||
| @ -1006,10 +1024,10 @@ TEST_SUITE("query") { | ||||
|     IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUsr("usr"))); | ||||
|     IndexFunc* cf = current.Resolve(current.ToFuncId(HashUsr("usr"))); | ||||
| 
 | ||||
|     pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     pf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
|     cf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
| @ -1051,14 +1069,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(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|     pf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(1, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
|     pf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
|     cf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(4, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
|     cf->callers.push_back( | ||||
|         IndexFuncRef{Range(Position(5, 0)), IndexFuncId(0), SymbolRole::None}); | ||||
| 
 | ||||
|     QueryDatabase db; | ||||
|     IdMap previous_map(&db, previous.id_cache); | ||||
|  | ||||
							
								
								
									
										81
									
								
								src/query.h
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								src/query.h
									
									
									
									
									
								
							| @ -20,40 +20,10 @@ using QueryVarId = Id<QueryVar>; | ||||
| 
 | ||||
| struct IdMap; | ||||
| 
 | ||||
| using Generation = uint32_t; | ||||
| 
 | ||||
| // Example use: |WithGen<Id<QueryType>>|, to mark an |Id| reference with
 | ||||
| // generation, so that by comparising the generation with that stored in the
 | ||||
| // referenced Query object, we can tell if the reference is stale (the
 | ||||
| // referenced object has been deleted or reused).
 | ||||
| template <typename T> | ||||
| struct WithGen { | ||||
|   Generation gen; | ||||
|   T value; | ||||
|   WithGen() : gen(-1) {} | ||||
|   WithGen(const T& value) : gen(-1), value(value) {} | ||||
|   WithGen(Generation gen, const T& value) : gen(gen), value(value) {} | ||||
| 
 | ||||
|   bool HasValue() const { return value.HasValue(); } | ||||
|   explicit operator bool() const { return HasValue(); } | ||||
| 
 | ||||
|   bool operator==(const WithGen& o) const { | ||||
|     return gen == o.gen && value == o.value; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename TVisitor, typename T> | ||||
| void Reflect(TVisitor& visitor, WithGen<T>& value) { | ||||
|   Reflect(visitor, value.value); | ||||
| } | ||||
| 
 | ||||
| struct QueryLocation { | ||||
|   Range range; | ||||
|   QueryFileId path; | ||||
|   SymbolRole role = SymbolRole::None; | ||||
| 
 | ||||
|   QueryLocation() {}  // Do not use, needed for reflect.
 | ||||
|   QueryLocation(QueryFileId path, Range range) : range(range), path(path) {} | ||||
|   SymbolRole role; | ||||
| 
 | ||||
|   QueryLocation OffsetStartColumn(int16_t offset) const { | ||||
|     QueryLocation result = *this; | ||||
| @ -62,6 +32,7 @@ struct QueryLocation { | ||||
|   } | ||||
| 
 | ||||
|   bool HasValue() const { return range.HasValue(); } | ||||
|   QueryFileId FileId() const { return path; } | ||||
| 
 | ||||
|   bool operator==(const QueryLocation& o) const { | ||||
|     return path == o.path && range == o.range; | ||||
| @ -129,16 +100,11 @@ struct QueryFuncRef { | ||||
|   // NOTE: id_ can be -1 if the function call is not coming from a function.
 | ||||
|   QueryFuncId id_; | ||||
|   QueryLocation loc; | ||||
|   bool is_implicit = false; | ||||
| 
 | ||||
|   bool HasValue() const { return id_.HasValue(); } | ||||
| 
 | ||||
|   QueryFuncRef() {}  // Do not use, needed for reflect.
 | ||||
|   QueryFuncRef(QueryFuncId id, QueryLocation loc, bool is_implicit) | ||||
|       : id_(id), loc(loc), is_implicit(is_implicit) {} | ||||
| 
 | ||||
|   std::tuple<QueryFuncId, QueryLocation, bool> ToTuple() const { | ||||
|     return std::make_tuple(id_, loc, is_implicit); | ||||
|   std::tuple<QueryFuncId, QueryLocation> ToTuple() const { | ||||
|     return std::make_tuple(id_, loc); | ||||
|   } | ||||
|   bool operator==(const QueryFuncRef& o) const { | ||||
|     return ToTuple() == o.ToTuple(); | ||||
| @ -148,7 +114,7 @@ struct QueryFuncRef { | ||||
|     return ToTuple() < o.ToTuple(); | ||||
|   } | ||||
| }; | ||||
| MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc, is_implicit); | ||||
| MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc); | ||||
| 
 | ||||
| // 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.
 | ||||
| @ -251,7 +217,8 @@ MAKE_REFLECT_STRUCT(QueryFile::Def, | ||||
|                     dependencies); | ||||
| 
 | ||||
| struct QueryType { | ||||
|   using Def = TypeDefDefinitionData<QueryTypeId, | ||||
|   using Def = TypeDefDefinitionData<QueryFileId, | ||||
|                                     QueryTypeId, | ||||
|                                     QueryFuncId, | ||||
|                                     QueryVarId, | ||||
|                                     QueryLocation>; | ||||
| @ -261,18 +228,18 @@ struct QueryType { | ||||
|   using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Generation gen; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<QueryTypeId> derived; | ||||
|   std::vector<QueryVarId> instances; | ||||
|   std::vector<QueryLocation> uses; | ||||
| 
 | ||||
|   explicit QueryType(const Usr& usr) : usr(usr), gen(0) {} | ||||
|   explicit QueryType(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| 
 | ||||
| struct QueryFunc { | ||||
|   using Def = FuncDefDefinitionData<QueryTypeId, | ||||
|   using Def = FuncDefDefinitionData<QueryFileId, | ||||
|                                     QueryTypeId, | ||||
|                                     QueryFuncId, | ||||
|                                     QueryVarId, | ||||
|                                     QueryFuncRef, | ||||
| @ -283,18 +250,18 @@ struct QueryFunc { | ||||
|   using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Generation gen; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<QueryLocation> declarations; | ||||
|   std::vector<QueryFuncId> derived; | ||||
|   std::vector<QueryFuncRef> callers; | ||||
| 
 | ||||
|   explicit QueryFunc(const Usr& usr) : usr(usr), gen(0) {} | ||||
|   explicit QueryFunc(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| 
 | ||||
| struct QueryVar { | ||||
|   using Def = VarDefDefinitionData<QueryTypeId, | ||||
|   using Def = VarDefDefinitionData<QueryFileId, | ||||
|                                    QueryTypeId, | ||||
|                                    QueryFuncId, | ||||
|                                    QueryVarId, | ||||
|                                    QueryLocation>; | ||||
| @ -303,13 +270,12 @@ struct QueryVar { | ||||
|   using UsesUpdate = MergeableUpdate<QueryVarId, QueryLocation>; | ||||
| 
 | ||||
|   Usr usr; | ||||
|   Generation gen; | ||||
|   Maybe<Id<void>> symbol_idx; | ||||
|   optional<Def> def; | ||||
|   std::vector<QueryLocation> declarations; | ||||
|   std::vector<QueryLocation> uses; | ||||
| 
 | ||||
|   explicit QueryVar(const Usr& usr) : usr(usr), gen(0) {} | ||||
|   explicit QueryVar(const Usr& usr) : usr(usr) {} | ||||
| }; | ||||
| 
 | ||||
| struct IndexUpdate { | ||||
| @ -428,6 +394,7 @@ template <typename I> | ||||
| struct IndexToQuery; | ||||
| 
 | ||||
| // clang-format off
 | ||||
| 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; }; | ||||
| @ -450,7 +417,8 @@ struct IdMap { | ||||
| 
 | ||||
|   // FIXME Too verbose
 | ||||
|   // clang-format off
 | ||||
|   QueryLocation ToQuery(Range range) const; | ||||
|   QueryLocation ToQuery(Range range, SymbolRole role) const; | ||||
|   QueryFileId ToQuery(IndexFileId) const; | ||||
|   QueryTypeId ToQuery(IndexTypeId id) const; | ||||
|   QueryFuncId ToQuery(IndexFuncId id) const; | ||||
|   QueryVarId ToQuery(IndexVarId id) const; | ||||
| @ -463,12 +431,6 @@ struct IdMap { | ||||
|     return ToQuery(*id); | ||||
|   } | ||||
|   template <typename I> | ||||
|   Maybe<WithGen<typename IndexToQuery<I>::type>> ToQuery(Maybe<I> id, int) const { | ||||
|     if (!id) | ||||
|       return nullopt; | ||||
|     return ToQuery(*id, 0); | ||||
|   } | ||||
|   template <typename I> | ||||
|   std::vector<typename IndexToQuery<I>::type> ToQuery(const std::vector<I>& a) const { | ||||
|     std::vector<typename IndexToQuery<I>::type> ret; | ||||
|     ret.reserve(a.size()); | ||||
| @ -476,14 +438,7 @@ struct IdMap { | ||||
|       ret.push_back(ToQuery(x)); | ||||
|     return ret; | ||||
|   } | ||||
|   template <typename I> | ||||
|   std::vector<WithGen<typename IndexToQuery<I>::type>> ToQuery(std::vector<I> a, int) const { | ||||
|     std::vector<WithGen<typename IndexToQuery<I>::type>> ret; | ||||
|     ret.reserve(a.size()); | ||||
|     for (auto& x : a) | ||||
|       ret.push_back(ToQuery(x, 0)); | ||||
|     return ret; | ||||
|   } | ||||
|   std::vector<QueryLocation> ToQuery(const std::vector<Range>& a) const; | ||||
|   // clang-format on
 | ||||
| 
 | ||||
|   SymbolIdx ToSymbol(IndexTypeId id) const; | ||||
|  | ||||
| @ -106,8 +106,8 @@ optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db, | ||||
|       break; | ||||
|     } | ||||
|     case SymbolKind::File: { | ||||
|       return QueryLocation(QueryFileId(symbol.idx), | ||||
|                            Range(Position(1, 1), Position(1, 1))); | ||||
|       return QueryLocation{Range(Position(0, 0), Position(0, 0)), | ||||
|                            QueryFileId(symbol.idx), SymbolRole::None}; | ||||
|     } | ||||
|     case SymbolKind::Invalid: { | ||||
|       assert(false && "unexpected"); | ||||
| @ -123,21 +123,21 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, | ||||
|     case SymbolKind::Type: { | ||||
|       QueryType& type = db->types[symbol.idx]; | ||||
|       if (type.def && type.def->definition_spelling) | ||||
|         return type.def->definition_spelling->path; | ||||
|         return type.def->definition_spelling->FileId(); | ||||
|       break; | ||||
|     } | ||||
|     case SymbolKind::Func: { | ||||
|       QueryFunc& func = db->funcs[symbol.idx]; | ||||
|       if (!func.declarations.empty()) | ||||
|         return func.declarations[0].path; | ||||
|         return func.declarations[0].FileId(); | ||||
|       if (func.def && func.def->definition_spelling) | ||||
|         return func.def->definition_spelling->path; | ||||
|         return func.def->definition_spelling->FileId(); | ||||
|       break; | ||||
|     } | ||||
|     case SymbolKind::Var: { | ||||
|       QueryVar& var = db->vars[symbol.idx]; | ||||
|       if (var.def && var.def->definition_spelling) | ||||
|         return var.def->definition_spelling->path; | ||||
|         return var.def->definition_spelling->FileId(); | ||||
|       break; | ||||
|     } | ||||
|     case SymbolKind::File: { | ||||
| @ -401,7 +401,7 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db, | ||||
|                                    WorkingFiles* working_files, | ||||
|                                    const QueryLocation& location) { | ||||
|   std::string path; | ||||
|   lsDocumentUri uri = GetLsDocumentUri(db, location.path, &path); | ||||
|   lsDocumentUri uri = GetLsDocumentUri(db, location.FileId(), &path); | ||||
|   optional<lsRange> range = | ||||
|       GetLsRange(working_files->GetFileByFilename(path), location.range); | ||||
|   if (!range) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user