-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] Add background request task support #19041
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| //! A stateful LSP implementation that calls into the ty API. | ||
|
|
||
| use crate::session::client::Client; | ||
| use crate::session::{DocumentSnapshot, Session}; | ||
| use crate::session::{DocumentSnapshot, Session, WorkspaceSnapshot}; | ||
|
|
||
| use lsp_types::notification::Notification as LSPNotification; | ||
| use lsp_types::request::Request; | ||
|
|
@@ -25,11 +25,24 @@ pub(super) trait SyncRequestHandler: RequestHandler { | |
| ) -> super::Result<<<Self as RequestHandler>::RequestType as Request>::Result>; | ||
| } | ||
|
|
||
| /// A request handler that can be run on a background thread. | ||
| pub(super) trait BackgroundDocumentRequestHandler: RequestHandler { | ||
| /// Whether this request be retried if it was cancelled due to a modification to the Salsa database. | ||
| 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: &<<Self as RequestHandler>::RequestType as Request>::Params, | ||
| ) -> std::borrow::Cow<lsp_types::Url>; | ||
|
|
@@ -40,14 +53,15 @@ pub(super) trait BackgroundDocumentRequestHandler: RequestHandler { | |
| client: &Client, | ||
| params: <<Self as RequestHandler>::RequestType as Request>::Params, | ||
| ) -> super::Result<<<Self as RequestHandler>::RequestType as Request>::Result>; | ||
| } | ||
|
|
||
| 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. | ||
| pub(super) trait BackgroundRequestHandler: RetriableRequestHandler { | ||
| fn run( | ||
| snapshot: WorkspaceSnapshot, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should call this |
||
| client: &Client, | ||
| params: <<Self as RequestHandler>::RequestType as Request>::Params, | ||
| ) -> super::Result<<<Self as RequestHandler>::RequestType as Request>::Result>; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing I'd find helpful here is some prose (perhaps on the module doc) that briefly explains the traits here and how they're connected. If you think this code is going to be heavily refactored soon, then it might not make sense to add docs.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely! Most of this stuff is currently in my and Micha's mind but it would be useful to have it written down. I'll prioritize it soon as there are now more people who'll be working on the server. |
||
| } | ||
|
|
||
| /// A supertrait for any server notification handler. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| use std::collections::{BTreeMap, VecDeque}; | ||
| use std::ops::{Deref, DerefMut}; | ||
| use std::panic::AssertUnwindSafe; | ||
| use std::sync::Arc; | ||
|
|
||
| use anyhow::{Context, anyhow}; | ||
|
|
@@ -223,6 +224,14 @@ impl Session { | |
| self.index().key_from_url(url) | ||
| } | ||
|
|
||
| pub(crate) fn take_workspace_snapshot(&self) -> WorkspaceSnapshot { | ||
| WorkspaceSnapshot { | ||
| projects: AssertUnwindSafe(self.projects.values().cloned().collect()), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest removing the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would mean that the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Edit: Nevermind, it works. |
||
| index: self.index.clone().unwrap(), | ||
| position_encoding: self.position_encoding, | ||
| } | ||
| } | ||
|
|
||
| pub(crate) fn initialize_workspaces(&mut self, workspace_settings: Vec<(Url, ClientOptions)>) { | ||
| assert!(!self.workspaces.all_initialized()); | ||
|
|
||
|
|
@@ -453,6 +462,28 @@ impl DocumentSnapshot { | |
| } | ||
| } | ||
|
|
||
| /// An immutable snapshot of the current state of [`Session`]. | ||
| pub(crate) struct WorkspaceSnapshot { | ||
| projects: AssertUnwindSafe<Vec<ProjectDatabase>>, | ||
| index: Arc<index::Index>, | ||
| position_encoding: PositionEncoding, | ||
| } | ||
|
|
||
| #[expect(dead_code)] | ||
| impl WorkspaceSnapshot { | ||
| pub(crate) fn projects(&self) -> &[ProjectDatabase] { | ||
| &self.projects | ||
| } | ||
|
|
||
| pub(crate) fn index(&self) -> &index::Index { | ||
| &self.index | ||
| } | ||
|
|
||
| pub(crate) fn position_encoding(&self) -> PositionEncoding { | ||
| self.position_encoding | ||
| } | ||
| } | ||
|
|
||
| #[derive(Debug, Default)] | ||
| pub(crate) struct Workspaces { | ||
| workspaces: BTreeMap<Url, Workspace>, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment saying why this code is kept around even though it isn't used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I split the workspace diagnostics work into two PRs to ease up the review process. This is going to be used in the follow-up PR (#18939). Sorry, I should've highlighted this as a review comment!