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_foldingRange.cc
src/messages/textDocument_formatting.cc
src/messages/textDocument_documentHighlight.cc
src/messages/textDocument_documentSymbol.cc
src/messages/textDocument_document.cc
src/messages/textDocument_hover.cc
src/messages/textDocument_references.cc
src/messages/textDocument_rename.cc

View File

@ -62,12 +62,6 @@ struct lsDocumentOnTypeFormattingOptions {
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter,
moreTriggerCharacter);
// Document link options
struct lsDocumentLinkOptions {
// Document links have a resolve provider as well.
bool resolveProvider = false;
};
MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, resolveProvider);
// Save options.
struct lsSaveOptions {
@ -132,34 +126,22 @@ struct lsServerCapabilities {
lsCompletionOptions completionProvider;
// The server provides signature help support.
lsSignatureHelpOptions signatureHelpProvider;
// The server provides goto definition support.
bool definitionProvider = true;
// The server provides Goto Type Definition support.
bool typeDefinitionProvider = true;
// The server provides Goto Implementation support.
bool implementationProvider = true;
// The server provides find references support.
bool referencesProvider = true;
// The server provides document highlight support.
bool documentHighlightProvider = true;
// The server provides document symbol support.
bool documentSymbolProvider = true;
// The server provides workspace symbol support.
bool workspaceSymbolProvider = true;
// The server provides code actions.
bool codeActionProvider = true;
// The server provides code lens.
lsCodeLensOptions codeLensProvider;
// The server provides document formatting.
bool documentFormattingProvider = true;
// The server provides document range formatting.
bool documentRangeFormattingProvider = true;
// The server provides document formatting on typing.
lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
// The server provides rename support.
bool renameProvider = true;
// The server provides document link support.
lsDocumentLinkOptions documentLinkProvider;
struct DocumentLinkOptions {
bool resolveProvider = true;
} documentLinkProvider;
bool foldingRangeProvider = true;
// The server provides execute command support.
struct ExecuteCommandOptions {
@ -172,6 +154,7 @@ struct lsServerCapabilities {
} workspaceFolders;
} workspace;
};
MAKE_REFLECT_STRUCT(lsServerCapabilities::DocumentLinkOptions, resolveProvider);
MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands);
MAKE_REFLECT_STRUCT(lsServerCapabilities::Workspace::WorkspaceFolders,
supported, changeNotifications);

View File

@ -4,16 +4,116 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
using namespace clang;
#include <algorithm>
MAKE_HASHABLE(SymbolIdx, t.usr, t.kind);
namespace ccls {
namespace {
MethodType kMethodType = "textDocument/documentSymbol";
MethodType documentHighlight = "textDocument/documentHighlight",
documentLink = "textDocument/documentLink",
documentSymbol = "textDocument/documentSymbol";
struct In_TextDocumentDocumentSymbol : public RequestMessage {
MethodType GetMethodType() const override { return kMethodType; }
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 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 {
lsTextDocumentIdentifier textDocument;
// false: outline; true: all symbols
@ -23,10 +123,10 @@ struct In_TextDocumentDocumentSymbol : public RequestMessage {
int endLine = -1;
} params;
};
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol::Params, textDocument, all,
MAKE_REFLECT_STRUCT(In_textDocumentDocumentSymbol::Params, textDocument, all,
startLine, endLine);
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentDocumentSymbol);
MAKE_REFLECT_STRUCT(In_textDocumentDocumentSymbol, id, params);
REGISTER_IN_MESSAGE(In_textDocumentDocumentSymbol);
struct lsDocumentSymbol {
std::string name;
@ -56,10 +156,10 @@ bool Ignore(const QueryVar::Def *def) {
return !def || def->is_local();
}
struct Handler_TextDocumentDocumentSymbol
: BaseMessageHandler<In_TextDocumentDocumentSymbol> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDocumentSymbol *request) override {
struct Handler_textDocumentDocumentSymbol
: BaseMessageHandler<In_textDocumentDocumentSymbol> {
MethodType GetMethodType() const override { return documentSymbol; }
void Run(In_textDocumentDocumentSymbol *request) override {
auto &params = request->params;
QueryFile *file;
@ -180,5 +280,6 @@ struct Handler_TextDocumentDocumentSymbol
}
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol);
REGISTER_MESSAGE_HANDLER(Handler_textDocumentDocumentSymbol);
} // 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