diff options
Diffstat (limited to 'Build/source/utils/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h')
-rw-r--r-- | Build/source/utils/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h b/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h new file mode 100644 index 00000000000..612d186f6fb --- /dev/null +++ b/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/textDocument/SemanticTokens.h @@ -0,0 +1,267 @@ +#pragma once + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +enum class HighlightingKind_clangD { + Variable = 0, + LocalVariable, + Parameter, + Function, + Method, + StaticMethod, + Field, + StaticField, + Class, + Interface, + Enum, + EnumConstant, + Typedef, + Type, + Unknown, + Namespace, + TemplateParameter, + Concept, + Primitive, + Macro, + + // This one is different from the other kinds as it's a line style + // rather than a token style. + InactiveCode, + + LastKind = InactiveCode +}; +std::string toSemanticTokenType(HighlightingKind_clangD kind); + +enum class HighlightingModifier_clangD { + Declaration, + Deprecated, + Deduced, + Readonly, + Static, + Abstract, + DependentName, + DefaultLibrary, + + FunctionScope, + ClassScope, + FileScope, + GlobalScope, + + LastModifier = GlobalScope +}; +std::string toSemanticTokenModifier(HighlightingModifier_clangD modifier); + +enum SemanticTokenType { + ls_namespace=0,// 'namespace', + /** + * Represents a generic type. Acts as a fallback for types which + * can't be mapped to a specific type like class or enum. + */ + ls_type,// 'type', + ls_class,// 'class', + ls_enum,// 'enum', + ls_interface,// 'interface', + ls_struct,// 'struct', + ls_typeParameter,// 'typeParameter', + ls_parameter,// 'parameter', + ls_variable,// 'variable', + ls_property,// 'property', + ls_enumMember,// 'enumMember', + ls_event,// 'event', + ls_function,// 'function', + ls_method,// 'method', + ls_macro,// 'macro', + ls_keyword,// 'keyword', + ls_modifier,// 'modifier', + ls_comment,// 'comment', + ls_string,// 'string', + ls_number,// 'number', + ls_regexp,// 'regexp', + ls_operator,// 'operator' + lastKind = ls_operator +}; +std::string to_string(SemanticTokenType); +unsigned toSemanticTokenType(std::vector<SemanticTokenType>& modifiers); + +enum TokenType_JDT { + PACKAGE_JDT=0, + CLASS_JDT, + INTERFACE_JDT, + ENUM_JDT, + ENUM_MEMBER_JDT, + TYPE_JDT, + TYPE_PARAMETER_JDT, + ANNOTATION_JDT, + ANNOTATION_MEMBER_JDT, + METHOD_JDT, + PROPERTY_JDT, + VARIABLE_JDT, + PARAMETER_JDT +}; +std::string to_string(TokenType_JDT); + +enum SemanticTokenModifier { + ls_declaration=0,// 'declaration', + ls_definition,// 'definition', + ls_readonly,// 'readonly', + ls_static,// 'static', + ls_deprecated,// 'deprecated', + ls_abstract,// 'abstract', + ls_async,// 'async', + ls_modification,// 'modification', + ls_documentation,// 'documentation', + ls_defaultLibrary,// 'defaultLibrary' + LastModifier = ls_defaultLibrary +}; +std::string to_string(SemanticTokenModifier); +unsigned toSemanticTokenModifiers(std::vector<SemanticTokenModifier>&); +/// Specifies a single semantic token in the document. +/// This struct is not part of LSP, which just encodes lists of tokens as +/// arrays of numbers directly. +struct SemanticToken { + /// token line number, relative to the previous token + unsigned deltaLine = 0; + /// token start character, relative to the previous token + /// (relative to 0 or the previous token's start if they are on the same line) + unsigned deltaStart = 0; + /// the length of the token. A token cannot be multiline + unsigned length = 0; + /// will be looked up in `SemanticTokensLegend.tokenTypes` + unsigned tokenType = 0; + /// each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + unsigned tokenModifiers = 0; +}; +bool operator==(const SemanticToken&, const SemanticToken&); +struct SemanticTokens{ + + /** + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. + * + * --- + * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: + * - at index `5*i` - `deltaLine`: token line number, relative to the previous token + * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line) + * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline. + * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536. + * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + * + * --- + * ### How to encode tokens + * + * Here is an example for encoding a file with 3 tokens in a uint32 array: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, + * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, + * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } + * ``` + * + * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types. + * For this example, we will choose the following legend which must be passed in when registering the provider: + * ``` + * tokenTypes: ['property', 'type', 'class'], + * tokenModifiers: ['private', 'static'] + * ``` + * + * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked + * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, + * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because + * bits 0 and 1 are set. Using this legend, the tokens now are: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token + * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` + * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the + * `startChar` of the third token will not be altered: + * ``` + * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + */ + std::vector<int32_t> data; + static std::vector<int32_t> encodeTokens(std::vector<SemanticToken>& tokens); + + /** + * An optional result id. If provided and clients support delta updating + * the client will include the result id in the next semantic token request. + * A server can then instead of computing all semantic tokens again simply + * send a delta. + */ + boost::optional<std::string> resultId; + MAKE_SWAP_METHOD(SemanticTokens, data, resultId) +}; +MAKE_REFLECT_STRUCT(SemanticTokens, data, resultId) + +/// Body of textDocument/semanticTokens/full request. +struct SemanticTokensParams { + /// The text document. + lsTextDocumentIdentifier textDocument; + MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument) +}; +MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument) + + +/// Body of textDocument/semanticTokens/full/delta request. +/// Requests the changes in semantic tokens since a previous response. +struct SemanticTokensDeltaParams { + /// The text document. + lsTextDocumentIdentifier textDocument; + /** + * The result id of a previous response. The result Id can either point to + * a full response or a delta response depending on what was received last. + */ + std::string previousResultId; + + MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId) +}; +MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId) + +/// Describes a a replacement of a contiguous range of semanticTokens. +struct SemanticTokensEdit { + // LSP specifies `start` and `deleteCount` which are relative to the array + // encoding of the previous tokens. + // We use token counts instead, and translate when serializing this struct. + unsigned startToken = 0; + unsigned deleteTokens = 0; + std::vector<int32_t> tokens; // encoded as a flat integer array + + MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens) +}; +MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens) + + +/// This models LSP SemanticTokensDelta | SemanticTokens, which is the result of +/// textDocument/semanticTokens/full/delta. +struct SemanticTokensOrDelta { + boost::optional<std::string > resultId; + /// Set if we computed edits relative to a previous set of tokens. + boost::optional< std::vector<SemanticTokensEdit> > edits; + /// Set if we computed a fresh set of tokens. + /// Set if we computed edits relative to a previous set of tokens. + boost::optional<std::vector<int32_t>> tokens; // encoded as integer array + MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens) +}; +MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens) + + +struct SemanticTokensLegend { + std::vector<std::string> tokenTypes; + std::vector<std::string> tokenModifiers; + MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers) +}; +MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers) + +DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full, SemanticTokensParams,boost::optional<SemanticTokens >,"textDocument/semanticTokens/full") +DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full_delta, SemanticTokensDeltaParams, boost::optional<SemanticTokensOrDelta >, "textDocument/semanticTokens/full/delta")
\ No newline at end of file |