Skip to content

Commit

Permalink
Auto merge of rust-lang#17850 - Veykril:rust-analyzer-crate, r=Veykril
Browse files Browse the repository at this point in the history
internal: Reply to requests with defaults when vfs is still loading

There is no reason for us to hit the database with queries when we certainly haven't reached a stable state yet. Instead we just reply with default request results until we are in a state where we can do meaningful work. This should save us from wasting resources while starting up at worst, and at best save us from creating query and interning entries that are non-meaningful which ultimately just end up wasting memory.
  • Loading branch information
bors committed Aug 12, 2024
2 parents 563dc1c + 234d383 commit 5e753ff
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/tools/rust-analyzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
resolver = "2"

[workspace.package]
rust-version = "1.78"
rust-version = "1.80"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["rust-analyzer team"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,45 @@ impl RequestDispatcher<'_> {
self
}

/// Dispatches a non-latency-sensitive request onto the thread pool.
/// Dispatches a non-latency-sensitive request onto the thread pool. When the VFS is marked not
/// ready this will return a default constructed [`R::Result`].
pub(crate) fn on<const ALLOW_RETRYING: bool, R>(
&mut self,
f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
) -> &mut Self
where
R: lsp_types::request::Request + 'static,
R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
R::Result: Serialize,
R: lsp_types::request::Request<
Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
Result: Serialize + Default,
> + 'static,
{
if !self.global_state.vfs_done {
if let Some(lsp_server::Request { id, .. }) =
self.req.take_if(|it| it.method == R::METHOD)
{
self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default()));
}
return self;
}
self.on_with_thread_intent::<true, ALLOW_RETRYING, R>(ThreadIntent::Worker, f)
}

/// Dispatches a non-latency-sensitive request onto the thread pool. When the VFS is marked not
/// ready this will return the parameter as is.
pub(crate) fn on_identity<const ALLOW_RETRYING: bool, R, Params>(
&mut self,
f: fn(GlobalStateSnapshot, Params) -> anyhow::Result<R::Result>,
) -> &mut Self
where
R: lsp_types::request::Request<Params = Params, Result = Params> + 'static,
Params: Serialize + DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
{
if !self.global_state.vfs_done {
if let Some((request, params, _)) = self.parse::<R>() {
self.global_state.respond(lsp_server::Response::new_ok(request.id, &params))
}
return self;
}
self.on_with_thread_intent::<true, ALLOW_RETRYING, R>(ThreadIntent::Worker, f)
}

