#pragma once #include "serializer.h" #include "utils.h" #include #include #include #include #include #include #include using std::experimental::optional; using std::experimental::nullopt; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////// OUTGOING MESSAGES ///////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// enum class IpcId : int { // Language server specific requests. CancelRequest = 0, Initialize, Initialized, TextDocumentDocumentSymbol, TextDocumentCodeLens, CodeLensResolve, WorkspaceSymbol, // Internal implementation detail. Quit, IsAlive, OpenProject, Cout }; MAKE_ENUM_HASHABLE(IpcId); template void Reflect(TVisitor& visitor, IpcId& value) { int value0 = static_cast(value); Reflect(visitor, value0); value = static_cast(value0); } struct RequestId { optional id0; optional id1; }; void Reflect(Writer& visitor, RequestId& value) { assert(value.id0.has_value() || value.id1.has_value()); if (value.id0) { Reflect(visitor, value.id0.value()); } else { Reflect(visitor, value.id1.value()); } } void Reflect(Reader& visitor, RequestId& id) { if (visitor.IsInt()) Reflect(visitor, id.id0); else if (visitor.IsString()) Reflect(visitor, id.id1); else std::cerr << "Unable to deserialize id" << std::endl; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////// INCOMING MESSAGES ///////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// const char* MethodIdToString(IpcId id) { switch (id) { case IpcId::CancelRequest: return "$/cancelRequest"; case IpcId::Initialize: return "initialize"; case IpcId::Initialized: return "initialized"; case IpcId::TextDocumentDocumentSymbol: return "textDocument/documentSymbol"; case IpcId::TextDocumentCodeLens: return "textDocument/codeLens"; case IpcId::CodeLensResolve: return "codeLens/resolve"; case IpcId::WorkspaceSymbol: return "workspace/symbol"; default: assert(false); exit(1); } } struct BaseIpcMessage; struct MessageRegistry { static MessageRegistry* instance_; static MessageRegistry* instance(); using Allocator = std::function(Reader& visitor)>; std::unordered_map allocators; template void Register() { std::string method_name = MethodIdToString(T::kIpcId); allocators[method_name] = [](Reader& visitor) { auto result = MakeUnique(); Reflect(visitor, *result); return result; }; } std::unique_ptr ReadMessageFromStdin() { int content_length = -1; int iteration = 0; while (true) { if (++iteration > 10) { assert(false && "bad parser state"); exit(1); } std::string line; std::getline(std::cin, line); // std::cin >> line; if (line.compare(0, 14, "Content-Length") == 0) { content_length = atoi(line.c_str() + 16); } if (line == "\r") break; } // bad input that is not a message. if (content_length < 0) { std::cerr << "parsing command failed (no Content-Length header)" << std::endl; return nullptr; } std::string content; content.reserve(content_length); for (int i = 0; i < content_length; ++i) { char c; std::cin >> c; content += c; } rapidjson::Document document; document.Parse(content.c_str(), content_length); assert(!document.HasParseError()); return Parse(document); } std::unique_ptr Parse(Reader& visitor) { std::string jsonrpc = visitor["jsonrpc"].GetString(); if (jsonrpc != "2.0") exit(1); std::string method; ReflectMember(visitor, "method", method); if (allocators.find(method) == allocators.end()) { std::cerr << "Unable to find registered handler for method \"" << method << "\"" << std::endl; return nullptr; } Allocator& allocator = allocators[method]; return allocator(visitor); } }; MessageRegistry* MessageRegistry::instance_ = nullptr; MessageRegistry* MessageRegistry::instance() { if (!instance_) instance_ = new MessageRegistry(); return instance_; } struct BaseIpcMessage { const IpcId method_id; BaseIpcMessage(IpcId method_id) : method_id(method_id) {} }; template struct IpcMessage : public BaseIpcMessage { IpcMessage() : BaseIpcMessage(T::kIpcId) {} }; template struct lsOutMessage { // All derived types need to reflect on the |jsonrpc| member. std::string jsonrpc = "2.0"; // Send the message to the language client by writing it to stdout. void Write(std::ostream& out) { rapidjson::StringBuffer output; Writer writer(output); auto that = static_cast(this); Reflect(writer, *that); out << "Content-Length: " << output.GetSize(); out << (char)13 << char(10) << char(13) << char(10); // CRLFCRLF out << output.GetString(); out.flush(); } }; struct lsResponseError { struct Data { virtual void Write(Writer& writer) = 0; }; enum class lsErrorCodes : int { ParseError = -32700, InvalidRequest = -32600, MethodNotFound = -32601, InvalidParams = -32602, InternalError = -32603, serverErrorStart = -32099, serverErrorEnd = -32000, ServerNotInitialized = -32002, UnknownErrorCode = -32001 }; lsErrorCodes code; // Short description. std::string message; std::unique_ptr data; void Write(Writer& visitor) { auto& value = *this; int code = static_cast(this->code); visitor.StartObject(); REFLECT_MEMBER2("code", code); REFLECT_MEMBER(message); if (data) { visitor.Key("data"); data->Write(visitor); } visitor.EndObject(); } }; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ////////////////////////////// PRIMITIVE TYPES ////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// struct lsDocumentUri { std::string raw_uri; lsDocumentUri() {} static lsDocumentUri FromPath(const std::string& path) { lsDocumentUri result; result.SetPath(path); return result; } bool operator==(const lsDocumentUri& other) const { return raw_uri == other.raw_uri; } void SetPath(const std::string& path) { // file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests raw_uri = path; size_t index = raw_uri.find(":"); if (index != -1) { raw_uri.replace(raw_uri.begin() + index, raw_uri.begin() + index + 1, "%3A"); } raw_uri = "file:///" + raw_uri; //std::cerr << "Set uri to " << raw_uri << " from " << path; } std::string GetPath() { // TODO: make this not a hack. std::string result = raw_uri; size_t index = result.find("%3A"); if (index != -1) { result.replace(result.begin() + index, result.begin() + index + 3, ":"); } index = result.find("file://"); if (index != -1) { result.replace(result.begin() + index, result.begin() + index + 8, ""); } std::replace(result.begin(), result.end(), '\\', '/'); return result; } }; MAKE_HASHABLE(lsDocumentUri, t.raw_uri); template void Reflect(TVisitor& visitor, lsDocumentUri& value) { Reflect(visitor, value.raw_uri); } struct lsPosition { // Note: these are 0-based. int line = 0; int character = 0; lsPosition() {} lsPosition(int line, int character) : line(line), character(character) {} bool operator==(const lsPosition& other) const { return line == other.line && character == other.character; } }; MAKE_HASHABLE(lsPosition, t.line, t.character); template void Reflect(TVisitor& visitor, lsPosition& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(line); REFLECT_MEMBER(character); REFLECT_MEMBER_END(); } struct lsRange { lsPosition start; lsPosition end; lsRange() {} lsRange(lsPosition position) : start(position), end(position) {} bool operator==(const lsRange& other) const { return start == other.start && end == other.end; } }; MAKE_HASHABLE(lsRange, t.start, t.end); template void Reflect(TVisitor& visitor, lsRange& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(start); REFLECT_MEMBER(end); REFLECT_MEMBER_END(); } struct lsLocation { lsDocumentUri uri; lsRange range; lsLocation() {} lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {} bool operator==(const lsLocation& other) const { return uri == other.uri && range == other.range; } }; MAKE_HASHABLE(lsLocation, t.uri, t.range); template void Reflect(TVisitor& visitor, lsLocation& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(uri); REFLECT_MEMBER(range); REFLECT_MEMBER_END(); } enum class lsSymbolKind : int { File = 1, Module = 2, Namespace = 3, Package = 4, Class = 5, Method = 6, Property = 7, Field = 8, Constructor = 9, Enum = 10, Interface = 11, Function = 12, Variable = 13, Constant = 14, String = 15, Number = 16, Boolean = 17, Array = 18 }; void Reflect(Writer& writer, lsSymbolKind& value) { writer.Int(static_cast(value)); } void Reflect(Reader& reader, lsSymbolKind& value) { value = static_cast(reader.GetInt()); } struct lsSymbolInformation { std::string name; lsSymbolKind kind; lsLocation location; std::string containerName; }; template void Reflect(TVisitor& visitor, lsSymbolInformation& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(name); REFLECT_MEMBER(kind); REFLECT_MEMBER(location); REFLECT_MEMBER(containerName); REFLECT_MEMBER_END(); } template struct lsCommand { // Title of the command (ie, 'save') std::string title; // Actual command identifier. std::string command; // Arguments to run the command with. T arguments; }; template void Reflect(TVisitor& visitor, lsCommand& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(title); REFLECT_MEMBER(command); REFLECT_MEMBER(arguments); REFLECT_MEMBER_END(); } template struct lsCodeLens { // The range in which this code lens is valid. Should only span a single line. lsRange range; // The command this code lens represents. optional> command; // A data entry field that is preserved on a code lens item between // a code lens and a code lens resolve request. TData data; }; template void Reflect(TVisitor& visitor, lsCodeLens& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(range); REFLECT_MEMBER(command); REFLECT_MEMBER(data); REFLECT_MEMBER_END(); } // TODO: TextDocumentEdit // TODO: WorkspaceEdit struct lsTextDocumentIdentifier { lsDocumentUri uri; }; template void Reflect(TVisitor& visitor, lsTextDocumentIdentifier& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(uri); REFLECT_MEMBER_END(); } // TODO: TextDocumentItem // TODO: VersionedTextDocumentIdentifier // TODO: TextDocumentPositionParams // TODO: DocumentFilter // TODO: DocumentSelector ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ////////////////////////////// INITIALIZATION /////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Workspace specific client capabilities. struct lsWorkspaceClientCapabilites { // The client supports applying batch edits to the workspace. optional applyEdit; struct lsWorkspaceEdit { // The client supports versioned document changes in `WorkspaceEdit`s optional documentChanges; }; // Capabilities specific to `WorkspaceEdit`s optional workspaceEdit; struct lsGenericDynamicReg { // Did foo notification supports dynamic registration. optional dynamicRegistration; }; // Capabilities specific to the `workspace/didChangeConfiguration` notification. optional didChangeConfiguration; // Capabilities specific to the `workspace/didChangeWatchedFiles` notification. optional didChangeWatchedFiles; // Capabilities specific to the `workspace/symbol` request. optional symbol; // Capabilities specific to the `workspace/executeCommand` request. optional executeCommand; }; template void Reflect(TVisitor& visitor, lsWorkspaceClientCapabilites::lsWorkspaceEdit& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(documentChanges); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsWorkspaceClientCapabilites::lsGenericDynamicReg& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(dynamicRegistration); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsWorkspaceClientCapabilites& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(applyEdit); REFLECT_MEMBER(workspaceEdit); REFLECT_MEMBER(didChangeConfiguration); REFLECT_MEMBER(didChangeWatchedFiles); REFLECT_MEMBER(symbol); REFLECT_MEMBER(executeCommand); REFLECT_MEMBER_END(); } // Text document specific client capabilities. struct lsTextDocumentClientCapabilities { struct lsSynchronization { // Whether text document synchronization supports dynamic registration. optional dynamicRegistration; // The client supports sending will save notifications. optional willSave; // The client supports sending a will save request and // waits for a response providing text edits which will // be applied to the document before it is saved. optional willSaveWaitUntil; // The client supports did save notifications. optional didSave; }; lsSynchronization synchronization; struct lsCompletion { // Whether completion supports dynamic registration. optional dynamicRegistration; struct lsCompletionItem { // Client supports snippets as insert text. // // A snippet can define tab stops and placeholders with `$1`, `$2` // and `${3:foo}`. `$0` defines the final tab stop, it defaults to // the end of the snippet. Placeholders with equal identifiers are linked, // that is typing in one will update others too. optional snippetSupport; }; // The client supports the following `CompletionItem` specific // capabilities. optional completionItem; }; // Capabilities specific to the `textDocument/completion` optional completion; struct lsGenericDynamicReg { // Whether foo supports dynamic registration. optional dynamicRegistration; }; // Capabilities specific to the `textDocument/hover` optional hover; // Capabilities specific to the `textDocument/signatureHelp` optional signatureHelp; // Capabilities specific to the `textDocument/references` optional references; // Capabilities specific to the `textDocument/documentHighlight` optional documentHighlight; // Capabilities specific to the `textDocument/documentSymbol` optional documentSymbol; // Capabilities specific to the `textDocument/formatting` optional formatting; // Capabilities specific to the `textDocument/rangeFormatting` optional rangeFormatting; // Capabilities specific to the `textDocument/onTypeFormatting` optional onTypeFormatting; // Capabilities specific to the `textDocument/definition` optional definition; // Capabilities specific to the `textDocument/codeAction` optional codeAction; struct CodeLensRegistrationOptions : public lsGenericDynamicReg { // Code lens has a resolve provider as well. bool resolveProvider; }; // Capabilities specific to the `textDocument/codeLens` optional codeLens; // Capabilities specific to the `textDocument/documentLink` optional documentLink; // Capabilities specific to the `textDocument/rename` optional rename; }; template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsSynchronization& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(dynamicRegistration); REFLECT_MEMBER(willSave); REFLECT_MEMBER(willSaveWaitUntil); REFLECT_MEMBER(didSave); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsCompletion& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(dynamicRegistration); REFLECT_MEMBER(completionItem); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(snippetSupport); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::lsGenericDynamicReg& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(dynamicRegistration); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities::CodeLensRegistrationOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(dynamicRegistration); REFLECT_MEMBER(resolveProvider); REFLECT_MEMBER_END(); } template void Reflect(TVisitor& visitor, lsTextDocumentClientCapabilities& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(synchronization); REFLECT_MEMBER(completion); REFLECT_MEMBER(hover); REFLECT_MEMBER(signatureHelp); REFLECT_MEMBER(references); REFLECT_MEMBER(documentHighlight); REFLECT_MEMBER(documentSymbol); REFLECT_MEMBER(formatting); REFLECT_MEMBER(rangeFormatting); REFLECT_MEMBER(onTypeFormatting); REFLECT_MEMBER(definition); REFLECT_MEMBER(codeAction); REFLECT_MEMBER(codeLens); REFLECT_MEMBER(documentLink); REFLECT_MEMBER(rename); REFLECT_MEMBER_END(); } struct lsClientCapabilities { // Workspace specific client capabilities. optional workspace; // Text document specific client capabilities. optional textDocument; /** * Experimental client capabilities. */ // experimental?: any; // TODO }; template void Reflect(TVisitor& visitor, lsClientCapabilities& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(workspace); REFLECT_MEMBER(textDocument); REFLECT_MEMBER_END(); } struct lsInitializeParams { // The process Id of the parent process that started // the server. Is null if the process has not been started by another process. // If the parent process is not alive then the server should exit (see exit notification) its process. optional processId; // The rootPath of the workspace. Is null // if no folder is open. // // @deprecated in favour of rootUri. optional rootPath; // The rootUri of the workspace. Is null if no // folder is open. If both `rootPath` and `rootUri` are set // `rootUri` wins. optional rootUri; // User provided initialization options. // initializationOptions?: any; // TODO // The capabilities provided by the client (editor or tool) lsClientCapabilities capabilities; enum class lsTrace { // NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose'; Off, // off Messages, // messages Verbose // verbose }; // The initial trace setting. If omitted trace is disabled ('off'). lsTrace trace = lsTrace::Off; }; void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) { std::string v = reader.GetString(); if (v == "off") value = lsInitializeParams::lsTrace::Off; else if (v == "messages") value = lsInitializeParams::lsTrace::Messages; else if (v == "verbose") value = lsInitializeParams::lsTrace::Verbose; } void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) { switch (value) { case lsInitializeParams::lsTrace::Off: writer.String("off"); break; case lsInitializeParams::lsTrace::Messages: writer.String("messages"); break; case lsInitializeParams::lsTrace::Verbose: writer.String("verbose"); break; } } template void Reflect(TVisitor& visitor, lsInitializeParams& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(processId); REFLECT_MEMBER(rootPath); REFLECT_MEMBER(rootUri); REFLECT_MEMBER(capabilities); REFLECT_MEMBER(trace); REFLECT_MEMBER_END(); } struct lsInitializeError { // Indicates whether the client should retry to send the // initilize request after showing the message provided // in the ResponseError. bool retry; }; template void Reflect(TVisitor& visitor, lsInitializeError& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(retry); REFLECT_MEMBER_END(); } // Defines how the host (editor) should sync document changes to the language server. enum class lsTextDocumentSyncKind { // Documents should not be synced at all. None = 0, // Documents are synced by always sending the full content // of the document. Full = 1, // Documents are synced by sending the full content on open. // After that only incremental updates to the document are // send. Incremental = 2 }; template void Reflect(TVisitor& visitor, lsTextDocumentSyncKind& value) { int value0 = static_cast(value); Reflect(visitor, value0); value = static_cast(value0); } // Completion options. struct lsCompletionOptions { // The server provides support to resolve additional // information for a completion item. bool resolveProvider = false; // The characters that trigger completion automatically. std::vector triggerCharacters; }; template void Reflect(TVisitor& visitor, lsCompletionOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(resolveProvider); REFLECT_MEMBER(triggerCharacters); REFLECT_MEMBER_END(); } // Signature help options. struct lsSignatureHelpOptions { // The characters that trigger signature help automatically. std::vector triggerCharacters; }; template void Reflect(TVisitor& visitor, lsSignatureHelpOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(triggerCharacters); REFLECT_MEMBER_END(); } // Code Lens options. struct lsCodeLensOptions { // Code lens has a resolve provider as well. bool resolveProvider = false; }; template void Reflect(TVisitor& visitor, lsCodeLensOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(resolveProvider); REFLECT_MEMBER_END(); } // Format document on type options struct lsDocumentOnTypeFormattingOptions { // A character on which formatting should be triggered, like `}`. std::string firstTriggerCharacter; // More trigger characters. std::vector moreTriggerCharacter; }; template void Reflect(TVisitor& visitor, lsDocumentOnTypeFormattingOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(firstTriggerCharacter); REFLECT_MEMBER(moreTriggerCharacter); REFLECT_MEMBER_END(); } // Document link options struct lsDocumentLinkOptions { // Document links have a resolve provider as well. bool resolveProvider = false; }; template void Reflect(TVisitor& visitor, lsDocumentLinkOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(resolveProvider); REFLECT_MEMBER_END(); } // Execute command options. struct lsExecuteCommandOptions { // The commands to be executed on the server std::vector commands; }; template void Reflect(TVisitor& visitor, lsExecuteCommandOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(commands); REFLECT_MEMBER_END(); } // Save options. struct lsSaveOptions { // The client is supposed to include the content on save. bool includeText = false; }; template void Reflect(TVisitor& visitor, lsSaveOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(includeText); REFLECT_MEMBER_END(); } struct lsTextDocumentSyncOptions { // Open and close notifications are sent to the server. bool openClose = false; // Change notificatins are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full // and TextDocumentSyncKindIncremental. optional change; // Will save notifications are sent to the server. bool willSave = false; // Will save wait until requests are sent to the server. bool willSaveWaitUntil = false; // Save notifications are sent to the server. optional save; }; template void Reflect(TVisitor& visitor, lsTextDocumentSyncOptions& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(openClose); REFLECT_MEMBER(change); REFLECT_MEMBER(willSave); REFLECT_MEMBER(willSaveWaitUntil); REFLECT_MEMBER(save); REFLECT_MEMBER_END(); } struct lsServerCapabilities { // Defines how text documents are synced. Is either a detailed structure defining each notification or // for backwards compatibility the TextDocumentSyncKind number. optional textDocumentSync; // The server provides hover support. bool hoverProvider = false; // The server provides completion support. optional completionProvider; // The server provides signature help support. optional signatureHelpProvider; // The server provides goto definition support. bool definitionProvider = false; // The server provides find references support. bool referencesProvider = false; // The server provides document highlight support. bool documentHighlightProvider = false; // The server provides document symbol support. bool documentSymbolProvider = false; // The server provides workspace symbol support. bool workspaceSymbolProvider = false; // The server provides code actions. bool codeActionProvider = false; // The server provides code lens. optional codeLensProvider; // The server provides document formatting. bool documentFormattingProvider = false; // The server provides document range formatting. bool documentRangeFormattingProvider = false; // The server provides document formatting on typing. optional documentOnTypeFormattingProvider; // The server provides rename support. bool renameProvider = false; // The server provides document link support. optional documentLinkProvider; // The server provides execute command support. optional executeCommandProvider; }; template void Reflect(TVisitor& visitor, lsServerCapabilities& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(textDocumentSync); REFLECT_MEMBER(hoverProvider); REFLECT_MEMBER(completionProvider); REFLECT_MEMBER(signatureHelpProvider); REFLECT_MEMBER(definitionProvider); REFLECT_MEMBER(referencesProvider); REFLECT_MEMBER(documentHighlightProvider); REFLECT_MEMBER(documentSymbolProvider); REFLECT_MEMBER(workspaceSymbolProvider); REFLECT_MEMBER(codeActionProvider); REFLECT_MEMBER(codeLensProvider); REFLECT_MEMBER(documentFormattingProvider); REFLECT_MEMBER(documentRangeFormattingProvider); REFLECT_MEMBER(documentOnTypeFormattingProvider); REFLECT_MEMBER(renameProvider); REFLECT_MEMBER(documentLinkProvider); REFLECT_MEMBER(executeCommandProvider); REFLECT_MEMBER_END(); } struct lsInitializeResult { // The capabilities the language server provides. lsServerCapabilities capabilities; }; template void Reflect(TVisitor& visitor, lsInitializeResult& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(capabilities); REFLECT_MEMBER_END(); } struct Ipc_InitializeRequest : public IpcMessage { const static IpcId kIpcId = IpcId::Initialize; RequestId id; lsInitializeParams params; }; template void Reflect(TVisitor& visitor, Ipc_InitializeRequest& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } struct Out_InitializeResponse : public lsOutMessage { RequestId id; lsInitializeResult result; }; template void Reflect(TVisitor& visitor, Out_InitializeResponse& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER(id); REFLECT_MEMBER(result); REFLECT_MEMBER_END(); } struct Ipc_InitializedNotification : public IpcMessage { const static IpcId kIpcId = IpcId::Initialized; RequestId id; }; template void Reflect(TVisitor& visitor, Ipc_InitializedNotification& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER_END(); } // Cancel an existing request. struct Ipc_CancelRequest : public IpcMessage { static const IpcId kIpcId = IpcId::CancelRequest; RequestId id; }; template void Reflect(TVisitor& visitor, Ipc_CancelRequest& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER_END(); } // List symbols in a document. struct lsDocumentSymbolParams { lsTextDocumentIdentifier textDocument; }; template void Reflect(TVisitor& visitor, lsDocumentSymbolParams& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(textDocument); REFLECT_MEMBER_END(); } struct Ipc_TextDocumentDocumentSymbol : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentDocumentSymbol; RequestId id; lsDocumentSymbolParams params; }; template void Reflect(TVisitor& visitor, Ipc_TextDocumentDocumentSymbol& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } struct Out_TextDocumentDocumentSymbol : public lsOutMessage { RequestId id; std::vector result; }; template void Reflect(TVisitor& visitor, Out_TextDocumentDocumentSymbol& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER(id); REFLECT_MEMBER(result); REFLECT_MEMBER_END(); } // List code lens in a document. struct lsDocumentCodeLensParams { lsTextDocumentIdentifier textDocument; }; template void Reflect(TVisitor& visitor, lsDocumentCodeLensParams& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(textDocument); REFLECT_MEMBER_END(); } struct lsCodeLensUserData {}; template void Reflect(TVisitor& visitor, lsCodeLensUserData& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER_END(); } struct lsCodeLensCommandArguments { lsDocumentUri uri; lsPosition position; std::vector locations; }; void Reflect(Writer& visitor, lsCodeLensCommandArguments& value) { visitor.StartArray(); Reflect(visitor, value.uri); Reflect(visitor, value.position); Reflect(visitor, value.locations); visitor.EndArray(); } void Reflect(Reader& visitor, lsCodeLensCommandArguments& value) { auto it = visitor.Begin(); Reflect(*it, value.uri); ++it; Reflect(*it, value.position); ++it; Reflect(*it, value.locations); } using TCodeLens = lsCodeLens; struct Ipc_TextDocumentCodeLens : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentCodeLens; RequestId id; lsDocumentCodeLensParams params; }; template void Reflect(TVisitor& visitor, Ipc_TextDocumentCodeLens& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } struct Out_TextDocumentCodeLens : public lsOutMessage { RequestId id; std::vector> result; }; template void Reflect(TVisitor& visitor, Out_TextDocumentCodeLens& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER(id); REFLECT_MEMBER(result); REFLECT_MEMBER_END(); } struct Ipc_CodeLensResolve : public IpcMessage { const static IpcId kIpcId = IpcId::CodeLensResolve; RequestId id; TCodeLens params; }; template void Reflect(TVisitor& visitor, Ipc_CodeLensResolve& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } struct Out_CodeLensResolve : public lsOutMessage { RequestId id; TCodeLens result; }; template void Reflect(TVisitor& visitor, Out_CodeLensResolve& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER(id); REFLECT_MEMBER(result); REFLECT_MEMBER_END(); } // Search for symbols in the workspace. struct lsWorkspaceSymbolParams { std::string query; }; template void Reflect(TVisitor& visitor, lsWorkspaceSymbolParams& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(query); REFLECT_MEMBER_END(); } struct Ipc_WorkspaceSymbol : public IpcMessage { const static IpcId kIpcId = IpcId::WorkspaceSymbol; RequestId id; lsWorkspaceSymbolParams params; }; template void Reflect(TVisitor& visitor, Ipc_WorkspaceSymbol& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } struct Out_WorkspaceSymbol : public lsOutMessage { RequestId id; std::vector result; }; template void Reflect(TVisitor& visitor, Out_WorkspaceSymbol& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER(id); REFLECT_MEMBER(result); REFLECT_MEMBER_END(); } // Show a message to the user. enum class lsMessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 }; template void Reflect(TWriter& writer, lsMessageType& value) { int value0 = static_cast(value); Reflect(writer, value0); value = static_cast(value0); } struct Out_ShowLogMessageParams { lsMessageType type = lsMessageType::Error; std::string message; }; template void Reflect(TVisitor& visitor, Out_ShowLogMessageParams& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(type); REFLECT_MEMBER(message); REFLECT_MEMBER_END(); } struct Out_ShowLogMessage : public lsOutMessage { enum class DisplayType { Show, Log }; DisplayType display_type = DisplayType::Show; std::string method() { if (display_type == DisplayType::Log) return "window/logMessage"; return "window/showMessage"; } Out_ShowLogMessageParams params; }; template void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); REFLECT_MEMBER2("method", value.method()); REFLECT_MEMBER(params); REFLECT_MEMBER_END(); }