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