mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 04:32:33 +00:00 
			
		
		
		
	Add SymbolRole to SymbolRef and fix $cquery/{base,derived} by ordering definitions before uses
This commit is contained in:
		
							parent
							
								
									777193d02f
								
							
						
					
					
						commit
						16bf3158c5
					
				| @ -65,3 +65,23 @@ enum class StorageClass : uint8_t { | |||||||
| }; | }; | ||||||
| MAKE_REFLECT_TYPE_PROXY(StorageClass, | MAKE_REFLECT_TYPE_PROXY(StorageClass, | ||||||
|                         std::underlying_type<StorageClass>::type); |                         std::underlying_type<StorageClass>::type); | ||||||
|  | 
 | ||||||
|  | enum class SymbolRole : uint8_t { | ||||||
|  |   Declaration = 1 << 0, | ||||||
|  |   Definition = 1 << 1, | ||||||
|  |   Reference = 1 << 2, | ||||||
|  |   Implicit = 1 << 3, | ||||||
|  | 
 | ||||||
|  |   ChildOf = 1 << 4, | ||||||
|  |   BaseOf = 1 << 5, | ||||||
|  |   CalledBy = 1 << 6, | ||||||
|  | }; | ||||||
|  | MAKE_REFLECT_TYPE_PROXY(SymbolRole, std::underlying_type<SymbolRole>::type); | ||||||
|  | 
 | ||||||
