mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Speed up resolving "Generate delegate method" assist (part 1)
Fix #19322 Sometimes there are 185 "Generate delegate" assists with the same assist_id and asssist_kind. This commit introduces and additional differentiator: assist_subtype. Therefore, when the LSP client sends an assist resolve request, rust-analyzer only need to compute edits for a single assist instead of 185.
This commit is contained in:
parent
dab1329f35
commit
7aa70a86d1
@ -92,19 +92,18 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
methods.sort_by(|(a, _), (b, _)| a.cmp(b));
|
methods.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||||
for (name, method) in methods {
|
for (index, (name, method)) in methods.into_iter().enumerate() {
|
||||||
let adt = ast::Adt::Struct(strukt.clone());
|
let adt = ast::Adt::Struct(strukt.clone());
|
||||||
let name = name.display(ctx.db(), current_edition).to_string();
|
let name = name.display(ctx.db(), current_edition).to_string();
|
||||||
// if `find_struct_impl` returns None, that means that a function named `name` already exists.
|
// if `find_struct_impl` returns None, that means that a function named `name` already exists.
|
||||||
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
|
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let field = make::ext::field_from_idents(["self", &field_name])?;
|
let field = make::ext::field_from_idents(["self", &field_name])?;
|
||||||
|
|
||||||
acc.add_group(
|
acc.add_group(
|
||||||
&GroupLabel("Generate delegate methods…".to_owned()),
|
&GroupLabel("Generate delegate methods…".to_owned()),
|
||||||
AssistId("generate_delegate_methods", AssistKind::Generate),
|
AssistId("generate_delegate_methods", AssistKind::Generate, Some(index)),
|
||||||
format!("Generate delegate for `{field_name}.{name}()`",),
|
format!("Generate delegate for `{field_name}.{name}()`",),
|
||||||
target,
|
target,
|
||||||
|edit| {
|
|edit| {
|
||||||
|
@ -201,7 +201,7 @@ impl Struct {
|
|||||||
pub(crate) fn delegate(&self, field: Field, acc: &mut Assists, ctx: &AssistContext<'_>) {
|
pub(crate) fn delegate(&self, field: Field, acc: &mut Assists, ctx: &AssistContext<'_>) {
|
||||||
let db = ctx.db();
|
let db = ctx.db();
|
||||||
|
|
||||||
for delegee in &field.impls {
|
for (index, delegee) in field.impls.iter().enumerate() {
|
||||||
let trait_ = match delegee {
|
let trait_ = match delegee {
|
||||||
Delegee::Bound(b) => b,
|
Delegee::Bound(b) => b,
|
||||||
Delegee::Impls(i, _) => i,
|
Delegee::Impls(i, _) => i,
|
||||||
@ -229,7 +229,11 @@ impl Struct {
|
|||||||
|
|
||||||
acc.add_group(
|
acc.add_group(
|
||||||
&GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)),
|
&GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)),
|
||||||
AssistId("generate_delegate_trait", ide_db::assists::AssistKind::Generate),
|
AssistId(
|
||||||
|
"generate_delegate_trait",
|
||||||
|
ide_db::assists::AssistKind::Generate,
|
||||||
|
Some(index),
|
||||||
|
),
|
||||||
format!("Generate delegate trait impl `{}` for `{}`", signature, field.name),
|
format!("Generate delegate trait impl `{}` for `{}`", signature, field.name),
|
||||||
field.range,
|
field.range,
|
||||||
|builder| {
|
|builder| {
|
||||||
|
@ -105,7 +105,7 @@ impl FromStr for AssistKind {
|
|||||||
/// Unique identifier of the assist, should not be shown to the user
|
/// Unique identifier of the assist, should not be shown to the user
|
||||||
/// directly.
|
/// directly.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct AssistId(pub &'static str, pub AssistKind);
|
pub struct AssistId(pub &'static str, pub AssistKind, pub Option<usize>);
|
||||||
|
|
||||||
/// A way to control how many assist to resolve during the assist resolution.
|
/// A way to control how many assist to resolve during the assist resolution.
|
||||||
/// When an assist is resolved, its edits are calculated that might be costly to always do by default.
|
/// When an assist is resolved, its edits are calculated that might be costly to always do by default.
|
||||||
@ -128,6 +128,8 @@ pub struct SingleResolve {
|
|||||||
pub assist_id: String,
|
pub assist_id: String,
|
||||||
// The kind of the assist.
|
// The kind of the assist.
|
||||||
pub assist_kind: AssistKind,
|
pub assist_kind: AssistKind,
|
||||||
|
/// Subtype of the assist. When many assists have the same id, it differentiates among them.
|
||||||
|
pub assist_subtype: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssistResolveStrategy {
|
impl AssistResolveStrategy {
|
||||||
@ -136,7 +138,9 @@ impl AssistResolveStrategy {
|
|||||||
AssistResolveStrategy::None => false,
|
AssistResolveStrategy::None => false,
|
||||||
AssistResolveStrategy::All => true,
|
AssistResolveStrategy::All => true,
|
||||||
AssistResolveStrategy::Single(single_resolve) => {
|
AssistResolveStrategy::Single(single_resolve) => {
|
||||||
single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1
|
single_resolve.assist_id == id.0
|
||||||
|
&& single_resolve.assist_kind == id.1
|
||||||
|
&& single_resolve.assist_subtype == id.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1568,13 +1568,21 @@ pub(crate) fn handle_code_action_resolve(
|
|||||||
fn parse_action_id(action_id: &str) -> anyhow::Result<(usize, SingleResolve), String> {
|
fn parse_action_id(action_id: &str) -> anyhow::Result<(usize, SingleResolve), String> {
|
||||||
let id_parts = action_id.split(':').collect::<Vec<_>>();
|
let id_parts = action_id.split(':').collect::<Vec<_>>();
|
||||||
match id_parts.as_slice() {
|
match id_parts.as_slice() {
|
||||||
[assist_id_string, assist_kind_string, index_string] => {
|
[assist_id_string, assist_kind_string, index_string, subtype_str] => {
|
||||||
let assist_kind: AssistKind = assist_kind_string.parse()?;
|
let assist_kind: AssistKind = assist_kind_string.parse()?;
|
||||||
let index: usize = match index_string.parse() {
|
let index: usize = match index_string.parse() {
|
||||||
Ok(index) => index,
|
Ok(index) => index,
|
||||||
Err(e) => return Err(format!("Incorrect index string: {e}")),
|
Err(e) => return Err(format!("Incorrect index string: {e}")),
|
||||||
};
|
};
|
||||||
Ok((index, SingleResolve { assist_id: assist_id_string.to_string(), assist_kind }))
|
let assist_subtype = subtype_str.parse::<usize>().ok();
|
||||||
|
Ok((
|
||||||
|
index,
|
||||||
|
SingleResolve {
|
||||||
|
assist_id: assist_id_string.to_string(),
|
||||||
|
assist_kind,
|
||||||
|
assist_subtype,
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => Err("Action id contains incorrect number of segments".to_owned()),
|
_ => Err("Action id contains incorrect number of segments".to_owned()),
|
||||||
}
|
}
|
||||||
|
@ -1514,7 +1514,12 @@ pub(crate) fn code_action(
|
|||||||
(Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
|
(Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
|
||||||
(None, Some((index, code_action_params, version))) => {
|
(None, Some((index, code_action_params, version))) => {
|
||||||
res.data = Some(lsp_ext::CodeActionData {
|
res.data = Some(lsp_ext::CodeActionData {
|
||||||
id: format!("{}:{}:{index}", assist.id.0, assist.id.1.name()),
|
id: format!(
|
||||||
|
"{}:{}:{index}:{}",
|
||||||
|
assist.id.0,
|
||||||
|
assist.id.1.name(),
|
||||||
|
assist.id.2.map(|x| x.to_string()).unwrap_or("".to_owned())
|
||||||
|
),
|
||||||
code_action_params,
|
code_action_params,
|
||||||
version,
|
version,
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user