diff --git a/src/lib.rs b/src/lib.rs index 4253c76..406332a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,6 +135,9 @@ pub use document_link::*; mod document_symbols; pub use document_symbols::*; +mod notebook; +pub use notebook::*; + mod file_operations; pub use file_operations::*; @@ -1594,6 +1597,12 @@ pub struct ClientCapabilities { #[serde(skip_serializing_if = "Option::is_none")] pub text_document: Option, + /// Capabilities specific to the notebook document support. + /// + /// @since 3.17.0 + #[serde(skip_serializing_if = "Option::is_none")] + pub notebook_document: Option, + /// Window specific client capabilities. #[serde(skip_serializing_if = "Option::is_none")] pub window: Option, @@ -1910,6 +1919,13 @@ pub struct ServerCapabilities { #[serde(skip_serializing_if = "Option::is_none")] pub text_document_sync: Option, + /// Defines how notebook documents are synced. + /// + /// @since 3.17.0 + #[serde(skip_serializing_if = "Option::is_none")] + pub notebook_document_sync: + Option>, + /// Capabilities specific to `textDocument/selectionRange` requests. #[serde(skip_serializing_if = "Option::is_none")] pub selection_range_provider: Option, diff --git a/src/notebook.rs b/src/notebook.rs new file mode 100644 index 0000000..15a3a15 --- /dev/null +++ b/src/notebook.rs @@ -0,0 +1,432 @@ +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; + +use crate::{LSPObject, Url}; + +pub use notification_params::*; + +/// A notebook document. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocument { + /// The notebook document's URI. + uri: Url, + /// The type of the notebook. + notebook_type: String, + /// The version number of this document (it will increase after each + /// change, including undo/redo). + version: i32, + /// Additional metadata stored with the notebook + /// document. + #[serde(skip_serializing_if = "Option::is_none")] + metadata: Option, + /// The cells of a notebook. + cells: Vec, +} + +/// A notebook cell. +/// +/// A cell's document URI must be unique across ALL notebook +/// cells and can therefore be used to uniquely identify a +/// notebook cell or the cell's text document. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookCell { + /// The cell's kind + kind: NotebookCellKind, + /// The URI of the cell's text document content. + document: Url, + /// Additional metadata stored with the cell. + #[serde(skip_serializing_if = "Option::is_none")] + metadata: Option, + /// Additional execution summary information + /// if supported by the client. + #[serde(skip_serializing_if = "Option::is_none")] + execution_summary: Option, +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecutionSummary { + /// A strict monotonically increasing value + /// indicating the execution order of a cell + /// inside a notebook. + execution_order: u32, + /// Whether the execution was successful or + /// not if known by the client. + #[serde(skip_serializing_if = "Option::is_none")] + success: Option, +} + +#[derive(Debug, Eq, PartialEq, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum NotebookCellKind { + /// A markup-cell is formatted source that is used for display. + Markup = 1, + /// A code-cell is source code. + Code = 2, +} + +/// Capabilities specific to the notebook document support. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentClientCapabilities { + /// Capabilities specific to notebook document synchronization + /// + /// @since 3.17.0 + pub synchronization: NotebookDocumentSyncClientCapabilities, +} + +/// Notebook specific client capabilities. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentSyncClientCapabilities { + /// 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, + + /// The client supports sending execution summary data per cell. + #[serde(skip_serializing_if = "Option::is_none")] + pub execution_summary_report: Option, +} + +/// Options specific to a notebook plus its cells +/// to be synced to the server. +/// +/// If a selector provides a notebook document +/// filter but no cell selector all cells of a +/// matching notebook document will be synced. +/// +/// If a selector provides no notebook document +/// filter but only a cell selector all notebook +/// documents that contain at least one matching +/// cell will be synced. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentSyncOptions { + /// The notebooks to be synced + notebook_selector: Vec, + /// Whether save notification should be forwarded to + /// the server. Will only be honored if mode === `notebook`. + #[serde(skip_serializing_if = "Option::is_none")] + save: Option, +} + +/// Registration options specific to a notebook. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentSyncRegistrationOptions { + /// The notebooks to be synced + notebook_selector: Vec, + /// Whether save notification should be forwarded to + /// the server. Will only be honored if mode === `notebook`. + #[serde(skip_serializing_if = "Option::is_none")] + save: Option, + /// The id used to register the request. The id can be used to deregister + /// the request again. See also Registration#id. + #[serde(skip_serializing_if = "Option::is_none")] + id: Option, +} + +/// A notebook cell text document filter denotes a cell text +/// document by different properties. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookCellTextDocumentFilter { + /// A filter that matches against the notebook + /// containing the notebook cell. If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + notebook: Notebook, + /// A language id like `python`. + /// + /// Will be matched against the language id of the + /// notebook cell document. '*' matches every language. + #[serde(skip_serializing_if = "Option::is_none")] + language: Option, +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(untagged)] +pub enum NotebookSelector { + ByNotebook(NotebookSelectorByNotebook), + ByCells(NotebookSelectorByCells), +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookSelectorByNotebook { + /// The notebook to be synced. If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + notebook: Notebook, + /// The cells of the matching notebook to be synced. + #[serde(skip_serializing_if = "Option::is_none")] + cells: Option>, +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookSelectorByCells { + /// The notebook to be synced. If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + #[serde(skip_serializing_if = "Option::is_none")] + notebook: Option, + /// The cells of the matching notebook to be synced. + cells: Vec, +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookCellSelector { + language: String, +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(untagged)] +pub enum Notebook { + String(String), + NotebookDocumentFilter(NotebookDocumentFilter), +} + +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(untagged)] +pub enum NotebookDocumentFilter { + ByType(NotebookDocumentFilterByType), + ByScheme(NotebookDocumentFilterByScheme), + ByPattern(NotebookDocumentFilterByPattern), +} + +/// A notebook document filter denotes a notebook document by +/// different properties. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentFilterByType { + /// The type of the enclosing notebook. + notebook_type: String, + /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + #[serde(skip_serializing_if = "Option::is_none")] + scheme: Option, + /// A glob pattern. + #[serde(skip_serializing_if = "Option::is_none")] + pattern: Option, +} + +/// A notebook document filter denotes a notebook document by +/// different properties. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentFilterByScheme { + /// The type of the enclosing notebook. + #[serde(skip_serializing_if = "Option::is_none")] + notebook_type: Option, + /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + scheme: String, + /// A glob pattern. + #[serde(skip_serializing_if = "Option::is_none")] + pattern: Option, +} + +/// A notebook document filter denotes a notebook document by +/// different properties. +/// +/// @since 3.17.0 +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NotebookDocumentFilterByPattern { + /// The type of the enclosing notebook. + #[serde(skip_serializing_if = "Option::is_none")] + notebook_type: Option, + /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + #[serde(skip_serializing_if = "Option::is_none")] + scheme: Option, + /// A glob pattern. + pattern: String, +} + +mod notification_params { + use serde::{Deserialize, Serialize}; + + use crate::{ + TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, + VersionedTextDocumentIdentifier, + }; + + use super::*; + + /// The params sent in an open notebook document notification. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct DidOpenNotebookDocumentParams { + /// The notebook document that got opened. + notebook_document: NotebookDocument, + /// The text documents that represent the content + /// of a notebook cell. + cell_text_documents: Vec, + } + + /// The params sent in a change notebook document notification. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct DidChangeNotebookDocumentParams { + /// The notebook document that did change. The version number points + /// to the version after all provided changes have been applied. + notebook_document: VersionedNotebookDocumentIdentifier, + + /// The actual changes to the notebook document. + /// + /// The change describes single state change to the notebook document. + /// So it moves a notebook document, its cells and its cell text document + /// contents from state S to S'. + /// + /// To mirror the content of a notebook using change events use the + /// following approach: + /// - start with the same initial content + /// - apply the 'notebookDocument/didChange' notifications in the order + /// you receive them. + change: NotebookDocumentChangeEvent, + } + + /// A versioned notebook document identifier. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct VersionedNotebookDocumentIdentifier { + /// The version number of this notebook document. + version: i32, + /// The notebook document's URI. + uri: Url, + } + + /// A change event for a notebook document. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookDocumentChangeEvent { + /// The changed meta data if any. + #[serde(skip_serializing_if = "Option::is_none")] + metadata: Option, + + /// Changes to cells + #[serde(skip_serializing_if = "Option::is_none")] + cells: Option, + } + + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookDocumentCellChange { + /// Changes to the cell structure to add or + /// remove cells. + #[serde(skip_serializing_if = "Option::is_none")] + structure: Option, + + /// Changes to notebook cells properties like its + /// kind, execution summary or metadata. + #[serde(skip_serializing_if = "Option::is_none")] + data: Option>, + + /// Changes to the text content of notebook cells. + #[serde(skip_serializing_if = "Option::is_none")] + text_content: Option>, + } + + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookDocumentChangeTextContent { + document: VersionedTextDocumentIdentifier, + changes: Vec, + } + + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookDocumentCellChangeStructure { + /// The change to the cell array. + array: NotebookCellArrayChange, + /// Additional opened cell text documents. + #[serde(skip_serializing_if = "Option::is_none")] + did_open: Option>, + /// Additional closed cell text documents. + #[serde(skip_serializing_if = "Option::is_none")] + did_close: Option>, + } + + /// A change describing how to move a `NotebookCell` + /// array from state S to S'. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookCellArrayChange { + /// The start offset of the cell that changed. + start: u32, + + /// The deleted cells + delete_count: u32, + + /// The new cells, if any + #[serde(skip_serializing_if = "Option::is_none")] + cells: Option>, + } + + /// The params sent in a save notebook document notification. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct DidSaveNotebookDocumentParams { + /// The notebook document that got saved. + notebook_document: NotebookDocumentIdentifier, + } + + /// A literal to identify a notebook document in the client. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct NotebookDocumentIdentifier { + /// The notebook document's URI. + uri: Url, + } + + /// The params sent in a close notebook document notification. + /// + /// @since 3.17.0 + #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct DidCloseNotebookDocumentParams { + /// The notebook document that got closed. + notebook_document: NotebookDocumentIdentifier, + + /// The text documents that represent the content + /// of a notebook cell that got closed. + cell_text_documents: Vec, + } +} diff --git a/src/notification.rs b/src/notification.rs index 6417707..5a4112b 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -58,6 +58,19 @@ macro_rules! lsp_notification { $crate::notification::PublishDiagnostics }; + ("notebookDocument/didOpen") => { + $crate::notification::DidOpenNotebookDocument + }; + ("notebookDocument/didChange") => { + $crate::notification::DidChangeNotebookDocument + }; + ("notebookDocument/didSave") => { + $crate::notification::DidSaveNotebookDocument + }; + ("notebookDocument/didClose") => { + $crate::notification::DidCloseNotebookDocument + }; + ("workspace/didChangeConfiguration") => { $crate::notification::DidChangeConfiguration }; @@ -231,6 +244,34 @@ impl Notification for DidSaveTextDocument { const METHOD: &'static str = "textDocument/didSave"; } +#[derive(Debug)] +pub enum DidOpenNotebookDocument {} +impl Notification for DidOpenNotebookDocument { + type Params = DidOpenNotebookDocumentParams; + const METHOD: &'static str = "notebookDocument/didOpen"; +} + +#[derive(Debug)] +pub enum DidChangeNotebookDocument {} +impl Notification for DidChangeNotebookDocument { + type Params = DidChangeNotebookDocumentParams; + const METHOD: &'static str = "notebookDocument/didChange"; +} + +#[derive(Debug)] +pub enum DidSaveNotebookDocument {} +impl Notification for DidSaveNotebookDocument { + type Params = DidSaveNotebookDocumentParams; + const METHOD: &'static str = "notebookDocument/didSave"; +} + +#[derive(Debug)] +pub enum DidCloseNotebookDocument {} +impl Notification for DidCloseNotebookDocument { + type Params = DidCloseNotebookDocumentParams; + const METHOD: &'static str = "notebookDocument/didClose"; +} + /// The watched files notification is sent from the client to the server when the client detects changes to files and folders /// watched by the language client (note although the name suggest that only file events are sent it is about file system events which include folders as well). /// It is recommended that servers register for these file system events using the registration mechanism.