|  | inline uint8_t operator&(SymbolRole lhs, SymbolRole rhs) { | ||||||
|  |   return uint8_t(lhs) & uint8_t(rhs); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline SymbolRole operator|(SymbolRole lhs, SymbolRole rhs) { | ||||||
|  |   return SymbolRole(uint8_t(lhs) | uint8_t(rhs)); | ||||||
|  | } | ||||||
|  | |||||||
| @ -23,8 +23,17 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> { | |||||||
| 
 | 
 | ||||||
|     Out_LocationList out; |     Out_LocationList out; | ||||||
|     out.id = request->id; |     out.id = request->id; | ||||||
|     for (const SymbolRef& ref : |     std::vector<SymbolRef> refs = | ||||||
|          FindSymbolsAtLocation(working_file, file, request->params.position)) { |         FindSymbolsAtLocation(working_file, file, request->params.position); | ||||||
|  |     // A template definition may be a use of its primary template.
 | ||||||
|  |     // We want to get the definition instead of the use.
 | ||||||
|  |     // Order by |Definition| DESC, range size ASC.
 | ||||||
|  |     std::stable_sort(refs.begin(), refs.end(), | ||||||
|  |                      [](const SymbolRef& a, const SymbolRef& b) { | ||||||
|  |                        return (a.role & SymbolRole::Definition) > | ||||||
|  |                               (b.role & SymbolRole::Definition); | ||||||
|  |                      }); | ||||||
|  |     for (const SymbolRef& ref : refs) { | ||||||
|       if (ref.idx.kind == SymbolKind::Type) { |       if (ref.idx.kind == SymbolKind::Type) { | ||||||
|         QueryType& type = db->types[ref.idx.idx]; |         QueryType& type = db->types[ref.idx.idx]; | ||||||
|         if (!type.def) |         if (!type.def) | ||||||
| @ -32,11 +41,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> { | |||||||
|         std::vector<QueryLocation> locations = |         std::vector<QueryLocation> locations = | ||||||
|             ToQueryLocation(db, type.def->parents); |             ToQueryLocation(db, type.def->parents); | ||||||
|         out.result = GetLsLocations(db, working_files, locations); |         out.result = GetLsLocations(db, working_files, locations); | ||||||
|  |         break; | ||||||
|       } else if (ref.idx.kind == SymbolKind::Func) { |       } else if (ref.idx.kind == SymbolKind::Func) { | ||||||
|         QueryFunc& func = db->funcs[ref.idx.idx]; |         QueryFunc& func = db->funcs[ref.idx.idx]; | ||||||
|         std::vector<QueryLocation> locations = |         std::vector<QueryLocation> locations = | ||||||
|             ToQueryLocation(db, func.def->base); |             ToQueryLocation(db, func.def->base); | ||||||
|         out.result = GetLsLocations(db, working_files, locations); |         out.result = GetLsLocations(db, working_files, locations); | ||||||
|  |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     QueueManager::WriteStdout(IpcId::CqueryBase, out); |     QueueManager::WriteStdout(IpcId::CqueryBase, out); | ||||||
|  | |||||||
| @ -23,18 +23,29 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> { | |||||||
| 
 | 
 | ||||||
|     Out_LocationList out; |     Out_LocationList out; | ||||||
|     out.id = request->id; |     out.id = request->id; | ||||||
|     for (const SymbolRef& ref : |     std::vector<SymbolRef> refs = | ||||||
|          FindSymbolsAtLocation(working_file, file, request->params.position)) { |       FindSymbolsAtLocation(working_file, file, request->params.position); | ||||||
|  |     // A template definition may be a use of its primary template.
 | ||||||
|  |     // We want to get the definition instead of the use.
 | ||||||
|  |     // Order by |Definition| DESC, range size ASC.
 | ||||||
|  |     std::stable_sort(refs.begin(), refs.end(), | ||||||
|  |                      [](const SymbolRef& a, const SymbolRef& b) { | ||||||
|  |                        return (a.role & SymbolRole::Definition) > | ||||||
|  |                               (b.role & SymbolRole::Definition); | ||||||
|  |                      }); | ||||||
|  |     for (const SymbolRef& ref : refs) { | ||||||
|       if (ref.idx.kind == SymbolKind::Type) { |       if (ref.idx.kind == SymbolKind::Type) { | ||||||
|         QueryType& type = db->types[ref.idx.idx]; |         QueryType& type = db->types[ref.idx.idx]; | ||||||
|         std::vector<QueryLocation> locations = |         std::vector<QueryLocation> locations = | ||||||
|             ToQueryLocation(db, type.derived); |             ToQueryLocation(db, type.derived); | ||||||
|         out.result = GetLsLocations(db, working_files, locations); |         out.result = GetLsLocations(db, working_files, locations); | ||||||
|  |         break; | ||||||
|       } else if (ref.idx.kind == SymbolKind::Func) { |       } else if (ref.idx.kind == SymbolKind::Func) { | ||||||
|         QueryFunc& func = db->funcs[ref.idx.idx]; |         QueryFunc& func = db->funcs[ref.idx.idx]; | ||||||
|         std::vector<QueryLocation> locations = |         std::vector<QueryLocation> locations = | ||||||
|             ToQueryLocation(db, func.derived); |             ToQueryLocation(db, func.derived); | ||||||
|         out.result = GetLsLocations(db, working_files, locations); |         out.result = GetLsLocations(db, working_files, locations); | ||||||
|  |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     QueueManager::WriteStdout(IpcId::CqueryDerived, out); |     QueueManager::WriteStdout(IpcId::CqueryDerived, out); | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								src/query.cc
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/query.cc
									
									
									
									
									
								
							| @ -219,30 +219,31 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { | |||||||
|   }(); |   }(); | ||||||
| 
 | 
 | ||||||
|   auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) { |   auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) { | ||||||
|     def.outline.push_back(SymbolRef(idx, id_map.ToQuery(range))); |     def.outline.push_back( | ||||||
|  |         SymbolRef(idx, SymbolRole::Declaration, id_map.ToQuery(range))); | ||||||
|   }; |   }; | ||||||
|   auto add_all_symbols = [&def, &id_map](SymbolIdx idx, Range range) { |   auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role, | ||||||
|     def.all_symbols.push_back(SymbolRef(idx, id_map.ToQuery(range))); |                                          Range range) { | ||||||
|  |     def.all_symbols.push_back(SymbolRef(idx, role, id_map.ToQuery(range))); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   for (const IndexType& type : indexed.types) { |   for (const IndexType& type : indexed.types) { | ||||||
|     if (type.def.definition_spelling.has_value()) |     if (type.def.definition_spelling.has_value()) | ||||||
|       add_all_symbols(id_map.ToSymbol(type.id), |       add_all_symbols(id_map.ToSymbol(type.id), SymbolRole::Definition, | ||||||
|                       type.def.definition_spelling.value()); |                       type.def.definition_spelling.value()); | ||||||
|     if (type.def.definition_extent.has_value()) |     if (type.def.definition_extent.has_value()) | ||||||
|       add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value()); |       add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value()); | ||||||
|     for (const Range& use : type.uses) |     for (const Range& use : type.uses) | ||||||
|       add_all_symbols(id_map.ToSymbol(type.id), use); |       add_all_symbols(id_map.ToSymbol(type.id), SymbolRole::Reference, use); | ||||||
|   } |   } | ||||||
|   for (const IndexFunc& func : indexed.funcs) { |   for (const IndexFunc& func : indexed.funcs) { | ||||||
|     if (func.def.definition_spelling.has_value()) |     if (func.def.definition_spelling.has_value()) | ||||||
|       add_all_symbols(id_map.ToSymbol(func.id), |       add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Definition, | ||||||
|                       func.def.definition_spelling.value()); |                       func.def.definition_spelling.value()); | ||||||
|     if (func.def.definition_extent.has_value()) |     if (func.def.definition_extent.has_value()) | ||||||
|       add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value()); |       add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value()); | ||||||
|     for (const IndexFunc::Declaration& decl : func.declarations) { |     for (const IndexFunc::Declaration& decl : func.declarations) { | ||||||
|       // TODO: add more outline info?
 |       add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration, decl.spelling); | ||||||
|       add_all_symbols(id_map.ToSymbol(func.id), decl.spelling); |  | ||||||
|       add_outline(id_map.ToSymbol(func.id), decl.spelling); |       add_outline(id_map.ToSymbol(func.id), decl.spelling); | ||||||
|     } |     } | ||||||
|     for (const IndexFuncRef& caller : func.callers) { |     for (const IndexFuncRef& caller : func.callers) { | ||||||
| @ -256,21 +257,22 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { | |||||||
|           range.start.column--; |           range.start.column--; | ||||||
|         range.end.column++; |         range.end.column++; | ||||||
|       } |       } | ||||||
|       add_all_symbols(id_map.ToSymbol(func.id), range); |       add_all_symbols(id_map.ToSymbol(func.id), | ||||||
|  |                       SymbolRole::Implicit | SymbolRole::CalledBy, range); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   for (const IndexVar& var : indexed.vars) { |   for (const IndexVar& var : indexed.vars) { | ||||||
|     if (var.def.definition_spelling.has_value()) |     if (var.def.definition_spelling.has_value()) | ||||||
|       add_all_symbols(id_map.ToSymbol(var.id), |       add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Definition, | ||||||
|                       var.def.definition_spelling.value()); |                       var.def.definition_spelling.value()); | ||||||
|     if (var.def.definition_extent.has_value()) |     if (var.def.definition_extent.has_value()) | ||||||
|       add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value()); |       add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value()); | ||||||
|     for (const Range& decl : var.declarations) { |     for (const Range& decl : var.declarations) { | ||||||
|       add_all_symbols(id_map.ToSymbol(var.id), decl); |       add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Declaration, decl); | ||||||
|       add_outline(id_map.ToSymbol(var.id), decl); |       add_outline(id_map.ToSymbol(var.id), decl); | ||||||
|     } |     } | ||||||
|     for (const Range& use : var.uses) |     for (const Range& use : var.uses) | ||||||
|       add_all_symbols(id_map.ToSymbol(var.id), use); |       add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Reference, use); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   std::sort(def.outline.begin(), def.outline.end(), |   std::sort(def.outline.begin(), def.outline.end(), | ||||||
|  | |||||||
| @ -81,10 +81,12 @@ MAKE_HASHABLE(SymbolIdx, t.kind, t.idx); | |||||||
| 
 | 
 | ||||||
| struct SymbolRef { | struct SymbolRef { | ||||||
|   SymbolIdx idx; |   SymbolIdx idx; | ||||||
|  |   SymbolRole role; | ||||||
|   QueryLocation loc; |   QueryLocation loc; | ||||||
| 
 | 
 | ||||||
|   SymbolRef() {}  // Do not use, needed for reflect.
 |   SymbolRef() {}  // Do not use, needed for reflect.
 | ||||||
|   SymbolRef(SymbolIdx idx, QueryLocation loc) : idx(idx), loc(loc) {} |   SymbolRef(SymbolIdx idx, SymbolRole role, QueryLocation loc) | ||||||
|  |       : idx(idx), role(role), loc(loc) {} | ||||||
| 
 | 
 | ||||||
|   bool operator==(const SymbolRef& that) const { |   bool operator==(const SymbolRef& that) const { | ||||||
|     return idx == that.idx && loc == that.loc; |     return idx == that.idx && loc == that.loc; | ||||||
|  | |||||||
| @ -488,6 +488,7 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, | |||||||
|   return nullopt; |   return nullopt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // TODO Sort only by range length, not |kind| or |idx|
 | ||||||
| std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file, | std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file, | ||||||
|                                              QueryFile* file, |                                              QueryFile* file, | ||||||
|                                              lsPosition position) { |                                              lsPosition position) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user