Expand Down Expand Up @@ -198,11 +227,7 @@ impl RequestDispatcher<'_> {
R: lsp_types::request::Request,
R::Params: DeserializeOwned + fmt::Debug,
{
let req = match &self.req {
Some(req) if req.method == R::METHOD => self.req.take()?,
_ => return None,
};

let req = self.req.take_if(|it| it.method == R::METHOD)?;
let res = crate::from_json(R::METHOD, &req.params);
match res {
Ok(params) => {
Expand Down
10 changes: 8 additions & 2 deletions src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Request for FetchDependencyList {
#[serde(rename_all = "camelCase")]
pub struct FetchDependencyListParams {}

#[derive(Deserialize, Serialize, Debug)]
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct FetchDependencyListResult {
pub crates: Vec<CrateInfoResult>,
Expand Down Expand Up @@ -194,7 +194,7 @@ pub struct TestItem {
pub runnable: Option<Runnable>,
}

#[derive(Deserialize, Serialize, Debug)]
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct DiscoverTestResults {
pub tests: Vec<TestItem>,
Expand Down Expand Up @@ -690,6 +690,12 @@ pub enum ExternalDocsResponse {
WithLocal(ExternalDocsPair),
}

impl Default for ExternalDocsResponse {
fn default() -> Self {
ExternalDocsResponse::Simple(None)
}
}

#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ExternalDocsPair {
Expand Down
41 changes: 27 additions & 14 deletions src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,10 @@ impl GlobalState {
}

if self.config.discover_workspace_config().is_none() {
let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
self.fetch_workspaces_queue.request_op("startup".to_owned(), req);
self.fetch_workspaces_queue.request_op(
"startup".to_owned(),
FetchWorkspaceRequest { path: None, force_crate_graph_reload: false },
);
if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
self.fetch_workspaces_queue.should_start_op()
{
Expand Down Expand Up @@ -545,6 +547,10 @@ impl GlobalState {
let snapshot = self.snapshot();
self.task_pool.handle.spawn_with_sender(ThreadIntent::LatencySensitive, {
let subscriptions = subscriptions.clone();
// Do not fetch semantic diagnostics (and populate query results) if we haven't even
// loaded the initial workspace yet.
let fetch_semantic =
self.vfs_done && self.fetch_workspaces_queue.last_op_result().is_some();
move |sender| {
let diags = fetch_native_diagnostics(
&snapshot,
Expand All @@ -556,22 +562,29 @@ impl GlobalState {
.send(Task::Diagnostics(DiagnosticsTaskKind::Syntax(generation, diags)))
.unwrap();

let diags = fetch_native_diagnostics(
&snapshot,
subscriptions,
slice,
NativeDiagnosticsFetchKind::Semantic,
);
sender
.send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(generation, diags)))
.unwrap();
if fetch_semantic {
let diags = fetch_native_diagnostics(
&snapshot,
subscriptions,
slice,
NativeDiagnosticsFetchKind::Semantic,
);
sender
.send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(
generation, diags,
)))
.unwrap();
}
}
});
start = end;
}
}

fn update_tests(&mut self) {
if !self.vfs_done {
return;
}
let db = self.analysis_host.raw_database();
let subscriptions = self
.mem_docs
Expand Down Expand Up @@ -1052,9 +1065,9 @@ impl GlobalState {
.on::<NO_RETRY, lsp_request::GotoImplementation>(handlers::handle_goto_implementation)
.on::<NO_RETRY, lsp_request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
.on::<NO_RETRY, lsp_request::InlayHintRequest>(handlers::handle_inlay_hints)
.on::<NO_RETRY, lsp_request::InlayHintResolveRequest>(handlers::handle_inlay_hints_resolve)
.on_identity::<NO_RETRY, lsp_request::InlayHintResolveRequest, _>(handlers::handle_inlay_hints_resolve)
.on::<NO_RETRY, lsp_request::CodeLensRequest>(handlers::handle_code_lens)
.on::<NO_RETRY, lsp_request::CodeLensResolve>(handlers::handle_code_lens_resolve)
.on_identity::<NO_RETRY, lsp_request::CodeLensResolve, _>(handlers::handle_code_lens_resolve)
.on::<NO_RETRY, lsp_request::PrepareRenameRequest>(handlers::handle_prepare_rename)
.on::<NO_RETRY, lsp_request::Rename>(handlers::handle_rename)
.on::<NO_RETRY, lsp_request::References>(handlers::handle_references)
Expand All @@ -1081,7 +1094,7 @@ impl GlobalState {
.on::<NO_RETRY, lsp_ext::Runnables>(handlers::handle_runnables)
.on::<NO_RETRY, lsp_ext::RelatedTests>(handlers::handle_related_tests)
.on::<NO_RETRY, lsp_ext::CodeActionRequest>(handlers::handle_code_action)
.on::<RETRY, lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
.on_identity::<RETRY, lsp_ext::CodeActionResolveRequest, _>(handlers::handle_code_action_resolve)
.on::<NO_RETRY, lsp_ext::HoverRequest>(handlers::handle_hover)
.on::<NO_RETRY, lsp_ext::ExternalDocs>(handlers::handle_open_docs)
.on::<NO_RETRY, lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
Expand Down
2 changes: 1 addition & 1 deletion src/tools/rust-analyzer/docs/dev/lsp-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!---
lsp/ext.rs hash: e92e1f12229b0071
lsp/ext.rs hash: 3429c08745984b3d
If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue:
Expand Down

0 comments on commit 5e753ff

Please sign in to comment.