From be9bf5ec66e9f7b88fecc7ea9edfe0c095e514e0 Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:04:35 +0800 Subject: [PATCH] dev: improve code quality of sync-lsp (#632) --- crates/sync-lsp/src/lib.rs | 422 ++++++++++++---------------- crates/tinymist/src/actor/editor.rs | 9 +- crates/tinymist/src/server.rs | 39 ++- 3 files changed, 216 insertions(+), 254 deletions(-) diff --git a/crates/sync-lsp/src/lib.rs b/crates/sync-lsp/src/lib.rs index 97ab404fe..170fdfb0b 100644 --- a/crates/sync-lsp/src/lib.rs +++ b/crates/sync-lsp/src/lib.rs @@ -1,3 +1,4 @@ +use core::fmt; use std::any::Any; use std::path::Path; use std::pin::Pin; @@ -5,50 +6,54 @@ use std::sync::{Arc, Weak}; use std::{collections::HashMap, path::PathBuf}; use futures::future::MaybeDone; -use lsp_server::{ErrorCode, Message, Notification, Request, RequestId, Response, ResponseError}; -use lsp_types::notification::{Notification as Notif, PublishDiagnostics}; -use lsp_types::request::{self, RegisterCapability, Request as Req, UnregisterCapability}; -use lsp_types::*; +use lsp_server::{ErrorCode, Message, Notification, Request, RequestId, Response}; +use lsp_types::{notification::Notification as Notif, request::Request as Req, *}; use parking_lot::Mutex; use reflexo::{time::Instant, ImmutPath}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::Serialize; use serde_json::{from_value, Value as JsonValue}; use tinymist_query::CompilerQueryResponse; pub mod req_queue; pub mod transport; -pub type ReqHandler = Box FnOnce(&'a mut S, lsp_server::Response) + Send + Sync>; -type ReqQueue = req_queue::ReqQueue<(String, Instant), ReqHandler>; - -pub type LspResult = Result; - -/// Returns Ok(Some()) -> Already responded -/// Returns Ok(None) -> Need to respond none -/// Returns Err(..) -> Need to respond error -pub type ScheduledResult = LspResult>; - +/// The common error type for the language server. +pub use lsp_server::ResponseError; +/// The common result type for the language server. +pub type LspResult = Result; +/// A future that may be done in place or not. pub type ResponseFuture = MaybeDone + Send>>>; +/// A future that may be rejected before actual started. pub type LspResponseFuture = LspResult>; -pub type QueryFuture = anyhow::Result>>; - +/// A future that could be rejected by common error in `LspResponseFuture`. pub type SchedulableResponse = LspResponseFuture>; +/// The common future type for the language server. pub type AnySchedulableResponse = SchedulableResponse; +/// The result of a scheduled response which could be finally catched by +/// `schedule_tail`. +/// - Returns Ok(Some()) -> Already responded +/// - Returns Ok(None) -> Need to respond none +/// - Returns Err(..) -> Need to respond error +pub type ScheduledResult = LspResult>; +/// The future type for a lsp query. +pub type QueryFuture = anyhow::Result>>; +/// A helper function to create a `LspResponseFuture` pub fn just_ok(res: T) -> Result>, E> { Ok(futures::future::MaybeDone::Done(Ok(res))) } - +/// A helper function to create a `LspResponseFuture` pub fn just_result(res: Result) -> Result>, E> { Ok(futures::future::MaybeDone::Done(res)) } - +/// A helper function to create a `LspResponseFuture` pub fn just_future( fut: impl std::future::Future> + Send + 'static, ) -> Result>, E> { Ok(futures::future::MaybeDone::Future(Box::pin(fut))) } +/// Converts a `ScheduledResult` to a `SchedulableResponse`. macro_rules! reschedule { ($expr:expr) => { match $expr { @@ -63,28 +68,12 @@ macro_rules! reschedule { type AnyCaster = Arc &mut S + Send + Sync>; +/// A Lsp client with typed service `S`. pub struct TypedLspClient { client: LspClient, caster: AnyCaster, } -impl Clone for TypedLspClient { - fn clone(&self) -> Self { - Self { - client: self.client.clone(), - caster: self.caster.clone(), - } - } -} - -impl std::ops::Deref for TypedLspClient { - type Target = LspClient; - - fn deref(&self) -> &Self::Target { - &self.client - } -} - impl TypedLspClient { pub fn to_untyped(self) -> LspClient { self.client @@ -92,6 +81,7 @@ impl TypedLspClient { } impl TypedLspClient { + /// Casts the service to another type. pub fn cast(&self, f: fn(&mut S) -> &mut T) -> TypedLspClient { let caster = self.caster.clone(); TypedLspClient { @@ -100,7 +90,9 @@ impl TypedLspClient { } } - pub fn send_request( + /// Sends a request to the client and registers a handler handled by the + /// service `S`. + pub fn send_request( &self, params: R::Params, handler: impl FnOnce(&mut S, lsp_server::Response) + Send + Sync + 'static, @@ -111,6 +103,23 @@ impl TypedLspClient { } } +impl Clone for TypedLspClient { + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + caster: self.caster.clone(), + } + } +} + +impl std::ops::Deref for TypedLspClient { + type Target = LspClient; + + fn deref(&self) -> &Self::Target { + &self.client + } +} + /// The root of the language server host. /// Will close connection when dropped. #[derive(Debug, Clone)] @@ -137,6 +146,9 @@ impl LspClientRoot { } } +type ReqHandler = Box FnOnce(&'a mut dyn Any, lsp_server::Response) + Send + Sync>; +type ReqQueue = req_queue::ReqQueue<(String, Instant), ReqHandler>; + /// The host for the language server, or known as the LSP client. #[derive(Debug, Clone)] pub struct LspClient { @@ -144,22 +156,25 @@ pub struct LspClient { pub handle: tokio::runtime::Handle, sender: Weak>, - req_queue: Arc>>, + req_queue: Arc>, } impl LspClient { + /// converts the client to a typed client. pub fn to_typed(&self) -> TypedLspClient { TypedLspClient { client: self.clone(), - caster: Arc::new(|s| s.downcast_mut().unwrap()), + caster: Arc::new(|s| s.downcast_mut().expect("invalid cast")), } } + /// Checks if there are pending requests. pub fn has_pending_requests(&self) -> bool { self.req_queue.lock().incoming.has_pending() } - pub fn send_request_( + /// Sends a request to the client and registers a handler. + pub fn send_request_( &self, params: R::Params, handler: impl FnOnce(&mut dyn Any, lsp_server::Response) + Send + Sync + 'static, @@ -178,6 +193,7 @@ impl LspClient { log::warn!("failed to send request: {res:?}"); } + /// Completes an server2client request in the request queue. pub fn complete_request(&self, service: &mut S, response: lsp_server::Response) { let mut req_queue = self.req_queue.lock(); let Some(handler) = req_queue.outgoing.complete(response.id.clone()) else { @@ -188,34 +204,16 @@ impl LspClient { handler(service, response) } - pub fn send_notification_(&self, notif: lsp_server::Notification) { - let Some(sender) = self.sender.upgrade() else { - log::warn!("failed to send request: connection closed"); - return; - }; - let Err(res) = sender.send(notif.into()) else { - return; - }; - log::warn!("failed to send notification: {res:?}"); - } - - pub fn send_notification(&self, params: N::Params) { - self.send_notification_(lsp_server::Notification::new(N::METHOD.to_owned(), params)); - } - - pub fn register_request(&self, request: &lsp_server::Request, request_received: Instant) { + /// Registers an client2server request in the request queue. + pub fn register_request(&self, request: &lsp_server::Request, received_at: Instant) { let mut req_queue = self.req_queue.lock(); - log::info!( - "handling {} - ({}) at {request_received:0.2?}", - request.method, - request.id, - ); - req_queue.incoming.register( - request.id.clone(), - (request.method.clone(), request_received), - ); + let method = request.method.clone(); + let req_id = request.id.clone(); + log::info!("handling {method} - ({req_id}) at {received_at:0.2?}"); + req_queue.incoming.register(req_id, (method, received_at)); } + /// Completes an client2server request in the request queue. pub fn respond(&self, response: lsp_server::Response) { let mut req_queue = self.req_queue.lock(); if let Some((method, start)) = req_queue.incoming.complete(response.id.clone()) { @@ -233,49 +231,26 @@ impl LspClient { } } - pub fn publish_diagnostics( - &self, - uri: Url, - diagnostics: Vec, - version: Option, - ) { - self.send_notification::(PublishDiagnosticsParams { - uri, - diagnostics, - version, - }); - } - - // todo: handle error - pub fn register_capability(&self, registrations: Vec) -> anyhow::Result<()> { - self.send_request_::( - RegistrationParams { registrations }, - |_, resp| { - if let Some(err) = resp.error { - log::error!("failed to register capability: {err:?}"); - } - }, - ); - Ok(()) + /// Sends an untyped notification to the client. + pub fn send_notification_(&self, notif: lsp_server::Notification) { + let Some(sender) = self.sender.upgrade() else { + log::warn!("failed to send notification: connection closed"); + return; + }; + let Err(res) = sender.send(notif.into()) else { + return; + }; + log::warn!("failed to send notification: {res:?}"); } - pub fn unregister_capability( - &self, - unregisterations: Vec, - ) -> anyhow::Result<()> { - self.send_request_::( - UnregistrationParams { unregisterations }, - |_, resp| { - if let Some(err) = resp.error { - log::error!("failed to unregister capability: {err:?}"); - } - }, - ); - Ok(()) + /// Sends a typed notification to the client. + pub fn send_notification(&self, params: N::Params) { + self.send_notification_(lsp_server::Notification::new(N::METHOD.to_owned(), params)); } } impl LspClient { + /// Schedules a query from the client. pub fn schedule_query(&self, req_id: RequestId, query_fut: QueryFuture) -> ScheduledResult { let fut = query_fut.map_err(|e| internal_error(e.to_string()))?; let fut: AnySchedulableResponse = Ok(match fut { @@ -293,6 +268,7 @@ impl LspClient { self.schedule(req_id, fut) } + /// Schedules a request from the client. pub fn schedule( &self, req_id: RequestId, @@ -320,22 +296,26 @@ impl LspClient { Ok(Some(())) } + /// Catch the early rejected requests. fn schedule_tail(&self, req_id: RequestId, resp: ScheduledResult) { match resp { + // Already responded Ok(Some(())) => {} + // The requests that doesn't start. _ => self.respond(result_to_response(req_id, resp)), } } } -type LspRawPureHandler = fn(srv: &mut S, args: T) -> LspResult<()>; -type LspRawHandler = fn(srv: &mut S, req_id: RequestId, args: T) -> ScheduledResult; -type LspBoxPureHandler = Box LspResult<()>>; -type LspBoxHandler = Box ScheduledResult>; -type ExecuteCmdMap = HashMap<&'static str, LspBoxHandler>>; -type RegularCmdMap = HashMap<&'static str, LspBoxHandler>; -type NotifyCmdMap = HashMap<&'static str, LspBoxPureHandler>; -type ResourceMap = HashMap>>; +type AsyncHandler = fn(srv: &mut S, args: T) -> SchedulableResponse; +type PureHandler = fn(srv: &mut S, args: T) -> LspResult<()>; +type RawHandler = fn(srv: &mut S, req_id: RequestId, args: T) -> ScheduledResult; +type BoxPureHandler = Box LspResult<()>>; +type BoxHandler = Box ScheduledResult>; +type ExecuteCmdMap = HashMap<&'static str, BoxHandler>>; +type RegularCmdMap = HashMap<&'static str, BoxHandler>; +type NotifyCmdMap = HashMap<&'static str, BoxPureHandler>; +type ResourceMap = HashMap>>; pub trait Initializer { type I: for<'de> serde::Deserialize<'de>; @@ -371,19 +351,16 @@ where pub fn with_command_( mut self, cmd: &'static str, - handler: LspRawHandler>, + handler: RawHandler>, ) -> Self { - self.exec_cmds.insert( - cmd, - Box::new(move |s, _client, req_id, req| handler(s, req_id, req)), - ); + self.exec_cmds.insert(cmd, raw_to_boxed(handler)); self } - pub fn with_command( + pub fn with_command( mut self, cmd: &'static str, - handler: fn(&mut Args::S, Vec) -> SchedulableResponse, + handler: AsyncHandler, R>, ) -> Self { self.exec_cmds.insert( cmd, @@ -394,31 +371,22 @@ where pub fn with_notification_( mut self, - handler: LspRawPureHandler, + handler: PureHandler, ) -> Self { self.notify_cmds.insert(R::METHOD, Box::new(handler)); self } - pub fn with_notification( - mut self, - handler: LspRawPureHandler, - ) -> Self { + pub fn with_notification(mut self, handler: PureHandler) -> Self { self.notify_cmds.insert( R::METHOD, - Box::new(move |s, req| { - let req = serde_json::from_value::(req).unwrap(); // todo: soft unwrap - handler(s, req) - }), + Box::new(move |s, req| handler(s, from_json(req)?)), ); self } - pub fn with_raw_request(mut self, handler: LspRawHandler) -> Self { - self.regular_cmds.insert( - R::METHOD, - Box::new(move |s, _client, req_id, req| handler(s, req_id, req)), - ); + pub fn with_raw_request(mut self, handler: RawHandler) -> Self { + self.regular_cmds.insert(R::METHOD, raw_to_boxed(handler)); self } @@ -429,24 +397,19 @@ where ) -> Self { self.regular_cmds.insert( R::METHOD, - Box::new(move |s, _client, req_id, req| { - let req = serde_json::from_value::(req).unwrap(); // todo: soft unwrap - handler(s, req_id, req) - }), + Box::new(move |s, _client, req_id, req| handler(s, req_id, from_json(req)?)), ); self } pub fn with_request( mut self, - handler: fn(&mut Args::S, R::Params) -> SchedulableResponse, + handler: AsyncHandler, ) -> Self { self.regular_cmds.insert( R::METHOD, Box::new(move |s, client, req_id, req| { - let req = serde_json::from_value::(req).unwrap(); // todo: soft unwrap - let res = handler(s, req); - client.schedule(req_id, res) + client.schedule(req_id, handler(s, from_json(req)?)) }), ); self @@ -455,12 +418,9 @@ where pub fn with_resource_( mut self, path: ImmutPath, - handler: LspRawHandler>, + handler: RawHandler>, ) -> Self { - self.resource_routes.insert( - path, - Box::new(move |s, _client, req_id, req| handler(s, req_id, req)), - ); + self.resource_routes.insert(path, raw_to_boxed(handler)); self } @@ -496,6 +456,22 @@ enum State { ShuttingDown, } +impl State { + fn opt(&self) -> Option<&S> { + match &self { + State::Ready(s) => Some(s), + _ => None, + } + } + + fn opt_mut(&mut self) -> Option<&mut S> { + match self { + State::Ready(s) => Some(s), + _ => None, + } + } +} + pub struct LspDriver { /// State to synchronize with the client. state: State, @@ -515,31 +491,21 @@ pub struct LspDriver { impl LspDriver { pub fn state(&self) -> Option<&Args::S> { - match &self.state { - State::Ready(s) => Some(s), - _ => None, - } + self.state.opt() } pub fn state_mut(&mut self) -> Option<&mut Args::S> { - match &mut self.state { - State::Ready(s) => Some(s), - _ => None, - } + self.state.opt_mut() } pub fn ready(&mut self, params: Args::I) -> AnySchedulableResponse { let args = match &mut self.state { State::Uninitialized(args) => args, - _ => { - return just_result(Err(resp_err( - ErrorCode::InvalidRequest, - "Server is already initialized", - ))) - } + _ => return just_result(Err(invalid_request("server is already initialized"))), }; - let (s, res) = args.take().unwrap().initialize(params); + let args = args.take().expect("already initialized"); + let (s, res) = args.initialize(params); self.state = State::Ready(s); res @@ -594,7 +560,7 @@ where // } while let Ok(msg) = inbox.recv() { - const EXIT_METHOD: &str = lsp_types::notification::Exit::METHOD; + const EXIT_METHOD: &str = notification::Exit::METHOD; let loop_start = Instant::now(); match msg { Message::Request(req) => self.on_request(loop_start, req), @@ -632,33 +598,38 @@ where let resp = match (&mut self.state, &*req.method) { (State::Uninitialized(args), request::Initialize::METHOD) => { // todo: what will happen if the request cannot be deserialized? - let params = serde_json::from_value::(req.params).unwrap(); - let (s, res) = args.take().unwrap().initialize(params); - self.state = State::Initializing(s); - res + let params = serde_json::from_value::(req.params); + match params { + Ok(params) => { + let args = args.take().expect("already initialized"); + let (s, res) = args.initialize(params); + self.state = State::Initializing(s); + res + } + Err(e) => just_result(Err(invalid_request(e))), + } + } + (State::Uninitialized(..) | State::Initializing(..), _) => { + just_result(Err(not_initialized())) + } + (_, request::Initialize::METHOD) => { + just_result(Err(invalid_request("server is already initialized"))) } - (State::Uninitialized(..) | State::Initializing(..), _) => just_result(Err(resp_err( - ErrorCode::ServerNotInitialized, - "Server is not initialized yet", - ))), - (_, request::Initialize::METHOD) => just_result(Err(resp_err( - ErrorCode::InvalidRequest, - "Server is already initialized", - ))), // todo: generalize this (State::Ready(..), request::ExecuteCommand::METHOD) => { reschedule!(self.on_execute_command(req)) } (State::Ready(s), _) => { - let is_shutdown = req.method == request::Shutdown::METHOD; + let method = req.method.as_str(); + let is_shutdown = method == request::Shutdown::METHOD; - let Some(handler) = self.requests.get(req.method.as_str()) else { - log::warn!("unhandled request: {}", req.method); + let Some(handler) = self.requests.get(method) else { + log::warn!("unhandled request: {method}"); return; }; - let result = handler(s, &self.client, req.id.clone(), req.params); - self.client.schedule_tail(req.id, result); + let result = handler(s, &self.client, req_id.clone(), req.params); + self.client.schedule_tail(req_id, result); if is_shutdown { self.state = State::ShuttingDown; @@ -666,10 +637,9 @@ where return; } - (State::ShuttingDown, _) => just_result(Err(resp_err( - ErrorCode::InvalidRequest, - "Server is shutting down", - ))), + (State::ShuttingDown, _) => { + just_result(Err(invalid_request("server is shutting down"))) + } }; let result = self.client.schedule(req_id.clone(), resp); @@ -678,15 +648,7 @@ where /// The entry point for the `workspace/executeCommand` request. fn on_execute_command(&mut self, req: Request) -> ScheduledResult { - let s = match &mut self.state { - State::Ready(s) => s, - _ => { - return Err(resp_err( - ErrorCode::ServerNotInitialized, - "Server is not ready", - )) - } - }; + let s = self.state.opt_mut().ok_or_else(not_initialized)?; let params = from_value::(req.params) .map_err(|e| invalid_params(e.to_string()))?; @@ -710,15 +672,7 @@ where /// Get static resources with help of tinymist service, for example, a /// static help pages for some typst function. pub fn get_resources(&mut self, req_id: RequestId, args: Vec) -> ScheduledResult { - let s = match &mut self.state { - State::Ready(s) => s, - _ => { - return Err(resp_err( - ErrorCode::ServerNotInitialized, - "Server is not ready", - )) - } - }; + let s = self.state.opt_mut().ok_or_else(not_initialized)?; let path = from_value::(args[0].clone()).map_err(|e| invalid_params(e.to_string()))?; @@ -748,19 +702,11 @@ where let result = handler(s, not.params); let request_duration = request_received.elapsed(); + let method = ¬.method; if let Err(err) = result { - log::error!( - "notifing {} failed in {:0.2?}: {:?}", - not.method, - request_duration, - err - ); + log::error!("notifing {method} failed in {request_duration:0.2?}: {err:?}"); } else { - log::info!( - "notifing {} succeeded in {:0.2?}", - not.method, - request_duration - ); + log::info!("notifing {method} succeeded in {request_duration:0.2?}"); } Ok(()) @@ -802,58 +748,48 @@ where } } -fn resp_err(code: ErrorCode, msg: impl Into) -> ResponseError { +fn from_json(json: JsonValue) -> LspResult { + serde_json::from_value(json).map_err(invalid_request) +} + +fn raw_to_boxed(handler: RawHandler) -> BoxHandler { + Box::new(move |s, _client, req_id, req| handler(s, req_id, req)) +} + +fn resp_err(code: ErrorCode, msg: impl fmt::Display) -> ResponseError { ResponseError { code: code as i32, - message: msg.into(), + message: msg.to_string(), data: None, } } -pub fn from_json( - what: &'static str, - json: &serde_json::Value, -) -> anyhow::Result { - serde_json::from_value(json.clone()) - .map_err(|e| anyhow::anyhow!("Failed to deserialize {what}: {e}; {json}")) +pub fn invalid_params(msg: impl fmt::Display) -> ResponseError { + resp_err(ErrorCode::InvalidParams, msg) } -pub fn invalid_params(msg: impl Into) -> ResponseError { - ResponseError { - code: ErrorCode::InvalidParams as i32, - message: msg.into(), - data: None, - } +pub fn internal_error(msg: impl fmt::Display) -> ResponseError { + resp_err(ErrorCode::InternalError, msg) } -pub fn internal_error(msg: impl Into) -> ResponseError { - ResponseError { - code: ErrorCode::InternalError as i32, - message: msg.into(), - data: None, - } +pub fn not_initialized() -> ResponseError { + resp_err(ErrorCode::ServerNotInitialized, "not initialized yet") } pub fn method_not_found() -> ResponseError { - ResponseError { - code: ErrorCode::MethodNotFound as i32, - message: "Method not found".to_string(), - data: None, - } + resp_err(ErrorCode::MethodNotFound, "method not found") +} + +pub fn invalid_request(msg: impl fmt::Display) -> ResponseError { + resp_err(ErrorCode::InvalidRequest, msg) } pub fn result_to_response( id: RequestId, result: Result, ) -> Response { - match result { - Ok(resp) => match serde_json::to_value(resp) { - Ok(resp) => Response::new_ok(id, resp), - Err(e) => { - let e = internal_error(e.to_string()); - Response::new_err(id, e.code, e.message) - } - }, + match result.and_then(|t| serde_json::to_value(t).map_err(internal_error)) { + Ok(resp) => Response::new_ok(id, resp), Err(e) => Response::new_err(id, e.code, e.message), } } diff --git a/crates/tinymist/src/actor/editor.rs b/crates/tinymist/src/actor/editor.rs index 1598dd67e..2a417287b 100644 --- a/crates/tinymist/src/actor/editor.rs +++ b/crates/tinymist/src/actor/editor.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use log::info; -use lsp_types::Url; +use lsp_types::{notification::PublishDiagnostics, PublishDiagnosticsParams, Url}; use tinymist_query::{DiagnosticsMap, LspDiagnostic}; use tokio::sync::mpsc; @@ -136,7 +136,12 @@ impl EditorActor { None => path_diags.remove(group), }; - self.client.publish_diagnostics(url, to_publish, None) + self.client + .send_notification::(PublishDiagnosticsParams { + uri: url, + diagnostics: to_publish, + version: None, + }); } } // Notification diff --git a/crates/tinymist/src/server.rs b/crates/tinymist/src/server.rs index e16369a1d..bce7d8e88 100644 --- a/crates/tinymist/src/server.rs +++ b/crates/tinymist/src/server.rs @@ -17,6 +17,7 @@ use reflexo_typst::{ vfs::notify::{FileChangeSet, MemoryEvent}, Bytes, Error, ImmutPath, TaskInputs, Time, }; +use request::{RegisterCapability, UnregisterCapability}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value as JsonValue}; use sync_lsp::*; @@ -295,6 +296,31 @@ impl LanguageState { } impl LanguageState { + // todo: handle error + fn register_capability(&self, registrations: Vec) -> anyhow::Result<()> { + self.client.send_request_::( + RegistrationParams { registrations }, + |_, resp| { + if let Some(err) = resp.error { + log::error!("failed to register capability: {err:?}"); + } + }, + ); + Ok(()) + } + + fn unregister_capability(&self, unregisterations: Vec) -> anyhow::Result<()> { + self.client.send_request_::( + UnregistrationParams { unregisterations }, + |_, resp| { + if let Some(err) = resp.error { + log::error!("failed to unregister capability: {err:?}"); + } + }, + ); + Ok(()) + } + /// Registers or unregisters semantic tokens. fn enable_sema_token_caps(&mut self, enable: bool) -> anyhow::Result<()> { if !self.const_config().tokens_dynamic_registration { @@ -306,15 +332,13 @@ impl LanguageState { (true, false) => { trace!("registering semantic tokens"); let options = get_semantic_tokens_options(); - self.client - .register_capability(vec![get_semantic_tokens_registration(options)]) + self.register_capability(vec![get_semantic_tokens_registration(options)]) .inspect(|_| self.sema_tokens_registered = enable) .context("could not register semantic tokens") } (false, true) => { trace!("unregistering semantic tokens"); - self.client - .unregister_capability(vec![get_semantic_tokens_unregistration()]) + self.unregister_capability(vec![get_semantic_tokens_unregistration()]) .inspect(|_| self.sema_tokens_registered = enable) .context("could not unregister semantic tokens") } @@ -350,15 +374,13 @@ impl LanguageState { match (enable, self.formatter_registered) { (true, false) => { trace!("registering formatter"); - self.client - .register_capability(vec![get_formatting_registration()]) + self.register_capability(vec![get_formatting_registration()]) .inspect(|_| self.formatter_registered = enable) .context("could not register formatter") } (false, true) => { trace!("unregistering formatter"); - self.client - .unregister_capability(vec![get_formatting_unregistration()]) + self.unregister_capability(vec![get_formatting_unregistration()]) .inspect(|_| self.formatter_registered = enable) .context("could not unregister formatter") } @@ -409,7 +431,6 @@ impl LanguageState { const CONFIG_METHOD_ID: &str = "workspace/didChangeConfiguration"; let err = self - .client .register_capability(vec![Registration { id: CONFIG_REGISTRATION_ID.to_owned(), method: CONFIG_METHOD_ID.to_owned(),