mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 09:05:10 +00:00
Implement textDocument/documentLink
This commit is contained in:
parent
617cdd89de
commit
8fa853c321
@ -222,8 +222,7 @@ target_sources(ccls PRIVATE
|
|||||||
src/messages/textDocument_did.cc
|
src/messages/textDocument_did.cc
|
||||||
src/messages/textDocument_foldingRange.cc
|
src/messages/textDocument_foldingRange.cc
|
||||||
src/messages/textDocument_formatting.cc
|
src/messages/textDocument_formatting.cc
|
||||||
src/messages/textDocument_documentHighlight.cc
|
src/messages/textDocument_document.cc
|
||||||
src/messages/textDocument_documentSymbol.cc
|
|
||||||
src/messages/textDocument_hover.cc
|
src/messages/textDocument_hover.cc
|
||||||
src/messages/textDocument_references.cc
|
src/messages/textDocument_references.cc
|
||||||
src/messages/textDocument_rename.cc
|
src/messages/textDocument_rename.cc
|
||||||
|
@ -62,12 +62,6 @@ struct lsDocumentOnTypeFormattingOptions {
|
|||||||
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter,
|
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter,
|
||||||
moreTriggerCharacter);
|
moreTriggerCharacter);
|
||||||
|
|
||||||
// Document link options
|
|
||||||
struct lsDocumentLinkOptions {
|
|
||||||
// Document links have a resolve provider as well.
|
|
||||||
bool resolveProvider = false;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, resolveProvider);
|
|
||||||
|
|
||||||
// Save options.
|
// Save options.
|
||||||
struct lsSaveOptions {
|
struct lsSaveOptions {
|
||||||
@ -132,34 +126,22 @@ struct lsServerCapabilities {
|
|||||||
lsCompletionOptions completionProvider;
|
lsCompletionOptions completionProvider;
|
||||||
// The server provides signature help support.
|
// The server provides signature help support.
|
||||||
lsSignatureHelpOptions signatureHelpProvider;
|
lsSignatureHelpOptions signatureHelpProvider;
|
||||||
// The server provides goto definition support.
|
|
||||||
bool definitionProvider = true;
|
bool definitionProvider = true;
|
||||||
// The server provides Goto Type Definition support.
|
|
||||||
bool typeDefinitionProvider = true;
|
bool typeDefinitionProvider = true;
|
||||||
// The server provides Goto Implementation support.
|
|
||||||
bool implementationProvider = true;
|
bool implementationProvider = true;
|
||||||
// The server provides find references support.
|
|
||||||
bool referencesProvider = true;
|
bool referencesProvider = true;
|
||||||
// The server provides document highlight support.
|
|
||||||
bool documentHighlightProvider = true;
|
bool documentHighlightProvider = true;
|
||||||
// The server provides document symbol support.
|
|
||||||
bool documentSymbolProvider = true;
|
bool documentSymbolProvider = true;
|
||||||
// The server provides workspace symbol support.
|
|
||||||
bool workspaceSymbolProvider = true;
|
bool workspaceSymbolProvider = true;
|
||||||
// The server provides code actions.
|
|
||||||
bool codeActionProvider = true;
|
bool codeActionProvider = true;
|
||||||
// The server provides code lens.
|
|
||||||
lsCodeLensOptions codeLensProvider;
|
lsCodeLensOptions codeLensProvider;
|
||||||
// The server provides document formatting.
|
|
||||||
bool documentFormattingProvider = true;
|
bool documentFormattingProvider = true;
|
||||||
// The server provides document range formatting.
|
|
||||||
bool documentRangeFormattingProvider = true;
|
bool documentRangeFormattingProvider = true;
|
||||||
// The server provides document formatting on typing.
|
|
||||||
lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
|
lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
|
||||||
// The server provides rename support.
|
|
||||||
bool renameProvider = true;
|
bool renameProvider = true;
|
||||||
// The server provides document link support.
|
struct DocumentLinkOptions {
|
||||||
lsDocumentLinkOptions documentLinkProvider;
|
bool resolveProvider = true;
|
||||||
|
} documentLinkProvider;
|
||||||
bool foldingRangeProvider = true;
|
bool foldingRangeProvider = true;
|
||||||
// The server provides execute command support.
|
// The server provides execute command support.
|
||||||
struct ExecuteCommandOptions {
|
struct ExecuteCommandOptions {
|
||||||
@ -172,6 +154,7 @@ struct lsServerCapabilities {
|
|||||||
} workspaceFolders;
|
} workspaceFolders;
|
||||||
} workspace;
|
} workspace;
|
||||||
};
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsServerCapabilities::DocumentLinkOptions, resolveProvider);
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands);
|
MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands);
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::Workspace::WorkspaceFolders,
|
MAKE_REFLECT_STRUCT(lsServerCapabilities::Workspace::WorkspaceFolders,
|
||||||
supported, changeNotifications);
|
supported, changeNotifications);
|
||||||
|
@ -4,16 +4,116 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
using namespace ccls;
|
|
||||||
using namespace clang;
|
#include <algorithm>
|
||||||
|
|
||||||
MAKE_HASHABLE(SymbolIdx, t.usr, t.kind);
|
MAKE_HASHABLE(SymbolIdx, t.usr, t.kind);
|
||||||
|
|
||||||
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/documentSymbol";
|
MethodType documentHighlight = "textDocument/documentHighlight",
|
||||||
|
documentLink = "textDocument/documentLink",
|
||||||
|
documentSymbol = "textDocument/documentSymbol";
|
||||||
|
|
||||||
struct In_TextDocumentDocumentSymbol : public RequestMessage {
|
struct lsDocumentHighlight {
|
||||||
MethodType GetMethodType() const override { return kMethodType; }
|
enum Kind { Text = 1, Read = 2, Write = 3 };
|
||||||
|
|
||||||
|
lsRange range;
|
||||||
|
int kind = 1;
|
||||||
|
|
||||||
|
// ccls extension
|
||||||
|
Role role = Role::None;
|
||||||
|
|
||||||
|
bool operator<(const lsDocumentHighlight &o) const {
|
||||||
|
return !(range == o.range) ? range < o.range : kind < o.kind;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role);
|
||||||
|
|
||||||
|
struct In_TextDocumentDocumentHighlight : public RequestMessage {
|
||||||
|
MethodType GetMethodType() const override { return documentHighlight; }
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentHighlight, id, params);
|
||||||
|
REGISTER_IN_MESSAGE(In_TextDocumentDocumentHighlight);
|
||||||
|
|
||||||
|
struct Handler_TextDocumentDocumentHighlight
|
||||||
|
: BaseMessageHandler<In_TextDocumentDocumentHighlight> {
|
||||||
|
MethodType GetMethodType() const override { return documentHighlight; }
|
||||||
|
void Run(In_TextDocumentDocumentHighlight *request) override {
|
||||||
|
int file_id;
|
||||||
|
QueryFile *file;
|
||||||
|
if (!FindFileOrFail(db, project, request->id,
|
||||||
|
request->params.textDocument.uri.GetPath(), &file,
|
||||||
|
&file_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
|
||||||
|
std::vector<lsDocumentHighlight> result;
|
||||||
|
|
||||||
|
std::vector<SymbolRef> syms =
|
||||||
|
FindSymbolsAtLocation(wfile, file, request->params.position, true);
|
||||||
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
|
if (refcnt <= 0)
|
||||||
|
continue;
|
||||||
|
Usr usr = sym.usr;
|
||||||
|
SymbolKind kind = sym.kind;
|
||||||
|
if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) {
|
||||||
|
return usr == sym1.usr && kind == sym1.kind;
|
||||||
|
}))
|
||||||
|
continue;
|
||||||
|
if (auto loc = GetLsLocation(db, working_files, sym, file_id)) {
|
||||||
|
lsDocumentHighlight highlight;
|
||||||
|
highlight.range = loc->range;
|
||||||
|
if (sym.role & Role::Write)
|
||||||
|
highlight.kind = lsDocumentHighlight::Write;
|
||||||
|
else if (sym.role & Role::Read)
|
||||||
|
highlight.kind = lsDocumentHighlight::Read;
|
||||||
|
else
|
||||||
|
highlight.kind = lsDocumentHighlight::Text;
|
||||||
|
highlight.role = sym.role;
|
||||||
|
result.push_back(highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
pipeline::Reply(request->id, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentHighlight);
|
||||||
|
|
||||||
|
struct In_textDocumentDocumentLink : public RequestMessage {
|
||||||
|
MethodType GetMethodType() const override { return documentLink; }
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(In_textDocumentDocumentLink, id, params);
|
||||||
|
REGISTER_IN_MESSAGE(In_textDocumentDocumentLink);
|
||||||
|
|
||||||
|
struct lsDocumentLink {
|
||||||
|
lsRange range;
|
||||||
|
lsDocumentUri target;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsDocumentLink, range, target);
|
||||||
|
|
||||||
|
struct Handler_textDocumentDocumentLink
|
||||||
|
: BaseMessageHandler<In_textDocumentDocumentLink> {
|
||||||
|
MethodType GetMethodType() const override { return documentLink; }
|
||||||
|
void Run(In_textDocumentDocumentLink *request) override {
|
||||||
|
QueryFile *file;
|
||||||
|
if (!FindFileOrFail(db, project, request->id,
|
||||||
|
request->params.textDocument.uri.GetPath(), &file))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<lsDocumentLink> result;
|
||||||
|
for (const IndexInclude &include : file->def->includes)
|
||||||
|
result.push_back({lsRange{{include.line, 0}, {include.line + 1, 0}},
|
||||||
|
lsDocumentUri::FromPath(include.resolved_path)});
|
||||||
|
pipeline::Reply(request->id, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_MESSAGE_HANDLER(Handler_textDocumentDocumentLink);
|
||||||
|
|
||||||
|
struct In_textDocumentDocumentSymbol : public RequestMessage {
|
||||||
|
MethodType GetMethodType() const override { return documentSymbol; }
|
||||||
struct Params {
|
struct Params {
|
||||||
lsTextDocumentIdentifier textDocument;
|
lsTextDocumentIdentifier textDocument;
|
||||||
// false: outline; true: all symbols
|
// false: outline; true: all symbols
|
||||||
@ -23,10 +123,10 @@ struct In_TextDocumentDocumentSymbol : public RequestMessage {
|
|||||||
int endLine = -1;
|
int endLine = -1;
|
||||||
} params;
|
} params;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol::Params, textDocument, all,
|
MAKE_REFLECT_STRUCT(In_textDocumentDocumentSymbol::Params, textDocument, all,
|
||||||
startLine, endLine);
|
startLine, endLine);
|
||||||
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol, id, params);
|
MAKE_REFLECT_STRUCT(In_textDocumentDocumentSymbol, id, params);
|
||||||
REGISTER_IN_MESSAGE(In_TextDocumentDocumentSymbol);
|
REGISTER_IN_MESSAGE(In_textDocumentDocumentSymbol);
|
||||||
|
|
||||||
struct lsDocumentSymbol {
|
struct lsDocumentSymbol {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -56,10 +156,10 @@ bool Ignore(const QueryVar::Def *def) {
|
|||||||
return !def || def->is_local();
|
return !def || def->is_local();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Handler_TextDocumentDocumentSymbol
|
struct Handler_textDocumentDocumentSymbol
|
||||||
: BaseMessageHandler<In_TextDocumentDocumentSymbol> {
|
: BaseMessageHandler<In_textDocumentDocumentSymbol> {
|
||||||
MethodType GetMethodType() const override { return kMethodType; }
|
MethodType GetMethodType() const override { return documentSymbol; }
|
||||||
void Run(In_TextDocumentDocumentSymbol *request) override {
|
void Run(In_textDocumentDocumentSymbol *request) override {
|
||||||
auto ¶ms = request->params;
|
auto ¶ms = request->params;
|
||||||
|
|
||||||
QueryFile *file;
|
QueryFile *file;
|
||||||
@ -180,5 +280,6 @@ struct Handler_TextDocumentDocumentSymbol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol);
|
REGISTER_MESSAGE_HANDLER(Handler_textDocumentDocumentSymbol);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
} // namespace ccls
|
@ -1,79 +0,0 @@
|
|||||||
// Copyright 2017-2018 ccls Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "message_handler.h"
|
|
||||||
#include "pipeline.hh"
|
|
||||||
#include "query_utils.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
using namespace ccls;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
MethodType kMethodType = "textDocument/documentHighlight";
|
|
||||||
|
|
||||||
struct lsDocumentHighlight {
|
|
||||||
enum Kind { Text = 1, Read = 2, Write = 3 };
|
|
||||||
|
|
||||||
lsRange range;
|
|
||||||
int kind = 1;
|
|
||||||
|
|
||||||
// ccls extension
|
|
||||||
Role role = Role::None;
|
|
||||||
|
|
||||||
bool operator<(const lsDocumentHighlight &o) const {
|
|
||||||
return !(range == o.range) ? range < o.range : kind < o.kind;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role);
|
|
||||||
|
|
||||||
struct In_TextDocumentDocumentHighlight : public RequestMessage {
|
|
||||||
MethodType GetMethodType() const override { return kMethodType; }
|
|
||||||
lsTextDocumentPositionParams params;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentHighlight, id, params);
|
|
||||||
REGISTER_IN_MESSAGE(In_TextDocumentDocumentHighlight);
|
|
||||||
|
|
||||||
struct Handler_TextDocumentDocumentHighlight
|
|
||||||
: BaseMessageHandler<In_TextDocumentDocumentHighlight> {
|
|
||||||
MethodType GetMethodType() const override { return kMethodType; }
|
|
||||||
void Run(In_TextDocumentDocumentHighlight *request) override {
|
|
||||||
int file_id;
|
|
||||||
QueryFile *file;
|
|
||||||
if (!FindFileOrFail(db, project, request->id,
|
|
||||||
request->params.textDocument.uri.GetPath(), &file,
|
|
||||||
&file_id))
|
|
||||||
return;
|
|
||||||
|
|
||||||
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
|
|
||||||
std::vector<lsDocumentHighlight> result;
|
|
||||||
|
|
||||||
std::vector<SymbolRef> syms =
|
|
||||||
FindSymbolsAtLocation(wfile, file, request->params.position, true);
|
|
||||||
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
|
||||||
if (refcnt <= 0)
|
|
||||||
continue;
|
|
||||||
Usr usr = sym.usr;
|
|
||||||
SymbolKind kind = sym.kind;
|
|
||||||
if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) {
|
|
||||||
return usr == sym1.usr && kind == sym1.kind;
|
|
||||||
}))
|
|
||||||
continue;
|
|
||||||
if (auto loc = GetLsLocation(db, working_files, sym, file_id)) {
|
|
||||||
lsDocumentHighlight highlight;
|
|
||||||
highlight.range = loc->range;
|
|
||||||
if (sym.role & Role::Write)
|
|
||||||
highlight.kind = lsDocumentHighlight::Write;
|
|
||||||
else if (sym.role & Role::Read)
|
|
||||||
highlight.kind = lsDocumentHighlight::Read;
|
|
||||||
else
|
|
||||||
highlight.kind = lsDocumentHighlight::Text;
|
|
||||||
highlight.role = sym.role;
|
|
||||||
result.push_back(highlight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(result.begin(), result.end());
|
|
||||||
pipeline::Reply(request->id, result);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentHighlight);
|
|
||||||
} // namespace
|
|
Loading…
Reference in New Issue
Block a user