Skip to content

Commit f9c3602

Browse files
committed
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.
1 parent a641562 commit f9c3602

File tree

5 files changed

+30
-10
lines changed

5 files changed

+30
-10
lines changed

crates/ide-assists/src/handlers/generate_delegate_methods.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,18 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
9292
});
9393
}
9494
methods.sort_by(|(a, _), (b, _)| a.cmp(b));
95-
for (name, method) in methods {
95+
for (index, (name, method)) in methods.into_iter().enumerate() {
9696
let adt = ast::Adt::Struct(strukt.clone());
9797
let name = name.display(ctx.db(), current_edition).to_string();
9898
// if `find_struct_impl` returns None, that means that a function named `name` already exists.
9999
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
100100
continue;
101101
};
102-
103102
let field = make::ext::field_from_idents(["self", &field_name])?;
104103

105104
acc.add_group(
106105
&GroupLabel("Generate delegate methods…".to_owned()),
107-
AssistId("generate_delegate_methods", AssistKind::Generate),
106+
AssistId("generate_delegate_methods", AssistKind::Generate, Some(index)),
108107
format!("Generate delegate for `{field_name}.{name}()`",),
109108
target,
110109
|edit| {

crates/ide-assists/src/handlers/generate_delegate_trait.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl Struct {
201201
pub(crate) fn delegate(&self, field: Field, acc: &mut Assists, ctx: &AssistContext<'_>) {
202202
let db = ctx.db();
203203

204-
for delegee in &field.impls {
204+
for (index, delegee) in field.impls.iter().enumerate() {
205205
let trait_ = match delegee {
206206
Delegee::Bound(b) => b,
207207
Delegee::Impls(i, _) => i,
@@ -229,7 +229,11 @@ impl Struct {
229229

230230
acc.add_group(
231231
&GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)),
232-
AssistId("generate_delegate_trait", ide_db::assists::AssistKind::Generate),
232+
AssistId(
233+
"generate_delegate_trait",
234+
ide_db::assists::AssistKind::Generate,
235+
Some(index),
236+
),
233237
format!("Generate delegate trait impl `{}` for `{}`", signature, field.name),
234238
field.range,
235239
|builder| {

crates/ide-db/src/assists.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl FromStr for AssistKind {
105105
/// Unique identifier of the assist, should not be shown to the user
106106
/// directly.
107107
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108-
pub struct AssistId(pub &'static str, pub AssistKind);
108+
pub struct AssistId(pub &'static str, pub AssistKind, pub Option<usize>);
109109

110110
/// A way to control how many assist to resolve during the assist resolution.
111111
/// 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 {
128128
pub assist_id: String,
129129
// The kind of the assist.
130130
pub assist_kind: AssistKind,
131+
/// Subtype of the assist. When many assists have the same id, it differentiates among them.
132+
pub assist_subtype: Option<usize>,
131133
}
132134

133135
impl AssistResolveStrategy {
@@ -136,7 +138,9 @@ impl AssistResolveStrategy {
136138
AssistResolveStrategy::None => false,
137139
AssistResolveStrategy::All => true,
138140
AssistResolveStrategy::Single(single_resolve) => {
139-
single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1
141+
single_resolve.assist_id == id.0
142+
&& single_resolve.assist_kind == id.1
143+
&& single_resolve.assist_subtype == id.2
140144
}
141145
}
142146
}

crates/rust-analyzer/src/handlers/request.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1556,13 +1556,21 @@ pub(crate) fn handle_code_action_resolve(
15561556
fn parse_action_id(action_id: &str) -> anyhow::Result<(usize, SingleResolve), String> {
15571557
let id_parts = action_id.split(':').collect::<Vec<_>>();
15581558
match id_parts.as_slice() {
1559-
[assist_id_string, assist_kind_string, index_string] => {
1559+
[assist_id_string, assist_kind_string, index_string, subtype_str] => {
15601560
let assist_kind: AssistKind = assist_kind_string.parse()?;
15611561
let index: usize = match index_string.parse() {
15621562
Ok(index) => index,
15631563
Err(e) => return Err(format!("Incorrect index string: {e}")),
15641564
};
1565-
Ok((index, SingleResolve { assist_id: assist_id_string.to_string(), assist_kind }))
1565+
let assist_subtype = subtype_str.parse::<usize>().ok();
1566+
Ok((
1567+
index,
1568+
SingleResolve {
1569+
assist_id: assist_id_string.to_string(),
1570+
assist_kind,
1571+
assist_subtype,
1572+
},
1573+
))
15661574
}
15671575
_ => Err("Action id contains incorrect number of segments".to_owned()),
15681576
}

crates/rust-analyzer/src/lsp/to_proto.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,12 @@ pub(crate) fn code_action(
15151515
(Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
15161516
(None, Some((index, code_action_params, version))) => {
15171517
res.data = Some(lsp_ext::CodeActionData {
1518-
id: format!("{}:{}:{index}", assist.id.0, assist.id.1.name()),
1518+
id: format!(
1519+
"{}:{}:{index}:{}",
1520+
assist.id.0,
1521+
assist.id.1.name(),
1522+
assist.id.2.map(|x| x.to_string()).unwrap_or("".to_owned())
1523+
),
15191524
code_action_params,
15201525
version,
15211526
});

0 commit comments

Comments
 (0)