Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update lsp-types to 0.97 and add notebook support #401

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
rust-version: [1.64.0, beta, nightly]
rust-version: [1.70.0, beta, nightly]
runtime: [runtime-tokio, runtime-agnostic]
include:
- rust-version: nightly
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
- uses: actions/checkout@v3
- id: install-rust
name: Install Rust toolchain
uses: dtolnay/rust-toolchain@1.64.0
uses: dtolnay/rust-toolchain@1.70.0
with:
components: clippy
- name: Run cargo clippy
Expand All @@ -67,7 +67,7 @@ jobs:
- uses: actions/checkout@v3
- id: install-rust
name: Install Rust toolchain
uses: dtolnay/rust-toolchain@1.64.0
uses: dtolnay/rust-toolchain@1.70.0
with:
components: rustfmt
- name: Run cargo fmt
Expand Down
18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tower-lsp"
version = "0.20.0"
authors = ["Eyal Kalderon <[email protected]>"]
edition = "2021"
rust-version = "1.64.0"
rust-version = "1.70.0"
description = "Language Server Protocol implementation based on Tower"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/ebkalderon/tower-lsp"
Expand All @@ -24,26 +24,26 @@ proposed = ["lsp-types/proposed"]
async-codec-lite = { version = "0.0", optional = true }
async-trait = "0.1"
auto_impl = "1.0"
bytes = "1.0"
dashmap = "5.1"
bytes = "1.5"
dashmap = "5.5"
futures = { version = "0.3", default-features = false, features = ["std", "async-await"] }
httparse = "1.8"
lsp-types = "0.94.1"
memchr = "2.5"
lsp-types = "0.97.0"
memchr = "2.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.17", optional = true }
tokio = { version = "1.35", optional = true }
tokio-util = { version = "0.7", optional = true, features = ["codec"] }
tower-lsp-macros = { version = "0.9", path = "./tower-lsp-macros" }
tower = { version = "0.4", default-features = false, features = ["util"] }
tracing = "0.1"

[dev-dependencies]
async-tungstenite = { version = "0.22", features = ["tokio-runtime"] }
async-tungstenite = { version = "0.23.0", features = ["tokio-runtime"] }
tracing-subscriber = "0.3"
tokio = { version = "1.17", features = ["io-util", "io-std", "macros", "rt-multi-thread"] }
tokio = { version = "1.35", features = ["io-util", "io-std", "macros", "rt-multi-thread"] }
tokio-util = { version = "0.7", features = ["compat"] }
ws_stream_tungstenite = { version = "0.10", features = ["tokio_io"] }
ws_stream_tungstenite = { version = "0.11.0", features = ["tokio_io"] }

[workspace]
members = [".", "./tower-lsp-macros"]
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.64.0
1.70.0
9 changes: 2 additions & 7 deletions src/jsonrpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod response;
mod router;

/// A unique ID used to correlate requests and responses together.
#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[derive(Default, Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Id {
/// Numeric ID.
Expand All @@ -33,15 +33,10 @@ pub enum Id {
/// While `null` is considered a valid request ID by the JSON-RPC 2.0 specification, its use is
/// _strongly_ discouraged because the specification also uses a `null` value to indicate an
/// unknown ID in the [`Response`] object.
#[default]
Null,
}

impl Default for Id {
fn default() -> Self {
Id::Null
}
}

impl Display for Id {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Expand Down
48 changes: 48 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,54 @@ pub trait LanguageServer: Send + Sync + 'static {
warn!("Got a textDocument/didClose notification, but it is not implemented");
}

// Notebook Document Synchronization

/// The [`notebookDocument/didOpen`] notification is sent from the client to the server when a new notebook document is opened.
/// It is only sent for notebooks selected by the `notebookDocumentSync` server capability.
///
/// [`notebookDocument/didOpen`]: https://microsoft.github.io/language-server-protocol/specification/#notebookDocument_didChange
///
// TODO: Write more documentation
#[rpc(name = "notebookDocument/didOpen")]
async fn notebook_did_open(&self, params: DidOpenNotebookDocumentParams) {
let _ = params;
warn!("Got a notebookDocument/didOpen notification, but it is not implemented");
}

/// The [`notebookDocument/didChange`] notification is sent from the client to the server when a notebook document changes.
/// It is only sent for notebooks selected by the `notebookDocumentSync` server capability.
///
/// [`notebookDocument/didChange`]: https://microsoft.github.io/language-server-protocol/specification#notebookDocument_didChange
///
// TODO: Write more documentation
#[rpc(name = "notebookDocument/didChange")]
async fn notebook_did_change(&self, params: DidChangeNotebookDocumentParams) {
let _ = params;
warn!("Got a notebookDocument/didChange notification, but it is not implemented");
}

