diff --git a/CMakeLists.txt b/CMakeLists.txt index a16583e31..5c6bdbcdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 0836b436a..113701ff1 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -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); diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_document.cc similarity index 58% rename from src/messages/textDocument_documentSymbol.cc rename to src/messages/textDocument_document.cc index 6047ae0e6..4041519e2 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_document.cc @@ -4,16 +4,116 @@ #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; -using namespace clang; + +#include 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 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 { + 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 result; + + std::vector 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 { + 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 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 kMethodType; } +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 { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_TextDocumentDocumentSymbol *request) override { +struct Handler_textDocumentDocumentSymbol + : BaseMessageHandler { + MethodType GetMethodType() const override { return documentSymbol; } + void Run(In_textDocumentDocumentSymbol *request) override { auto ¶ms = request->params; QueryFile *file; @@ -180,5 +280,6 @@ struct Handler_TextDocumentDocumentSymbol } } }; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol); +REGISTER_MESSAGE_HANDLER(Handler_textDocumentDocumentSymbol); } // namespace +} // namespace ccls diff --git a/src/messages/textDocument_documentHighlight.cc b/src/messages/textDocument_documentHighlight.cc deleted file mode 100644 index 69489e354..000000000 --- a/src/messages/textDocument_documentHighlight.cc +++ /dev/null @@ -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 -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 { - 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 result; - - std::vector 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