diff --git a/.gitignore b/.gitignore index a9d37c5..9ca37ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target Cargo.lock +/.settings/ +/.project diff --git a/src/lib.rs b/src/lib.rs index 93309ec..5ea7ced 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,13 @@ +//! Language Server Protocol types for Rust. +//! Based on: https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md +//! Last protocol update 14/Oct/2016 at commit: +//! https://github.com/Microsoft/language-server-protocol/commit/63f5d02d39d0135c234162a28d0523c9323ab3f7 + + #![feature(proc_macro)] +#![allow(non_upper_case_globals)] + #[macro_use] extern crate enum_primitive; extern crate serde; @@ -11,125 +19,106 @@ use std::collections::HashMap; use serde::de::Error; use serde_json::Value; +/// The base protocol now offers support for request cancellation. To cancel a request, +/// a notification message with the following properties is sent: +/// +/// A request that got canceled still needs to return from the server and send a response back. +/// It can not be left open / hanging. This is in line with the JSON RPC protocol that requires +/// that every request sends a response back. In addition it allows for returning partial results on cancel. +pub const NOTIFICATION__Cancel: &'static str = "$/cancelRequest"; + #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct CancelParams { /// The request id to cancel. pub id: String, } -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidChangeTextDocumentParams { - /// The document that did change. The version number points - /// to the version after all provided content changes have - /// been applied. - #[serde(rename="textDocument")] - pub text_document: VersionedTextDocumentIdentifier, - /// The actual content changes. - #[serde(rename="contentChanges")] - pub content_changes: Vec, -} +/* ----------------- Basic JSON Structures ----------------- */ -/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings. The corresponding JSON structure looks like this: -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct TextDocumentIdentifier { - /// The text document's URI. - pub uri: String, +/// 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, PartialEq, 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, } -/// An identifier to denote a specific version of a text document. -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct VersionedTextDocumentIdentifier { - /// The text document's URI. - pub uri: String, - /// The version number of this document. - pub version: u64, +/// 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, 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, } +/// Represents a location inside a resource, such as a line inside a text file. #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct TextDocumentItem { - /// The text document's URI. +pub struct Location { pub uri: String, + pub range: Range, +} - /// The text document's language identifier. - #[serde(rename="languageId")] - pub language_id: String, - - /// The version number of this document (it will strictly increase after each - /// change, including undo/redo). - pub version: u64, +/// Represents a diagnostic, such as a compiler error or warning. +/// Diagnostic objects are only valid in the scope of a resource. +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct Diagnostic { + /// The range at which the message applies. + pub range: Range, - /// The content of the opened text document. - pub text: String, -} + /// The diagnostic's severity. Can be omitted. If omitted it is up to the + /// client to interpret diagnostics as error, warning, info or hint. + pub severity: Option, -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidOpenTextDocumentParams { - /// The document that was opened. - #[serde(rename="textDocument")] - pub text_document: TextDocumentItem, -} + /// The diagnostic's code. Can be omitted. + pub code: Option, +// code?: number | string; -/// 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, PartialEq, Deserialize, Serialize)] -pub struct TextDocumentContentChangeEvent { - /// The range of the document that changed. - pub range: Option, - /// The length of the range that got replaced. - #[serde(rename="rangeLength")] - pub range_length: Option, - /// The new text of the document. - pub text: String, -} + /// A human-readable string describing the source of this + /// diagnostic, e.g. 'typescript' or 'super lint'. + pub source: Option, -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidCloseTextDocumentParams { - /// The document that was closed. - #[serde(rename="textDocument")] - pub text_document: TextDocumentIdentifier, + /// The diagnostic's message. + pub message: String, } -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidSaveTextDocumentParams { - /// The document that was saved. - #[serde(rename="textDocument")] - pub text_document: TextDocumentIdentifier, -} +pub type NumberOrString = String; /* FIXME: todo */ -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidChangeWatchedFilesParams { - /// The actual file events. - pub changes: Vec, -} -/// The file event type. -#[derive(Debug, PartialEq, Copy, Clone)] -pub enum FileChangeType { - /// The file got created. - Created = 1, - /// The file got changed. - Changed = 2, - /// The file got deleted. - Deleted = 3, +/// The protocol currently supports the following diagnostic severities: +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum DiagnosticSeverity { + /// Reports an error. + Error = 1, + /// Reports a warning. + Warning = 2, + /// Reports an information. + Information = 3, + /// Reports a hint. + Hint = 4, } -impl serde::Deserialize for FileChangeType { +impl serde::Deserialize for DiagnosticSeverity { fn deserialize(deserializer: &mut D) -> Result where D: serde::Deserializer { Ok(match try!(u8::deserialize(deserializer)) { - 1 => FileChangeType::Created, - 2 => FileChangeType::Changed, - 3 => FileChangeType::Deleted, + 1 => DiagnosticSeverity::Error, + 2 => DiagnosticSeverity::Warning, + 3 => DiagnosticSeverity::Information, + 4 => DiagnosticSeverity::Hint, _ => { - return Err(D::Error::invalid_value("Expected a value of 1, 2 or 3 to deserialze \ - to FileChangeType")) + return Err(D::Error::invalid_value("Expected a value of 1, 2, 3 or 4 to \ + deserialize to DiagnosticSeverity")) } }) } } -impl serde::Serialize for FileChangeType { +impl serde::Serialize for DiagnosticSeverity { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { @@ -137,72 +126,141 @@ impl serde::Serialize for FileChangeType { } } -/// An event describing a file change. +/** + 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, 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>, +} + +/// A textual edit applicable to a text document. +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +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. + #[serde(rename="newText")] + pub new_text: String, +} + +/// A workspace edit represents changes to many resources managed in the workspace. +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct WorkspaceEdit { + /// Holds changes to existing resources. + pub changes: HashMap>, +// changes: { [uri: string]: TextEdit[]; }; +} + +/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings. +/// The corresponding JSON structure looks like this: #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct FileEvent { - /// The file's URI. +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: String, - /// The change type. - pub typ: FileChangeType, } -/// Position in a text document expressed as zero-based line and character offset. -#[derive(Debug, PartialEq, 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, -} +/// An item to transfer a text document from the client to the server. +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct TextDocumentItem { + /// The text document's URI. + pub uri: String, -#[derive(Debug, 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, + /// The text document's language identifier. + #[serde(rename="languageId")] + pub language_id: Option, + + /// The version number of this document (it will strictly increase after each + /// change, including undo/redo). + pub version: Option, + + /// The content of the opened text document. + pub text: String, } -/// Represents a location inside a resource, such as a line inside a text file. +/// An identifier to denote a specific version of a text document. #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct Location { +pub struct VersionedTextDocumentIdentifier +//extends TextDocumentIdentifier +{ + // This field was "mixed-in" from TextDocumentIdentifier + /// The text document's URI. pub uri: String, - pub range: Range, + + /// The version number of this document. + pub version: u64, } /// A parameter literal used in requests to pass a text document and a position inside that document. #[derive(Debug, PartialEq, Deserialize, Serialize)] 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. #[serde(rename="textDocument")] pub text_document: TextDocumentIdentifier, + /// The position inside the text document. pub position: Position, } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +/* ========================= Actual Protocol ========================= */ + +/** + * The initialize request is sent as the first request from the client to the server. + */ +pub const REQUEST__Initialize: &'static str = "initialize"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct InitializeParams { /// The process Id of the parent process that started - /// the server. + /// 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. #[serde(rename="processId")] - pub process_id: u64, + pub process_id: Option, + /// The rootPath of the workspace. Is null /// if no folder is open. #[serde(rename="rootPath")] pub root_path: Option, + /// User provided initialization options. + #[serde(rename="initializationOptions")] + pub initialization_options: Option, + /// The capabilities provided by the client (editor) pub capabilities: ClientCapabilities, } -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct ClientCapabilities { - _dummy: Option<()>, -} +/** + * Where ClientCapabilities are currently empty: + */ +pub type ClientCapabilities = Value; #[derive(Debug, PartialEq, Default, Deserialize, Serialize)] pub struct InitializeResult { + /// The capabilities the language server provides. pub capabilities: ServerCapabilities, } @@ -214,99 +272,227 @@ pub struct InitializeError { 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, PartialEq, Clone, Copy)] +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, +} + +impl serde::Deserialize for TextDocumentSyncKind { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + Ok(match try!(u8::deserialize(deserializer)) { + 0 => TextDocumentSyncKind::None, + 1 => TextDocumentSyncKind::Full, + 2 => TextDocumentSyncKind::Incremental, + _ => { + return Err(D::Error::invalid_value("Expected a value between 1 and 2 (inclusive) \ + to deserialize to TextDocumentSyncKind")) + } + }) + } +} + +impl serde::Serialize for TextDocumentSyncKind { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serializer.serialize_u8(*self as u8) + } +} + +/// Completion options. +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct CompletionOptions { + /// The server provides support to resolve additional information for a completion item. + #[serde(skip_serializing_if="Option::is_none")] + #[serde(rename="resolveProvider")] + pub resolve_provider: Option, + + /// The characters that trigger completion automatically. + #[serde(rename="triggerCharacters")] + pub trigger_characters: Vec, +} + +/// Signature help options. +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct SignatureHelpOptions { + /// The characters that trigger signature help automatically. + #[serde(skip_serializing_if="Option::is_none")] + #[serde(rename="triggerCharacters")] + pub trigger_characters: Option>, +} + +/// Code Lens options. +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct CodeLensOptions { + /// Code lens has a resolve provider as well. + #[serde(rename="resolveProvider")] + pub resolve_provider: Option, +} + +/// Format document on type options +#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct DocumentOnTypeFormattingOptions { + /// A character on which formatting should be triggered, like `}`. + #[serde(rename="firstTriggerCharacter")] + pub first_trigger_character: String, + + /// More trigger characters. + #[serde(skip_serializing_if="Option::is_none")] + #[serde(rename="moreTriggerCharacter")] + pub more_trigger_character: Option>, +} + #[derive(Debug, PartialEq, Default, Deserialize, Serialize)] pub struct ServerCapabilities { /// Defines how text documents are synced. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="textDocumentSync")] pub text_document_sync: Option, + /// The server provides hover support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="hoverProvider")] pub hover_provider: Option, + /// The server provides completion support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="completionProvider")] pub completion_provider: Option, + /// The server provides signature help support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="signatureHelpProvider")] pub signature_help_provider: Option, + /// The server provides goto definition support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="definitionProvider")] pub definition_provider: Option, + /// The server provides find references support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="referencesProvider")] pub references_provider: Option, + /// The server provides document highlight support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="documentHighlightProvider")] pub document_highlight_provider: Option, + /// The server provides document symbol support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="documentSymbolProvider")] pub document_symbol_provider: Option, + /// The server provides workspace symbol support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="workspaceSymbolProvider")] pub workspace_symbol_provider: Option, + /// The server provides code actions. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="codeActionProvider")] pub code_action_provider: Option, + /// The server provides code lens. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="codeLensProvider")] pub code_lens_provider: Option, + /// The server provides document formatting. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="documentFormattingProvider")] pub document_formatting_provider: Option, + /// The server provides document range formatting. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="documentRangeFormattingProvider")] pub document_range_formatting_provider: Option, + /// The server provides document formatting on typing. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="documentOnTypeFormattingProvider")] pub document_on_type_formatting_provider: Option, + /// The server provides rename support. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="renameProvider")] pub rename_provider: Option, } -/// Defines how the host (editor) should sync document changes to the language server. +/** + * The shutdown request is sent from the client to the server. It asks the server to shut down, + * but to not exit (otherwise the response might not be delivered correctly to the client). + * There is a separate exit notification that asks the server to exit. + */ +pub const REQUEST__Shutdown: &'static str = "shutdown"; + +/** + * A notification to ask the server to exit its process. + * The server should exit with success code 0 if the shutdown request has been received before; + * otherwise with error code 1. + */ +pub const NOTIFICATION__Exit: &'static str = "exit"; + +/** + * The show message notification is sent from a server to a client to ask the client to display a particular message + * in the user interface. + */ +pub const NOTIFICATION__ShowMessage: &'static str = "window/showMessage"; + +#[derive(Debug, PartialEq, 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, PartialEq, Clone, Copy)] -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, +pub enum MessageType { + /// An error message. + Error = 1, + /// A warning message. + Warning = 2, + /// An information message. + Info = 3, + /// A log message. + Log = 4, } -impl serde::Deserialize for TextDocumentSyncKind { +impl serde::Deserialize for MessageType { fn deserialize(deserializer: &mut D) -> Result where D: serde::Deserializer { Ok(match try!(u8::deserialize(deserializer)) { - 0 => TextDocumentSyncKind::None, - 1 => TextDocumentSyncKind::Full, - 2 => TextDocumentSyncKind::Incremental, + 1 => MessageType::Error, + 2 => MessageType::Warning, + 3 => MessageType::Info, + 4 => MessageType::Log, _ => { - return Err(D::Error::invalid_value("Expected a value between 1 and 2 (inclusive) \ - to deserialize to TextDocumentSyncKind")) + return Err(D::Error::invalid_value("Expected a value of 1, 2, 3 or 4 to \ + deserialze to MessageType")) } }) } } -impl serde::Serialize for TextDocumentSyncKind { +impl serde::Serialize for MessageType { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { @@ -314,117 +500,301 @@ impl serde::Serialize for TextDocumentSyncKind { } } -/// Completion options. -#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] -pub struct CompletionOptions { - /// The server provides support to resolve additional information for a completion item. +/** + * The show message request is sent from a server to a client to ask the client to display a particular message + * in the user interface. In addition to the show message notification the request allows to pass actions and to + * wait for an answer from the client. + */ +pub const REQUEST__ShowMessageRequest: &'static str = "window/showMessageRequest"; + + +#[derive(Debug, PartialEq, 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")] - #[serde(rename="resolveProvider")] - pub resolve_provider: Option, + pub actions: Option>, +} - /// The characters that trigger completion automatically. - #[serde(rename="triggerCharacters")] - pub trigger_characters: Vec, +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct MessageActionItem { + /// A short title like 'Retry', 'Open Log' etc. + pub title: String, +} + +/** + * The log message notification is sent from the server to the client to ask the client to log a particular message. + */ +pub const NOTIFICATION__LogMessage: &'static str = "window/logMessage"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct LogMessageParams { + /// The message type. See {@link MessageType} + #[serde(rename="type")] + pub typ: MessageType, + + /// The actual message + pub message: String, +} + +/** + * The telemetry notification is sent from the server to the client to ask the client to log a telemetry event. + */ +pub const NOTIFICATION__TelemetryEvent: &'static str = "telemetry/event"; + +/** + * A notification sent from the client to the server to signal the change of configuration settings. + */ +pub const NOTIFICATION__WorkspaceChangeConfiguration: &'static str = "workspace/didChangeConfiguration"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidChangeConfigurationParams { + /// The actual changed settings + pub settings: Value, +} + +/** + * The document open notification is sent from the client to the server to signal newly opened text documents. + * The document's truth is now managed by the client and the server must not try to read the document's truth + * using the document's uri. + */ +pub const NOTIFICATION__DidOpenTextDocument: &'static str = "textDocument/didOpen"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidOpenTextDocumentParams { + /// The document that was opened. + #[serde(rename="textDocument")] + pub text_document: TextDocumentItem, +} + +/** + * The document change notification is sent from the client to the server to signal changes to a text document. + * In 2.0 the shape of the params has changed to include proper version numbers and language ids. + */ +pub const NOTIFICATION__DidChangeTextDocument: &'static str = "textDocument/didChange"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidChangeTextDocumentParams { + /// The document that did change. The version number points + /// to the version after all provided content changes have + /// been applied. + #[serde(rename="textDocument")] + pub text_document: VersionedTextDocumentIdentifier, + /// The actual content changes. + #[serde(rename="contentChanges")] + pub content_changes: Vec, +} + +/// 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, PartialEq, Deserialize, Serialize)] +pub struct TextDocumentContentChangeEvent { + /// The range of the document that changed. + pub range: Option, + + /// The length of the range that got replaced. + /// NOTE: seems redundant, see: https://github.com/Microsoft/language-server-protocol/issues/9 + #[serde(rename="rangeLength")] + pub range_length: Option, + + /// The new text of the document. + pub text: String, +} + +/** + * The document close notification is sent from the client to the server when the document got closed in the client. + * The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri + * the truth now exists on disk). + */ +pub const NOTIFICATION__DidCloseTextDocument: &'static str = "textDocument/didClose"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidCloseTextDocumentParams { + /// The document that was closed. + #[serde(rename="textDocument")] + pub text_document: TextDocumentIdentifier, +} + +/** + * The document save notification is sent from the client to the server when the document was saved in the client. + */ +pub const NOTIFICATION__DidSaveTextDocument: &'static str = "textDocument/didSave"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidSaveTextDocumentParams { + /// The document that was saved. + #[serde(rename="textDocument")] + pub text_document: TextDocumentIdentifier, +} + +/** + * The watched files notification is sent from the client to the server when the client detects changes to files + * watched by the language client. + */ +pub const NOTIFICATION__DidChangeWatchedFiles: &'static str = "workspace/didChangeWatchedFiles"; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DidChangeWatchedFilesParams { + /// The actual file events. + pub changes: Vec, +} + +/// The file event type. +#[derive(Debug, PartialEq, Copy, Clone)] +pub enum FileChangeType { + /// The file got created. + Created = 1, + + /// The file got changed. + Changed = 2, + + /// The file got deleted. + Deleted = 3, +} + +impl serde::Deserialize for FileChangeType { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + Ok(match try!(u8::deserialize(deserializer)) { + 1 => FileChangeType::Created, + 2 => FileChangeType::Changed, + 3 => FileChangeType::Deleted, + _ => { + return Err(D::Error::invalid_value("Expected a value of 1, 2 or 3 to deserialze \ + to FileChangeType")) + } + }) + } } -/// Signature help options. -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct SignatureHelpOptions { - /// The characters that trigger signature help automatically. - #[serde(skip_serializing_if="Vec::is_empty")] - #[serde(rename="triggerCharacters")] - pub trigger_characters: Vec, +impl serde::Serialize for FileChangeType { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serializer.serialize_u8(*self as u8) + } } -/// Code Lens options. +/// An event describing a file change. #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct CodeLensOptions { - /// Code lens has a resolve provider as well. - #[serde(rename="resolveProvider")] - pub resolve_provider: Option, -} +pub struct FileEvent { -/// Format document on type options -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DocumentOnTypeFormattingOptions { - /// A character on which formatting should be triggered, like `}`. - #[serde(rename="firstTriggerCharacter")] - pub first_trigger_character: String, - /// More trigger characters. - #[serde(skip_serializing_if="Vec::is_empty")] - #[serde(rename="moreTriggerCharacter")] - pub more_trigger_character: Vec, -} + /// The file's URI. + pub uri: String, -/// A textual edit applicable to a text document. -#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] -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. - #[serde(rename="newText")] - pub new_text: String, + /// The change type. + #[serde(rename="type")] + pub typ: FileChangeType, } -/// A workspace edit represents changes to many resources managed in the workspace. +/** + * Diagnostics notification are sent from the server to the client to signal results of validation runs. + */ +pub const NOTIFICATION__PublishDiagnostics: &'static str = "textDocument/publishDiagnostics"; + #[derive(Debug, PartialEq, Default, Deserialize, Serialize)] -pub struct WorkspaceEdit { - /// Holds changes to existing resources. - pub changes: HashMap>, +pub struct PublishDiagnosticsParams { + /// The URI for which diagnostic information is reported. + pub uri: String, + + /// An array of diagnostic information items. + pub diagnostics: Vec, } +/** + The Completion request is sent from the client to the server to compute completion items at a given cursor position. + Completion items are presented in the IntelliSense user interface. If computing full completion items is expensive, + servers can additionally provide a handler for the completion item resolve request ('completionItem/resolve'). + This request is sent when a completion item is selected in the user interface. A typically use case is for example: + the 'textDocument/completion' request doesn't fill in the documentation property for returned completion items + since it is expensive to compute. When the item is selected in the user interface then a 'completionItem/resolve' + request is sent with the selected completion item as a param. The returned completion item should have the + documentation property filled in. +*/ +// result: CompletionItem[] | CompletionList FIXME +pub const REQUEST__Completion: &'static str = "textDocument/completion"; + /// Represents a collection of [completion items](#CompletionItem) to be presented /// in the editor. #[derive(Debug, PartialEq, Default, Deserialize, Serialize)] pub struct CompletionList { + /// This list it not complete. Further typing should result in recomputing /// this list. #[serde(rename="isIncomplete")] pub is_incomplete: bool, + /// The completion items. pub items: Vec, } #[derive(Debug, PartialEq, Default, Deserialize, Serialize)] 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, + /// 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, + /// A human-readable string that represents a doc-comment. #[serde(skip_serializing_if="Option::is_none")] pub documentation: Option, + /// 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")] #[serde(rename="sortText")] pub sort_text: Option, + /// 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")] #[serde(rename="filterText")] pub filter_text: Option, + /// 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")] #[serde(rename="insertText")] pub insert_text: Option, + /// An edit which is applied to a document when selecting /// this completion. When an edit is provided the value of /// insertText is ignored. #[serde(skip_serializing_if="Option::is_none")] #[serde(rename="textEdit")] pub text_edit: Option, + + /// 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")] + #[serde(rename="additionalTextEdits")] + pub additional_text_edits: Option>, + + /// 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, + /// 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")] @@ -478,16 +848,37 @@ impl serde::Serialize for CompletionItemKind { } } +/// The request is sent from the client to the server to resolve additional information for a given completion item. +pub const REQUEST__ResolveCompletionItem: &'static str = "completionItem/resolve"; + + +/// The hover request is sent from the client to the server to request hover information at a given text +/// document position. +pub const REQUEST__Hover: &'static str = "textDocument/hover"; + /// The result of a hover request. #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct Hover { /// The hover's content - pub contents: Vec, + pub contents: Vec, /* FIXME: need to review if this is correct*/ + //contents: MarkedString | MarkedString[]; - /// An optional range + /// An optional range is a range inside a text document + /// that is used to visualize a hover, e.g. by changing the background color. pub range: Option, } +/** + 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} + ``` + */ +//type MarkedString = string | { language: string; value: string }; #[derive(Debug, PartialEq)] pub enum MarkedString { String(String), @@ -539,6 +930,13 @@ impl serde::Serialize for MarkedString { } } } +// FIXME review and test MarkedString serialization + + +/// The signature help request is sent from the client to the server to request signature information at +/// a given cursor position. +pub const REQUEST__SignatureHelp: &'static str = "textDocument/signatureHelp"; + /// Signature help represents the signature of something /// callable. There can be multiple signature but only one @@ -568,11 +966,11 @@ pub struct SignatureInformation { /// The human-readable doc-comment of this signature. Will be shown /// in the UI but can be omitted. - pub documentation: String, + pub documentation: Option, /// The parameters of this signature. - #[serde(skip_serializing_if="Vec::is_empty")] - pub parameters: Vec, + #[serde(skip_serializing_if="Option::is_none")] + pub parameters: Option>, } /// Represents a parameter of a callable-signature. A parameter can @@ -585,18 +983,34 @@ pub struct ParameterInformation { /// The human-readable doc-comment of this signature. Will be shown /// in the UI but can be omitted. - #[serde(skip_serializing_if="String::is_empty")] - pub documentation: String, + #[serde(skip_serializing_if="Option::is_none")] + pub documentation: Option, } +/// The goto definition request is sent from the client to the server to resolve the definition location of +/// a symbol at a given text document position. +pub const REQUEST__GotoDefinition: &'static str = "textDocument/definition"; + +/// The references request is sent from the client to the server to resolve project-wide references for the +/// symbol denoted by the given text document position. +pub const REQUEST__References: &'static str = "textDocument/references"; + #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct ReferenceParams { +pub struct ReferenceParams +//extends TextDocumentPositionParams +{ + + // This field was "mixed-in" from TextDocumentPositionParams /// The text document. #[serde(rename="textDocument")] pub text_document: TextDocumentIdentifier, + + // This field was "mixed-in" from TextDocumentPositionParams /// The position inside the text document. pub position: Position, + // ReferenceParams properties: + pub context: ReferenceContext, } @@ -607,6 +1021,17 @@ pub struct ReferenceContext { pub include_declaration: bool, } +/** + The document highlight request is sent from the client to the server to resolve a document highlights + for a given text document position. + For programming languages this usually highlights all references to the symbol scoped to this file. + However we kept 'textDocument/documentHighlight' and 'textDocument/references' separate requests since + the first one is allowed to be more fuzzy. + Symbol matches usually have a DocumentHighlightKind of Read or Write whereas fuzzy or textual matches + use Textas the kind. +*/ +pub const REQUEST__DocumentHighlight: &'static str = "textDocument/documentHighlight"; + /// 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. @@ -656,6 +1081,12 @@ impl serde::Serialize for DocumentHighlightKind { } } +/** + * The document symbol request is sent from the client to the server to list all symbols found in a given + * text document. + */ +pub const REQUEST__DocumentSymbols: &'static str = "textDocument/documentSymbol"; + #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct DocumentSymbolParams { /// The text document. @@ -678,7 +1109,7 @@ pub struct SymbolInformation { /// The name of the symbol containing this symbol. #[serde(rename="containerName")] - pub container_name: String, + pub container_name: Option } /// A symbol kind. @@ -728,6 +1159,12 @@ impl serde::Serialize for SymbolKind { } } +/** + * The workspace symbol request is sent from the client to the server to list project-wide symbols + * matching the query string. + */ +pub const REQUEST__WorkspaceSymbols: &'static str = "workspace/symbol"; + /// The parameters of a Workspace Symbol Request. #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct WorkspaceSymbolParams { @@ -735,10 +1172,18 @@ pub struct WorkspaceSymbolParams { pub query: String, } +/** + * The code action request is sent from the client to the server to compute commands for a given text document + * and range. The request is triggered when the user moves the cursor into a problem marker in the editor or + * presses the lightbulb associated with a marker. + */ +pub const REQUEST__CodeAction: &'static str = "textDocument/codeAction"; + /// Params for the CodeActionRequest #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct CodeActionParams { /// The document in which the command was invoked. + #[serde(rename="textDocument")] pub text_document: TextDocumentIdentifier, /// The range for which the command was invoked. @@ -756,6 +1201,11 @@ pub struct CodeActionContext { pub diagnostics: Vec, } +/** + * The code lens request is sent from the client to the server to compute code lenses for a given text document. + */ +pub const REQUEST__CodeLens: &'static str = "textDocument/codeLens"; + #[derive(Debug, PartialEq, Deserialize, Serialize)] pub struct CodeLensParams { /// The document to request code lens for. @@ -765,6 +1215,7 @@ pub struct CodeLensParams { /// 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, PartialEq, Deserialize, Serialize)] @@ -780,181 +1231,103 @@ pub struct CodeLens { pub data: Option, } +/** + * The code lens resolve request is sent from the client to the server to resolve the command for a + * given code lens item. + */ +pub const REQUEST__CodeLensResolve: &'static str = "codeLens/resolve"; + +/** + * The document formatting request is sent from the server to the client to format a whole document. + */ +pub const REQUEST__Formatting: &'static str = "textDocument/formatting"; + #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct RenameParams { +pub struct DocumentFormattingParams { /// The document to format. #[serde(rename="textDocument")] pub text_document: TextDocumentIdentifier, - /// The position at which this request was sent. - pub position: Position, - - /// 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. - #[serde(rename="newName")] - pub new_name: String, -} - -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct ShowMessageParams { - /// The message type. See {@link MessageType} - #[serde(rename="type")] - pub typ: MessageType, - - /// The actual message - pub message: String, + /// The format options. + pub options: FormattingOptions, } +/// Value-object describing what options formatting should use. #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct ShowMessageRequestParams { - /// The message type. See {@link MessageType} - #[serde(rename="type")] - pub typ: MessageType, - - /// The actual message - pub message: String, +pub struct FormattingOptions { + /// Size of a tab in spaces. + #[serde(rename="tabSize")] + pub tab_size: u64, - /// The message action items to present. - #[serde(skip_serializing_if="Vec::is_empty")] - pub actions: Vec, -} + #[serde(rename="insertSpaces")] + /// Prefer spaces over tabs. + pub insert_spaces: bool, -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct MessageActionItem { - /// A short title like 'Retry', 'Open Log' etc. - pub title: String, +// +// /// Signature for further properties. +// + //[key: string]: boolean | number | string; + // FIXME what is this, I don't quite get it + } -#[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct LogMessageParams { - /// The message type. See {@link MessageType} - #[serde(rename="type")] - pub typ: MessageType, - - /// The actual message - pub message: String, -} +/// The document range formatting request is sent from the client to the server to format a given range in a document. +pub const REQUEST__RangeFormatting: &'static str = "textDocument/rangeFormatting"; #[derive(Debug, PartialEq, Deserialize, Serialize)] -pub struct DidChangeConfigurationParams { - /// The actual changed settings - pub settings: Value, -} - -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum MessageType { - /// An error message. - Error = 1, - /// A warning message. - Warning = 2, - /// An information message. - Info = 3, - /// A log message. - Log = 4, -} +pub struct DocumentRangeFormattingParams { -impl serde::Deserialize for MessageType { - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - Ok(match try!(u8::deserialize(deserializer)) { - 1 => MessageType::Error, - 2 => MessageType::Warning, - 3 => MessageType::Info, - 4 => MessageType::Log, - _ => { - return Err(D::Error::invalid_value("Expected a value of 1, 2, 3 or 4 to \ - deserialze to MessageType")) - } - }) - } -} + /// The document to format. + #[serde(rename="textDocument")] + pub text_document: TextDocumentIdentifier, -impl serde::Serialize for MessageType { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - serializer.serialize_u8(*self as u8) - } -} -#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] -pub struct PublishDiagnosticsParams { - /// The URI for which diagnostic information is reported. - pub uri: String, + /// The range to format + pub range: Range, - /// An array of diagnostic information items. - pub diagnostics: Vec, + /// The format options + pub options: FormattingOptions, } -#[derive(Debug, PartialEq, Default, Deserialize, Serialize)] -pub struct Diagnostic { - /// The range at which the message applies - pub range: Range, +/** + * The document on type formatting request is sent from the client to the server to format parts of + * the document during typing. + */ +pub const REQUEST__OnTypeFormatting: &'static str = "textDocument/onTypeFormatting"; - /// The diagnostic's severity. Can be omitted. If omitted it is up to the - /// client to interpret diagnostics as error, warning, info or hint. - pub severity: Option, +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct DocumentOnTypeFormattingParams { + /// The document to format. + #[serde(rename="textDocument")] + pub text_document: TextDocumentIdentifier, - /// The diagnostic's code. Can be omitted. - pub code: String, - /// number | string; + /// The position at which this request was sent. + pub position: Position, - /// A human-readable string describing the source of this - /// diagnostic, e.g. 'typescript' or 'super lint'. - pub source: Option, + /// The character that has been typed. + pub ch: String, - /// The diagnostic's message. - pub message: String, + /// The format options. + pub options: FormattingOptions, } -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum DiagnosticSeverity { - /// Reports an error. - Error = 1, - /// Reports a warning. - Warning = 2, - /// Reports an information. - Information = 3, - /// Reports a hint. - Hint = 4, -} +/** + * The rename request is sent from the client to the server to perform a workspace-wide rename of a symbol. + */ +pub const REQUEST__Rename: &'static str = "textDocument/rename"; -impl serde::Deserialize for DiagnosticSeverity { - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - Ok(match try!(u8::deserialize(deserializer)) { - 1 => DiagnosticSeverity::Error, - 2 => DiagnosticSeverity::Warning, - 3 => DiagnosticSeverity::Information, - 4 => DiagnosticSeverity::Hint, - _ => { - return Err(D::Error::invalid_value("Expected a value of 1, 2, 3 or 4 to \ - deserialze to DiagnosticSeverity")) - } - }) - } -} +#[derive(Debug, PartialEq, Deserialize, Serialize)] +pub struct RenameParams { + /// The document to format. + #[serde(rename="textDocument")] + pub text_document: TextDocumentIdentifier, -impl serde::Serialize for DiagnosticSeverity { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - serializer.serialize_u8(*self as u8) - } -} + /// The position at which this request was sent. + pub position: Position, -/// Represents a reference to a command. Provides a title which will be used to represent a command in the UI and, optionally, an array of arguments which will be passed to the command handler function when invoked. -#[derive(Debug, PartialEq, 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="Vec::is_empty")] - pub arguments: Vec, -} + /// 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. + #[serde(rename="newName")] + pub new_name: String, +} \ No newline at end of file