mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	Add excludeRole to documentSymbol and override declaration's range/selectionRange with definition's
This commit is contained in:
		
							parent
							
								
									478f849ada
								
							
						
					
					
						commit
						5d27ac9f34
					
				@ -95,13 +95,15 @@ void MessageHandler::textDocument_documentLink(TextDocumentParam ¶m,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
struct DocumentSymbolParam : TextDocumentParam {
 | 
					struct DocumentSymbolParam : TextDocumentParam {
 | 
				
			||||||
  // false: outline; true: all symbols
 | 
					  // Include sym if `!(sym.role & excludeRole)`.
 | 
				
			||||||
  bool all = false;
 | 
					  Role excludeRole = Role((int)Role::All - (int)Role::Definition -
 | 
				
			||||||
 | 
					                          (int)Role::Declaration - (int)Role::Dynamic);
 | 
				
			||||||
  // If >= 0, return Range[] instead of SymbolInformation[] to reduce output.
 | 
					  // If >= 0, return Range[] instead of SymbolInformation[] to reduce output.
 | 
				
			||||||
  int startLine = -1;
 | 
					  int startLine = -1;
 | 
				
			||||||
  int endLine = -1;
 | 
					  int endLine = -1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine);
 | 
					REFLECT_STRUCT(DocumentSymbolParam, textDocument, excludeRole, startLine,
 | 
				
			||||||
 | 
					               endLine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct DocumentSymbol {
 | 
					struct DocumentSymbol {
 | 
				
			||||||
  std::string name;
 | 
					  std::string name;
 | 
				
			||||||
@ -149,18 +151,22 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  int file_id;
 | 
					  int file_id;
 | 
				
			||||||
  auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply, &file_id);
 | 
					  auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply, &file_id);
 | 
				
			||||||
  if (!wf) {
 | 
					  if (!wf)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  auto Allows = [&](SymbolRef sym) {
 | 
				
			||||||
 | 
					    return !(sym.role & param.excludeRole);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (param.startLine >= 0) {
 | 
					  if (param.startLine >= 0) {
 | 
				
			||||||
    std::vector<lsRange> result;
 | 
					    std::vector<lsRange> result;
 | 
				
			||||||
    for (auto [sym, refcnt] : file->symbol2refcnt)
 | 
					    for (auto [sym, refcnt] : file->symbol2refcnt) {
 | 
				
			||||||
      if (refcnt > 0 && (param.all || sym.extent.Valid()) &&
 | 
					      if (refcnt <= 0 || !Allows(sym) ||
 | 
				
			||||||
          param.startLine <= sym.range.start.line &&
 | 
					          !(param.startLine <= sym.range.start.line &&
 | 
				
			||||||
          sym.range.start.line <= param.endLine)
 | 
					            sym.range.start.line <= param.endLine))
 | 
				
			||||||
        if (auto loc = GetLsLocation(db, wfiles, sym, file_id))
 | 
					        continue;
 | 
				
			||||||
          result.push_back(loc->range);
 | 
					      if (auto loc = GetLsLocation(db, wfiles, sym, file_id))
 | 
				
			||||||
 | 
					        result.push_back(loc->range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    std::sort(result.begin(), result.end());
 | 
					    std::sort(result.begin(), result.end());
 | 
				
			||||||
    reply(result);
 | 
					    reply(result);
 | 
				
			||||||
  } else if (g_config->client.hierarchicalDocumentSymbolSupport) {
 | 
					  } else if (g_config->client.hierarchicalDocumentSymbolSupport) {
 | 
				
			||||||
@ -171,22 +177,26 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
 | 
				
			|||||||
      if (refcnt <= 0 || !sym.extent.Valid())
 | 
					      if (refcnt <= 0 || !sym.extent.Valid())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind});
 | 
					      auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind});
 | 
				
			||||||
 | 
					      auto &ds = r.first->second;
 | 
				
			||||||
 | 
					      if (!ds || sym.role & Role::Definition) {
 | 
				
			||||||
 | 
					        if (!ds)
 | 
				
			||||||
 | 
					          ds = std::make_unique<DocumentSymbol>();
 | 
				
			||||||
 | 
					        if (auto range = GetLsRange(wf, sym.range)) {
 | 
				
			||||||
 | 
					          ds->selectionRange = *range;
 | 
				
			||||||
 | 
					          ds->range = ds->selectionRange;
 | 
				
			||||||
 | 
					          // For a macro expansion, M(name), we may use `M` for extent and
 | 
				
			||||||
 | 
					          // `name` for spell, do the check as selectionRange must be a subrange
 | 
				
			||||||
 | 
					          // of range.
 | 
				
			||||||
 | 
					          if (sym.extent.Valid())
 | 
				
			||||||
 | 
					            if (auto range1 = GetLsRange(wf, sym.extent);
 | 
				
			||||||
 | 
					                range1 && range1->Includes(*range))
 | 
				
			||||||
 | 
					              ds->range = *range1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      if (!r.second)
 | 
					      if (!r.second)
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      auto &ds = r.first->second;
 | 
					 | 
				
			||||||
      ds = std::make_unique<DocumentSymbol>();
 | 
					 | 
				
			||||||
      if (auto range = GetLsRange(wf, sym.range)) {
 | 
					 | 
				
			||||||
        ds->selectionRange = *range;
 | 
					 | 
				
			||||||
        ds->range = ds->selectionRange;
 | 
					 | 
				
			||||||
        // For a macro expansion, M(name), we may use `M` for extent and `name`
 | 
					 | 
				
			||||||
        // for spell, do the check as selectionRange must be a subrange of
 | 
					 | 
				
			||||||
        // range.
 | 
					 | 
				
			||||||
        if (sym.extent.Valid())
 | 
					 | 
				
			||||||
          if (auto range1 = GetLsRange(wf, sym.extent);
 | 
					 | 
				
			||||||
              range1 && range1->Includes(*range))
 | 
					 | 
				
			||||||
            ds->range = *range1;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      std::vector<const void *> def_ptrs;
 | 
					      std::vector<const void *> def_ptrs;
 | 
				
			||||||
 | 
					      SymbolKind kind = SymbolKind::Unknown;
 | 
				
			||||||
      WithEntity(db, sym, [&](const auto &entity) {
 | 
					      WithEntity(db, sym, [&](const auto &entity) {
 | 
				
			||||||
        auto *def = entity.AnyDef();
 | 
					        auto *def = entity.AnyDef();
 | 
				
			||||||
        if (!def)
 | 
					        if (!def)
 | 
				
			||||||
@ -195,20 +205,14 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
 | 
				
			|||||||
        ds->detail = def->detailed_name;
 | 
					        ds->detail = def->detailed_name;
 | 
				
			||||||
        for (auto &def : entity.def)
 | 
					        for (auto &def : entity.def)
 | 
				
			||||||
          if (def.file_id == file_id && !Ignore(&def)) {
 | 
					          if (def.file_id == file_id && !Ignore(&def)) {
 | 
				
			||||||
            ds->kind = def.kind;
 | 
					            kind = ds->kind = def.kind;
 | 
				
			||||||
            if (def.spell || def.kind == SymbolKind::Namespace)
 | 
					            def_ptrs.push_back(&def);
 | 
				
			||||||
              def_ptrs.push_back(&def);
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      if (!(param.all || sym.role & Role::Definition ||
 | 
					      if (def_ptrs.empty() || !(kind == SymbolKind::Namespace || Allows(sym))) {
 | 
				
			||||||
            ds->kind == SymbolKind::Function ||
 | 
					 | 
				
			||||||
            ds->kind == SymbolKind::Method ||
 | 
					 | 
				
			||||||
            ds->kind == SymbolKind::Namespace)) {
 | 
					 | 
				
			||||||
        ds.reset();
 | 
					        ds.reset();
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (def_ptrs.empty())
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
      if (sym.kind == Kind::Func)
 | 
					      if (sym.kind == Kind::Func)
 | 
				
			||||||
        funcs.emplace_back(std::move(def_ptrs), ds.get());
 | 
					        funcs.emplace_back(std::move(def_ptrs), ds.get());
 | 
				
			||||||
      else if (sym.kind == Kind::Type)
 | 
					      else if (sym.kind == Kind::Type)
 | 
				
			||||||
@ -252,8 +256,7 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
 | 
				
			|||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    std::vector<SymbolInformation> result;
 | 
					    std::vector<SymbolInformation> result;
 | 
				
			||||||
    for (auto [sym, refcnt] : file->symbol2refcnt) {
 | 
					    for (auto [sym, refcnt] : file->symbol2refcnt) {
 | 
				
			||||||
      if (refcnt <= 0 || !sym.extent.Valid() ||
 | 
					      if (refcnt <= 0 || !Allows(sym))
 | 
				
			||||||
          !(param.all || sym.role & Role::Definition))
 | 
					 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      if (std::optional<SymbolInformation> info =
 | 
					      if (std::optional<SymbolInformation> info =
 | 
				
			||||||
              GetSymbolInfo(db, sym, false)) {
 | 
					              GetSymbolInfo(db, sym, false)) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user