/// The [`notebookDocument/didSave`] notification is sent from the client to the server when a notebook document is saved.
/// It is only sent for notebooks selected by the `notebookDocumentSync` server capability.
///
/// [`notebookDocument/didSave`]: https://microsoft.github.io/language-server-protocol/specification#notebookDocument_didSave
#[rpc(name = "notebookDocument/didSave")]
async fn notebook_did_save(&self, params: DidSaveNotebookDocumentParams) {
let _ = params;
warn!("Got a notebookDocument/didSave notification, but it is not implemented");
}

/// The [`notebookDocument/didClose`] notification is sent from the client to the server when a notebook document is closed.
/// It is only sent for notebooks selected by the `notebookDocumentSync` server capability.
///
/// [`notebookDocument/didClose`]: https://microsoft.github.io/language-server-protocol/specification#notebookDocument_didClose
///
// TODO: Write more documentation
#[rpc(name = "notebookDocument/didClose")]
async fn notebook_did_close(&self, params: DidCloseNotebookDocumentParams) {
let _ = params;
warn!("Got a notebookDocument/didClose notification, but it is not implemented");
}

// Language Features

/// The [`textDocument/declaration`] request asks the server for the declaration location of a
Expand Down
27 changes: 17 additions & 10 deletions src/service/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::task::{Context, Poll};
use futures::channel::mpsc::{self, Sender};
use futures::future::BoxFuture;
use futures::sink::SinkExt;
use lsp_types::request::WorkspaceDiagnosticRefresh;
use lsp_types::*;
use serde::Serialize;
use serde_json::Value;
Expand Down Expand Up @@ -210,10 +211,12 @@ impl Client {
use lsp_types::notification::TelemetryEvent;
match serde_json::to_value(data) {
Err(e) => error!("invalid JSON in `telemetry/event` notification: {}", e),
Ok(mut value) => {
if !value.is_null() && !value.is_array() && !value.is_object() {
value = Value::Array(vec![value]);
}
Ok(value) => {
let value = match value {
Value::Object(value) => OneOf::Left(value),
Value::Array(value) => OneOf::Right(value),
value => OneOf::Right(vec![value]),
};
self.send_notification_unchecked::<TelemetryEvent>(value)
.await;
}
Expand Down Expand Up @@ -361,7 +364,7 @@ impl Client {
/// This notification will only be sent if the server is initialized.
pub async fn publish_diagnostics(
&self,
uri: Url,
uri: Uri,
diags: Vec<Diagnostic>,
version: Option<i32>,
) {
Expand Down Expand Up @@ -672,26 +675,30 @@ mod tests {
#[tokio::test(flavor = "current_thread")]
async fn telemetry_event() {
let null = json!(null);
let expected = Request::from_notification::<TelemetryEvent>(null.clone());
let value = OneOf::Right(vec![null.clone()]);
let expected = Request::from_notification::<TelemetryEvent>(value);
assert_client_message(|p| async move { p.telemetry_event(null).await }, expected).await;

let array = json!([1, 2, 3]);
let expected = Request::from_notification::<TelemetryEvent>(array.clone());
let value = OneOf::Right(array.as_array().unwrap().to_owned());
let expected = Request::from_notification::<TelemetryEvent>(value);
assert_client_message(|p| async move { p.telemetry_event(array).await }, expected).await;

let object = json!({});
let expected = Request::from_notification::<TelemetryEvent>(object.clone());
let value = OneOf::Left(object.as_object().unwrap().to_owned());
let expected = Request::from_notification::<TelemetryEvent>(value);
assert_client_message(|p| async move { p.telemetry_event(object).await }, expected).await;

let other = json!("hello");
let wrapped = Value::Array(vec![other.clone()]);
let expected = Request::from_notification::<TelemetryEvent>(wrapped);
let value = OneOf::Right(wrapped.as_array().unwrap().to_owned());
let expected = Request::from_notification::<TelemetryEvent>(value);
assert_client_message(|p| async move { p.telemetry_event(other).await }, expected).await;
}

#[tokio::test(flavor = "current_thread")]
async fn publish_diagnostics() {
let uri: Url = "file:///path/to/file".parse().unwrap();
let uri: Uri = "file:///path/to/file".parse().unwrap();
let diagnostics = vec![Diagnostic::new_simple(Default::default(), "example".into())];

let params = PublishDiagnosticsParams::new(uri.clone(), diagnostics.clone(), None);
Expand Down