//! A stateful LSP implementation that calls into the ty API. use std::panic::AssertUnwindSafe; use crate::session::client::Client; use crate::session::{DocumentSnapshot, Session, SessionSnapshot}; use lsp_types::notification::Notification as LSPNotification; use lsp_types::request::Request; use ty_project::ProjectDatabase; /// A supertrait for any server request handler. pub(super) trait RequestHandler { type RequestType: Request; const METHOD: &'static str = <::RequestType as Request>::METHOD; } /// A request handler that needs mutable access to the session. /// This will block the main message receiver loop, meaning that no /// incoming requests or notifications will be handled while `run` is /// executing. Try to avoid doing any I/O or long-running computations. pub(super) trait SyncRequestHandler: RequestHandler { fn run( session: &mut Session, client: &Client, params: <::RequestType as Request>::Params, ) -> super::Result<<::RequestType as Request>::Result>; } pub(super) trait RetriableRequestHandler: RequestHandler { /// Whether this request can be cancelled if the Salsa database is modified. const RETRY_ON_CANCELLATION: bool = false; /// The error to return if the request was cancelled due to a modification to the Salsa database. fn salsa_cancellation_error() -> lsp_server::ResponseError { lsp_server::ResponseError { code: lsp_server::ErrorCode::ContentModified as i32, message: "content modified".to_string(), data: None, } } } /// A request handler that can be run on a background thread. /// /// This handler is specific to requests that operate on a single document. pub(super) trait BackgroundDocumentRequestHandler: RetriableRequestHandler { fn document_url( params: &<::RequestType as Request>::Params, ) -> std::borrow::Cow; fn run_with_snapshot( db: &ProjectDatabase, snapshot: DocumentSnapshot, client: &Client, params: <::RequestType as Request>::Params, ) -> super::Result<<::RequestType as Request>::Result>; } /// A request handler that can be run on a background thread. pub(super) trait BackgroundRequestHandler: RetriableRequestHandler { fn run( snapshot: AssertUnwindSafe, client: &Client, params: <::RequestType as Request>::Params, ) -> super::Result<<::RequestType as Request>::Result>; } /// A supertrait for any server notification handler. pub(super) trait NotificationHandler { type NotificationType: LSPNotification; const METHOD: &'static str = <::NotificationType as LSPNotification>::METHOD; } /// A notification handler that needs mutable access to the session. /// This will block the main message receiver loop, meaning that no /// incoming requests or notifications will be handled while `run` is /// executing. Try to avoid doing any I/O or long-running computations. pub(super) trait SyncNotificationHandler: NotificationHandler { fn run( session: &mut Session, client: &Client, params: <::NotificationType as LSPNotification>::Params, ) -> super::Result<()>; } /// A notification handler that can be run on a background thread. pub(super) trait BackgroundDocumentNotificationHandler: NotificationHandler { /// `document_url` can be implemented automatically with /// `define_document_url!(params: &)` in the trait /// implementation. fn document_url( params: &<::NotificationType as LSPNotification>::Params, ) -> std::borrow::Cow; fn run_with_snapshot( snapshot: DocumentSnapshot, client: &Client, params: <::NotificationType as LSPNotification>::Params, ) -> super::Result<()>; }