From 18937b4175d598878f9b1457040b66fa830f9d92 Mon Sep 17 00:00:00 2001 From: ykiko Date: Tue, 3 Sep 2024 20:14:47 +0800 Subject: [PATCH] update Protocol. --- include/Protocol/Basic.h | 187 +++++ include/Protocol/Document/DidChange.h | 0 include/Protocol/Document/DidClose.h | 0 include/Protocol/Document/DidOpen.h | 0 include/Protocol/Document/DidSave.h | 0 include/Protocol/Language/CallHierarchy.h | 92 +++ include/Protocol/Language/CodeAction.h | 1 + include/Protocol/Language/CodeLens.h | 38 + include/Protocol/Language/Completion.h | 1 + include/Protocol/Language/Declaration.h | 32 + include/Protocol/Language/Definition.h | 31 + include/Protocol/Language/DocumentColor.h | 1 + include/Protocol/Language/DocumentHighlight.h | 48 ++ include/Protocol/Language/DocumentLink.h | 52 ++ include/Protocol/Language/DocumentSymbol.h | 72 ++ include/Protocol/Language/FoldingRange.h | 1 + include/Protocol/Language/Formatting.h | 1 + include/Protocol/Language/Hover.h | 41 + include/Protocol/Language/Implementation.h | 31 + include/Protocol/Language/InlayHint.h | 1 + include/Protocol/Language/InlineValue.h | 1 + include/Protocol/Language/OnTypeFormatting.h | 1 + include/Protocol/Language/RangeFormatting.h | 1 + include/Protocol/Language/Reference.h | 37 + include/Protocol/Language/Rename.h | 1 + include/Protocol/Language/SelectionRange.h | 1 + include/Protocol/Language/SemanticToken.h | 195 +++++ include/Protocol/Language/SignatureHelp.h | 1 + include/Protocol/Language/TypeDefinition.h | 31 + include/Protocol/Language/TypeHierarchy.h | 63 ++ include/Protocol/Lifecycle/Exit.h | 0 include/Protocol/Lifecycle/Initialize.h | 0 include/Protocol/Lifecycle/Initialized.h | 0 include/Protocol/Lifecycle/Shutdown.h | 0 include/Protocol/Message.h | 73 ++ include/Protocol/Protocol.h | 709 ++++++++++++++++++ include/Protocol/README.md | 93 +++ tests/test.cpp | 1 + 38 files changed, 1838 insertions(+) create mode 100644 include/Protocol/Basic.h create mode 100644 include/Protocol/Document/DidChange.h create mode 100644 include/Protocol/Document/DidClose.h create mode 100644 include/Protocol/Document/DidOpen.h create mode 100644 include/Protocol/Document/DidSave.h create mode 100644 include/Protocol/Language/CallHierarchy.h create mode 100644 include/Protocol/Language/CodeAction.h create mode 100644 include/Protocol/Language/CodeLens.h create mode 100644 include/Protocol/Language/Completion.h create mode 100644 include/Protocol/Language/Declaration.h create mode 100644 include/Protocol/Language/Definition.h create mode 100644 include/Protocol/Language/DocumentColor.h create mode 100644 include/Protocol/Language/DocumentHighlight.h create mode 100644 include/Protocol/Language/DocumentLink.h create mode 100644 include/Protocol/Language/DocumentSymbol.h create mode 100644 include/Protocol/Language/FoldingRange.h create mode 100644 include/Protocol/Language/Formatting.h create mode 100644 include/Protocol/Language/Hover.h create mode 100644 include/Protocol/Language/Implementation.h create mode 100644 include/Protocol/Language/InlayHint.h create mode 100644 include/Protocol/Language/InlineValue.h create mode 100644 include/Protocol/Language/OnTypeFormatting.h create mode 100644 include/Protocol/Language/RangeFormatting.h create mode 100644 include/Protocol/Language/Reference.h create mode 100644 include/Protocol/Language/Rename.h create mode 100644 include/Protocol/Language/SelectionRange.h create mode 100644 include/Protocol/Language/SemanticToken.h create mode 100644 include/Protocol/Language/SignatureHelp.h create mode 100644 include/Protocol/Language/TypeDefinition.h create mode 100644 include/Protocol/Language/TypeHierarchy.h create mode 100644 include/Protocol/Lifecycle/Exit.h create mode 100644 include/Protocol/Lifecycle/Initialize.h create mode 100644 include/Protocol/Lifecycle/Initialized.h create mode 100644 include/Protocol/Lifecycle/Shutdown.h create mode 100644 include/Protocol/Message.h create mode 100644 include/Protocol/Protocol.h create mode 100644 include/Protocol/README.md diff --git a/include/Protocol/Basic.h b/include/Protocol/Basic.h new file mode 100644 index 00000000..eb3afef1 --- /dev/null +++ b/include/Protocol/Basic.h @@ -0,0 +1,187 @@ +#pragma once + +#include +#include +#include +#include + +namespace clice::protocol { + +using Integer = int; +using UInteger = unsigned int; +using String = std::string; +using StringRef = std::string_view; + +template +struct Combine : Ts... {}; + +class URI { +private: + String scheme; + String authority; + String body; + +public: +}; + +using DocumentUri = String; + +/// Position in a text document expressed as zero-based line and zero-based character offset. +struct Position { + /// line position in a document (zero-based). + UInteger line; + + /// character offset on a line in a document (zero-based). + /// The meaning of this offset is determined by the negotiated `PositionEncodingKind`. + UInteger character; +}; + +/// A range in a text document expressed as (zero-based) start and end positions. +struct Range { + /// The range's start position. + Position start; + + /// The range's end position. + Position end; +}; + +/// An item to transfer a text document from the client to the server. +struct TextDocumentItem { + /// The text document's URI. + DocumentUri uri; + + /// The text document's language identifier. + String languageId; + + /// The version number of this document (it will strictly increase after each change, including + /// undo/redo). + Integer version; + + /// The content of the opened text document. + String text; +}; + +/// Text documents are identified using a URI. +struct TextDocumentIdentifier { + /// The text document's URI. + DocumentUri uri; +}; + +/// A parameter literal used in requests to pass a text document and a position inside that document. +struct TextDocumentPositionParams { + /// The text document. + TextDocumentIdentifier textDocument; + + /// The position inside the text document. + Position position; +}; + +/// A textual edit applicable to a text document. +struct TextEdit { + /// The range of the text document to be manipulated. To insert text into a document create a + /// range where start === end. + Range range; + + /// The string to be inserted. For delete operations use an empty string. + String newText; +}; + +/// Represents a location inside a resource, such as a line inside a text file. +struct Location { + URI uri; + Range range; +}; + +/// Represents a link between a source and a target location. +struct LocationLink { + /// Span of the origin of this link. + Range originSelectionRange; + + /// The target resource identifier of this link. + URI targetUri; + + /// The full target range of this link. If the target for example is a symbol then target range is the + /// range enclosing this symbol not including leading/trailing whitespace but everything else + /// like comments. This information is typically used to highlight the range in the editor. + Range targetRange; + + /// The range that should be selected and revealed when this link is being followed, e.g the name of a + /// function. Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + Range targetSelectionRange; +}; + +/// Represents a diagnostic, such as a compiler error or warning. +/// Diagnostic objects are only valid in the scope of a resource. +struct Diagnostic { + + /// Represents a related message and source code location for a diagnostic. + /// This should be used to point to code locations that cause or are related to + /// a diagnostics, e.g when duplicating a symbol in a scope. + struct DiagnosticRelatedInformation { + /// The location of this related diagnostic information. + Location location; + + /// The message of this related diagnostic information. + String message; + }; + + /// Structure to capture a description for an error code. + struct CodeDescription { + /// An URI where the code is described. + URI href; + }; + + /// The range at which the message applies. + Range 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. + Integer severity; + + /// The diagnostic's code. Can be omitted. + Integer code; + + /// A human-readable string describing the source of this diagnostic, e.g. 'typescript' or 'super lint'. + String source; + + /// The diagnostic's message. + String message; + + /// An array of related diagnostic information, e.g. when symbol-names within a scope collide all + /// definitions can be marked via this property. + // TODO: std::vector relatedInformation; +}; + +/// Represents a reference to a command. +struct Command { + /// Title of the command, like `save`. + String title; + + /// The identifier of the actual command handler. + String command; + + /// Arguments that the command handler should be invoked with. + /// arguments?: LSPAny[]; +}; + +struct MarkupKind { + StringRef m_Value; + + MarkupKind(StringRef value) : m_Value(value) {} + + /// Plain text is supported as a content format + constexpr inline static StringRef PlainText = "plaintext"; + + /// Markdown is supported as a content format + constexpr inline static StringRef Markdown = "markdown"; +}; + +struct MarkupContent { + /// The type of the Markup + MarkupKind kind; + + /// The content itself + String value; +}; + +} // namespace clice::protocol diff --git a/include/Protocol/Document/DidChange.h b/include/Protocol/Document/DidChange.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Document/DidClose.h b/include/Protocol/Document/DidClose.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Document/DidOpen.h b/include/Protocol/Document/DidOpen.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Document/DidSave.h b/include/Protocol/Document/DidSave.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Language/CallHierarchy.h b/include/Protocol/Language/CallHierarchy.h new file mode 100644 index 00000000..7927dce7 --- /dev/null +++ b/include/Protocol/Language/CallHierarchy.h @@ -0,0 +1,92 @@ +#pragma once + +#include "DocumentSymbol.h" + +namespace clice::protocol { + +/*=========================================================================/ +/ / +/============================= CallHierarchy ==============================/ +/ / +/=========================================================================*/ + +struct CallHierarchyItem { + /// The name of this item. + String name; + + /// The kind of this item. + SymbolKind kind; + + /// Tags for this item. + std::vector tags; + + /// More detail for this item, e.g. the signature of a function. + std::string detail; + + /// The resource identifier of this item. + URI uri; + + /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. + /// comments and code. + Range range; + + /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a + /// function. + Range selectionRange; + + /// A data entry field that is preserved between a call hierarchy prepare and incoming calls or outgoing + /// calls requests. std::any data; + /// data?: LSPAny; +}; + +/// Client Capability: +/// - property name (optional): `textDocument.callHierarchy` +/// - property type: `CallHierarchyClientCapabilities` defined as follows: +struct CallHierarchyClientCapabilities { + + /// Whether callHierarchy supports dynamic registration. + bool dynamicRegistration = false; +}; + +/// Request: +/// - method: 'textDocument/prepareCallHierarchy' +/// - params: `PrepareCallHierarchyParams` defined follows: +using CallHierarchyPrepareParams = Combine; + +/// Response: +/// - result: `CallHierarchyItem[]` +using CallHierarchyPrepareResult = std::vector; + +/*=========================================================================/ +/ / +/====================== Call Hierarchy Incoming Calls =====================/ +/ / +/=========================================================================*/ + +struct CallHierarchyIncomingCallsParamsBody { + /// The item for which incoming calls are to be computed. + CallHierarchyItem item; +}; + +/// Request: +/// - method: 'textDocument/callHierarchy/incomingCalls' +/// - params: `CallHierarchyIncomingCallsParams` defined follows: +using CallHierarchyIncomingCallsParams = Combine; + +struct CallHierarchyIncomingCall { + /// The item that was called. + CallHierarchyItem from; + /// The range at which at which the calls were made. + Range fromRanges; +}; + +/// Response: +/// - result: `CallHierarchyIncomingCall[]` +using CallHierarchyIncomingCallsResult = std::vector; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/CodeAction.h b/include/Protocol/Language/CodeAction.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/CodeAction.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/CodeLens.h b/include/Protocol/Language/CodeLens.h new file mode 100644 index 00000000..a02f815b --- /dev/null +++ b/include/Protocol/Language/CodeLens.h @@ -0,0 +1,38 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument/codeLens` +/// - property type: `CodeLensClientCapabilities` defined as follows: +struct CodeLensClientCapabilities { + /// Whether codeLens supports dynamic registration. + bool dynamicRegistration = false; +}; + +struct CodeLensParamsBody { + /// The document to request code lens for. + TextDocumentIdentifier textDocument; +}; + +/// Request: +/// - method: 'textDocument/codeLens' +/// - params: `CodeLensParams` defined follows: +using CodeLensParams = Combine< + // WorkDoneProgressParams, + // PartialResultParams, + CodeLensParamsBody>; + +struct CodeLens { + /// The range in which this code lens is valid. Should only span a single line. + Range range; + + /// The command this code lens represents. + /// TODO: Command command; + + /// data?: LSPAny; +}; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/Completion.h b/include/Protocol/Language/Completion.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/Completion.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/Declaration.h b/include/Protocol/Language/Declaration.h new file mode 100644 index 00000000..4db65aa5 --- /dev/null +++ b/include/Protocol/Language/Declaration.h @@ -0,0 +1,32 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.declaration` +/// - property type: `DeclarationClientCapabilities` defined as follows: +struct DeclarationClientCapabilities { + /// Whether declaration supports dynamic registration. If this is set to + ///`true` the client supports the new `DeclarationRegistrationOptions` + /// return value for the corresponding server capability as well. + bool dynamicRegistration = false; + + /// The client supports additional metadata in the form of declaration links. + bool linkSupport = false; +}; + +/// Request: +/// - method: 'textDocument/declaration' +/// - params: `DeclarationParams` defined follows: +using DeclarationParams = Combine; + +/// Response: +/// result: Location +using DeclarationResult = Location; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/Definition.h b/include/Protocol/Language/Definition.h new file mode 100644 index 00000000..cde410c7 --- /dev/null +++ b/include/Protocol/Language/Definition.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.definition` +/// - property type: `DefinitionClientCapabilities` defined as follows: +struct DefinitionClientCapabilities { + + /// Whether definition supports dynamic registration. + bool dynamicRegistration = false; + + /// The client supports additional metadata in the form of definition links. + bool linkSupport = false; +}; + +/// Request: +/// - method: 'textDocument/definition' +/// - params: `DefinitionParams` defined follows: +using DefinitionParams = Combine; + +/// Response: +/// result: Location +using DefinitionResult = Location; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/DocumentColor.h b/include/Protocol/Language/DocumentColor.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/DocumentColor.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/DocumentHighlight.h b/include/Protocol/Language/DocumentHighlight.h new file mode 100644 index 00000000..6821daf6 --- /dev/null +++ b/include/Protocol/Language/DocumentHighlight.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.documentHighlight` +/// - property type: `DocumentHighlightClientCapabilities` defined as follows: +struct DocumentHighlightClientCapabilities { + + /// Whether documentHighlight supports dynamic registration. + bool dynamicRegistration = false; +}; + +/// Request: +/// - method: 'textDocument/documentHighlight' +/// - params: `DocumentHighlightParams` defined follows: +using DocumentHighlightParams = Combine; +/// A document highlight kind. +enum class DocumentHighlightKind { + /// A textual occurrence. + Text = 1, + /// Read-access of a symbol, like reading a variable. + Read = 2, + /// Write-access of a symbol, like writing to a variable. + Write = 3, +}; + +/// A document highlight is a range inside a text document which deserves +/// special attention. Usually a document highlight is visualized by changing +/// the background color of its range. +struct DocumentHighlight { + /// The range this highlight applies to. + Range range; + + /// The highlight kind, default is DocumentHighlightKind.Text. + DocumentHighlightKind kind = DocumentHighlightKind::Text; +}; + +/// Response: +/// result: DocumentHighlight[] +using DocumentHighlightResult = std::vector; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/DocumentLink.h b/include/Protocol/Language/DocumentLink.h new file mode 100644 index 00000000..13293b18 --- /dev/null +++ b/include/Protocol/Language/DocumentLink.h @@ -0,0 +1,52 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.documentLink` +/// - property type: `DocumentLinkClientCapabilities` defined as follows: +struct DocumentLinkClientCapabilities { + + /// Whether documentLink supports dynamic registration. + bool dynamicRegistration = false; + + /// Whether the client support the `tooltip` property on `DocumentLink`. + bool tooltipSupport = false; +}; + +struct DocumentLinkParamsBody { + /// The document to provide document links for. + TextDocumentIdentifier textDocument; +}; + +/// Request: +/// - method: 'textDocument/documentLink' +/// - params: `DocumentLinkParams` defined follows: +using DocumentLinkParams = Combine< + // WorkDoneProgressParams, + // PartialResultParams, + DocumentLinkParamsBody>; + +/// A document link is a range in a text document that links to an internal or +/// external resource, like another text document or a web site. +struct DocumentLink { + /// The range this link applies to. + Range range; + + /// The uri this link points to. If missing a resolve request is sent later. + std::string target; + + /// The tooltip text when you hover over this link. + std::string tooltip; + + // data?: LSPAny; +}; + +/// Response: +/// - result: `DocumentLink[]` +using DocumentLinkResult = std::vector; + +} // namespace clice::protocol + diff --git a/include/Protocol/Language/DocumentSymbol.h b/include/Protocol/Language/DocumentSymbol.h new file mode 100644 index 00000000..d2518b6f --- /dev/null +++ b/include/Protocol/Language/DocumentSymbol.h @@ -0,0 +1,72 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// A symbol kind. +enum class SymbolKind : uint8_t { + File = 1, + Module, + Namespace, + Package, + Class, + Method, + Property, + Field, + Constructor, + Enum, + Interface, + Function, + Variable, + Constant, + String, + Number, + Boolean, + Array, + Object, + Key, + Null, + EnumMember, + Struct, + Event, + Operator, + TypeParameter +}; + +/// Symbol tags are extra annotations that tweak the rendering of a symbol. +enum class SymbolTag : uint8_t { + /// Render a symbol as obsolete, usually using a strike-out. + Deprecated = 1, +}; + +/// Represents programming constructs like variables, classes, interfaces etc. +/// that appear in a document. Document symbols can be hierarchical and they +/// have two ranges: one that encloses its definition and one that points to its +/// most interesting range, e.g. the range of an identifier. +struct DocumentSymbol { + /// The name of this symbol. + String name; + + /// More detail for this symbol, e.g the signature of a function. + String detail; + + /// The kind of this symbol. + SymbolKind kind; + + /// Tags for this symbol. + std::vector tags; + + /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. + /// comments and code. + Range range; + + /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a + /// function. Must be contained by the `range`. + Range selectionRange; + + /// Children of this symbol, e.g. properties of a class. + std::vector children; +}; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/FoldingRange.h b/include/Protocol/Language/FoldingRange.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/FoldingRange.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/Formatting.h b/include/Protocol/Language/Formatting.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/Formatting.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/Hover.h b/include/Protocol/Language/Hover.h new file mode 100644 index 00000000..48d71a00 --- /dev/null +++ b/include/Protocol/Language/Hover.h @@ -0,0 +1,41 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument/hover` +/// - property type: `HoverClientCapabilities` defined as follows: +struct HoverClientCapabilities { + + /// Whether hover supports dynamic registration. + bool dynamicRegistration = false; + + /// Client supports the follow content formats for the content property. The order describes the preferred + /// format of the client. + std::vector contentFormat; +}; + +/// Request: +/// - method: 'textDocument/hover' +/// - params: `HoverParams` defined follows: +using HoverParams = Combine; + +/// The result of a hover request. +struct Hover { + /// The hover's content + MarkupContent contents; + + /// An optional range is a range inside a text document that is used to visualize a hover, e.g. by + /// changing the background color. + Range range; +}; + +/// Response: +/// result: Hover +using HoverResult = Hover; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/Implementation.h b/include/Protocol/Language/Implementation.h new file mode 100644 index 00000000..8c382828 --- /dev/null +++ b/include/Protocol/Language/Implementation.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.implementation` +/// - property type: `ImplementationClientCapabilities` defined as follows: +struct ImplementationClientCapabilities { + + /// Whether implementation supports dynamic registration. + bool dynamicRegistration = false; + + /// The client supports additional metadata in the form of implementation links. + bool linkSupport = false; +}; + +/// Request: +/// - method: 'textDocument/implementation' +/// - params: `ImplementationParams` defined follows: +using ImplementationParams = Combine; + +/// Response: +/// result: Location +using ImplementationResult = Location; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/InlayHint.h b/include/Protocol/Language/InlayHint.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/InlayHint.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/InlineValue.h b/include/Protocol/Language/InlineValue.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/InlineValue.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/OnTypeFormatting.h b/include/Protocol/Language/OnTypeFormatting.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/OnTypeFormatting.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/RangeFormatting.h b/include/Protocol/Language/RangeFormatting.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/RangeFormatting.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/Reference.h b/include/Protocol/Language/Reference.h new file mode 100644 index 00000000..a6ef2154 --- /dev/null +++ b/include/Protocol/Language/Reference.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument.references` +/// - property type: `ReferenceClientCapabilities` defined as follows: +struct ReferenceClientCapabilities { + + /// Whether references supports dynamic registration. + bool dynamicRegistration = false; +}; + +struct ReferenceContext { + /// Include the declaration of the current symbol. + bool includeDeclaration = false; +}; + +struct ReferenceParamsBody { + ReferenceContext context; +}; + +/// Request: +/// - method: 'textDocument/references' +/// - params: `ReferenceParams` defined follows: +using ReferenceParams = Combine; + +/// Response: +/// result: Location[] +using ReferenceResult = std::vector; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/Rename.h b/include/Protocol/Language/Rename.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/Rename.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/SelectionRange.h b/include/Protocol/Language/SelectionRange.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/SelectionRange.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/SemanticToken.h b/include/Protocol/Language/SemanticToken.h new file mode 100644 index 00000000..0bc2307f --- /dev/null +++ b/include/Protocol/Language/SemanticToken.h @@ -0,0 +1,195 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +enum class SemanticTokenType : uint8_t { + /// Represents a comment. + Comment, + /// Represents a number literal. + Number, + /// Represents a character literal. + Char, + /// Represents a string literal. + String, + /// Represents a C/C++ keyword (e.g., `int`, `class`, `struct`). + Keyword, + /// Represents a compiler built-in macro, function, or keyword (e.g., `__stdcall`, + /// `__attribute__`, `__FUNCSIG__`). + Builtin, + /// Represents a preprocessor directive (e.g., `#include`, `#define`, `#if`). + Directive, + /// Represents a header file path (e.g., ``). + HeaderPath, + /// Represents a C/C++ macro name, both in definition and invocation. + Macro, + /// Represents a C/C++ macro parameter, both in definition and invocation. + MacroParameter, + /// Represents a C++ namespace name. + Namespace, + /// Represents a C/C++ type name. + Type, + /// Represents a C/C++ struct name. + Struct, + /// Represents a C/C++ union name. + Union, + /// Represents a C/C++ class name. + Class, + /// Represents a C/C++ field name. + Field, + /// Represents a C/C++ enum name. + Enum, + /// Represents a C/C++ enum field (member) name. + EnumMember, + /// Represents a C/C++ variable name. + Variable, + /// Represents a C/C++ function name. + Function, + /// Represents a C++ method name. + Method, + /// Represents a C/C++ function/method parameter name. + Parameter, + /// Represents a C++ dependent name in a template context (e.g., `name` in `auto y = T::name` + /// where T is a template parameter). + /// Note: This includes `T::template name(...)`; it's not possible to distinguish whether a name + /// is a function or a functor in a dependent context. + DependentName, + /// Represents a C++ dependent type name (e.g., `type` in `typename std::vector::type` where + /// T is a template parameter). + /// Note: This includes `typename T::template type<...>`. + DependentType, + /// Represents a C++20 concept name. + Concept, + /// Represents a C++11 attribute name. + Attribute, + /// Represents parentheses `()`. + Paren, + /// Represents curly braces `{}`. + Brace, + /// Represents square brackets `[]`. + Bracket, + /// Represents angle brackets `<>`. + Angle, + /// Represents the scope resolution operator `::`. + Scope, + /// Represents built-in operators (e.g., `+` in `1 + 2`). + Operator, + /// Represents punctuation in non-expression contexts (e.g., `;`, `,` in enum declaration, `=` + /// and `&` in lambda capture). + Delimiter, + Unknown, + Invalid +}; + +enum class SemanticTokenModifier : uint32_t { + /// emit for a name in declaration. + /// e.g. function declaration, variable declaration, class declaration. + Declaration, + /// emit for a name in definition. + /// e.g. function definition, variable definition, class definition. + Definition, + /// emit for a name in reference(not declaration or definition). + /// e.g. `x` in `x + 1`, `X` in `X::type` + Reference, + Const, + Constexpr, + Consteval, + Virtual, + PureVirtual, + Inline, + Static, + Deprecated, + Local, + /// emit for left bracket. + Left, + /// emit for right bracket. + Right, + /// emit for operators which are part of type. + /// e.g. `*` in `int*`, `&` in `int&`. + Intype, + /// emit for operators which are overloaded. + /// e.g. `+` in `std::string("123") + c;` + Overloaded, + None, +}; + +/// Client Capability: +/// - property name(optional): `textDocument.semanticTokens` +/// - property type: `SemanticTokensClientCapabilities` defined as follows: +struct SemanticTokensClientCapabilities { + /// Whether implementation supports dynamic registration. If this is set to `true` the client + bool dynamicRegistration = false; + + struct Requests { + // FIXME: + }; + + /// The token types that the client supports. + std::vector tokenTypes; + + /// The token modifiers that the client supports. + std::vector tokenModifiers; + + /// The formats the client supports. + /// formats: TokenFormat[]; + + /// Whether the client supports tokens that can overlap each other. + bool overlappingTokenSupport = false; + + /// Whether the client supports tokens that can span multiple lines. + bool multilineTokenSupport = false; + + /// Whether the client allows the server to actively cancel a semantic token request. + bool serverCancelSupport = false; + + /// Whether the client uses semantic tokens to augment existing syntax tokens. + bool serverCancelSupports = false; +}; + +struct SemanticTokensLegend { + /// The token types a server uses. + std::vector tokenTypes; + + /// The token modifiers a server uses. + std::vector tokenModifiers; +}; + +/// Server Capability: +/// - property name(optional): `textDocument.semanticTokens` +/// - property type: `SemanticTokensOptionss` defined as follows: +struct SemanticTokensOptions { + /// The legend used by the server. + SemanticTokensLegend legend; + + /// Server supports providing semantic tokens for a specific range. + bool range = false; + + /// Server supports providing semantic tokens for a full document. + bool full = false; +}; + +/// Request: +/// - method: `textDocument/semanticTokens/full` +/// - params: `SemanticTokensParams` defined as follows: +struct SemanticTokensParamsBody { + /// The text document. + TextDocumentIdentifier textDocument; +}; + +using SemanticTokensParams = Combine< + // WorkDoneProgressParams, + // PartialResultParams, + SemanticTokensParamsBody>; + +/// Response: +/// - result: `SemanticTokens` defined as follows: +struct SemanticTokens { + /// An optional result id. + String resultId; + + /// The actual tokens. + std::vector data; +}; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/SignatureHelp.h b/include/Protocol/Language/SignatureHelp.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/include/Protocol/Language/SignatureHelp.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/Protocol/Language/TypeDefinition.h b/include/Protocol/Language/TypeDefinition.h new file mode 100644 index 00000000..47f6f438 --- /dev/null +++ b/include/Protocol/Language/TypeDefinition.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../Basic.h" + +namespace clice::protocol { + +/// Client Capability: +/// - property name (optional): `textDocument/typeDefinition` +/// - property type: `TypeDefinitionClientCapabilities` defined as follows: +struct TypeDefinitionClientCapabilities { + + /// Whether typeDefinition supports dynamic registration. + bool dynamicRegistration = false; + + /// The client supports additional metadata in the form of typeDefinition links. + bool linkSupport = false; +}; + +/// Request: +/// - method: 'textDocument/typeDefinition' +/// - params: `TypeDefinitionParams` defined follows: +using TypeDefinitionParams = Combine; + +/// Response: +/// result: Location +using TypeDefinitionResult = Location; + +} // namespace clice::protocol diff --git a/include/Protocol/Language/TypeHierarchy.h b/include/Protocol/Language/TypeHierarchy.h new file mode 100644 index 00000000..3695c0d4 --- /dev/null +++ b/include/Protocol/Language/TypeHierarchy.h @@ -0,0 +1,63 @@ +#pragma once + +#include "DocumentSymbol.h" + +namespace clice::protocol { + +struct TypeHierarchyItem { + + /// The name of this item. + String name; + + /// The kind of this item. + SymbolKind kind; + + /// Tags for this item. + std::vector tags; + + /// More detail for this item, e.g. the signature of a function. + std::string detail; + + /// The resource identifier of this item. + DocumentUri uri; + + /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. + /// comments and code. + Range range; + + /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a + /// function. + Range selectionRange; + + /// A data entry field that is preserved between a call hierarchy prepare and incoming calls or outgoing + /// calls requests. + /// data?: LSPAny; +}; + +/// Client Capability: +/// - property name (optional): `textDocument/typeHierarchy` +/// - property type: `TypeHierarchyClientCapabilities` defined as follows: +struct TypeHierarchyClientCapabilities { + /// Whether typeHierarchy supports dynamic registration. + bool dynamicRegistration = false; +}; + +/// Request: +/// - method: 'textDocument/prepareTypeHierarchy' +/// - params: `TypeHierarchyParams` defined follows: +using TypeHierarchyParams = Combine; + +/// Response: +/// - result: `TypeHierarchyItem[]` +using TypeHierarchyResult = std::vector; + +/*=========================================================================/ +/ / +/======================== Type Hierarchy Supertypes =======================/ +/ / +/=========================================================================*/ + +// TODO: +} // namespace clice::protocol diff --git a/include/Protocol/Lifecycle/Exit.h b/include/Protocol/Lifecycle/Exit.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Lifecycle/Initialize.h b/include/Protocol/Lifecycle/Initialize.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Lifecycle/Initialized.h b/include/Protocol/Lifecycle/Initialized.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Lifecycle/Shutdown.h b/include/Protocol/Lifecycle/Shutdown.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Protocol/Message.h b/include/Protocol/Message.h new file mode 100644 index 00000000..94b0db47 --- /dev/null +++ b/include/Protocol/Message.h @@ -0,0 +1,73 @@ +#include + +namespace clice::protocol { + +/// A request message to describe a request between the client and the server. +/// Every processed request must send a response back to the sender of the request. +template +struct Request { + String jsonrpc = "2.0"; + + /// The request id. + Integer id; + + /// The method to be invoked. + String method; + + /// The method's params. + Params params; +}; + +enum class ErrorCode : Integer { + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, +}; + +struct ResponseError { + /// A number indicating the error type that occurred. + ErrorCode code; + + /// A string providing a short description of the error. + String message; + + /// A Primitive or Structured value that contains additional information about the error. + // TODO: std::optional data; +}; + +/// A Response Message sent as a result of a request. If a request doesn’t provide a result value +/// the receiver of a request still needs to return a response message to conform to the JSON-RPC +/// specification. The result property of the ResponseMessage should be set to null in this case to signal a +/// successful request. +template +struct Response { + String jsonrpc = "2.0"; + + /// The request id. + Integer id; + + /// The result of the request. + std::optional result; + + /// The error of the request. + std::optional error; +}; + +/// A notification message to inform the server that the client has successfully registered itself. +template +struct Registration { + String jsonrpc = "2.0"; + + /// The method to be invoked. + String method; + + /// The registration's id. + Integer id; + + /// The registration's options. + RegistrationOptions registerOptions; +}; + +} // namespace clice::protocol diff --git a/include/Protocol/Protocol.h b/include/Protocol/Protocol.h new file mode 100644 index 00000000..4eae7d5a --- /dev/null +++ b/include/Protocol/Protocol.h @@ -0,0 +1,709 @@ +#pragma once + +#include +#include +#include +#include + +#include "Language/SemanticToken.h" + +namespace clice { + +// Defined by JSON RPC. +enum class ErrorCode { + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + + ServerNotInitialized = -32002, + UnknownErrorCode = -32001, + + // Defined by the protocol. + RequestCancelled = -32800, + ContentModified = -32801, +}; + +struct ResourceOperationKind { + /// Supports creating new files and folders. + constexpr inline static std::string_view Create = "create"; + + /// Supports renaming existing files and folders. + constexpr inline static std::string_view Rename = "rename"; + + /// Supports deleting existing files and folders. + constexpr inline static std::string_view Delete = "delete"; +}; + +struct FailureHandlingKind { + /// Applying the workspace change is simply aborted if one of the changes + /// provided fails. All operations executed before the failing operation stay + /// executed. + constexpr inline static std::string_view Abort = "abort"; + + /// All operations are executed transactionally. That is they either all + /// succeed or no changes at all are applied to the workspace. + constexpr inline static std::string_view Transactional = "transactional"; + + /// If the workspace edit contains only textual file changes they are executed + /// transactionally. If resource changes (create, rename or delete file) are + /// part of the change the failure handling strategy is abort. + constexpr inline static std::string_view TextOnlyTransactional = "textOnlyTransactional"; + + /// The client tries to undo the operations already executed. But there is no + /// guarantee that this is succeeding. + constexpr inline static std::string_view Undo = "undo"; +}; + +/// A symbol kind. +enum class SymbolKind { + 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, + Object = 19, + Key = 20, + Null = 21, + EnumMember = 22, + Struct = 23, + Event = 24, + Operator = 25, + TypeParameter = 26, +}; + +struct WorkspaceEditClientCapabilities { + /// The client supports versioned document changes in `WorkspaceEdit`s + std::optional documentChanges; + + /// The resource operations the client supports. Clients should at least + /// support 'create', 'rename' and 'delete' files and folders. + /// possible values are in ResourceOperationKind + std::optional> resourceOperations; + + /// The failure handling strategy of a client if applying the workspace edit + /// fails. + /// possible values are in FailureHandlingKind + std::optional failureHandling; + + /// Whether the client normalizes line endings to the client specific + /// setting. + /// If set to `true` the client will normalize line ending characters + /// in a workspace edit to the client specific new line character(s). + std::optional normalizesLineEndings; + + struct ChangeAnnotationSupport { + /// Whether the client groups edits with equal labels into tree nodes, + /// for instance all edits labelled with "Changes in Strings" would + /// be a tree node. + std::optional groupsOnLabel; + }; + + /// Whether the client in general supports change annotations on text edits, + /// create file, rename file and delete file changes. + std::optional changeAnnotationSupport; +}; + +struct DidChangeConfigurationClientCapabilities { + /// Did change configuration notification supports dynamic registration. + std::optional dynamicRegistration; +}; + +struct DidChangeWatchedFilesClientCapabilities { + /// Did change watched files notification supports dynamic registration. + /// Please note that the current protocol doesn't support static + /// configuration for file changes from the server side. + std::optional dynamicRegistration; + + /// Whether the client has support for relative patterns or not. + std::optional supportsRelativePattern; +}; + +struct WorkspaceSymbolClientCapabilities { + /// Symbol request supports dynamic registration. + std::optional dynamicRegistration; + + struct SymbolKind_ { + /// The symbol kind values the client supports. When this + /// property exists the client also guarantees that it will + /// handle values outside its set gracefully and falls back + /// to a default value when unknown. + /// + /// If this property is not present the client only supports + /// the symbol kinds from `File` to `Array` as defined in + /// the initial version of the protocol. + std::vector valueSet; + }; + + /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. + std::optional symbolKind; + + struct TagSupport { + /// The tags supported by the client. + std::vector valueSet; + }; + + /// The client supports tags on `SymbolInformation` and `WorkspaceSymbol`. + /// Clients supporting tags have to handle unknown tags gracefully. + std::optional tagSupport; + + struct ResolveSupport { + /// The properties that a client can resolve lazily. Usually `location.range`. + std::vector properties; + }; + + /// The client support partial workspace symbols. The client will send the + /// request `workspaceSymbol/resolve` to the server to resolve additional + /// properties. + std::optional resolveSupport; +}; + +struct ExecuteCommandClientCapabilities { + /// Execute command supports dynamic registration. + std::optional dynamicRegistration; +}; + +struct SemanticTokensWorkspaceClientCapabilities { + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// semantic tokens currently shown. It should be used with absolute care + /// and is useful for situation where a server for example detect a project + /// wide change that requires such a calculation. + std::optional refreshSupport; +}; + +struct CodeLensWorkspaceClientCapabilities { + /** + * Whether the client implementation supports a refresh request sent from the + * server to the client. + * + * Note that this event is global and will force the client to refresh all + * code lenses currently shown. It should be used with absolute care and is + * useful for situation where a server for example detect a project wide + * change that requires such a calculation. + */ + std::optional refreshSupport; +}; + +/// Client workspace capabilities specific to inline values. +struct InlineValueWorkspaceClientCapabilities { + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// inline values currently shown. It should be used with absolute care and + /// is useful for situation where a server for example detect a project wide + /// change that requires such a calculation. + std::optional refreshSupport; +}; + +/// Client workspace capabilities specific to inlay hints. +struct InlayHintWorkspaceClientCapabilities { + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// inlay hints currently shown. It should be used with absolute care and + /// is useful for situation where a server for example detects a project wide + /// change that requires such a calculation. + std::optional refreshSupport; +}; + +/// Workspace client capabilities specific to diagnostic pull requests. +struct DiagnosticWorkspaceClientCapabilities { + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// pulled diagnostics currently shown. It should be used with absolute care + /// and is useful for situation where a server for example detects a project + /// wide change that requires such a calculation. + std::optional refreshSupport; +}; + +struct ClientCapabilities { + struct Workplace { + /// The client supports applying batch edits + /// to the workspace by supporting the request + /// 'workspace/applyEdit' + std::optional applyEdit; + + /// Capabilities specific to `WorkspaceEdit`s + std::optional workspaceEdit; + + /// Capabilities specific to the `workspace/didChangeConfiguration` notification. + std::optional didChangeConfiguration; + + /// Capabilities specific to the `workspace/didChangeWatchedFiles` notification. + std::optional didChangeWatchedFiles; + + /// Capabilities specific to the `workspace/symbol` request. + std::optional symbol; + + /// Capabilities specific to the `workspace/executeCommand` request. + std::optional executeCommand; + + /// The client has support for workspace folders. + std::optional workspaceFolders; + + /// The client supports `workspace/configuration` requests. + std::optional configuration; + + /// Capabilities specific to the semantic token requests scoped to the workspace. + std::optional semanticTokens; + + /// Capabilities specific to the code lens requests scoped to the workspace. + std::optional codeLens; + + struct FileOperations { + /// Whether the client supports dynamic registration for file requests/notifications. + std::optional dynamicRegistration; + + /// The client has support for sending didCreateFiles notifications. + std::optional didCreate; + + /// The client has support for sending willCreateFiles requests. + std::optional willCreate; + + /// The client has support for sending didRenameFiles notifications. + std::optional didRename; + + /// The client has support for sending willRenameFiles requests. + std::optional willRename; + + /// The client has support for sending didDeleteFiles notifications. + std::optional didDelete; + + /// The client has support for sending willDeleteFiles requests. + std::optional willDelete; + }; + + /// The client has support for file requests/notifications. + std::optional fileOperations; + + /// Client workspace capabilities specific to inline values. + std::optional inlineValue; + + /// Client workspace capabilities specific to inlay hints. + std::optional inlayHint; + + /// Client workspace capabilities specific to diagnostics. + std::optional diagnostic; + }; + + /// Workspace specific client capabilities. + std::optional workspace; + + /// Text document specific client capabilities. + /// TODO: textDocument?: TextDocumentClientCapabilities; + + /// Capabilities specific to the notebook document support. + /// TODO: notebookDocument?: NotebookDocumentClientCapabilities; + + /// Window specific client capabilities. + /// TODO: window: {...} + + /// General client capabilities. + /// TODO: general: {...} + + /// Experimental client capabilities. + /// experimental?: LSPAny; +}; + +/// TODO: +struct URI {}; + +struct WorkspaceFolder { + /// The associated URI for this workspace folder. + URI uri; + + /// The name of the workspace folder. Used to refer to this + /// workspace folder in the user interface. + std::string name; +}; + +struct InitializeParams { + /// 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. + std::optional processId; + + struct ClientInfo { + std::string_view name; + std::optional version; + }; + + /// Information about the client + std::optional clientInfo; + + /// The locale the client is currently showing the user interface + /// in. This must not necessarily be the locale of the operating + /// system. + /// + /// Uses IETF language tags as the value's syntax + /// (See https://en.wikipedia.org/wiki/IETF_language_tag) + /// + /// @since 3.16.0 + std::optional locale; + + /// User provided initialization options. + /// TODO: initializationOptions?: LSPAny; + + /// The capabilities provided by the client (editor or tool). + ClientCapabilities capabilities; + + /// The initial trace setting. If omitted trace is disabled ('off'). + /// TODO: trace?: TraceValue; + + /// The workspace folders configured in the client when the server starts. + /// This property is only available if the client supports workspace folders. + /// It can be `null` if the client supports workspace folders but none are + /// configured. + std::optional> workspaceFolders; +}; + +/*===========================================================================// +// RESPONSES // +//===========================================================================*/ + +struct PositionEncodingKind { + /// Character offsets count UTF-8 code units (e.g bytes). + constexpr inline static std::string_view UTF8 = "utf-8"; + + /// Character offsets count UTF-16 code units. + /// This is the default and must always be supported by servers. + constexpr inline static std::string_view UTF16 = "utf-16"; + + /// Character offsets count UTF-32 code units. + /// Implementation note: these are the same as Unicode code points, + /// so this `PositionEncodingKind` may also be used for an + /// encoding-agnostic representation of character offsets. + constexpr inline static std::string_view UTF32 = "utf-32"; +}; + +/// Defines how the host (editor) should sync document changes to the language server. +enum class TextDocumentSyncKind { + /// 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 sent. + Incremental = 2, +}; + +/// Completion options. +struct CompletionOptions { + /// + /// The additional characters, beyond the defaults provided by the client (typically + ///[a-zA-Z]), that should automatically trigger a completion request. For example + ///`.` in JavaScript represents the beginning of an object property or method and is + /// thus a good candidate for triggering a completion request. + /// + /// Most tools trigger a completion request automatically without explicitly + /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they + /// do so when the user starts to type an identifier. For example if the user + /// types `c` in a JavaScript file code complete will automatically pop up + /// present `console` besides others as a completion item. Characters that + /// make up identifiers don't need to be listed here. + std::array triggerCharacters = {".", "<", ">", ":", "\"", "/", "*"}; + + /// The list of all possible characters that commit a completion. This field + /// can be used if clients don't support individual commit characters per + /// completion item. See client capability `completion.completionItem.commitCharactersSupport`. + /// + /// If a server provides both `allCommitCharacters` and commit characters on + /// an individual completion item the ones on the completion item win. + /// + /// allCommitCharacters?: string[]; + /// NOTICE: We don't set `(` etc as allCommitCharacters as they interact poorly with snippet results. + /// See https://github.com/clangd/vscode-clangd/issues/357 + /// Hopefully we can use them one day without this side-effect: + /// https://github.com/microsoft/vscode/issues/42544 + + /// The server provides support to resolve additional information for a completion item. + bool resolveProvider = false; + + /// The server supports the following `CompletionItem` specific capabilities. + /// TODO: completionItem?: {...} +}; + +struct SignatureHelpOptions { + /// The characters that trigger signature help automatically. + std::array triggerCharacters = {"(", ")", "{", "}", "<", ">", ","}; + + /// List of characters that re-trigger signature help. + /// These trigger characters are only active when signature help is already showing. + /// All trigger characters are also counted as re-trigger characters. + std::array retriggerCharacters = {","}; +}; + +struct CodeLensOptions { + /// Code lens has a resolve provider as well. + bool resolveProvider = false; +}; + +struct DocumentLinkOptions { + /// Document links have a resolve provider as well. + bool resolveProvider = false; +}; + +struct DocumentOnTypeFormattingOptions { + /// A character on which formatting should be triggered, like `{`. + std::string_view firstTriggerCharacter = "\n"; + + /// More trigger characters. + /// moreTriggerCharacter?: string[]; +}; + +struct SemanticTokensOptions { + /// The legend used by the server + protocol::SemanticTokensLegend legend; + + /// Server supports providing semantic tokens for a specific range of a document. + bool range = false; // TODO: further check + + struct Full { + /// Server supports providing semantic tokens for a full document. + bool delta = true; + }; + + /// Server supports providing semantic tokens for a full document. + Full full; +}; + +struct ServerCapabilities { + /// The position encoding the server picked from the encodings offered + /// by the client via the client capability `general.positionEncodings`. + /// + /// If the client didn't provide any position encodings the only valid + /// value that a server can return is 'utf-16'. + /// + /// If omitted it defaults to 'utf-16'. + /// + /// possible values: ['utf-8', 'utf-16', 'utf-32'] in PositionEncodingKind + std::string_view positionEncoding = PositionEncodingKind::UTF16; + + /// Defines how text documents are synced. Is either a detailed structure + /// defining each notification or for backwards compatibility the + /// TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`. + TextDocumentSyncKind textDocumentSync = TextDocumentSyncKind::Incremental; + + /// Defines how notebook documents are synced. + /// TODO: notebookDocumentSync?: NotebookDocumentSyncOptions | NotebookDocumentSyncRegistrationOptions; + + /// The server provides completion support. + CompletionOptions completionProvider; + + /// The server provides hover support. + bool hoverProvider = true; + + /// The server provides signature help support. + SignatureHelpOptions signatureHelpProvider; + + /// The server provides go to declaration support. + bool declarationProvider = true; + + /// 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 code actions. The `CodeActionOptions` return type is + /// only valid if the client signals code action literal support via the + /// client capability `textDocument.codeAction.codeActionLiteralSupport`. + bool codeActionProvider = true; // TODO: provide CodeActionOptions + + /// The server provides code lens. + CodeLensOptions codeLensProvider; + + /// The server provides document link support. + DocumentLinkOptions documentLinkProvider; + + /// The server provides color provider support. + bool colorProvider = false; // TODO: check what is colorProvider + + /// The server provides document formatting. + bool documentFormattingProvider = true; + + /// The server provides document range formatting. + bool documentRangeFormattingProvider = true; + + /// The server provides document formatting on typing. + DocumentOnTypeFormattingOptions documentOnTypeFormattingProvider; + + /// The server provides rename support. RenameOptions may only be + /// specified if the client states that it supports + /// `prepareSupport` in its initial `initialize` request. + bool renameProvider = true; + + /// The server provides folding provider support. + bool foldingRangeProvider = true; + + /// The server provides execute command support. + /// executeCommandProvider?: ExecuteCommandOptions; + + /// The server provides selection range support. + bool selectionRangeProvider = true; + + /// The server provides linked editing range support. + bool linkedEditingRangeProvider = true; + + /// The server provides call hierarchy support. + bool callHierarchyProvider = true; + + /// The server provides semantic tokens support. + SemanticTokensOptions semanticTokensProvider; + + /// Whether server provides moniker support. + bool monikerProvider = false; // TODO: further discussion + + /// The server provides type hierarchy support. + bool typeHierarchyProvider = true; + + /// The server provides inline values. + bool inlineValueProvider = true; + + /// The server provides inlay hints. + bool inlayHintProvider = true; + + /// The server has support for pull model diagnostics. + /// TODO: diagnosticProvider?: DiagnosticOptions + + /// The server provides workspace symbol support. + bool workspaceSymbolProvider = true; + + /// The server is interested in file notifications/requests. + /// TODO: fileOperations?: {...} +}; + +struct InitializeResult { + /// The capabilities the language server provides. + ServerCapabilities capabilities; + + struct ServerInfo { + /// The name of the server as defined by the server. + std::string_view name = "clice"; + + /// The server's version as defined by the server. + std::string_view version = "0.0.1"; + }; + + /// Information about the server. + ServerInfo serverInfo; +}; + +/*===================================================/ +/ / +/======= Text Document Synchronization ==========/ +/ / +/===================================================*/ + +/// An item to transfer a text document from the client to the server. +struct TextDocumentItem { + /// The text document's URI. + std::string_view uri; + + /// The text document's language identifier. + std::string_view languageId; + + /// he version number of this document (it will increase after each change, including undo/redo). + int version; + + /// The content of the opened text document. + std::string_view text; +}; + +/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings. +struct TextDocumentIdentifier { + /// The text document's URI. + std::string_view uri; +}; + +struct VersionedTextDocumentIdentifier { + /// The text document's URI. + std::string_view uri; + + /// The version number of this document. + /// + /// The version number of a document will increase after each change, + /// including undo/redo. The number doesn't need to be consecutive. + int version; +}; + +struct DidOpenTextDocumentParams { + /// The document that was opened. + TextDocumentItem textDocument; +}; + +struct TextDocumentContentChangeEvent { + // TODO: +}; + +struct DidChangeTextDocumentParams { + /// The document that did change. The version number points + /// to the version after all provided content changes have + /// been applied. + VersionedTextDocumentIdentifier textDocument; + + /// The actual content changes. The content changes describe single state + /// changes to the document. So if there are two content changes c1 (at + /// array index 0) and c2 (at array index 1) for a document in state S then + /// c1 moves the document from S to S' and c2 from S' to S''. So c1 is + /// computed on the state S and c2 is computed on the state S'. + /// + /// To mirror the content of a document using change events use the following + /// approach: + /// - start with the same initial content + /// - apply the 'textDocument/didChange' notifications in the order you receive them. + /// - apply the `TextDocumentContentChangeEvent`s in a single notification in the order you receive them. + std::vector contentChanges; +}; + +struct DidCloseTextDocumentParams { + /// The document that was closed. + TextDocumentIdentifier textDocument; +}; + +struct DidSaveTextDocumentParams { + /// The document that was saved. + TextDocumentIdentifier textDocument; + + /// Optional the content when saved. Depends on the includeText value + /// when the save notification was requested. + std::optional text; +}; + +} // namespace clice diff --git a/include/Protocol/README.md b/include/Protocol/README.md new file mode 100644 index 00000000..85045c48 --- /dev/null +++ b/include/Protocol/README.md @@ -0,0 +1,93 @@ +This file dictionary mainly describes the [Language Server Protocol Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/). Every interface in the protocol is defined as corresponding struct. + +For example, [Position](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position) has the following definition in the protocol: + +```typescript +interface Position { + line: uinteger; + character: uinteger; +} +``` + +then the corresponding representation in C++ is: + +```cpp +struct Position { + uinteger line; + uinteger character; +}; +``` + +We use template meta programming to reflect the protocol type so that the serialization and deserialization can be done automatically. The trick is only suitable for type which is aggregate and default constructible and does not have base classes. But there are many types in the protocol which are defined through inheritance. For example, [DeclarationParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#declarationParams) is defined as: + +```typescript +export interface DeclarationParams extends TextDocumentPositionParams, + WorkDoneProgressParams, PartialResultParams { +} +``` + +We use `Combine` to resolve the problem. `Combine` is defined as: + +```cpp +template +struct Combine : Ts... {}; +``` + +Then `DeclarationParams` can be defined as: + +```cpp +using DeclarationParams = Combine< + TextDocumentPositionParams, + WorkDoneProgressParams, + PartialResultParams +>; +``` + +Compared to direct inheritance, this way allows us to get the base class types of `DeclarationParams`. If the interface also has data members, you should define a struct to hold the data members separately and add it to `Combine` list. + +For example, we have [ReferenceParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#referenceParams) definition as follow: + +```typescript +export interface ReferenceParams extends TextDocumentPositionParams, + WorkDoneProgressParams, PartialResultParams { + context: ReferenceContext; +} +``` + +Then we can define `ReferenceParams` as: + +```cpp +struct ReferenceParamsBody { + ReferenceContext context; +}; + +using ReferenceParams = Combine< + TextDocumentPositionParams, + WorkDoneProgressParams, + PartialResultParams, + ReferenceParamsBody +>; +``` + +For number enum in TypeScript, it can define as corresponding `enum` in C++ directly, for string enum, we define it as `struct` with `static` members. + +```typescript +export namespace MarkupKind { + export const PlainText: 'plaintext' = 'plaintext'; + export const Markdown: 'markdown' = 'markdown'; +} +export type MarkupKind = 'plaintext' | 'markdown'; +``` + +```cpp +struct MarkupKind { + std::string_view m_value; + + constexpr MarkupKind(std::string_view value) : m_value(value) {} + + constexpr inline static std::string_view PlainText = "plaintext"; + constexpr inline static std::string_view Markdown = "markdown"; +}; +``` + + diff --git a/tests/test.cpp b/tests/test.cpp index cf32aa11..01370b4c 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -42,3 +42,4 @@ struct vector { using alloc_type = typename alloc_traits::template rebind::other; using reference = typename alloc_traits::reference; }; +