Implement textDocument/documentLink

This commit is contained in:
Fangrui Song 2018-10-24 18:03:57 -07:00
parent 617cdd89de
commit 8fa853c321
4 changed files with 119 additions and 115 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 &params = request->params; auto &params = 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

View File

@ -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