mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	Better definition/references on #include lines
This commit is contained in:
		
							parent
							
								
									75638b5387
								
							
						
					
					
						commit
						2a06fb55dd
					
				
							
								
								
									
										16
									
								
								src/lsp.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/lsp.h
									
									
									
									
									
								
							@ -8,22 +8,6 @@
 | 
			
		||||
#include <iosfwd>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////// OUTGOING MESSAGES /////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////// INCOMING MESSAGES /////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#define REGISTER_IN_MESSAGE(type) \
 | 
			
		||||
  static MessageRegistryRegister<type> type##message_handler_instance_;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -182,7 +182,7 @@ struct Handler_CclsCallHierarchy
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Run(In_CclsCallHierarchy* request) override {
 | 
			
		||||
    const auto& params = request->params;
 | 
			
		||||
    auto& params = request->params;
 | 
			
		||||
    Out_CclsCallHierarchy out;
 | 
			
		||||
    out.id = request->id;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -139,7 +139,7 @@ struct Handler_CclsInheritanceHierarchy
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Run(In_CclsInheritanceHierarchy* request) override {
 | 
			
		||||
    const auto& params = request->params;
 | 
			
		||||
    auto& params = request->params;
 | 
			
		||||
    Out_CclsInheritanceHierarchy out;
 | 
			
		||||
    out.id = request->id;
 | 
			
		||||
 | 
			
		||||
@ -158,11 +158,11 @@ struct Handler_CclsInheritanceHierarchy
 | 
			
		||||
      if (!FindFileOrFail(db, project, request->id,
 | 
			
		||||
                          params.textDocument.uri.GetPath(), &file))
 | 
			
		||||
        return;
 | 
			
		||||
      WorkingFile* working_file =
 | 
			
		||||
      WorkingFile* wfile =
 | 
			
		||||
          working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
 | 
			
		||||
      for (SymbolRef sym : FindSymbolsAtLocation(working_file, file,
 | 
			
		||||
                                                 request->params.position)) {
 | 
			
		||||
      for (SymbolRef sym :
 | 
			
		||||
           FindSymbolsAtLocation(wfile, file, params.position)) {
 | 
			
		||||
        if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
 | 
			
		||||
          out.result = BuildInitial(sym, params.derived, params.qualified,
 | 
			
		||||
                                    params.levels);
 | 
			
		||||
 | 
			
		||||
@ -202,7 +202,7 @@ struct Handler_CclsMemberHierarchy
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Run(In_CclsMemberHierarchy* request) override {
 | 
			
		||||
    const auto& params = request->params;
 | 
			
		||||
    auto& params = request->params;
 | 
			
		||||
    Out_CclsMemberHierarchy out;
 | 
			
		||||
    out.id = request->id;
 | 
			
		||||
 | 
			
		||||
@ -218,10 +218,10 @@ struct Handler_CclsMemberHierarchy
 | 
			
		||||
      if (!FindFileOrFail(db, project, request->id,
 | 
			
		||||
                          params.textDocument.uri.GetPath(), &file))
 | 
			
		||||
        return;
 | 
			
		||||
      WorkingFile* working_file =
 | 
			
		||||
      WorkingFile* wfile =
 | 
			
		||||
          working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
      for (SymbolRef sym :
 | 
			
		||||
           FindSymbolsAtLocation(working_file, file, params.position)) {
 | 
			
		||||
           FindSymbolsAtLocation(wfile, file, params.position)) {
 | 
			
		||||
        switch (sym.kind) {
 | 
			
		||||
          case SymbolKind::Func:
 | 
			
		||||
            out.result = BuildInitial(QueryFuncId(sym.id), params.qualified,
 | 
			
		||||
 | 
			
		||||
@ -50,27 +50,23 @@ struct Handler_TextDocumentDefinition
 | 
			
		||||
    : BaseMessageHandler<In_TextDocumentDefinition> {
 | 
			
		||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
			
		||||
  void Run(In_TextDocumentDefinition* request) override {
 | 
			
		||||
    auto& params = request->params;
 | 
			
		||||
    QueryFileId file_id;
 | 
			
		||||
    QueryFile* file;
 | 
			
		||||
    if (!FindFileOrFail(db, project, request->id,
 | 
			
		||||
                        request->params.textDocument.uri.GetPath(), &file,
 | 
			
		||||
                        &file_id)) {
 | 
			
		||||
                        params.textDocument.uri.GetPath(), &file, &file_id))
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WorkingFile* working_file =
 | 
			
		||||
        working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
 | 
			
		||||
    Out_TextDocumentDefinition out;
 | 
			
		||||
    out.id = request->id;
 | 
			
		||||
 | 
			
		||||
    Maybe<Use> on_def;
 | 
			
		||||
    bool has_symbol = false;
 | 
			
		||||
    int target_line = request->params.position.line;
 | 
			
		||||
    int target_column = request->params.position.character;
 | 
			
		||||
    WorkingFile* wfile =
 | 
			
		||||
        working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
    lsPosition& ls_pos = params.position;
 | 
			
		||||
 | 
			
		||||
    for (SymbolRef sym :
 | 
			
		||||
         FindSymbolsAtLocation(working_file, file, request->params.position)) {
 | 
			
		||||
    for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) {
 | 
			
		||||
      // Found symbol. Return definition.
 | 
			
		||||
      has_symbol = true;
 | 
			
		||||
 | 
			
		||||
@ -84,7 +80,7 @@ struct Handler_TextDocumentDefinition
 | 
			
		||||
          Use spell = *def.spell;
 | 
			
		||||
          // If on a definition, clear |uses| to find declarations below.
 | 
			
		||||
          if (spell.file == file_id &&
 | 
			
		||||
              spell.range.Contains(target_line, target_column)) {
 | 
			
		||||
              spell.range.Contains(ls_pos.line, ls_pos.character)) {
 | 
			
		||||
            on_def = spell;
 | 
			
		||||
            uses.clear();
 | 
			
		||||
            return false;
 | 
			
		||||
@ -114,7 +110,7 @@ struct Handler_TextDocumentDefinition
 | 
			
		||||
    // No symbols - check for includes.
 | 
			
		||||
    if (out.result.empty()) {
 | 
			
		||||
      for (const IndexInclude& include : file->def->includes) {
 | 
			
		||||
        if (include.line == target_line) {
 | 
			
		||||
        if (include.line == ls_pos.line) {
 | 
			
		||||
          lsLocationEx result;
 | 
			
		||||
          result.uri = lsDocumentUri::FromPath(include.resolved_path);
 | 
			
		||||
          out.result.push_back(result);
 | 
			
		||||
@ -125,7 +121,7 @@ struct Handler_TextDocumentDefinition
 | 
			
		||||
      // Find the best match of the identifier at point.
 | 
			
		||||
      if (!has_symbol) {
 | 
			
		||||
        lsPosition position = request->params.position;
 | 
			
		||||
        const std::string& buffer = working_file->buffer_content;
 | 
			
		||||
        const std::string& buffer = wfile->buffer_content;
 | 
			
		||||
        std::string_view query = LexIdentifierAroundPos(position, buffer);
 | 
			
		||||
        std::string_view short_query = query;
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@ -45,26 +45,25 @@ struct Handler_TextDocumentReferences
 | 
			
		||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
			
		||||
 | 
			
		||||
  void Run(In_TextDocumentReferences* request) override {
 | 
			
		||||
    auto& params = request->params;
 | 
			
		||||
    QueryFile* file;
 | 
			
		||||
    if (!FindFileOrFail(db, project, request->id,
 | 
			
		||||
                        request->params.textDocument.uri.GetPath(), &file)) {
 | 
			
		||||
                        params.textDocument.uri.GetPath(), &file))
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WorkingFile* working_file =
 | 
			
		||||
    WorkingFile* wfile =
 | 
			
		||||
        working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
 | 
			
		||||
    Out_TextDocumentReferences out;
 | 
			
		||||
    out.id = request->id;
 | 
			
		||||
    bool container = g_config->xref.container;
 | 
			
		||||
 | 
			
		||||
    for (const SymbolRef& sym :
 | 
			
		||||
         FindSymbolsAtLocation(working_file, file, request->params.position)) {
 | 
			
		||||
    for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position)) {
 | 
			
		||||
      // Found symbol. Return references.
 | 
			
		||||
      EachOccurrenceWithParent(
 | 
			
		||||
          db, sym, request->params.context.includeDeclaration,
 | 
			
		||||
          db, sym, params.context.includeDeclaration,
 | 
			
		||||
          [&](Use use, lsSymbolKind parent_kind) {
 | 
			
		||||
            if (use.role & request->params.context.role)
 | 
			
		||||
            if (use.role & params.context.role)
 | 
			
		||||
              if (std::optional<lsLocationEx> ls_loc =
 | 
			
		||||
                      GetLsLocationEx(db, working_files, use, container)) {
 | 
			
		||||
                if (container)
 | 
			
		||||
@ -75,23 +74,31 @@ struct Handler_TextDocumentReferences
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out.result.empty())
 | 
			
		||||
    if (out.result.empty()) {
 | 
			
		||||
      // |path| is the #include line. If the cursor is not on such line but line
 | 
			
		||||
      // = 0,
 | 
			
		||||
      // use the current filename.
 | 
			
		||||
      std::string path;
 | 
			
		||||
      if (params.position.line == 0)
 | 
			
		||||
        path = file->def->path;
 | 
			
		||||
      for (const IndexInclude& include : file->def->includes)
 | 
			
		||||
        if (include.line == request->params.position.line) {
 | 
			
		||||
          // |include| is the line the cursor is on.
 | 
			
		||||
        if (include.line == params.position.line) {
 | 
			
		||||
          path = include.resolved_path;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      if (path.size())
 | 
			
		||||
        for (QueryFile& file1 : db->files)
 | 
			
		||||
          if (file1.def)
 | 
			
		||||
              for (const IndexInclude& include1 : file1.def->includes)
 | 
			
		||||
                if (include1.resolved_path == include.resolved_path) {
 | 
			
		||||
            for (const IndexInclude& include : file1.def->includes)
 | 
			
		||||
              if (include.resolved_path == path) {
 | 
			
		||||
                // Another file |file1| has the same include line.
 | 
			
		||||
                lsLocationEx result;
 | 
			
		||||
                result.uri = lsDocumentUri::FromPath(file1.def->path);
 | 
			
		||||
                result.range.start.line = result.range.end.line =
 | 
			
		||||
                      include1.line;
 | 
			
		||||
                  include.line;
 | 
			
		||||
                out.result.push_back(std::move(result));
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
          break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((int)out.result.size() >= g_config->xref.maxNum)
 | 
			
		||||
 | 
			
		||||
@ -318,21 +318,20 @@ std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
 | 
			
		||||
 | 
			
		||||
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
 | 
			
		||||
                                             QueryFile* file,
 | 
			
		||||
                                             lsPosition position) {
 | 
			
		||||
                                             lsPosition& ls_pos) {
 | 
			
		||||
  std::vector<SymbolRef> symbols;
 | 
			
		||||
  symbols.reserve(1);
 | 
			
		||||
 | 
			
		||||
  int target_line = position.line;
 | 
			
		||||
  int target_column = position.character;
 | 
			
		||||
  if (working_file) {
 | 
			
		||||
    std::optional<int> index_line = working_file->GetIndexPosFromBufferPos(
 | 
			
		||||
        target_line, &target_column, false);
 | 
			
		||||
    if (index_line)
 | 
			
		||||
      target_line = *index_line;
 | 
			
		||||
    if (auto line = working_file->GetIndexPosFromBufferPos(
 | 
			
		||||
        ls_pos.line, &ls_pos.character, false)) {
 | 
			
		||||
      ls_pos.line = *line;
 | 
			
		||||
    } else {
 | 
			
		||||
      ls_pos.line = -1;
 | 
			
		||||
      return {};
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (const SymbolRef& sym : file->def->all_symbols) {
 | 
			
		||||
    if (sym.range.Contains(target_line, target_column))
 | 
			
		||||
    if (sym.range.Contains(ls_pos.line, ls_pos.character))
 | 
			
		||||
      symbols.push_back(sym);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@ std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
 | 
			
		||||
 | 
			
		||||
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
 | 
			
		||||
                                             QueryFile* file,
 | 
			
		||||
                                             lsPosition position);
 | 
			
		||||
                                             lsPosition& ls_pos);
 | 
			
		||||
 | 
			
		||||
template <typename Fn>
 | 
			
		||||
void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user