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
|
||||
* code actions (clang FixIts)
|
||||
* 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
|
||||
|
||||
|
@ -914,6 +914,7 @@ void RegisterMessageTypes() {
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentLink>();
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeAction>();
|
||||
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
|
||||
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
|
||||
@ -1539,6 +1540,9 @@ bool QueryDbMainLoop(
|
||||
response.result.capabilities.documentSymbolProvider = true;
|
||||
response.result.capabilities.workspaceSymbolProvider = true;
|
||||
|
||||
response.result.capabilities.documentLinkProvider = lsDocumentLinkOptions();
|
||||
response.result.capabilities.documentLinkProvider->resolveProvider = false;
|
||||
|
||||
ipc->SendOutMessageToClient(IpcId::Initialize, response);
|
||||
break;
|
||||
}
|
||||
@ -2097,6 +2101,68 @@ bool QueryDbMainLoop(
|
||||
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: {
|
||||
// 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::TextDocumentReferences:
|
||||
case IpcId::TextDocumentDocumentSymbol:
|
||||
case IpcId::TextDocumentDocumentLink:
|
||||
case IpcId::TextDocumentCodeAction:
|
||||
case IpcId::TextDocumentCodeLens:
|
||||
case IpcId::WorkspaceSymbol:
|
||||
|
@ -38,6 +38,8 @@ const char* IpcIdToString(IpcId id) {
|
||||
return "textDocument/references";
|
||||
case IpcId::TextDocumentDocumentSymbol:
|
||||
return "textDocument/documentSymbol";
|
||||
case IpcId::TextDocumentDocumentLink:
|
||||
return "textDocument/documentLink";
|
||||
case IpcId::TextDocumentCodeAction:
|
||||
return "textDocument/codeAction";
|
||||
case IpcId::TextDocumentCodeLens:
|
||||
|
@ -24,6 +24,7 @@ enum class IpcId : int {
|
||||
TextDocumentHover,
|
||||
TextDocumentReferences,
|
||||
TextDocumentDocumentSymbol,
|
||||
TextDocumentDocumentLink,
|
||||
TextDocumentCodeAction,
|
||||
TextDocumentCodeLens,
|
||||
CodeLensResolve,
|
||||
|
@ -74,6 +74,9 @@ struct IndexerConfig {
|
||||
// If false, the index will not be loaded from a previous run.
|
||||
bool enableCacheRead = true;
|
||||
|
||||
// If true, document links are reported for #include directives.
|
||||
bool showDocumentLinksOnIncludes = true;
|
||||
|
||||
// Enables code lens on parameter and function variables.
|
||||
bool codeLensOnLocalVariables = true;
|
||||
|
||||
@ -89,6 +92,8 @@ MAKE_REFLECT_STRUCT(IndexerConfig,
|
||||
indexerCount,
|
||||
enableIndexing, enableCacheWrite, enableCacheRead,
|
||||
|
||||
showDocumentLinksOnIncludes,
|
||||
|
||||
codeLensOnLocalVariables,
|
||||
|
||||
clientVersion);
|
||||
@ -1492,6 +1497,36 @@ struct Out_TextDocumentDocumentSymbol : public lsOutMessage<Out_TextDocumentDocu
|
||||
};
|
||||
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.
|
||||
struct lsDocumentCodeLensParams {
|
||||
lsTextDocumentIdentifier textDocument;
|
||||
|
@ -164,6 +164,22 @@ optional<int> WorkingFile::GetIndexLineFromBufferLine(int buffer_line) const {
|
||||
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 {
|
||||
*active_parameter = 0;
|
||||
|
||||
|
@ -44,6 +44,8 @@ struct WorkingFile {
|
||||
// accepts and returns 1-based lines.
|
||||
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
|
||||
// signature help to filter code completion results.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user