diff --git a/src/cache_manager.cc b/src/cache_manager.cc index 48e0be36..520e9dcf 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -2,7 +2,7 @@ #include "config.h" #include "indexer.h" -#include "language_server_api.h" +#include "lsp.h" #include "platform.h" #include diff --git a/src/clang_complete.h b/src/clang_complete.h index 806a729e..5df97256 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -3,7 +3,8 @@ #include "atomic_object.h" #include "clang_index.h" #include "clang_translation_unit.h" -#include "language_server_api_completion.h" +#include "lsp_completion.h" +#include "lsp_diagnostic.h" #include "lru_cache.h" #include "project.h" #include "threaded_queue.h" diff --git a/src/clang_format.h b/src/clang_format.h index 1a0b359d..862f3e06 100644 --- a/src/clang_format.h +++ b/src/clang_format.h @@ -2,7 +2,7 @@ #if USE_CLANG_CXX -#include "language_server_api.h" +#include "lsp.h" #include "working_files.h" #include diff --git a/src/clang_utils.h b/src/clang_utils.h index 01ce6da2..7f240e8b 100644 --- a/src/clang_utils.h +++ b/src/clang_utils.h @@ -1,6 +1,6 @@ #pragma once -#include "language_server_api.h" +#include "lsp_diagnostic.h" #include #if USE_CLANG_CXX diff --git a/src/code_complete_cache.h b/src/code_complete_cache.h index 3ae7bad8..76ed6104 100644 --- a/src/code_complete_cache.h +++ b/src/code_complete_cache.h @@ -1,6 +1,6 @@ #pragma once -#include "language_server_api_completion.h" +#include "lsp_completion.h" #include diff --git a/src/command_line.cc b/src/command_line.cc index d22c9449..affff753 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -7,7 +7,7 @@ #include "import_pipeline.h" #include "include_complete.h" #include "indexer.h" -#include "language_server_api.h" +#include "lsp_diagnostic.h" #include "lex_utils.h" #include "lru_cache.h" #include "match.h" diff --git a/src/import_pipeline.cc b/src/import_pipeline.cc index c530524e..2a133032 100644 --- a/src/import_pipeline.cc +++ b/src/import_pipeline.cc @@ -4,7 +4,7 @@ #include "config.h" #include "iindexer.h" #include "import_manager.h" -#include "language_server_api.h" +#include "lsp.h" #include "message_handler.h" #include "platform.h" #include "project.h" diff --git a/src/include_complete.h b/src/include_complete.h index 5d97ec6f..9806cffe 100644 --- a/src/include_complete.h +++ b/src/include_complete.h @@ -1,6 +1,6 @@ #pragma once -#include "language_server_api_completion.h" +#include "lsp_completion.h" #include #include diff --git a/src/indexer.h b/src/indexer.h index 34c4f81f..35777c40 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -7,7 +7,7 @@ #include "file_consumer.h" #include "file_contents.h" #include "language.h" -#include "language_server_api.h" +#include "lsp.h" #include "maybe.h" #include "nt_string.h" #include "performance.h" diff --git a/src/lex_utils.cc b/src/lex_utils.cc index 298a3f41..9ab0ef4b 100644 --- a/src/lex_utils.cc +++ b/src/lex_utils.cc @@ -46,23 +46,6 @@ lsPosition CharPos(std::string_view search, return result; } -ParseIncludeLineResult ParseIncludeLine(const std::string& line) { - static const std::regex pattern( - "(\\s*)" // [1]: spaces before '#' - "#" // - "(\\s*)" // [2]: spaces after '#' - "([^\\s\"<]*)" // [3]: "include" - "(\\s*)" // [4]: spaces before quote - "([\"<])?" // [5]: the first quote char - "([^\\s\">]*)" // [6]: path of file - "[\">]?" // - "(.*)"); // [7]: suffix after quote char - std::smatch match; - bool ok = std::regex_match(line, match, pattern); - std::string text = match[3].str() + match[6].str(); - return {ok, text, match}; -} - // TODO: eliminate |line_number| param. optional ExtractQuotedRange(int line_number, const std::string& line) { // Find starting and ending quote. diff --git a/src/lex_utils.h b/src/lex_utils.h index 09192763..f95035e6 100644 --- a/src/lex_utils.h +++ b/src/lex_utils.h @@ -1,10 +1,9 @@ #pragma once -#include "language_server_api.h" +#include "lsp.h" #include -#include #include #include @@ -15,14 +14,6 @@ lsPosition CharPos(std::string_view search, char character, int character_offset = 0); -struct ParseIncludeLineResult { - bool ok; - std::string text; // include the "include" part - std::smatch match; -}; - -ParseIncludeLineResult ParseIncludeLine(const std::string& line); - // TODO: eliminate |line_number| param. optional ExtractQuotedRange(int line_number, const std::string& line); diff --git a/src/language_server_api.cc b/src/lsp.cc similarity index 99% rename from src/language_server_api.cc rename to src/lsp.cc index f033d474..32bc3844 100644 --- a/src/language_server_api.cc +++ b/src/lsp.cc @@ -1,4 +1,4 @@ -#include "language_server_api.h" +#include "lsp.h" #include "recorder.h" #include "serializers/json.h" diff --git a/src/language_server_api.h b/src/lsp.h similarity index 81% rename from src/language_server_api.h rename to src/lsp.h index 35e60877..fe4330b3 100644 --- a/src/language_server_api.h +++ b/src/lsp.h @@ -292,110 +292,12 @@ struct lsFormattingOptions { }; MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces); -enum class lsDiagnosticSeverity { - // Reports an error. - Error = 1, - // Reports a warning. - Warning = 2, - // Reports an information. - Information = 3, - // Reports a hint. - Hint = 4 -}; -MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity); - -struct lsDiagnostic { - // The range at which the message applies. - lsRange range; - - // The diagnostic's severity. Can be omitted. If omitted it is up to the - // client to interpret diagnostics as error, warning, info or hint. - optional severity; - - // The diagnostic's code. Can be omitted. - int code = 0; - - // A human-readable string describing the source of this - // diagnostic, e.g. 'typescript' or 'super lint'. - std::string source = "cquery"; - - // The diagnostic's message. - std::string message; - - // Non-serialized set of fixits. - std::vector fixits_; -}; -MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message); - -enum class lsErrorCodes { - // Defined by JSON RPC - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - serverErrorStart = -32099, - serverErrorEnd = -32000, - ServerNotInitialized = -32002, - UnknownErrorCode = -32001, - - // Defined by the protocol. - RequestCancelled = -32800, -}; -MAKE_REFLECT_TYPE_PROXY(lsErrorCodes); -struct Out_Error : public lsOutMessage { - struct lsResponseError { - // A number indicating the error type that occurred. - lsErrorCodes code; - - // A string providing a short description of the error. - std::string message; - - // A Primitive or Structured value that contains additional - // information about the error. Can be omitted. - // optional data; - }; - - lsRequestId id; - - // The error object in case a request fails. - lsResponseError error; -}; -MAKE_REFLECT_STRUCT(Out_Error::lsResponseError, code, message); -MAKE_REFLECT_STRUCT(Out_Error, jsonrpc, id, error); - // Cancel an existing request. struct Ipc_CancelRequest : public RequestMessage { static const IpcId kIpcId = IpcId::CancelRequest; }; MAKE_REFLECT_STRUCT(Ipc_CancelRequest, id); -// Diagnostics -struct Out_TextDocumentPublishDiagnostics - : public lsOutMessage { - struct Params { - // The URI for which diagnostic information is reported. - lsDocumentUri uri; - - // An array of diagnostic information items. - std::vector diagnostics; - }; - - Params params; -}; -template -void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) { - std::string method = "textDocument/publishDiagnostics"; - REFLECT_MEMBER_START(); - REFLECT_MEMBER(jsonrpc); - REFLECT_MEMBER2("method", method); - REFLECT_MEMBER(params); - REFLECT_MEMBER_END(); -} -MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params, - uri, - diagnostics); - // MarkedString can be used to render human readable text. It is either a // markdown string or a code-block that provides a language and a code snippet. // The language identifier is sematically equal to the optional language diff --git a/src/language_server_api_completion.h b/src/lsp_completion.h similarity index 99% rename from src/language_server_api_completion.h rename to src/lsp_completion.h index 93aac29a..e06b4bd9 100644 --- a/src/language_server_api_completion.h +++ b/src/lsp_completion.h @@ -1,5 +1,5 @@ #pragma once -#include "language_server_api.h" +#include "lsp.h" // The kind of a completion entry. enum class lsCompletionItemKind { diff --git a/src/lsp_diagnostic.cc b/src/lsp_diagnostic.cc new file mode 100644 index 00000000..6461a3ad --- /dev/null +++ b/src/lsp_diagnostic.cc @@ -0,0 +1,20 @@ +#include "lsp_diagnostic.h" + +#include "queue_manager.h" +#include "working_files.h" + +void EmitDiagnostics(WorkingFiles* working_files, + std::string path, + std::vector diagnostics) { + // Emit diagnostics. + Out_TextDocumentPublishDiagnostics out; + out.params.uri = lsDocumentUri::FromPath(path); + out.params.diagnostics = diagnostics; + QueueManager::WriteStdout(IpcId::TextDocumentPublishDiagnostics, out); + + // Cache diagnostics so we can show fixits. + working_files->DoActionOnFile(path, [&](WorkingFile* working_file) { + if (working_file) + working_file->diagnostics_ = diagnostics; + }); +} diff --git a/src/lsp_diagnostic.h b/src/lsp_diagnostic.h new file mode 100644 index 00000000..a2bd0f40 --- /dev/null +++ b/src/lsp_diagnostic.h @@ -0,0 +1,106 @@ +#pragma once + +#include "lsp.h" + +enum class lsDiagnosticSeverity { + // Reports an error. + Error = 1, + // Reports a warning. + Warning = 2, + // Reports an information. + Information = 3, + // Reports a hint. + Hint = 4 +}; +MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity); + +struct lsDiagnostic { + // The range at which the message applies. + lsRange range; + + // The diagnostic's severity. Can be omitted. If omitted it is up to the + // client to interpret diagnostics as error, warning, info or hint. + optional severity; + + // The diagnostic's code. Can be omitted. + int code = 0; + + // A human-readable string describing the source of this + // diagnostic, e.g. 'typescript' or 'super lint'. + std::string source = "cquery"; + + // The diagnostic's message. + std::string message; + + // Non-serialized set of fixits. + std::vector fixits_; +}; +MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message); + +enum class lsErrorCodes { + // Defined by JSON RPC + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + serverErrorStart = -32099, + serverErrorEnd = -32000, + ServerNotInitialized = -32002, + UnknownErrorCode = -32001, + + // Defined by the protocol. + RequestCancelled = -32800, +}; +MAKE_REFLECT_TYPE_PROXY(lsErrorCodes); +struct Out_Error : public lsOutMessage { + struct lsResponseError { + // A number indicating the error type that occurred. + lsErrorCodes code; + + // A string providing a short description of the error. + std::string message; + + // A Primitive or Structured value that contains additional + // information about the error. Can be omitted. + // optional data; + }; + + lsRequestId id; + + // The error object in case a request fails. + lsResponseError error; +}; +MAKE_REFLECT_STRUCT(Out_Error::lsResponseError, code, message); +MAKE_REFLECT_STRUCT(Out_Error, jsonrpc, id, error); + +// Diagnostics +struct Out_TextDocumentPublishDiagnostics + : public lsOutMessage { + struct Params { + // The URI for which diagnostic information is reported. + lsDocumentUri uri; + + // An array of diagnostic information items. + std::vector diagnostics; + }; + + Params params; +}; +template +void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) { + std::string method = "textDocument/publishDiagnostics"; + REFLECT_MEMBER_START(); + REFLECT_MEMBER(jsonrpc); + REFLECT_MEMBER2("method", method); + REFLECT_MEMBER(params); + REFLECT_MEMBER_END(); +} +MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params, + uri, + diagnostics); + +struct WorkingFiles; +void EmitDiagnostics(WorkingFiles* working_files, + std::string path, + std::vector diagnostics); diff --git a/src/match.cc b/src/match.cc index 7afae12e..bec67dcf 100644 --- a/src/match.cc +++ b/src/match.cc @@ -1,6 +1,6 @@ #include "match.h" -#include "language_server_api.h" +#include "lsp.h" #include "queue_manager.h" #include diff --git a/src/message_handler.h b/src/message_handler.h index eafa3262..c81c5835 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -1,7 +1,7 @@ #pragma once #include "ipc.h" -#include "language_server_api.h" +#include "lsp.h" #include "query.h" #include diff --git a/src/messages/cquery_random.cc b/src/messages/cquery_random.cc index 23bdeae2..510088c0 100644 --- a/src/messages/cquery_random.cc +++ b/src/messages/cquery_random.cc @@ -128,7 +128,7 @@ struct CqueryRandomHandler : BaseMessageHandler { for (int i = 0; i < n; i++) { sum += x[i]; if (sum >= roulette) { - Maybe use = GetDefinitionExtentOfSymbol(db, syms[i]); + Maybe use = GetDefinitionExtent(db, syms[i]); if (!use) continue; if (auto ls_loc = GetLsLocationEx(db, working_files, *use, diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 718c0341..8c3435ef 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -498,7 +498,7 @@ struct InitializeHandler : BaseMessageHandler { Reflect(json_reader, *config); } catch (std::invalid_argument&) { // This will not trigger because parse error is handled in - // MessageRegistry::Parse in language_server_api.cc + // MessageRegistry::Parse in lsp.cc } } diff --git a/src/messages/text_document_code_lens.cc b/src/messages/text_document_code_lens.cc index a6aefa88..dfff5d16 100644 --- a/src/messages/text_document_code_lens.cc +++ b/src/messages/text_document_code_lens.cc @@ -177,7 +177,7 @@ struct TextDocumentCodeLensHandler // extent since that is better for outline. This tries to convert the // extent location to the spelling location. auto try_ensure_spelling = [&](Use use) { - Maybe def = GetDefinitionSpellingOfSymbol(db, use); + Maybe def = GetDefinitionSpell(db, use); if (!def || def->range.start.line != use.range.start.line) { return use; } @@ -214,7 +214,7 @@ struct TextDocumentCodeLensHandler // "Base" if (def->base.size() == 1) { - Maybe base_loc = GetDefinitionSpellingOfSymbol( + Maybe base_loc = GetDefinitionSpell( db, SymbolIdx{def->base[0], SymbolKind::Func}); if (base_loc) { optional ls_base = diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index 5a2706ff..267223f3 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -10,6 +10,8 @@ #include +#include + namespace { // How a completion was triggered @@ -106,6 +108,29 @@ void DecorateIncludePaths(const std::smatch& match, } } +struct ParseIncludeLineResult { + bool ok; + std::string text; // include the "include" part + std::smatch match; +}; + +ParseIncludeLineResult ParseIncludeLine(const std::string& line) { + static const std::regex pattern( + "(\\s*)" // [1]: spaces before '#' + "#" // + "(\\s*)" // [2]: spaces after '#' + "([^\\s\"<]*)" // [3]: "include" + "(\\s*)" // [4]: spaces before quote + "([\"<])?" // [5]: the first quote char + "([^\\s\">]*)" // [6]: path of file + "[\">]?" // + "(.*)"); // [7]: suffix after quote char + std::smatch match; + bool ok = std::regex_match(line, match, pattern); + std::string text = match[3].str() + match[6].str(); + return {ok, text, match}; +} + template char* tofixedbase64(T input, char* out) { const char* digits = diff --git a/src/messages/text_document_definition.cc b/src/messages/text_document_definition.cc index 825a0c77..62f36585 100644 --- a/src/messages/text_document_definition.cc +++ b/src/messages/text_document_definition.cc @@ -24,7 +24,7 @@ struct Out_TextDocumentDefinition }; MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result); -std::vector GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) { +std::vector GetNonDefDeclarationTargets(QueryDatabase* db, SymbolRef sym) { switch (sym.kind) { case SymbolKind::Var: { std::vector ret = GetNonDefDeclarations(db, sym); @@ -32,7 +32,7 @@ std::vector GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) { if (ret.empty()) { for (auto& def : db->GetVar(sym).def) if (def.type) { - if (Maybe use = GetDefinitionSpellingOfSymbol( + if (Maybe use = GetDefinitionSpell( db, SymbolIdx{*def.type, SymbolKind::Type})) { ret.push_back(*use); break; @@ -99,7 +99,7 @@ struct TextDocumentDefinitionHandler if (uses.empty()) { // The symbol has no definition or the cursor is on a definition. - uses = GetGotoDefinitionTargets(db, sym); + uses = GetNonDefDeclarationTargets(db, sym); // There is no declaration but the cursor is on a definition. if (uses.empty() && on_def) uses.push_back(*on_def); @@ -143,7 +143,7 @@ struct TextDocumentDefinitionHandler auto pos = name.find(query); if (pos == std::string::npos) continue; - Maybe use = GetDefinitionSpellingOfSymbol(db, db->symbols[i]); + Maybe use = GetDefinitionSpell(db, db->symbols[i]); if (!use) continue; @@ -157,7 +157,7 @@ struct TextDocumentDefinitionHandler } if (best_i != -1) { Maybe use = - GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]); + GetDefinitionSpell(db, db->symbols[best_i]); assert(use); if (auto ls_loc = GetLsLocationEx(db, working_files, *use, config->xref.container)) diff --git a/src/messages/workspace_symbol.cc b/src/messages/workspace_symbol.cc index 2e0ba211..0f66e7c1 100644 --- a/src/messages/workspace_symbol.cc +++ b/src/messages/workspace_symbol.cc @@ -23,7 +23,7 @@ bool InsertSymbolIntoResult(QueryDatabase* db, if (!info) return false; - Maybe location = GetDefinitionExtentOfSymbol(db, symbol); + Maybe location = GetDefinitionExtent(db, symbol); Use loc; if (location) loc = *location; diff --git a/src/query_utils.cc b/src/query_utils.cc index f0ff6a77..506a453e 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -40,13 +40,13 @@ std::vector GetDeclarations(std::vector& entities, } // namespace -Maybe GetDefinitionSpellingOfSymbol(QueryDatabase* db, SymbolIdx sym) { +Maybe GetDefinitionSpell(QueryDatabase* db, SymbolIdx sym) { Maybe ret; EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); }); return ret; } -Maybe GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) { +Maybe GetDefinitionExtent(QueryDatabase* db, SymbolIdx sym) { // Used to jump to file. if (sym.kind == SymbolKind::File) return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind, @@ -383,19 +383,3 @@ std::vector FindSymbolsAtLocation(WorkingFile* working_file, return symbols; } - -void EmitDiagnostics(WorkingFiles* working_files, - std::string path, - std::vector diagnostics) { - // Emit diagnostics. - Out_TextDocumentPublishDiagnostics out; - out.params.uri = lsDocumentUri::FromPath(path); - out.params.diagnostics = diagnostics; - QueueManager::WriteStdout(IpcId::TextDocumentPublishDiagnostics, out); - - // Cache diagnostics so we can show fixits. - working_files->DoActionOnFile(path, [&](WorkingFile* working_file) { - if (working_file) - working_file->diagnostics_ = diagnostics; - }); -} diff --git a/src/query_utils.h b/src/query_utils.h index fc107d87..1aea3256 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -5,8 +5,8 @@ #include -Maybe GetDefinitionSpellingOfSymbol(QueryDatabase* db, SymbolIdx sym); -Maybe GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym); +Maybe GetDefinitionSpell(QueryDatabase* db, SymbolIdx sym); +Maybe GetDefinitionExtent(QueryDatabase* db, SymbolIdx sym); Maybe GetDeclarationFileForSymbol(QueryDatabase* db, SymbolIdx sym); @@ -53,10 +53,6 @@ std::vector FindSymbolsAtLocation(WorkingFile* working_file, QueryFile* file, lsPosition position); -void EmitDiagnostics(WorkingFiles* working_files, - std::string path, - std::vector diagnostics); - template void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) { switch (sym.kind) { diff --git a/src/queue_manager.cc b/src/queue_manager.cc index 27ab052d..60d6e52f 100644 --- a/src/queue_manager.cc +++ b/src/queue_manager.cc @@ -1,7 +1,7 @@ #include "queue_manager.h" #include "cache_manager.h" -#include "language_server_api.h" +#include "lsp.h" #include "query.h" #include diff --git a/src/working_files.h b/src/working_files.h index 84855b9f..60ce3375 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -1,6 +1,6 @@ #pragma once -#include "language_server_api.h" +#include "lsp_diagnostic.h" #include "utils.h" #include