mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 00:55:08 +00:00
Report document links on includes
This commit is contained in:
parent
41e1dff4c9
commit
7a79532fff
@ -28,7 +28,7 @@ be productive with cquery. Here's a list of implemented features:
|
|||||||
* diagnostics
|
* diagnostics
|
||||||
* code actions (clang FixIts)
|
* code actions (clang FixIts)
|
||||||
* darken/fade code disabled by preprocessor
|
* darken/fade code disabled by preprocessor
|
||||||
* goto definition on include to jump to file
|
* goto definition, document links on include to jump to file
|
||||||
|
|
||||||
# Setup - build cquery, install extension, setup project
|
# Setup - build cquery, install extension, setup project
|
||||||
|
|
||||||
|
@ -914,6 +914,7 @@ void RegisterMessageTypes() {
|
|||||||
MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
|
MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
|
||||||
MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
|
MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
|
||||||
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
|
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
|
||||||
|
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentLink>();
|
||||||
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeAction>();
|
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeAction>();
|
||||||
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
|
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
|
||||||
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
|
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
|
||||||
@ -1539,6 +1540,9 @@ bool QueryDbMainLoop(
|
|||||||
response.result.capabilities.documentSymbolProvider = true;
|
response.result.capabilities.documentSymbolProvider = true;
|
||||||
response.result.capabilities.workspaceSymbolProvider = true;
|
response.result.capabilities.workspaceSymbolProvider = true;
|
||||||
|
|
||||||
|
response.result.capabilities.documentLinkProvider = lsDocumentLinkOptions();
|
||||||
|
response.result.capabilities.documentLinkProvider->resolveProvider = false;
|
||||||
|
|
||||||
ipc->SendOutMessageToClient(IpcId::Initialize, response);
|
ipc->SendOutMessageToClient(IpcId::Initialize, response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2097,6 +2101,68 @@ bool QueryDbMainLoop(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case IpcId::TextDocumentDocumentLink: {
|
||||||
|
auto msg = static_cast<Ipc_TextDocumentDocumentLink*>(message.get());
|
||||||
|
|
||||||
|
Out_TextDocumentDocumentLink response;
|
||||||
|
response.id = msg->id;
|
||||||
|
|
||||||
|
if (config->showDocumentLinksOnIncludes) {
|
||||||
|
QueryFile* file = FindFile(db, msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!file) {
|
||||||
|
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!working_file) {
|
||||||
|
std::cerr << "Unable to find working file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (const IndexInclude& include : file->def.includes) {
|
||||||
|
optional<int> buffer_line;
|
||||||
|
optional<std::string> buffer_line_content = working_file->GetBufferLineContentFromIndexLine(include.line, &buffer_line);
|
||||||
|
if (!buffer_line || !buffer_line_content)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Find starting and ending quote.
|
||||||
|
int start = 0;
|
||||||
|
while (start < buffer_line_content->size()) {
|
||||||
|
char c = (*buffer_line_content)[start];
|
||||||
|
++start;
|
||||||
|
if (c == '"' || c == '<')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (start == buffer_line_content->size())
|
||||||
|
continue;
|
||||||
|
int end = buffer_line_content->size();
|
||||||
|
while (end > 0) {
|
||||||
|
char c = (*buffer_line_content)[end];
|
||||||
|
if (c == '"' || c == '>')
|
||||||
|
break;
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
if (start >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
lsDocumentLink link;
|
||||||
|
link.target = lsDocumentUri::FromPath(include.resolved_path);
|
||||||
|
// Subtract 1 from line because querydb stores 1-based lines but
|
||||||
|
// vscode expects 0-based lines.
|
||||||
|
link.range.start.line = *buffer_line - 1;
|
||||||
|
link.range.start.character = start;
|
||||||
|
link.range.end.line = *buffer_line - 1;
|
||||||
|
link.range.end.character = end;
|
||||||
|
response.result.push_back(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Write(std::cerr);
|
||||||
|
ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentLink, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IpcId::TextDocumentCodeAction: {
|
case IpcId::TextDocumentCodeAction: {
|
||||||
// NOTE: This code snippet will generate some FixIts for testing:
|
// NOTE: This code snippet will generate some FixIts for testing:
|
||||||
//
|
//
|
||||||
@ -2495,6 +2561,7 @@ void LanguageServerStdinLoop(IndexerConfig* config, std::unordered_map<IpcId, Ti
|
|||||||
case IpcId::TextDocumentHover:
|
case IpcId::TextDocumentHover:
|
||||||
case IpcId::TextDocumentReferences:
|
case IpcId::TextDocumentReferences:
|
||||||
case IpcId::TextDocumentDocumentSymbol:
|
case IpcId::TextDocumentDocumentSymbol:
|
||||||
|
case IpcId::TextDocumentDocumentLink:
|
||||||
case IpcId::TextDocumentCodeAction:
|
case IpcId::TextDocumentCodeAction:
|
||||||
case IpcId::TextDocumentCodeLens:
|
case IpcId::TextDocumentCodeLens:
|
||||||
case IpcId::WorkspaceSymbol:
|
case IpcId::WorkspaceSymbol:
|
||||||
|
@ -38,6 +38,8 @@ const char* IpcIdToString(IpcId id) {
|
|||||||
return "textDocument/references";
|
return "textDocument/references";
|
||||||
case IpcId::TextDocumentDocumentSymbol:
|
case IpcId::TextDocumentDocumentSymbol:
|
||||||
return "textDocument/documentSymbol";
|
return "textDocument/documentSymbol";
|
||||||
|
case IpcId::TextDocumentDocumentLink:
|
||||||
|
return "textDocument/documentLink";
|
||||||
case IpcId::TextDocumentCodeAction:
|
case IpcId::TextDocumentCodeAction:
|
||||||
return "textDocument/codeAction";
|
return "textDocument/codeAction";
|
||||||
case IpcId::TextDocumentCodeLens:
|
case IpcId::TextDocumentCodeLens:
|
||||||
|
@ -24,6 +24,7 @@ enum class IpcId : int {
|
|||||||
TextDocumentHover,
|
TextDocumentHover,
|
||||||
TextDocumentReferences,
|
TextDocumentReferences,
|
||||||
TextDocumentDocumentSymbol,
|
TextDocumentDocumentSymbol,
|
||||||
|
TextDocumentDocumentLink,
|
||||||
TextDocumentCodeAction,
|
TextDocumentCodeAction,
|
||||||
TextDocumentCodeLens,
|
TextDocumentCodeLens,
|
||||||
CodeLensResolve,
|
CodeLensResolve,
|
||||||
|
@ -74,6 +74,9 @@ struct IndexerConfig {
|
|||||||
// If false, the index will not be loaded from a previous run.
|
// If false, the index will not be loaded from a previous run.
|
||||||
bool enableCacheRead = true;
|
bool enableCacheRead = true;
|
||||||
|
|
||||||
|
// If true, document links are reported for #include directives.
|
||||||
|
bool showDocumentLinksOnIncludes = true;
|
||||||
|
|
||||||
// Enables code lens on parameter and function variables.
|
// Enables code lens on parameter and function variables.
|
||||||
bool codeLensOnLocalVariables = true;
|
bool codeLensOnLocalVariables = true;
|
||||||
|
|
||||||
@ -89,6 +92,8 @@ MAKE_REFLECT_STRUCT(IndexerConfig,
|
|||||||
indexerCount,
|
indexerCount,
|
||||||
enableIndexing, enableCacheWrite, enableCacheRead,
|
enableIndexing, enableCacheWrite, enableCacheRead,
|
||||||
|
|
||||||
|
showDocumentLinksOnIncludes,
|
||||||
|
|
||||||
codeLensOnLocalVariables,
|
codeLensOnLocalVariables,
|
||||||
|
|
||||||
clientVersion);
|
clientVersion);
|
||||||
@ -1492,6 +1497,36 @@ struct Out_TextDocumentDocumentSymbol : public lsOutMessage<Out_TextDocumentDocu
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result);
|
MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result);
|
||||||
|
|
||||||
|
// List links a document
|
||||||
|
struct Ipc_TextDocumentDocumentLink : public IpcMessage<Ipc_TextDocumentDocumentLink> {
|
||||||
|
const static IpcId kIpcId = IpcId::TextDocumentDocumentLink;
|
||||||
|
|
||||||
|
struct DocumentLinkParams {
|
||||||
|
// The document to provide document links for.
|
||||||
|
lsTextDocumentIdentifier textDocument;
|
||||||
|
};
|
||||||
|
|
||||||
|
lsRequestId id;
|
||||||
|
DocumentLinkParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink::DocumentLinkParams, textDocument);
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink, id, params);
|
||||||
|
// A document link is a range in a text document that links to an internal or external resource, like another
|
||||||
|
// text document or a web site.
|
||||||
|
struct lsDocumentLink {
|
||||||
|
// The range this link applies to.
|
||||||
|
lsRange range;
|
||||||
|
// The uri this link points to. If missing a resolve request is sent later.
|
||||||
|
optional<lsDocumentUri> target;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsDocumentLink, range, target);
|
||||||
|
struct Out_TextDocumentDocumentLink : public lsOutMessage<Out_TextDocumentDocumentLink> {
|
||||||
|
lsRequestId id;
|
||||||
|
NonElidedVector<lsDocumentLink> result;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentLink, jsonrpc, id, result);
|
||||||
|
|
||||||
|
|
||||||
// List code lens in a document.
|
// List code lens in a document.
|
||||||
struct lsDocumentCodeLensParams {
|
struct lsDocumentCodeLensParams {
|
||||||
lsTextDocumentIdentifier textDocument;
|
lsTextDocumentIdentifier textDocument;
|
||||||
|
@ -164,6 +164,22 @@ optional<int> WorkingFile::GetIndexLineFromBufferLine(int buffer_line) const {
|
|||||||
return closest_index_line;
|
return closest_index_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<std::string> WorkingFile::GetBufferLineContentFromIndexLine(int indexed_line, optional<int>* out_buffer_line) const {
|
||||||
|
optional<int> buffer_line = GetBufferLineFromIndexLine(indexed_line);
|
||||||
|
if (out_buffer_line)
|
||||||
|
*out_buffer_line = buffer_line;
|
||||||
|
|
||||||
|
if (!buffer_line)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
if (*buffer_line < 1 || *buffer_line >= all_buffer_lines.size()) {
|
||||||
|
std::cerr << "GetBufferLineContentFromIndexLine buffer line lookup not in all_buffer_lines" << std::endl;
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_buffer_lines[*buffer_line - 1];
|
||||||
|
}
|
||||||
|
|
||||||
std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* active_parameter, lsPosition* completion_position) const {
|
std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* active_parameter, lsPosition* completion_position) const {
|
||||||
*active_parameter = 0;
|
*active_parameter = 0;
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ struct WorkingFile {
|
|||||||
// accepts and returns 1-based lines.
|
// accepts and returns 1-based lines.
|
||||||
optional<int> GetIndexLineFromBufferLine(int buffer_line) const;
|
optional<int> GetIndexLineFromBufferLine(int buffer_line) const;
|
||||||
|
|
||||||
|
optional<std::string> GetBufferLineContentFromIndexLine(int indexed_line, optional<int>* out_buffer_line) const;
|
||||||
|
|
||||||
// Finds the closest 'callable' name prior to position. This is used for
|
// Finds the closest 'callable' name prior to position. This is used for
|
||||||
// signature help to filter code completion results.
|
// signature help to filter code completion results.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user