mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-27 18:11:57 +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,24 +74,32 @@ 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;
|
||||||
for (QueryFile& file1 : db->files)
|
|
||||||
if (file1.def)
|
|
||||||
for (const IndexInclude& include1 : file1.def->includes)
|
|
||||||
if (include1.resolved_path == include.resolved_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;
|
|
||||||
out.result.push_back(std::move(result));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (path.size())
|
||||||
|
for (QueryFile& file1 : db->files)
|
||||||
|
if (file1.def)
|
||||||
|
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 =
|
||||||
|
include.line;
|
||||||
|
out.result.push_back(std::move(result));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((int)out.result.size() >= g_config->xref.maxNum)
|
if ((int)out.result.size() >= g_config->xref.maxNum)
|
||||||
out.result.resize(g_config->xref.maxNum);
|
out.result.resize(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