blob: a70f8c8762c8e210df9c2f8da689583db3099352 [file] [log] [blame]
/*!
Language Server Protocol types for Rust.
Based on: <https://microsoft.github.io/language-server-protocol/specification>
This library uses the URL crate for parsing URIs. Note that there is
some confusion on the meaning of URLs vs URIs:
<http://stackoverflow.com/a/28865728/393898>. According to that
information, on the classical sense of "URLs", "URLs" are a subset of
URIs, But on the modern/new meaning of URLs, they are the same as
URIs. The important take-away aspect is that the URL crate should be
able to parse any URI, such as `urn:isbn:0451450523`.
*/
#![allow(non_upper_case_globals)]
#![forbid(unsafe_code)]
#[macro_use]
extern crate bitflags;
use serde::{Deserialize, Serialize};
use serde_json;
use serde_repr::{Deserialize_repr, Serialize_repr};
pub use url::Url;
use std::collections::HashMap;
#[cfg(feature = "proposed")]
use base64;
use serde::de;
use serde::de::Error as Error_;
use serde_json::Value;
#[cfg(feature = "proposed")]
use serde::ser::SerializeSeq;
#[cfg(feature = "proposed")]
use std::{borrow::Cow, convert::TryFrom};
pub mod notification;
pub mod request;
/* ----------------- Auxiliary types ----------------- */
#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum NumberOrString {
Number(u64),
String(String),
}
/* ----------------- Cancel support ----------------- */
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct CancelParams {
/// The request id to cancel.
pub id: NumberOrString,
}
/* ----------------- Basic JSON Structures ----------------- */
/// Position in a text document expressed as zero-based line and character offset.
/// A position is between two characters like an 'insert' cursor in a editor.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Default, Deserialize, Serialize)]
pub struct Position {
/// Line position in a document (zero-based).
pub line: u64,
/// Character offset on a line in a document (zero-based).
pub character: u64,
}
impl Position {
pub fn new(line: u64, character: u64) -> Position {
Position { line, character }
}
}
/// A range in a text document expressed as (zero-based) start and end positions.
/// A range is comparable to a selection in an editor. Therefore the end position is exclusive.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default, Deserialize, Serialize)]
pub struct Range {
/// The range's start position.
pub start: Position,
/// The range's end position.
pub end: Position,
}
impl Range {
pub fn new(start: Position, end: Position) -> Range {
Range { start, end }
}
}
/// Represents a location inside a resource, such as a line inside a text file.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct Location {
pub uri: Url,
pub range: Range,
}
impl Location {
pub fn new(uri: Url, range: Range) -> Location {
Location { uri, range }
}
}
/// Represents a link between a source and a target location.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LocationLink {
/// Span of the origin of this link.
///
/// Used as the underlined span for mouse interaction. Defaults to the word range at
/// the mouse position.
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_selection_range: Option<Range>,
/// The target resource identifier of this link.
pub target_uri: Url,
/// The full target range of this link.
pub target_range: Range,
/// The span of this link.
pub target_selection_range: Range,
}
/// Represents a diagnostic, such as a compiler error or warning.
/// Diagnostic objects are only valid in the scope of a resource.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Diagnostic {
/// The range at which the message applies.
pub 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.
#[serde(skip_serializing_if = "Option::is_none")]
pub severity: Option<DiagnosticSeverity>,
/// The diagnostic's code. Can be omitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<NumberOrString>,
// code?: number | string;
/// A human-readable string describing the source of this
/// diagnostic, e.g. 'typescript' or 'super lint'.
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
/// The diagnostic's message.
pub message: String,
/// An array of related diagnostic information, e.g. when symbol-names within
/// a scope collide all definitions can be marked via this property.
#[serde(skip_serializing_if = "Option::is_none")]
pub related_information: Option<Vec<DiagnosticRelatedInformation>>,
/// Additional metadata about the diagnostic.
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<DiagnosticTag>>,
}
impl Diagnostic {
pub fn new(
range: Range,
severity: Option<DiagnosticSeverity>,
code: Option<NumberOrString>,
source: Option<String>,
message: String,
related_information: Option<Vec<DiagnosticRelatedInformation>>,
tags: Option<Vec<DiagnosticTag>>,
) -> Diagnostic {
Diagnostic {
range,
severity,
code,
source,
message,
related_information,
tags,
}
}
pub fn new_simple(range: Range, message: String) -> Diagnostic {
Self::new(range, None, None, None, message, None, None)
}
pub fn new_with_code_number(
range: Range,
severity: DiagnosticSeverity,
code_number: u64,
source: Option<String>,
message: String,
) -> Diagnostic {
let code = Some(NumberOrString::Number(code_number));
Self::new(range, Some(severity), code, source, message, None, None)
}
}
/// The protocol currently supports the following diagnostic severities:
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum DiagnosticSeverity {
/// Reports an error.
Error = 1,
/// Reports a warning.
Warning = 2,
/// Reports an information.
Information = 3,
/// Reports a hint.
Hint = 4,
}
/// Represents a related message and source code location for a diagnostic. This
/// should be used to point to code locations that cause or related to a
/// diagnostics, e.g when duplicating a symbol in a scope.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct DiagnosticRelatedInformation {
/// The location of this related diagnostic information.
pub location: Location,
/// The message of this related diagnostic information.
pub message: String,
}
/// The diagnostic tags.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum DiagnosticTag {
/// Unused or unnecessary code.
/// Clients are allowed to render diagnostics with this tag faded out instead of having
/// an error squiggle.
Unnecessary = 1,
/// Deprecated or obsolete code.
/// Clients are allowed to rendered diagnostics with this tag strike through.
Deprecated = 2,
}
/// Represents a reference to a command. Provides a title which will be used to represent a command in the UI.
/// Commands are identitifed using a string identifier and the protocol currently doesn't specify a set of
/// well known commands. So executing a command requires some tool extension code.
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct Command {
/// Title of the command, like `save`.
pub title: String,
/// The identifier of the actual command handler.
pub command: String,
/// Arguments that the command handler should be
/// invoked with.
#[serde(skip_serializing_if = "Option::is_none")]
pub arguments: Option<Vec<Value>>,
}
impl Command {
pub fn new(title: String, command: String, arguments: Option<Vec<Value>>) -> Command {
Command {
title,
command,
arguments,
}
}
}
/// A textual edit applicable to a text document.
///
/// If n `TextEdit`s are applied to a text document all text edits describe changes to the initial document version.
/// Execution wise text edits should applied from the bottom to the top of the text document. Overlapping text edits
/// are not supported.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextEdit {
/// The range of the text document to be manipulated. To insert
/// text into a document create a range where start === end.
pub range: Range,
/// The string to be inserted. For delete operations use an
/// empty string.
pub new_text: String,
}
impl TextEdit {
pub fn new(range: Range, new_text: String) -> TextEdit {
TextEdit { range, new_text }
}
}
/// Describes textual changes on a single text document. The text document is referred to as a
/// `VersionedTextDocumentIdentifier` to allow clients to check the text document version before an
/// edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are
/// applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to
/// sort the array or do any kind of ordering. However the edits must be non overlapping.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentEdit {
/// The text document to change.
pub text_document: VersionedTextDocumentIdentifier,
/// The edits to be applied.
pub edits: Vec<TextEdit>,
}
/// A special text edit to provide an insert and a replace operation.
///
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct InsertReplaceEdit {
/// The string to be inserted.
pub new_text: String,
/// The range if the insert is requested
pub insert: Range,
/// The range if the replace is requested.
pub replace: Range,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CompletionTextEdit {
Edit(TextEdit),
#[cfg(feature = "proposed")]
InsertAndReplace(InsertReplaceEdit),
}
impl From<TextEdit> for CompletionTextEdit {
fn from(edit: TextEdit) -> Self {
CompletionTextEdit::Edit(edit)
}
}
#[cfg(feature = "proposed")]
impl From<InsertReplaceEdit> for CompletionTextEdit {
fn from(edit: InsertReplaceEdit) -> Self {
CompletionTextEdit::InsertAndReplace(edit)
}
}
/// Options to create a file.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateFileOptions {
/// Overwrite existing file. Overwrite wins over `ignoreIfExists`
#[serde(skip_serializing_if = "Option::is_none")]
pub overwrite: Option<bool>,
/// Ignore if exists.
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore_if_exists: Option<bool>,
}
/// Create file operation
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateFile {
/// The resource to create.
pub uri: Url,
/// Additional options
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<CreateFileOptions>,
}
/// Rename file options
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RenameFileOptions {
/// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
#[serde(skip_serializing_if = "Option::is_none")]
pub overwrite: Option<bool>,
/// Ignores if target exists.
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore_if_exists: Option<bool>,
}
/// Rename file operation
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RenameFile {
/// The old (existing) location.
pub old_uri: Url,
/// The new location.
pub new_uri: Url,
/// Rename options.
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<RenameFileOptions>,
}
/// Delete file options
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeleteFileOptions {
/// Delete the content recursively if a folder is denoted.
#[serde(skip_serializing_if = "Option::is_none")]
pub recursive: Option<bool>,
/// Ignore the operation if the file doesn't exist.
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore_if_not_exists: Option<bool>,
}
/// Delete file operation
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeleteFile {
/// The file to delete.
pub uri: Url,
/// Delete options.
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<DeleteFileOptions>,
}
/// A workspace edit represents changes to many resources managed in the workspace.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceEdit {
/// Holds changes to existing resources.
#[serde(with = "url_map")]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub changes: Option<HashMap<Url, Vec<TextEdit>>>, // changes?: { [uri: string]: TextEdit[]; };
/// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
/// are either an array of `TextDocumentEdit`s to express changes to n different text documents
/// where each text document edit addresses a specific version of a text document. Or it can contain
/// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
///
/// Whether a client supports versioned document edits is expressed via
/// `workspace.workspaceEdit.documentChanges` client capability.
///
/// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
/// only plain `TextEdit`s using the `changes` property are supported.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_changes: Option<DocumentChanges>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum DocumentChanges {
Edits(Vec<TextDocumentEdit>),
Operations(Vec<DocumentChangeOperation>),
}
// TODO: Once https://github.com/serde-rs/serde/issues/912 is solved
// we can remove ResourceOp and switch to the following implementation
// of DocumentChangeOperation:
//
// #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
// #[serde(tag = "kind", rename_all="lowercase" )]
// pub enum DocumentChangeOperation {
// Create(CreateFile),
// Rename(RenameFile),
// Delete(DeleteFile),
//
// #[serde(other)]
// Edit(TextDocumentEdit),
// }
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged, rename_all = "lowercase")]
pub enum DocumentChangeOperation {
Op(ResourceOp),
Edit(TextDocumentEdit),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum ResourceOp {
Create(CreateFile),
Rename(RenameFile),
Delete(DeleteFile),
}
#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfigurationParams {
pub items: Vec<ConfigurationItem>,
}
#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfigurationItem {
/// The scope to get the configuration section for.
#[serde(skip_serializing_if = "Option::is_none")]
pub scope_uri: Option<String>,
///The configuration section asked for.
#[serde(skip_serializing_if = "Option::is_none")]
pub section: Option<String>,
}
mod url_map {
use super::*;
use std::fmt;
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<Option<HashMap<Url, Vec<TextEdit>>>, D::Error>
where
D: serde::Deserializer<'de>,
{
struct UrlMapVisitor;
impl<'de> de::Visitor<'de> for UrlMapVisitor {
type Value = HashMap<Url, Vec<TextEdit>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("map")
}
fn visit_map<M>(self, mut visitor: M) -> Result<Self::Value, M::Error>
where
M: de::MapAccess<'de>,
{
let mut values = HashMap::with_capacity(visitor.size_hint().unwrap_or(0));
// While there are entries remaining in the input, add them
// into our map.
while let Some((key, value)) = visitor.next_entry::<Url, _>()? {
values.insert(key, value);
}
Ok(values)
}
}
struct OptionUrlMapVisitor;
impl<'de> de::Visitor<'de> for OptionUrlMapVisitor {
type Value = Option<HashMap<Url, Vec<TextEdit>>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("option")
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(None)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(None)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(UrlMapVisitor).map(Some)
}
}
// Instantiate our Visitor and ask the Deserializer to drive
// it over the input data, resulting in an instance of MyMap.
deserializer.deserialize_option(OptionUrlMapVisitor)
}
pub fn serialize<S>(
changes: &Option<HashMap<Url, Vec<TextEdit>>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeMap;
match *changes {
Some(ref changes) => {
let mut map = serializer.serialize_map(Some(changes.len()))?;
for (k, v) in changes {
map.serialize_entry(k.as_str(), v)?;
}
map.end()
}
None => serializer.serialize_none(),
}
}
}
impl WorkspaceEdit {
pub fn new(changes: HashMap<Url, Vec<TextEdit>>) -> WorkspaceEdit {
WorkspaceEdit {
changes: Some(changes),
document_changes: None,
}
}
}
/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct TextDocumentIdentifier {
// !!!!!! Note:
// In the spec VersionedTextDocumentIdentifier extends TextDocumentIdentifier
// This modelled by "mixing-in" TextDocumentIdentifier in VersionedTextDocumentIdentifier,
// so any changes to this type must be effected in the sub-type as well.
/// The text document's URI.
pub uri: Url,
}
impl TextDocumentIdentifier {
pub fn new(uri: Url) -> TextDocumentIdentifier {
TextDocumentIdentifier { uri }
}
}
/// An item to transfer a text document from the client to the server.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentItem {
/// The text document's URI.
pub uri: Url,
/// The text document's language identifier.
pub language_id: String,
/// The version number of this document (it will strictly increase after each
/// change, including undo/redo).
pub version: i64,
/// The content of the opened text document.
pub text: String,
}
impl TextDocumentItem {
pub fn new(uri: Url, language_id: String, version: i64, text: String) -> TextDocumentItem {
TextDocumentItem {
uri,
language_id,
version,
text,
}
}
}
/// An identifier to denote a specific version of a text document.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct VersionedTextDocumentIdentifier {
// This field was "mixed-in" from TextDocumentIdentifier
/// The text document's URI.
pub uri: Url,
/// The version number of this document.
pub version: Option<i64>,
}
impl VersionedTextDocumentIdentifier {
pub fn new(uri: Url, version: i64) -> VersionedTextDocumentIdentifier {
VersionedTextDocumentIdentifier {
uri,
version: Some(version),
}
}
}
/// A parameter literal used in requests to pass a text document and a position inside that document.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentPositionParams {
// !!!!!! Note:
// In the spec ReferenceParams extends TextDocumentPositionParams
// This modelled by "mixing-in" TextDocumentPositionParams in ReferenceParams,
// so any changes to this type must be effected in sub-type as well.
/// The text document.
pub text_document: TextDocumentIdentifier,
/// The position inside the text document.
pub position: Position,
}
impl TextDocumentPositionParams {
pub fn new(
text_document: TextDocumentIdentifier,
position: Position,
) -> TextDocumentPositionParams {
TextDocumentPositionParams {
text_document,
position,
}
}
}
/// A document filter denotes a document through properties like language, schema or pattern.
/// Examples are a filter that applies to TypeScript files on disk or a filter the applies to JSON
/// files with name package.json:
///
/// { language: 'typescript', scheme: 'file' }
/// { language: 'json', pattern: '**/package.json' }
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct DocumentFilter {
/// A language id, like `typescript`.
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
/// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
#[serde(skip_serializing_if = "Option::is_none")]
pub scheme: Option<String>,
/// A glob pattern, like `*.{ts,js}`.
#[serde(skip_serializing_if = "Option::is_none")]
pub pattern: Option<String>,
}
/// A document selector is the combination of one or many document filters.
pub type DocumentSelector = Vec<DocumentFilter>;
// ========================= Actual Protocol =========================
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub 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.
pub process_id: Option<u64>,
/// The rootPath of the workspace. Is null
/// if no folder is open.
#[serde(skip_serializing_if = "Option::is_none")]
#[deprecated(note = "Use `root_uri` instead when possible")]
pub root_path: Option<String>,
/// The rootUri of the workspace. Is null if no
/// folder is open. If both `rootPath` and `rootUri` are set
/// `rootUri` wins.
#[serde(default)]
pub root_uri: Option<Url>,
/// User provided initialization options.
#[serde(skip_serializing_if = "Option::is_none")]
pub initialization_options: Option<Value>,
/// The capabilities provided by the client (editor)
pub capabilities: ClientCapabilities,
/// The initial trace setting. If omitted trace is disabled ('off').
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub trace: Option<TraceOption>,
/// 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.
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_folders: Option<Vec<WorkspaceFolder>>,
/// Information about the client.
#[serde(skip_serializing_if = "Option::is_none")]
pub client_info: Option<ClientInfo>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct ClientInfo {
/// The name of the client as defined by the client.
pub name: String,
/// The client's version as defined by the client.
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
pub struct InitializedParams {}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
pub enum TraceOption {
#[serde(rename = "off")]
Off,
#[serde(rename = "messages")]
Messages,
#[serde(rename = "verbose")]
Verbose,
}
impl Default for TraceOption {
fn default() -> TraceOption {
TraceOption::Off
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct GenericRegistrationOptions {
#[serde(flatten)]
pub text_document_registration_options: TextDocumentRegistrationOptions,
#[serde(flatten)]
pub options: GenericOptions,
#[serde(flatten)]
pub static_registration_options: StaticRegistrationOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct GenericOptions {
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct GenericParams {
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GenericCapability {
/// This capability supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GotoCapability {
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The client supports additional metadata in the form of definition links.
pub link_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceEditCapability {
/// The client supports versioned document changes in `WorkspaceEdit`s
#[serde(skip_serializing_if = "Option::is_none")]
pub document_changes: Option<bool>,
/// The resource operations the client supports. Clients should at least
/// support 'create', 'rename' and 'delete' files and folders.
#[serde(skip_serializing_if = "Option::is_none")]
pub resource_operations: Option<Vec<ResourceOperationKind>>,
/// The failure handling strategy of a client if applying the workspace edit
/// failes.
#[serde(skip_serializing_if = "Option::is_none")]
pub failure_handling: Option<FailureHandlingKind>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceCapability {
/// The server supports workspace folder.
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_folders: Option<WorkspaceFolderCapability>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceFolderCapability {
#[serde(skip_serializing_if = "Option::is_none")]
pub supported: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub change_notifications: Option<WorkspaceFolderCapabilityChangeNotifications>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum WorkspaceFolderCapabilityChangeNotifications {
Bool(bool),
Id(String),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceFolder {
/// The associated URI for this workspace folder.
pub uri: Url,
/// The name of the workspace folder. Defaults to the uri's basename.
pub name: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidChangeWorkspaceFoldersParams {
/// The actual workspace folder change event.
pub event: WorkspaceFoldersChangeEvent,
}
/// The workspace folder change event.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceFoldersChangeEvent {
/// The array of added workspace folders
pub added: Vec<WorkspaceFolder>,
/// The array of the removed workspace folders
pub removed: Vec<WorkspaceFolder>,
}
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
#[serde(rename_all = "lowercase")]
pub enum ResourceOperationKind {
Create,
Rename,
Delete,
}
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
#[serde(rename_all = "camelCase")]
pub enum FailureHandlingKind {
Abort,
Transactional,
TextOnlyTransactional,
Undo,
}
/// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SymbolKindCapability {
/// 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.
pub value_set: Option<Vec<SymbolKind>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SymbolCapability {
/// This capability supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
#[serde(skip_serializing_if = "Option::is_none")]
pub symbol_kind: Option<SymbolKindCapability>,
}
/// Workspace specific client capabilities.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceClientCapabilities {
/// The client supports applying batch edits to the workspace by supporting
/// the request 'workspace/applyEdit'
#[serde(skip_serializing_if = "Option::is_none")]
pub apply_edit: Option<bool>,
/// Capabilities specific to `WorkspaceEdit`s
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_edit: Option<WorkspaceEditCapability>,
/// Capabilities specific to the `workspace/didChangeConfiguration` notification.
#[serde(skip_serializing_if = "Option::is_none")]
pub did_change_configuration: Option<GenericCapability>,
/// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
#[serde(skip_serializing_if = "Option::is_none")]
pub did_change_watched_files: Option<GenericCapability>,
/// Capabilities specific to the `workspace/symbol` request.
#[serde(skip_serializing_if = "Option::is_none")]
pub symbol: Option<SymbolCapability>,
/// Capabilities specific to the `workspace/executeCommand` request.
#[serde(skip_serializing_if = "Option::is_none")]
pub execute_command: Option<GenericCapability>,
/// The client has support for workspace folders.
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_folders: Option<bool>,
/// The client supports `workspace/configuration` requests.
#[serde(skip_serializing_if = "Option::is_none")]
pub configuration: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SynchronizationCapability {
/// Whether text document synchronization supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The client supports sending will save notifications.
#[serde(skip_serializing_if = "Option::is_none")]
pub will_save: Option<bool>,
/// 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.
#[serde(skip_serializing_if = "Option::is_none")]
pub will_save_wait_until: Option<bool>,
/// The client supports did save notifications.
#[serde(skip_serializing_if = "Option::is_none")]
pub did_save: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionItemCapability {
/// 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.
#[serde(skip_serializing_if = "Option::is_none")]
pub snippet_support: Option<bool>,
/// Client supports commit characters on a completion item.
#[serde(skip_serializing_if = "Option::is_none")]
pub commit_characters_support: Option<bool>,
/// Client supports the follow content formats for the documentation
/// property. The order describes the preferred format of the client.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation_format: Option<Vec<MarkupKind>>,
/// Client supports the deprecated property on a completion item.
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated_support: Option<bool>,
/// Client supports the preselect property on a completion item.
#[serde(skip_serializing_if = "Option::is_none")]
pub preselect_support: Option<bool>,
/// Client supports the tag property on a completion item. Clients supporting
/// tags have to handle unknown tags gracefully. Clients especially need to
/// preserve unknown tags when sending a completion item back to the server in
/// a resolve call.
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "TagSupport::deserialize_compat"
)]
pub tag_support: Option<TagSupport<CompletionItemTag>>,
/// Client support insert replace edit to control different behavior if a
/// completion item is inserted in the text or should replace text.
///
/// @since 3.16.0 - Proposed state
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg(feature = "proposed")]
pub insert_replace_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum CompletionItemTag {
Deprecated = 1,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionItemKindCapability {
/// The completion item 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 completion items kinds from `Text` to `Reference` as defined in
/// the initial version of the protocol.
#[serde(skip_serializing_if = "Option::is_none")]
pub value_set: Option<Vec<CompletionItemKind>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HoverCapability {
/// Whether completion supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// Client supports the follow content formats for the content
/// property. The order describes the preferred format of the client.
#[serde(skip_serializing_if = "Option::is_none")]
pub content_format: Option<Vec<MarkupKind>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionCapability {
/// Whether completion supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The client supports the following `CompletionItem` specific
/// capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub completion_item: Option<CompletionItemCapability>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completion_item_kind: Option<CompletionItemKindCapability>,
/// The client supports to send additional context information for a
/// `textDocument/completion` requestion.
#[serde(skip_serializing_if = "Option::is_none")]
pub context_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureInformationSettings {
/// Client supports the follow content formats for the documentation
/// property. The order describes the preferred format of the client.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation_format: Option<Vec<MarkupKind>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameter_information: Option<ParameterInformationSettings>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ParameterInformationSettings {
/// The client supports processing label offsets instead of a
/// simple label string.
#[serde(skip_serializing_if = "Option::is_none")]
pub label_offset_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureHelpCapability {
/// Whether completion supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The client supports the following `SignatureInformation`
/// specific properties.
#[serde(skip_serializing_if = "Option::is_none")]
pub signature_information: Option<SignatureInformationSettings>,
/// The client supports to send additional context information for a
/// `textDocument/signatureHelp` request. A client that opts into
/// contextSupport will also support the `retriggerCharacters` on
/// `SignatureHelpOptions`.
#[serde(skip_serializing_if = "Option::is_none")]
pub context_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PublishDiagnosticsCapability {
/// Whether the clients accepts diagnostics with related information.
#[serde(skip_serializing_if = "Option::is_none")]
pub related_information: Option<bool>,
/// Client supports the tag property to provide meta data about a diagnostic.
/// Clients supporting tags have to handle unknown tags gracefully.
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "TagSupport::deserialize_compat"
)]
pub tag_support: Option<TagSupport<DiagnosticTag>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TagSupport<T> {
/// The tags supported by the client.
pub value_set: Vec<T>,
}
impl<T> TagSupport<T> {
/// Support for deserializing a boolean tag Support, in case it's present.
///
/// This is currently the case for vscode 1.41.1
fn deserialize_compat<'de, S>(serializer: S) -> Result<Option<TagSupport<T>>, S::Error>
where
S: serde::Deserializer<'de>,
T: serde::Deserialize<'de>,
{
Ok(
match Option::<Value>::deserialize(serializer).map_err(serde::de::Error::custom)? {
Some(Value::Bool(false)) => None,
Some(Value::Bool(true)) => Some(TagSupport { value_set: vec![] }),
Some(other) => {
Some(TagSupport::<T>::deserialize(other).map_err(serde::de::Error::custom)?)
}
None => None,
},
)
}
}
/// Text document specific client capabilities.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentClientCapabilities {
#[serde(skip_serializing_if = "Option::is_none")]
pub synchronization: Option<SynchronizationCapability>,
/// Capabilities specific to the `textDocument/completion`
#[serde(skip_serializing_if = "Option::is_none")]
pub completion: Option<CompletionCapability>,
/// Capabilities specific to the `textDocument/hover`
#[serde(skip_serializing_if = "Option::is_none")]
pub hover: Option<HoverCapability>,
/// Capabilities specific to the `textDocument/signatureHelp`
#[serde(skip_serializing_if = "Option::is_none")]
pub signature_help: Option<SignatureHelpCapability>,
/// Capabilities specific to the `textDocument/references`
#[serde(skip_serializing_if = "Option::is_none")]
pub references: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/documentHighlight`
#[serde(skip_serializing_if = "Option::is_none")]
pub document_highlight: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/documentSymbol`
#[serde(skip_serializing_if = "Option::is_none")]
pub document_symbol: Option<DocumentSymbolCapability>,
/// Capabilities specific to the `textDocument/formatting`
#[serde(skip_serializing_if = "Option::is_none")]
pub formatting: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/rangeFormatting`
#[serde(skip_serializing_if = "Option::is_none")]
pub range_formatting: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/onTypeFormatting`
#[serde(skip_serializing_if = "Option::is_none")]
pub on_type_formatting: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/declaration`
#[serde(skip_serializing_if = "Option::is_none")]
pub declaration: Option<GotoCapability>,
/// Capabilities specific to the `textDocument/definition`
#[serde(skip_serializing_if = "Option::is_none")]
pub definition: Option<GotoCapability>,
/// Capabilities specific to the `textDocument/typeDefinition`
#[serde(skip_serializing_if = "Option::is_none")]
pub type_definition: Option<GotoCapability>,
/// Capabilities specific to the `textDocument/implementation`
#[serde(skip_serializing_if = "Option::is_none")]
pub implementation: Option<GotoCapability>,
/// Capabilities specific to the `textDocument/codeAction`
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action: Option<CodeActionCapability>,
/// Capabilities specific to the `textDocument/codeLens`
#[serde(skip_serializing_if = "Option::is_none")]
pub code_lens: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/documentLink`
#[serde(skip_serializing_if = "Option::is_none")]
pub document_link: Option<DocumentLinkCapabilities>,
/// Capabilities specific to the `textDocument/documentColor` and the
/// `textDocument/colorPresentation` request.
#[serde(skip_serializing_if = "Option::is_none")]
pub color_provider: Option<GenericCapability>,
/// Capabilities specific to the `textDocument/rename`
#[serde(skip_serializing_if = "Option::is_none")]
pub rename: Option<RenameCapability>,
/// Capabilities specific to `textDocument/publishDiagnostics`.
#[serde(skip_serializing_if = "Option::is_none")]
pub publish_diagnostics: Option<PublishDiagnosticsCapability>,
/// Capabilities specific to `textDocument/foldingRange` requests.
#[serde(skip_serializing_if = "Option::is_none")]
pub folding_range: Option<FoldingRangeCapability>,
/// The client's semantic highlighting capability.
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg(feature = "proposed")]
pub semantic_highlighting_capabilities: Option<SemanticHighlightingClientCapability>,
/// Capabilities specific to the `textDocument/semanticTokens`
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg(feature = "proposed")]
pub semantic_tokens: Option<SemanticTokensClientCapabilities>,
}
/// Window specific client capabilities.
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WindowClientCapabilities {
/// Whether client supports create a work done progress UI from the server side.
#[serde(skip_serializing_if = "Option::is_none")]
pub work_done_progress: Option<bool>,
}
/// Where ClientCapabilities are currently empty:
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientCapabilities {
/// Workspace specific client capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace: Option<WorkspaceClientCapabilities>,
/// Text document specific client capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_document: Option<TextDocumentClientCapabilities>,
/// Window specific client capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub window: Option<WindowClientCapabilities>,
/// Experimental client capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub experimental: Option<Value>,
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InitializeResult {
/// The capabilities the language server provides.
pub capabilities: ServerCapabilities,
/// The capabilities the language server provides.
#[serde(skip_serializing_if = "Option::is_none")]
pub server_info: Option<ServerInfo>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct ServerInfo {
/// The name of the server as defined by the server.
pub name: String,
/// The servers's version as defined by the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct InitializeError {
/// Indicates whether the client should retry to send the
/// initilize request after showing the message provided
/// in the ResponseError.
pub retry: bool,
}
// The server can signal the following capabilities:
/// Defines how the host (editor) should sync document changes to the language server.
#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum 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.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionOptions {
/// The server provides support to resolve additional information for a completion item.
#[serde(skip_serializing_if = "Option::is_none")]
pub resolve_provider: Option<bool>,
/// The characters that trigger completion automatically.
#[serde(skip_serializing_if = "Option::is_none")]
pub trigger_characters: Option<Vec<String>>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
/// Signature help options.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureHelpOptions {
/// The characters that trigger signature help automatically.
#[serde(skip_serializing_if = "Option::is_none")]
pub trigger_characters: Option<Vec<String>>,
/// 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.
#[serde(skip_serializing_if = "Option::is_none")]
pub retrigger_characters: Option<Vec<String>>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
/// Signature help options.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct SignatureHelpRegistrationOptions {
#[serde(flatten)]
pub text_document_registration_options: TextDocumentRegistrationOptions,
}
/// Signature help options.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum SignatureHelpTriggerKind {
/// Signature help was invoked manually by the user or by a command.
Invoked = 1,
/// Signature help was triggered by a trigger character.
TriggerCharacter = 2,
/// Signature help was triggered by the cursor moving or by the document content changing.
ContentChange = 3,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureHelpParams {
/// The signature help context. This is only available if the client specifies
/// to send this using the client capability `textDocument.signatureHelp.contextSupport === true`
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<SignatureHelpContext>,
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureHelpContext {
/// Action that caused signature help to be triggered.
pub trigger_kind: SignatureHelpTriggerKind,
/// Character that caused signature help to be triggered.
/// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`
#[serde(skip_serializing_if = "Option::is_none")]
pub trigger_character: Option<String>,
/// `true` if signature help was already showing when it was triggered.
/// Retriggers occur when the signature help is already active and can be caused by actions such as
/// typing a trigger character, a cursor move, or document content changes.
pub is_retrigger: bool,
/// The currently active `SignatureHelp`.
/// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on
/// the user navigating through available signatures.
#[serde(skip_serializing_if = "Option::is_none")]
pub active_signature_help: Option<SignatureHelp>,
}
/// Code Lens options.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeLensOptions {
/// Code lens has a resolve provider as well.
#[serde(skip_serializing_if = "Option::is_none")]
pub resolve_provider: Option<bool>,
}
/// Format document on type options
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentOnTypeFormattingOptions {
/// A character on which formatting should be triggered, like `}`.
pub first_trigger_character: String,
/// More trigger characters.
#[serde(skip_serializing_if = "Option::is_none")]
pub more_trigger_character: Option<Vec<String>>,
}
/// Execute command options.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct ExecuteCommandOptions {
/// The commands to be executed on the server
pub commands: Vec<String>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
/// Save options.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SaveOptions {
/// The client is supposed to include the content on save.
#[serde(skip_serializing_if = "Option::is_none")]
pub include_text: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentSyncOptions {
/// Open and close notifications are sent to the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub open_close: Option<bool>,
/// Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
/// and TextDocumentSyncKindIncremental.
#[serde(skip_serializing_if = "Option::is_none")]
pub change: Option<TextDocumentSyncKind>,
/// Will save notifications are sent to the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub will_save: Option<bool>,
/// Will save wait until requests are sent to the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub will_save_wait_until: Option<bool>,
/// Save notifications are sent to the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub save: Option<SaveOptions>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum TextDocumentSyncCapability {
Kind(TextDocumentSyncKind),
Options(TextDocumentSyncOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ImplementationProviderCapability {
Simple(bool),
Options(StaticTextDocumentRegistrationOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum TypeDefinitionProviderCapability {
Simple(bool),
Options(StaticTextDocumentRegistrationOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ColorProviderCapability {
Simple(bool),
ColorProvider(ColorProviderOptions),
Options(StaticTextDocumentColorProviderOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CodeActionProviderCapability {
Simple(bool),
Options(CodeActionOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionCapability {
///
/// This capability supports dynamic registration.
///
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The client support code action literals as a valid
/// response of the `textDocument/codeAction` request.
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action_literal_support: Option<CodeActionLiteralSupport>,
/// Whether code action supports the `isPreferred` property.
#[serde(skip_serializing_if = "Option::is_none")]
pub is_preferred_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionLiteralSupport {
/// The code action kind is support with the following value set.
pub code_action_kind: CodeActionKindLiteralSupport,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionKindLiteralSupport {
/// The code action 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.
pub value_set: Vec<String>,
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ServerCapabilities {
/// Defines how text documents are synced.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_document_sync: Option<TextDocumentSyncCapability>,
/// Capabilities specific to `textDocument/selectionRange` requests.
#[serde(skip_serializing_if = "Option::is_none")]
pub selection_range_provider: Option<SelectionRangeProviderCapability>,
/// The server provides hover support.
#[serde(skip_serializing_if = "Option::is_none")]
pub hover_provider: Option<bool>,
/// The server provides completion support.
#[serde(skip_serializing_if = "Option::is_none")]
pub completion_provider: Option<CompletionOptions>,
/// The server provides signature help support.
#[serde(skip_serializing_if = "Option::is_none")]
pub signature_help_provider: Option<SignatureHelpOptions>,
/// The server provides goto definition support.
#[serde(skip_serializing_if = "Option::is_none")]
pub definition_provider: Option<bool>,
/// The server provides goto type definition support.
#[serde(skip_serializing_if = "Option::is_none")]
pub type_definition_provider: Option<TypeDefinitionProviderCapability>,
/// the server provides goto implementation support.
#[serde(skip_serializing_if = "Option::is_none")]
pub implementation_provider: Option<ImplementationProviderCapability>,
/// The server provides find references support.
#[serde(skip_serializing_if = "Option::is_none")]
pub references_provider: Option<bool>,
/// The server provides document highlight support.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_highlight_provider: Option<bool>,
/// The server provides document symbol support.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_symbol_provider: Option<bool>,
/// The server provides workspace symbol support.
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_symbol_provider: Option<bool>,
/// The server provides code actions.
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action_provider: Option<CodeActionProviderCapability>,
/// The server provides code lens.
#[serde(skip_serializing_if = "Option::is_none")]
pub code_lens_provider: Option<CodeLensOptions>,
/// The server provides document formatting.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_formatting_provider: Option<bool>,
/// The server provides document range formatting.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_range_formatting_provider: Option<bool>,
/// The server provides document formatting on typing.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_on_type_formatting_provider: Option<DocumentOnTypeFormattingOptions>,
/// The server provides rename support.
#[serde(skip_serializing_if = "Option::is_none")]
pub rename_provider: Option<RenameProviderCapability>,
/// The server provides document link support.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_link_provider: Option<DocumentLinkOptions>,
/// The server provides color provider support.
#[serde(skip_serializing_if = "Option::is_none")]
pub color_provider: Option<ColorProviderCapability>,
/// The server provides folding provider support.
#[serde(skip_serializing_if = "Option::is_none")]
pub folding_range_provider: Option<FoldingRangeProviderCapability>,
/// The server provides go to declaration support.
#[serde(skip_serializing_if = "Option::is_none")]
pub declaration_provider: Option<bool>,
/// The server provides execute command support.
#[serde(skip_serializing_if = "Option::is_none")]
pub execute_command_provider: Option<ExecuteCommandOptions>,
/// Workspace specific server capabilities
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace: Option<WorkspaceCapability>,
/// Semantic highlighting server capabilities.
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub semantic_highlighting: Option<SemanticHighlightingServerCapability>,
/// Call hierarchy provider capabilities.
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub call_hierarchy_provider: Option<CallHierarchyServerCapability>,
/// Semantic tokens server capabilities.
#[cfg(feature = "proposed")]
#[serde(skip_serializing_if = "Option::is_none")]
pub semantic_tokens_provider: Option<SemanticTokensServerCapabilities>,
/// Experimental server capabilities.
#[serde(skip_serializing_if = "Option::is_none")]
pub experimental: Option<Value>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentLinkCapabilities {
/// Whether document link supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// Whether the client support the `tooltip` property on `DocumentLink`.
#[serde(skip_serializing_if = "Option::is_none")]
pub tooltip_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ShowMessageParams {
/// The message type. See {@link MessageType}.
#[serde(rename = "type")]
pub typ: MessageType,
/// The actual message.
pub message: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum MessageType {
/// An error message.
Error = 1,
/// A warning message.
Warning = 2,
/// An information message.
Info = 3,
/// A log message.
Log = 4,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ShowMessageRequestParams {
/// The message type. See {@link MessageType}
#[serde(rename = "type")]
pub typ: MessageType,
/// The actual message
pub message: String,
/// The message action items to present.
#[serde(skip_serializing_if = "Option::is_none")]
pub actions: Option<Vec<MessageActionItem>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct MessageActionItem {
/// A short title like 'Retry', 'Open Log' etc.
pub title: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct LogMessageParams {
/// The message type. See {@link MessageType}
#[serde(rename = "type")]
pub typ: MessageType,
/// The actual message
pub message: String,
}
/// General parameters to to register for a capability.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Registration {
/// The id used to register the request. The id can be used to deregister
/// the request again.
pub id: String,
/// The method / capability to register for.
pub method: String,
/// Options necessary for the registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub register_options: Option<Value>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct RegistrationParams {
pub registrations: Vec<Registration>,
}
/// Since most of the registration options require to specify a document selector there is a base
/// interface that can be used.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentRegistrationOptions {
/// A document selector to identify the scope of the registration. If set to null
/// the document selector provided on the client side will be used.
pub document_selector: Option<DocumentSelector>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StaticRegistrationOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StaticTextDocumentRegistrationOptions {
/// A document selector to identify the scope of the registration. If set to null
/// the document selector provided on the client side will be used.
pub document_selector: Option<DocumentSelector>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ColorProviderOptions {}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StaticTextDocumentColorProviderOptions {
/// A document selector to identify the scope of the registration. If set to null
/// the document selector provided on the client side will be used.
pub document_selector: Option<DocumentSelector>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
}
/// General parameters to unregister a capability.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct Unregistration {
/// The id used to unregister the request or notification. Usually an id
/// provided during the register request.
pub id: String,
/// The method / capability to unregister for.
pub method: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct UnregistrationParams {
pub unregisterations: Vec<Unregistration>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct DidChangeConfigurationParams {
/// The actual changed settings
pub settings: Value,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidOpenTextDocumentParams {
/// The document that was opened.
pub text_document: TextDocumentItem,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidChangeTextDocumentParams {
/// The document that did change. The version number points
/// to the version after all provided content changes have
/// been applied.
pub text_document: VersionedTextDocumentIdentifier,
/// The actual content changes.
pub content_changes: Vec<TextDocumentContentChangeEvent>,
}
/// An event describing a change to a text document. If range and rangeLength are omitted
/// the new text is considered to be the full content of the document.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentContentChangeEvent {
/// The range of the document that changed.
#[serde(skip_serializing_if = "Option::is_none")]
pub range: Option<Range>,
/// The length of the range that got replaced.
/// NOTE: seems redundant, see: <https://github.com/Microsoft/language-server-protocol/issues/9>
#[serde(skip_serializing_if = "Option::is_none")]
pub range_length: Option<u64>,
/// The new text of the document.
pub text: String,
}
/// Descibe options to be used when registered for text document change events.
///
/// Extends TextDocumentRegistrationOptions
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextDocumentChangeRegistrationOptions {
/// A document selector to identify the scope of the registration. If set to null
/// the document selector provided on the client side will be used.
pub document_selector: Option<DocumentSelector>,
/// How documents are synced to the server. See TextDocumentSyncKind.Full
/// and TextDocumentSyncKindIncremental.
pub sync_kind: i32,
}
/// The parameters send in a will save text document notification.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WillSaveTextDocumentParams {
/// The document that will be saved.
pub text_document: TextDocumentIdentifier,
/// The 'TextDocumentSaveReason'.
pub reason: TextDocumentSaveReason,
}
/// Represents reasons why a text document is saved.
#[derive(Copy, Debug, Eq, PartialEq, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum TextDocumentSaveReason {
/// Manually triggered, e.g. by the user pressing save, by starting debugging,
/// or by an API call.
Manual = 1,
/// Automatic after a delay.
AfterDelay = 2,
/// When the editor lost focus.
FocusOut = 3,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidCloseTextDocumentParams {
/// The document that was closed.
pub text_document: TextDocumentIdentifier,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidSaveTextDocumentParams {
/// The document that was saved.
pub text_document: TextDocumentIdentifier,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct DidChangeWatchedFilesParams {
/// The actual file events.
pub changes: Vec<FileEvent>,
}
/// The file event type.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum FileChangeType {
/// The file got created.
Created = 1,
/// The file got changed.
Changed = 2,
/// The file got deleted.
Deleted = 3,
}
/// An event describing a file change.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct FileEvent {
/// The file's URI.
pub uri: Url,
/// The change type.
#[serde(rename = "type")]
pub typ: FileChangeType,
}
impl FileEvent {
pub fn new(uri: Url, typ: FileChangeType) -> FileEvent {
FileEvent { uri, typ }
}
}
/// Describe options to be used when registered for text document change events.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
pub struct DidChangeWatchedFilesRegistrationOptions {
/// The watchers to register.
pub watchers: Vec<FileSystemWatcher>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FileSystemWatcher {
/// The glob pattern to watch
pub glob_pattern: String,
/// The kind of events of interest. If omitted it defaults to WatchKind.Create |
/// WatchKind.Change | WatchKind.Delete which is 7.
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<WatchKind>,
}
bitflags! {
pub struct WatchKind: u8 {
/// Interested in create events.
const Create = 1;
/// Interested in change events
const Change = 2;
/// Interested in delete events
const Delete = 4;
}
}
impl<'de> serde::Deserialize<'de> for WatchKind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let i = u8::deserialize(deserializer)?;
WatchKind::from_bits(i).ok_or_else(|| {
D::Error::invalid_value(de::Unexpected::Unsigned(u64::from(i)), &"Unknown flag")
})
}
}
impl serde::Serialize for WatchKind {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(self.bits())
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct PublishDiagnosticsParams {
/// The URI for which diagnostic information is reported.
pub uri: Url,
/// An array of diagnostic information items.
pub diagnostics: Vec<Diagnostic>,
/// Optional the version number of the document the diagnostics are published for.
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<i64>,
}
impl PublishDiagnosticsParams {
pub fn new(
uri: Url,
diagnostics: Vec<Diagnostic>,
version: Option<i64>,
) -> PublishDiagnosticsParams {
PublishDiagnosticsParams {
uri,
diagnostics,
version,
}
}
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct CompletionRegistrationOptions {
#[serde(flatten)]
pub text_document_registration_options: TextDocumentRegistrationOptions,
#[serde(flatten)]
pub completion_options: CompletionOptions,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CompletionResponse {
Array(Vec<CompletionItem>),
List(CompletionList),
}
impl From<Vec<CompletionItem>> for CompletionResponse {
fn from(items: Vec<CompletionItem>) -> Self {
CompletionResponse::Array(items)
}
}
impl From<CompletionList> for CompletionResponse {
fn from(list: CompletionList) -> Self {
CompletionResponse::List(list)
}
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionParams {
// This field was "mixed-in" from TextDocumentPositionParams
#[serde(flatten)]
pub text_document_position: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
// CompletionParams properties:
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<CompletionContext>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionContext {
/// How the completion was triggered.
pub trigger_kind: CompletionTriggerKind,
/// The trigger character (a single character) that has trigger code complete.
/// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
#[serde(skip_serializing_if = "Option::is_none")]
pub trigger_character: Option<String>,
}
/// How a completion was triggered.
#[derive(Debug, PartialEq, Clone, Copy, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum CompletionTriggerKind {
Invoked = 1,
TriggerCharacter = 2,
TriggerForIncompleteCompletions = 3,
}
/// Represents a collection of [completion items](#CompletionItem) to be presented
/// in the editor.
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CompletionList {
/// This list it not complete. Further typing should result in recomputing
/// this list.
pub is_incomplete: bool,
/// The completion items.
pub items: Vec<CompletionItem>,
}
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
#[serde(untagged)]
pub enum Documentation {
String(String),
MarkupContent(MarkupContent),
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CompletionItem {
/// The label of this completion item. By default
/// also the text that is inserted when selecting
/// this completion.
pub label: String,
/// The kind of this completion item. Based of the kind
/// an icon is chosen by the editor.
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<CompletionItemKind>,
/// A human-readable string with additional information
/// about this item, like type or symbol information.
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
/// A human-readable string that represents a doc-comment.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<Documentation>,
/// Indicates if this item is deprecated.
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated: Option<bool>,
/// Select this item when showing.
#[serde(skip_serializing_if = "Option::is_none")]
pub preselect: Option<bool>,
/// A string that shoud be used when comparing this item
/// with other items. When `falsy` the label is used.
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_text: Option<String>,
/// A string that should be used when filtering a set of
/// completion items. When `falsy` the label is used.
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_text: Option<String>,
/// A string that should be inserted a document when selecting
/// this completion. When `falsy` the label is used.
#[serde(skip_serializing_if = "Option::is_none")]
pub insert_text: Option<String>,
/// The format of the insert text. The format applies to both the `insertText` property
/// and the `newText` property of a provided `textEdit`.
#[serde(skip_serializing_if = "Option::is_none")]
pub insert_text_format: Option<InsertTextFormat>,
/// An edit which is applied to a document when selecting
/// this completion. When an edit is provided the value of
/// insertText is ignored.
///
/// Most editors support two different operation when accepting a completion item. One is to insert a
/// completion text and the other is to replace an existing text with a competion text. Since this can
/// usually not predetermend by a server it can report both ranges. Clients need to signal support for
/// `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability
/// property.
///
/// *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a
/// [single line] and they must contain the position at which completion has been requested.
/// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of
/// the edit's replace range, that means it must be contained and starting at the same position.
///
/// @since 3.16.0 additional type `InsertReplaceEdit` - Proposed state
#[serde(skip_serializing_if = "Option::is_none")]
pub text_edit: Option<CompletionTextEdit>,
/// An optional array of additional text edits that are applied when
/// selecting this completion. Edits must not overlap with the main edit
/// nor with themselves.
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_text_edits: Option<Vec<TextEdit>>,
/// An optional command that is executed *after* inserting this completion. *Note* that
/// additional modifications to the current document should be described with the
/// additionalTextEdits-property.
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<Command>,
/// An data entry field that is preserved on a completion item between
/// a completion and a completion resolve request.
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
/// Tags for this completion item.
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<CompletionItemTag>>,
}
impl CompletionItem {
/// Create a CompletionItem with the minimum possible info (label and detail).
pub fn new_simple(label: String, detail: String) -> CompletionItem {
CompletionItem {
label,
detail: Some(detail),
..Self::default()
}
}
}
/// The kind of a completion entry.
#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum CompletionItemKind {
Text = 1,
Method = 2,
Function = 3,
Constructor = 4,
Field = 5,
Variable = 6,
Class = 7,
Interface = 8,
Module = 9,
Property = 10,
Unit = 11,
Value = 12,
Enum = 13,
Keyword = 14,
Snippet = 15,
Color = 16,
File = 17,
Reference = 18,
Folder = 19,
EnumMember = 20,
Constant = 21,
Struct = 22,
Event = 23,
Operator = 24,
TypeParameter = 25,
}
/// Defines how to interpret the insert text in a completion item
#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum InsertTextFormat {
PlainText = 1,
Snippet = 2,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HoverParams {
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
/// The result of a hover request.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct Hover {
/// The hover's content
pub contents: HoverContents,
/// An optional range is a range inside a text document
/// that is used to visualize a hover, e.g. by changing the background color.
#[serde(skip_serializing_if = "Option::is_none")]
pub range: Option<Range>,
}
/// Hover contents could be single entry or multiple entries.
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum HoverContents {
Scalar(MarkedString),
Array(Vec<MarkedString>),
Markup(MarkupContent),
}
/// The marked string is rendered:
/// - as markdown if it is represented as a string
/// - as code block of the given langauge if it is represented as a pair of a language and a value
///
/// The pair of a language and a value is an equivalent to markdown:
/// ```${language}
/// ${value}
/// ```
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum MarkedString {
String(String),
LanguageString(LanguageString),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct LanguageString {
pub language: String,
pub value: String,
}
impl MarkedString {
pub fn from_markdown(markdown: String) -> MarkedString {
MarkedString::String(markdown)
}
pub fn from_language_code(language: String, code_block: String) -> MarkedString {
MarkedString::LanguageString(LanguageString {
language,
value: code_block,
})
}
}
/// Signature help represents the signature of something
/// callable. There can be multiple signature but only one
/// active and only one active parameter.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SignatureHelp {
/// One or more signatures.
pub signatures: Vec<SignatureInformation>,
/// The active signature.
#[serde(skip_serializing_if = "Option::is_none")]
pub active_signature: Option<i64>,
/// The active parameter of the active signature.
#[serde(skip_serializing_if = "Option::is_none")]
pub active_parameter: Option<i64>,
}
/// Represents the signature of something callable. A signature
/// can have a label, like a function-name, a doc-comment, and
/// a set of parameters.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct SignatureInformation {
/// The label of this signature. Will be shown in
/// the UI.
pub label: String,
/// The human-readable doc-comment of this signature. Will be shown
/// in the UI but can be omitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<Documentation>,
/// The parameters of this signature.
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<Vec<ParameterInformation>>,
}
/// Represents a parameter of a callable-signature. A parameter can
/// have a label and a doc-comment.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ParameterInformation {
/// The label of this parameter information.
///
/// Either a string or an inclusive start and exclusive end offsets within its containing
/// signature label. (see SignatureInformation.label). *Note*: A label of type string must be
/// a substring of its containing signature label.
pub label: ParameterLabel,
/// The human-readable doc-comment of this parameter. Will be shown
/// in the UI but can be omitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<Documentation>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ParameterLabel {
Simple(String),
LabelOffsets([u64; 2]),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GotoDefinitionParams {
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// GotoDefinition response can be single location, or multiple Locations or a link.
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GotoDefinitionResponse {
Scalar(Location),
Array(Vec<Location>),
Link(Vec<LocationLink>),
}
impl From<Location> for GotoDefinitionResponse {
fn from(location: Location) -> Self {
GotoDefinitionResponse::Scalar(location)
}
}
impl From<Vec<Location>> for GotoDefinitionResponse {
fn from(locations: Vec<Location>) -> Self {
GotoDefinitionResponse::Array(locations)
}
}
impl From<Vec<LocationLink>> for GotoDefinitionResponse {
fn from(locations: Vec<LocationLink>) -> Self {
GotoDefinitionResponse::Link(locations)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReferenceParams {
// Text Document and Position fields
#[serde(flatten)]
pub text_document_position: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
// ReferenceParams properties:
pub context: ReferenceContext,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReferenceContext {
/// Include the declaration of the current symbol.
pub include_declaration: bool,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentHighlightParams {
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// 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.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct DocumentHighlight {
/// The range this highlight applies to.
pub range: Range,
/// The highlight kind, default is DocumentHighlightKind.Text.
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<DocumentHighlightKind>,
}
/// A document highlight kind.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum DocumentHighlightKind {
/// A textual occurrance.
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,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentSymbolCapability {
/// This capability supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// Specific capabilities for the `SymbolKind`.
#[serde(skip_serializing_if = "Option::is_none")]
pub symbol_kind: Option<SymbolKindCapability>,
/// The client support hierarchical document symbols.
#[serde(skip_serializing_if = "Option::is_none")]
pub hierarchical_document_symbol_support: Option<bool>,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DocumentSymbolResponse {
Flat(Vec<SymbolInformation>),
Nested(Vec<DocumentSymbol>),
}
impl From<Vec<SymbolInformation>> for DocumentSymbolResponse {
fn from(info: Vec<SymbolInformation>) -> Self {
DocumentSymbolResponse::Flat(info)
}
}
impl From<Vec<DocumentSymbol>> for DocumentSymbolResponse {
fn from(symbols: Vec<DocumentSymbol>) -> Self {
DocumentSymbolResponse::Nested(symbols)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentSymbolParams {
/// The text document.
pub text_document: TextDocumentIdentifier,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// 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.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentSymbol {
/// The name of this symbol.
pub name: String,
/// More detail for this symbol, e.g the signature of a function. If not provided the
/// name is used.
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
/// The kind of this symbol.
pub kind: SymbolKind,
/// Indicates if this symbol is deprecated.
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated: Option<bool>,
/// The range enclosing this symbol not including leading/trailing whitespace but everything else
/// like comments. This information is typically used to determine if the the clients cursor is
/// inside the symbol to reveal in the symbol in the UI.
pub 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 the `range`.
pub selection_range: Range,
/// Children of this symbol, e.g. properties of a class.
#[serde(skip_serializing_if = "Option::is_none")]
pub children: Option<Vec<DocumentSymbol>>,
}
/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SymbolInformation {
/// The name of this symbol.
pub name: String,
/// The kind of this symbol.
pub kind: SymbolKind,
/// Indicates if this symbol is deprecated.
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated: Option<bool>,
/// The location of this symbol.
pub location: Location,
/// The name of the symbol containing this symbol.
#[serde(skip_serializing_if = "Option::is_none")]
pub container_name: Option<String>,
}
/// A symbol kind.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum 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,
// Capturing all unknown enums by this lib.
Unknown = 255,
}
/// The parameters of a Workspace Symbol Request.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct WorkspaceSymbolParams {
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
/// A non-empty query string
pub query: String,
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct ExecuteCommandParams {
/// The identifier of the actual command handler.
pub command: String,
/// Arguments that the command should be invoked with.
#[serde(default)]
pub arguments: Vec<Value>,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
/// Execute command registration options.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ExecuteCommandRegistrationOptions {
/// The commands to be executed on the server
pub commands: Vec<String>,
#[serde(flatten)]
pub execute_command_options: ExecuteCommandOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ApplyWorkspaceEditParams {
/// The edits to apply.
pub edit: WorkspaceEdit,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct ApplyWorkspaceEditResponse {
/// Indicates whether the edit was applied or not.
pub applied: bool,
}
/// Params for the CodeActionRequest
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionParams {
/// The document in which the command was invoked.
pub text_document: TextDocumentIdentifier,
/// The range for which the command was invoked.
pub range: Range,
/// Context carrying additional information.
pub context: CodeActionContext,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// response for CodeActionRequest
pub type CodeActionResponse = Vec<CodeActionOrCommand>;
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CodeActionOrCommand {
Command(Command),
CodeAction(CodeAction),
}
impl From<Command> for CodeActionOrCommand {
fn from(comand: Command) -> Self {
CodeActionOrCommand::Command(comand)
}
}
impl From<CodeAction> for CodeActionOrCommand {
fn from(action: CodeAction) -> Self {
CodeActionOrCommand::CodeAction(action)
}
}
/// A set of predefined code action kinds
pub mod code_action_kind {
/// Empty kind.
pub const EMPTY: &str = "";
/// Base kind for quickfix actions: 'quickfix'
pub const QUICKFIX: &str = "quickfix";
/// Base kind for refactoring actions: 'refactor'
pub const REFACTOR: &str = "refactor";
/// Base kind for refactoring extraction actions: 'refactor.extract'
///
/// Example extract actions:
///
/// - Extract method
/// - Extract function
/// - Extract variable
/// - Extract interface from class
/// - ...
pub const REFACTOR_EXTRACT: &str = "refactor.extract";
/// Base kind for refactoring inline actions: 'refactor.inline'
///
/// Example inline actions:
///
/// - Inline function
/// - Inline variable
/// - Inline constant
/// - ...
pub const REFACTOR_INLINE: &str = "refactor.inline";
/// Base kind for refactoring rewrite actions: 'refactor.rewrite'
///
/// Example rewrite actions:
///
/// - Convert JavaScript function to class
/// - Add or remove parameter
/// - Encapsulate field
/// - Make method static
/// - Move method to base class
/// - ...
pub const REFACTOR_REWRITE: &str = "refactor.rewrite";
/// Base kind for source actions: `source`
///
/// Source code actions apply to the entire file.
pub const SOURCE: &str = "source";
/// Base kind for an organize imports source action: `source.organizeImports`
pub const SOURCE_ORGANIZE_IMPORTS: &str = "source.organizeImports";
}
#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct CodeAction {
/// A short, human-readable, title for this code action.
pub title: String,
/// The kind of the code action.
/// Used to filter code actions.
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<String>,
/// The diagnostics that this code action resolves.
#[serde(skip_serializing_if = "Option::is_none")]
pub diagnostics: Option<Vec<Diagnostic>>,
/// The workspace edit this code action performs.
#[serde(skip_serializing_if = "Option::is_none")]
pub edit: Option<WorkspaceEdit>,
/// A command this code action executes. If a code action
/// provides an edit and a command, first the edit is
/// executed and then the command.
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<Command>,
/// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
/// by keybindings.
/// A quick fix should be marked preferred if it properly addresses the underlying error.
/// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
#[serde(skip_serializing_if = "Option::is_none")]
pub is_preferred: Option<bool>,
}
/// Contains additional diagnostic information about the context in which
/// a code action is run.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct CodeActionContext {
/// An array of diagnostics.
pub diagnostics: Vec<Diagnostic>,
/// Requested kind of actions to return.
///
/// Actions not of this kind are filtered out by the client before being shown. So servers
/// can omit computing them.
#[serde(skip_serializing_if = "Option::is_none")]
pub only: Option<Vec<String>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeActionOptions {
/// CodeActionKinds that this server may return.
///
/// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
/// may list out every specific kind they provide.
#[serde(skip_serializing_if = "Option::is_none")]
pub code_action_kinds: Option<Vec<String>>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeLensParams {
/// The document to request code lens for.
pub text_document: TextDocumentIdentifier,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// A code lens represents a command that should be shown along with
/// source text, like the number of references, a way to run tests, etc.
///
/// A code lens is _unresolved_ when no command is associated to it. For performance
/// reasons the creation of a code lens and resolving should be done in two stages.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct CodeLens {
/// The range in which this code lens is valid. Should only span a single line.
pub range: Range,
/// The command this code lens represents.
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<Command>,
/// A data entry field that is preserved on a code lens item between
/// a code lens and a code lens resolve request.
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentLinkParams {
/// The document to provide document links for.
pub text_document: TextDocumentIdentifier,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// 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.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct DocumentLink {
/// The range this link applies to.
pub range: Range,
/// The uri this link points to.
pub target: Url,
/// The tooltip text when you hover over this link.
///
/// If a tooltip is provided, is will be displayed in a string that includes instructions on how to
/// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS,
/// user settings, and localization.
#[serde(skip_serializing_if = "Option::is_none")]
pub tooltip: Option<String>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentFormattingParams {
/// The document to format.
pub text_document: TextDocumentIdentifier,
/// The format options.
pub options: FormattingOptions,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
/// Value-object describing what options formatting should use.
#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FormattingOptions {
/// Size of a tab in spaces.
pub tab_size: u64,
/// Prefer spaces over tabs.
pub insert_spaces: bool,
/// Signature for further properties.
#[serde(flatten)]
pub properties: HashMap<String, FormattingProperty>,
/// Trim trailing whitespaces on a line.
#[serde(skip_serializing_if = "Option::is_none")]
pub trim_trailing_whitespace: Option<bool>,
/// Insert a newline character at the end of the file if one does not exist.
#[serde(skip_serializing_if = "Option::is_none")]
pub insert_final_newline: Option<bool>,
/// Trim all newlines after the final newline at the end of the file.
#[serde(skip_serializing_if = "Option::is_none")]
pub trim_final_newlines: Option<bool>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum FormattingProperty {
Bool(bool),
Number(f64),
String(String),
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentRangeFormattingParams {
/// The document to format.
pub text_document: TextDocumentIdentifier,
/// The range to format
pub range: Range,
/// The format options
pub options: FormattingOptions,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentOnTypeFormattingParams {
/// Text Document and Position fields.
#[serde(flatten)]
pub text_document_position: TextDocumentPositionParams,
/// The character that has been typed.
pub ch: String,
/// The format options.
pub options: FormattingOptions,
}
/// Extends TextDocumentRegistrationOptions
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentOnTypeFormattingRegistrationOptions {
/// A document selector to identify the scope of the registration. If set to null
/// the document selector provided on the client side will be used.
pub document_selector: Option<DocumentSelector>,
/// A character on which formatting should be triggered, like `}`.
pub first_trigger_character: String,
/// More trigger characters.
#[serde(skip_serializing_if = "Option::is_none")]
pub more_trigger_character: Option<Vec<String>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RenameParams {
/// Text Document and Position fields
#[serde(flatten)]
pub text_document_position: TextDocumentPositionParams,
/// The new name of the symbol. If the given name is not valid the
/// request must return a [ResponseError](#ResponseError) with an
/// appropriate message set.
pub new_name: String,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RenameProviderCapability {
Simple(bool),
Options(RenameOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RenameOptions {
/// Renames should be checked and tested before being executed.
#[serde(skip_serializing_if = "Option::is_none")]
pub prepare_provider: Option<bool>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RenameCapability {
/// Whether rename supports dynamic registration.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// Client supports testing for validity of rename operations before execution.
#[serde(skip_serializing_if = "Option::is_none")]
pub prepare_support: Option<bool>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum PrepareRenameResponse {
Range(Range),
RangeWithPlaceholder { range: Range, placeholder: String },
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentLinkOptions {
/// Document links have a resolve provider as well.
#[serde(skip_serializing_if = "Option::is_none")]
pub resolve_provider: Option<bool>,
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DocumentColorParams {
/// The text document
pub text_document: TextDocumentIdentifier,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ColorInformation {
/// The range in the document where this color appears.
pub range: Range,
/// The actual color value for this color range.
pub color: Color,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Color {
/// The red component of this color in the range [0-1].
pub red: f64,
/// The green component of this color in the range [0-1].
pub green: f64,
/// The blue component of this color in the range [0-1].
pub blue: f64,
/// The alpha component of this color in the range [0-1].
pub alpha: f64,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ColorPresentationParams {
/// The text document.
pub text_document: TextDocumentIdentifier,
/// The color information to request presentations for.
pub color: Color,
/// The range where the color would be inserted. Serves as a context.
pub range: Range,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Default, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ColorPresentation {
/// The label of this color presentation. It will be shown on the color
/// picker header. By default this is also the text that is inserted when selecting
/// this color presentation.
pub label: String,
/// An [edit](#TextEdit) which is applied to a document when selecting
/// this presentation for the color. When `falsy` the [label](#ColorPresentation.label)
/// is used.
#[serde(skip_serializing_if = "Option::is_none")]
pub text_edit: Option<TextEdit>,
/// An optional array of additional [text edits](#TextEdit) that are applied when
/// selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves.
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_text_edits: Option<Vec<TextEdit>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FoldingRangeParams {
/// The text document.
pub text_document: TextDocumentIdentifier,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum FoldingRangeProviderCapability {
Simple(bool),
FoldingProvider(FoldingProviderOptions),
Options(StaticTextDocumentColorProviderOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct FoldingProviderOptions {}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FoldingRangeCapability {
/// Whether implementation supports dynamic registration for folding range providers. If this is set to `true`
/// the client supports the new `(FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
/// return value for the corresponding server capability as well.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a
/// hint, servers are free to follow the limit.
#[serde(skip_serializing_if = "Option::is_none")]
pub range_limit: Option<u64>,
/// If set, the client signals that it only supports folding complete lines. If set, client will
/// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.
#[serde(skip_serializing_if = "Option::is_none")]
pub line_folding_only: Option<bool>,
}
/// Represents a folding range.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FoldingRange {
/// The zero-based line number from where the folded range starts.
pub start_line: u64,
/// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
#[serde(skip_serializing_if = "Option::is_none")]
pub start_character: Option<u64>,
/// The zero-based line number where the folded range ends.
pub end_line: u64,
/// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
#[serde(skip_serializing_if = "Option::is_none")]
pub end_character: Option<u64>,
/// Describes the kind of the folding range such as `comment' or 'region'. The kind
/// is used to categorize folding ranges and used by commands like 'Fold all comments'. See
/// [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<FoldingRangeKind>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct SelectionRangeOptions {
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct SelectionRangeRegistrationOptions {
#[serde(flatten)]
pub selection_range_options: SelectionRangeOptions,
#[serde(flatten)]
pub registration_options: StaticTextDocumentRegistrationOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum SelectionRangeProviderCapability {
Simple(bool),
Options(SelectionRangeOptions),
RegistrationOptions(SelectionRangeRegistrationOptions),
}
/// A parameter literal used in selection range requests.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SelectionRangeParams {
/// The text document.
pub text_document: TextDocumentIdentifier,
/// The positions inside the text document.
pub positions: Vec<Position>,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// Represents a selection range.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SelectionRange {
/// Range of the selection.
pub range: Range,
/// The parent selection range containing this range.
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<Box<SelectionRange>>,
}
/// Enum of known range kinds
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum FoldingRangeKind {
/// Folding range for a comment
Comment,
/// Folding range for a imports or includes
Imports,
/// Folding range for a region (e.g. `#region`)
Region,
}
/// Describes the content type that a client supports in various
/// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
///
/// Please note that `MarkupKinds` must not start with a `$`. This kinds
/// are reserved for internal usage.
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum MarkupKind {
/// Plain text is supported as a content format
PlainText,
/// Markdown is supported as a content format
Markdown,
}
/// A `MarkupContent` literal represents a string value which content is interpreted base on its
/// kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.
///
/// If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.
/// See <https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting>
///
/// Here is an example how such a string can be constructed using JavaScript / TypeScript:
/// ```ts
/// let markdown: MarkdownContent = {
/// kind: MarkupKind.Markdown,
/// value: [
/// '# Header',
/// 'Some text',
/// '```typescript',
/// 'someCode();',
/// '```'
/// ].join('\n')
/// };
/// ```
///
/// Please Note* that clients might sanitize the return markdown. A client could decide to
/// remove HTML from the markdown to avoid script execution.
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
pub struct MarkupContent {
pub kind: MarkupKind,
pub value: String,
}
pub type ProgressToken = NumberOrString;
/// The progress notification is sent from the server to the client to ask
/// the client to indicate progress.
#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ProgressParams {
/// The progress token provided by the client.
pub token: ProgressToken,
/// The progress data.
pub value: ProgressParamsValue,
}
#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
#[serde(untagged)]
pub enum ProgressParamsValue {
WorkDone(WorkDoneProgress),
}
/// The `window/workDoneProgress/create` request is sent from the server
/// to the clientto ask the client to create a work done progress.
#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressCreateParams {
/// The token to be used to report progress.
pub token: ProgressToken,
}
/// The `window/workDoneProgress/cancel` notification is sent from the client
/// to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressCancelParams {
/// The token to be used to report progress.
pub token: ProgressToken,
}
/// Options to signal work done progress support in server capabilities.
#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub work_done_progress: Option<bool>,
}
/// An optional token that a server can use to report work done progress
#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub work_done_token: Option<ProgressToken>,
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressBegin {
/// Mandatory title of the progress operation. Used to briefly inform
/// about the kind of operation being performed.
/// Examples: "Indexing" or "Linking dependencies".
pub title: String,
/// Controls if a cancel button should show to allow the user to cancel the
/// long running operation. Clients that don't support cancellation are allowed
/// to ignore the setting.
#[serde(skip_serializing_if = "Option::is_none")]
pub cancellable: Option<bool>,
/// Optional, more detailed associated progress message. Contains
/// complementary information to the `title`.
/// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
/// If unset, the previous progress message (if any) is still valid.
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
/// Optional progress percentage to display (value 100 is considered 100%).
/// If unset, the previous progress percentage (if any) is still valid.
#[serde(skip_serializing_if = "Option::is_none")]
pub percentage: Option<f64>,
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressReport {
/// Controls if a cancel button should show to allow the user to cancel the
/// long running operation. Clients that don't support cancellation are allowed
/// to ignore the setting.
#[serde(skip_serializing_if = "Option::is_none")]
pub cancellable: Option<bool>,
/// Optional, more detailed associated progress message. Contains
/// complementary information to the `title`.
/// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
/// If unset, the previous progress message (if any) is still valid.
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
/// Optional progress percentage to display (value 100 is considered 100%).
/// If unset, the previous progress percentage (if any) is still valid.
#[serde(skip_serializing_if = "Option::is_none")]
pub percentage: Option<f64>,
}
#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WorkDoneProgressEnd {
/// Optional, more detailed associated progress message. Contains
/// complementary information to the `title`.
/// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
/// If unset, the previous progress message (if any) is still valid.
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
}
#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum WorkDoneProgress {
Begin(WorkDoneProgressBegin),
Report(WorkDoneProgressReport),
End(WorkDoneProgressEnd),
}
/// A parameter literal used to pass a partial result token.
#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PartialResultParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub partial_result_token: Option<ProgressToken>,
}
#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticHighlightingClientCapability {
/// `true` if the client supports semantic highlighting support text documents. Otherwise, `false`. It is `false` by default.
pub semantic_highlighting: bool,
}
#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
#[cfg(feature = "proposed")]
pub struct SemanticHighlightingServerCapability {
/// A "lookup table" of semantic highlighting [TextMate scopes](https://manual.macromates.com/en/language_grammars)
/// supported by the language server. If not defined or empty, then the server does not support the semantic highlighting
/// feature. Otherwise, clients should reuse this "lookup table" when receiving semantic highlighting notifications from
/// the server.
#[serde(skip_serializing_if = "Option::is_none")]
pub scopes: Option<Vec<Vec<String>>>,
}
#[derive(Debug, Eq, PartialEq, Clone)]
#[cfg(feature = "proposed")]
pub struct SemanticHighlightingToken {
pub character: u32,
pub length: u16,
pub scope: u16,
}
#[cfg(feature = "proposed")]
impl SemanticHighlightingToken {
/// Deserializes the tokens from a base64 encoded string
fn deserialize_tokens<'de, D>(
deserializer: D,
) -> Result<Option<Vec<SemanticHighlightingToken>>, D::Error>
where
D: serde::Deserializer<'de>,
{
let opt_s = Option::<String>::deserialize(deserializer)?;
if let Some(s) = opt_s {
let bytes = base64::decode_config(s.as_str(), base64::STANDARD)
.map_err(|_| serde::de::Error::custom("Error parsing base64 string"))?;
let mut res = Vec::new();
for chunk in bytes.chunks_exact(8) {
res.push(SemanticHighlightingToken {
character: u32::from_be_bytes(<[u8; 4]>::try_from(&chunk[0..4]).unwrap()),
length: u16::from_be_bytes(<[u8; 2]>::try_from(&chunk[4..6]).unwrap()),
scope: u16::from_be_bytes(<[u8; 2]>::try_from(&chunk[6..8]).unwrap()),
});
}
Result::Ok(Some(res))
} else {
Result::Ok(None)
}
}
/// Serialize the tokens to a base64 encoded string
fn serialize_tokens<S>(
tokens: &Option<Vec<SemanticHighlightingToken>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
if let Some(tokens) = tokens {
let mut bytes = vec![];
for token in tokens {
bytes.extend_from_slice(&token.character.to_be_bytes());
bytes.extend_from_slice(&token.length.to_be_bytes());
bytes.extend_from_slice(&token.scope.to_be_bytes());
}
serializer.collect_str(&base64::display::Base64Display::with_config(
&bytes,
base64::STANDARD,
))
} else {
serializer.serialize_none()
}
}
}
/// Represents a semantic highlighting information that has to be applied on a specific line of the text document.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[cfg(feature = "proposed")]
pub struct SemanticHighlightingInformation {
/// The zero-based line position in the text document.
pub line: i32,
/// A base64 encoded string representing every single highlighted characters with its start position, length and the "lookup table" index of
/// of the semantic highlighting [TextMate scopes](https://manual.macromates.com/en/language_grammars).
/// If the `tokens` is empty or not defined, then no highlighted positions are available for the line.
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "SemanticHighlightingToken::deserialize_tokens",
serialize_with = "SemanticHighlightingToken::serialize_tokens"
)]
pub tokens: Option<Vec<SemanticHighlightingToken>>,
}
/// Parameters for the semantic highlighting (server-side) push notification.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticHighlightingParams {
/// The text document that has to be decorated with the semantic highlighting information.
pub text_document: VersionedTextDocumentIdentifier,
/// An array of semantic highlighting information.
pub lines: Vec<SemanticHighlightingInformation>,
}
/// A set of predefined token types. This set is not fixed
/// and clients can specify additional token types via the
/// corresponding client capabilities.
///
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
#[cfg(feature = "proposed")]
pub struct SemanticTokenType(Cow<'static, str>);
#[cfg(feature = "proposed")]
impl SemanticTokenType {
pub const COMMENT: SemanticTokenType = SemanticTokenType::new("comment");
pub const KEYWORD: SemanticTokenType = SemanticTokenType::new("keyword");
pub const STRING: SemanticTokenType = SemanticTokenType::new("string");
pub const NUMBER: SemanticTokenType = SemanticTokenType::new("number");
pub const REGEXP: SemanticTokenType = SemanticTokenType::new("regexp");
pub const OPERATOR: SemanticTokenType = SemanticTokenType::new("operator");
pub const NAMESPACE: SemanticTokenType = SemanticTokenType::new("namespace");
pub const TYPE: SemanticTokenType = SemanticTokenType::new("type");
pub const STRUCT: SemanticTokenType = SemanticTokenType::new("struct");
pub const CLASS: SemanticTokenType = SemanticTokenType::new("class");
pub const INTERFACE: SemanticTokenType = SemanticTokenType::new("interface");
pub const ENUM: SemanticTokenType = SemanticTokenType::new("enum");
pub const TYPE_PARAMETER: SemanticTokenType = SemanticTokenType::new("typeParameter");
pub const FUNCTION: SemanticTokenType = SemanticTokenType::new("function");
pub const MEMBER: SemanticTokenType = SemanticTokenType::new("member");
pub const PROPERTY: SemanticTokenType = SemanticTokenType::new("property");
pub const MACRO: SemanticTokenType = SemanticTokenType::new("macro");
pub const VARIABLE: SemanticTokenType = SemanticTokenType::new("variable");
pub const PARAMETER: SemanticTokenType = SemanticTokenType::new("parameter");
pub const LABEL: SemanticTokenType = SemanticTokenType::new("label");
pub const fn new(tag: &'static str) -> Self {
SemanticTokenType(Cow::Borrowed(tag))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
#[cfg(feature = "proposed")]
impl From<String> for SemanticTokenType {
fn from(from: String) -> Self {
SemanticTokenType(Cow::from(from))
}
}
#[cfg(feature = "proposed")]
impl From<&'static str> for SemanticTokenType {
fn from(from: &'static str) -> Self {
SemanticTokenType::new(from)
}
}
/// A set of predefined token modifiers. This set is not fixed
/// and clients can specify additional token types via the
/// corresponding client capabilities.
///
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
#[cfg(feature = "proposed")]
pub struct SemanticTokenModifier(Cow<'static, str>);
#[cfg(feature = "proposed")]
impl SemanticTokenModifier {
pub const DOCUMENTATION: SemanticTokenModifier = SemanticTokenModifier::new("documentation");
pub const DECLARATION: SemanticTokenModifier = SemanticTokenModifier::new("declaration");
pub const DEFINITION: SemanticTokenModifier = SemanticTokenModifier::new("definition");
pub const STATIC: SemanticTokenModifier = SemanticTokenModifier::new("static");
pub const ABSTRACT: SemanticTokenModifier = SemanticTokenModifier::new("abstract");
pub const DEPRECATED: SemanticTokenModifier = SemanticTokenModifier::new("deprecated");
pub const READONLY: SemanticTokenModifier = SemanticTokenModifier::new("readonly");
pub const fn new(tag: &'static str) -> Self {
SemanticTokenModifier(Cow::Borrowed(tag))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
#[cfg(feature = "proposed")]
impl From<String> for SemanticTokenModifier {
fn from(from: String) -> Self {
SemanticTokenModifier(Cow::from(from))
}
}
#[cfg(feature = "proposed")]
impl From<&'static str> for SemanticTokenModifier {
fn from(from: &'static str) -> Self {
SemanticTokenModifier::new(from)
}
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensLegend {
/// The token types a server uses.
pub token_types: Vec<SemanticTokenType>,
/// The token modifiers a server uses.
pub token_modifiers: Vec<SemanticTokenModifier>,
}
/// The actual tokens. For a detailed description about how the data is
/// structured please see
/// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
#[cfg(feature = "proposed")]
pub struct SemanticToken {
pub delta_line: u32,
pub delta_start: u32,
pub length: u32,
pub token_type: u32,
pub token_modifiers_bitset: u32,
}
#[cfg(feature = "proposed")]
impl SemanticToken {
fn deserialize_tokens<'de, D>(deserializer: D) -> Result<Vec<SemanticToken>, D::Error>
where
D: serde::Deserializer<'de>,
{
let data = Vec::<u32>::deserialize(deserializer)?;
let chunks = data.chunks_exact(5);
if !chunks.remainder().is_empty() {
return Result::Err(serde::de::Error::custom("Length is not divisible by 5"));
}
Result::Ok(
chunks
.map(|chunk| SemanticToken {
delta_line: chunk[0],
delta_start: chunk[1],
length: chunk[2],
token_type: chunk[3],
token_modifiers_bitset: chunk[4],
})
.collect(),
)
}
fn serialize_tokens<S>(tokens: &[SemanticToken], serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut seq = serializer.serialize_seq(Some(tokens.len() * 5))?;
for token in tokens.iter() {
seq.serialize_element(&token.delta_line)?;
seq.serialize_element(&token.delta_start)?;
seq.serialize_element(&token.length)?;
seq.serialize_element(&token.token_type)?;
seq.serialize_element(&token.token_modifiers_bitset)?;
}
seq.end()
}
fn deserialize_tokens_opt<'de, D>(
deserializer: D,
) -> Result<Option<Vec<SemanticToken>>, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(transparent)]
struct Wrapper {
#[serde(deserialize_with = "SemanticToken::deserialize_tokens")]
tokens: Vec<SemanticToken>,
}
Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|wrapper| wrapper.tokens))
}
fn serialize_tokens_opt<S>(
data: &Option<Vec<SemanticToken>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Serialize)]
#[serde(transparent)]
struct Wrapper {
#[serde(serialize_with = "SemanticToken::serialize_tokens")]
tokens: Vec<SemanticToken>,
}
let opt = data.as_ref().map(|t| Wrapper { tokens: t.to_vec() });
opt.serialize(serializer)
}
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokens {
/// 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 sematic tokens again simply
/// send a delta.
#[serde(skip_serializing_if = "Option::is_none")]
pub result_id: Option<String>,
/// The actual tokens. For a detailed description about how the data is
/// structured please see
/// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71
#[serde(
deserialize_with = "SemanticToken::deserialize_tokens",
serialize_with = "SemanticToken::serialize_tokens"
)]
pub data: Vec<SemanticToken>,
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensPartialResult {
#[serde(
deserialize_with = "SemanticToken::deserialize_tokens",
serialize_with = "SemanticToken::serialize_tokens"
)]
pub data: Vec<SemanticToken>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum SemanticTokensResult {
Tokens(SemanticTokens),
Partial(SemanticTokensPartialResult),
}
#[cfg(feature = "proposed")]
impl From<SemanticTokens> for SemanticTokensResult {
fn from(from: SemanticTokens) -> Self {
SemanticTokensResult::Tokens(from)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensPartialResult> for SemanticTokensResult {
fn from(from: SemanticTokensPartialResult) -> Self {
SemanticTokensResult::Partial(from)
}
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensEdit {
pub start: u32,
pub delete_count: u32,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "SemanticToken::deserialize_tokens_opt",
serialize_with = "SemanticToken::serialize_tokens_opt"
)]
pub data: Option<Vec<SemanticToken>>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum SemanticTokensEditResult {
Tokens(SemanticTokens),
TokensEdits(SemanticTokensEdit),
PartialTokens(SemanticTokensPartialResult),
PartialTokensEdit(SemanticTokensEditsPartialResult),
}
#[cfg(feature = "proposed")]
impl From<SemanticTokens> for SemanticTokensEditResult {
fn from(from: SemanticTokens) -> Self {
SemanticTokensEditResult::Tokens(from)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensEdit> for SemanticTokensEditResult {
fn from(from: SemanticTokensEdit) -> Self {
SemanticTokensEditResult::TokensEdits(from)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensPartialResult> for SemanticTokensEditResult {
fn from(from: SemanticTokensPartialResult) -> Self {
SemanticTokensEditResult::PartialTokens(from)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensEditsPartialResult> for SemanticTokensEditResult {
fn from(from: SemanticTokensEditsPartialResult) -> Self {
SemanticTokensEditResult::PartialTokensEdit(from)
}
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensEdits {
#[serde(skip_serializing_if = "Option::is_none")]
pub result_id: Option<String>,
/// For a detailed description how these edits are structured pls see
/// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131
pub edits: Vec<SemanticTokensEdit>,
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensEditsPartialResult {
pub edits: Vec<SemanticTokensEdit>,
}
/// Capabilities specific to the `textDocument/semanticTokens`
///
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensClientCapabilities {
/// Whether implementation supports dynamic registration. If this is set to `true`
/// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
/// return value for the corresponding server capability as well.
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_registration: Option<bool>,
/// The token types known by the client.
pub token_types: Vec<SemanticTokenType>,
/// The token modifiers known by the client.
pub token_modifiers: Vec<SemanticTokenModifier>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum SemanticTokensDocumentProvider {
Bool(bool),
/// The server supports deltas for full documents.
Edits {
#[serde(skip_serializing_if = "Option::is_none")]
edits: Option<bool>,
},
}
/// @since 3.16.0 - Proposed state
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensOptions {
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
/// The legend used by the server
pub legend: SemanticTokensLegend,
/// Server supports providing semantic tokens for a sepcific range
/// of a document.
#[serde(skip_serializing_if = "Option::is_none")]
pub range_provider: Option<bool>,
/// Server supports providing semantic tokens for a full document.
#[serde(skip_serializing_if = "Option::is_none")]
pub document_provider: Option<SemanticTokensDocumentProvider>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensRegistrationOptions {
#[serde(flatten)]
pub text_document_registration_options: TextDocumentRegistrationOptions,
#[serde(flatten)]
pub semantic_tokens_options: SemanticTokensOptions,
#[serde(flatten)]
pub static_registration_options: StaticRegistrationOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum SemanticTokensServerCapabilities {
SemanticTokensOptions(SemanticTokensOptions),
SemanticTokensRegistrationOptions(SemanticTokensRegistrationOptions),
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensOptions> for SemanticTokensServerCapabilities {
fn from(from: SemanticTokensOptions) -> Self {
SemanticTokensServerCapabilities::SemanticTokensOptions(from)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensRegistrationOptions> for SemanticTokensServerCapabilities {
fn from(from: SemanticTokensRegistrationOptions) -> Self {
SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(from)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensParams {
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
/// The text document.
pub text_document: TextDocumentIdentifier,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensEditsParams {
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
/// The text document.
pub text_document: TextDocumentIdentifier,
/// The previous result id.
pub previous_result_id: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct SemanticTokensRangeParams {
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
/// The text document.
pub text_document: TextDocumentIdentifier,
/// The range the semantic tokens are requested for.
pub range: Range,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum SemanticTokensRangeResult {
Tokens(SemanticTokens),
Partial(SemanticTokensPartialResult),
}
#[cfg(feature = "proposed")]
impl From<SemanticTokens> for SemanticTokensRangeResult {
fn from(tokens: SemanticTokens) -> Self {
SemanticTokensRangeResult::Tokens(tokens)
}
}
#[cfg(feature = "proposed")]
impl From<SemanticTokensPartialResult> for SemanticTokensRangeResult {
fn from(partial: SemanticTokensPartialResult) -> Self {
SemanticTokensRangeResult::Partial(partial)
}
}
/// Symbol tags are extra annotations that tweak the rendering of a symbol.
/// Since 3.15
#[derive(Debug, Eq, PartialEq, Clone, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
#[cfg(feature = "proposed")]
pub enum SymbolTag {
/// Render a symbol as obsolete, usually using a strike-out.
Deprecated = 1,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyOptions {
#[serde(flatten)]
pub work_done_progress_options: WorkDoneProgressOptions,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
#[cfg(feature = "proposed")]
pub enum CallHierarchyServerCapability {
Simple(bool),
Options(CallHierarchyOptions),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyPrepareParams {
#[serde(flatten)]
pub text_document_position_params: TextDocumentPositionParams,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyItem {
/// The name of this item.
pub name: String,
/// The kind of this item.
pub kind: SymbolKind,
/// Tags for this item.
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<SymbolTag>>,
/// More detail for this item, e.g. the signature of a function.
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
/// The resource identifier of this item.
pub uri: Url,
/// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
pub 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`](#CallHierarchyItem.range).
pub selection_range: Range,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyIncomingCallsParams {
pub item: CallHierarchyItem,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// Represents an incoming call, e.g. a caller of a method or constructor.
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyIncomingCall {
/// The item that makes the call.
pub from: CallHierarchyItem,
/// The range at which at which the calls appears. This is relative to the caller
/// denoted by [`this.from`](#CallHierarchyIncomingCall.from).
pub from_ranges: Vec<Range>,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyOutgoingCallsParams {
pub item: CallHierarchyItem,
#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
}
/// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
#[cfg(feature = "proposed")]
pub struct CallHierarchyOutgoingCall {
/// The item that is called.
pub to: CallHierarchyItem,
/// The range at which this item is called. This is the range relative to the caller, e.g the item
/// passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls)
/// and not [`this.to`](#CallHierarchyOutgoingCall.to).
pub from_ranges: Vec<Range>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
fn test_serialization<SER>(ms: &SER, expected: &str)
where
SER: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
{
let json_str = serde_json::to_string(ms).unwrap();
assert_eq!(&json_str, expected);
let deserialized: SER = serde_json::from_str(&json_str).unwrap();
assert_eq!(&deserialized, ms);
}
fn test_deserialization<T>(json: &str, expected: &T)
where
T: for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
{
let value = serde_json::from_str::<T>(json).unwrap();
assert_eq!(&value, expected);
}
#[test]
fn number_or_string() {
test_serialization(&NumberOrString::Number(123), r#"123"#);
test_serialization(&NumberOrString::String("abcd".into()), r#""abcd""#);
}
#[test]
fn marked_string() {
test_serialization(&MarkedString::from_markdown("xxx".into()), r#""xxx""#);
test_serialization(
&MarkedString::from_language_code("lang".into(), "code".into()),
r#"{"language":"lang","value":"code"}"#,
);
}
#[test]
fn language_string() {
test_serialization(
&LanguageString {
language: "LL".into(),
value: "VV".into(),
},
r#"{"language":"LL","value":"VV"}"#,
);
}
#[test]
fn workspace_edit() {
test_serialization(
&WorkspaceEdit {
changes: Some(vec![].into_iter().collect()),
document_changes: None,
},
r#"{"changes":{}}"#,
);
test_serialization(
&WorkspaceEdit {
changes: None,
document_changes: None,
},
r#"{}"#,
);
test_serialization(
&WorkspaceEdit {
changes: Some(
vec![(Url::parse("file://test").unwrap(), vec![])]
.into_iter()
.collect(),
),
document_changes: None,
},
r#"{"changes":{"file://test/":[]}}"#,
);
}
#[test]
fn formatting_options() {
test_serialization(
&FormattingOptions {
tab_size: 123,
insert_spaces: true,
properties: HashMap::new(),
trim_trailing_whitespace: None,
insert_final_newline: None,
trim_final_newlines: None,
},
r#"{"tabSize":123,"insertSpaces":true}"#,
);
test_serialization(
&FormattingOptions {
tab_size: 123,
insert_spaces: true,
properties: vec![("prop".to_string(), FormattingProperty::Number(1.0))]
.into_iter()
.collect(),
trim_trailing_whitespace: None,
insert_final_newline: None,
trim_final_newlines: None,
},
r#"{"tabSize":123,"insertSpaces":true,"prop":1.0}"#,
);
}
#[test]
fn root_uri_can_be_missing() {
serde_json::from_str::<InitializeParams>(r#"{ "capabilities": {} }"#).unwrap();
}
#[test]
fn test_watch_kind() {
test_serialization(&WatchKind::Create, "1");
test_serialization(&(WatchKind::Create | WatchKind::Change), "3");
test_serialization(
&(WatchKind::Create | WatchKind::Change | WatchKind::Delete),
"7",
);
}
#[test]
fn test_resource_operation_kind() {
test_serialization(
&vec![
ResourceOperationKind::Create,
ResourceOperationKind::Rename,
ResourceOperationKind::Delete,
],
r#"["create","rename","delete"]"#,
);
}
#[test]
fn test_code_action_response() {
test_serialization(
&vec![
CodeActionOrCommand::Command(Command {
title: "title".to_string(),
command: "command".to_string(),
arguments: None,
}),
CodeActionOrCommand::CodeAction(CodeAction {
title: "title".to_string(),
kind: Some(code_action_kind::QUICKFIX.to_owned()),
command: None,
diagnostics: None,
edit: None,
is_preferred: None,
}),
],
r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
)
}
#[cfg(feature = "proposed")]
#[test]
fn test_semantic_highlighting_information_serialization() {
test_serialization(
&SemanticHighlightingInformation {
line: 10,
tokens: Some(vec![
SemanticHighlightingToken {
character: 0x00000001,
length: 0x0002,
scope: 0x0003,
},
SemanticHighlightingToken {
character: 0x00112222,
length: 0x0FF0,
scope: 0x0202,
},
]),
},
r#"{"line":10,"tokens":"AAAAAQACAAMAESIiD/ACAg=="}"#,
);
test_serialization(
&SemanticHighlightingInformation {
line: 22,
tokens: None,
},
r#"{"line":22}"#,
);
}
#[test]
fn test_tag_support_deserialization() {
let mut empty = CompletionItemCapability::default();
empty.tag_support = None;
test_deserialization(r#"{}"#, &empty);
test_deserialization(r#"{"tagSupport": false}"#, &empty);
let mut t = CompletionItemCapability::default();
t.tag_support = Some(TagSupport { value_set: vec![] });
test_deserialization(r#"{"tagSupport": true}"#, &t);
let mut t = CompletionItemCapability::default();
t.tag_support = Some(TagSupport {
value_set: vec![CompletionItemTag::Deprecated],
});
test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t);
}
#[cfg(feature = "proposed")]
#[test]
fn test_semantic_tokens_support_serialization() {
test_serialization(
&SemanticTokens {
result_id: None,
data: vec![],
},
r#"{"data":[]}"#,
);
test_serialization(
&SemanticTokens {
result_id: None,
data: vec![SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
}],
},
r#"{"data":[2,5,3,0,3]}"#,
);
test_serialization(
&SemanticTokens {
result_id: None,
data: vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
],
},
r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
);
}
#[cfg(feature = "proposed")]
#[test]
fn test_semantic_tokens_support_deserialization() {
test_deserialization(
r#"{"data":[]}"#,
&SemanticTokens {
result_id: None,
data: vec![],
},
);
test_deserialization(
r#"{"data":[2,5,3,0,3]}"#,
&SemanticTokens {
result_id: None,
data: vec![SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
}],
},
);
test_deserialization(
r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
&SemanticTokens {
result_id: None,
data: vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
],
},
);
}
#[cfg(feature = "proposed")]
#[test]
#[should_panic]
fn test_semantic_tokens_support_deserialization_err() {
test_deserialization(
r#"{"data":[1]}"#,
&SemanticTokens {
result_id: None,
data: vec![],
},
);
}
#[cfg(feature = "proposed")]
#[test]
fn test_semantic_tokens_edit_support_deserialization() {
test_deserialization(
r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
&SemanticTokensEdit {
start: 0,
delete_count: 1,
data: Some(vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
]),
},
);
test_deserialization(
r#"{"start":0,"deleteCount":1}"#,
&SemanticTokensEdit {
start: 0,
delete_count: 1,
data: None,
},
);
}
#[cfg(feature = "proposed")]
#[test]
fn test_semantic_tokens_edit_support_serialization() {
test_serialization(
&SemanticTokensEdit {
start: 0,
delete_count: 1,
data: Some(vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
]),
},
r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
);
test_serialization(
&SemanticTokensEdit {
start: 0,
delete_count: 1,
data: None,
},
r#"{"start":0,"deleteCount":1}"#,
);
}
}