Trigger VSCode to rename after extract variable assist is applied

When the user applies the "Extract Variable" assist, the cursor is
positioned at the newly inserted variable. This commit adds a command
to the assist that triggers the rename action in VSCode. This way, the
user can quickly rename the variable after applying the assist.

Fixes part of: #17579
This commit is contained in:
bors 2024-07-11 08:55:34 +00:00 committed by Josh McKinney
parent 5577e4e3b1
commit 8efe8a8528
No known key found for this signature in database
GPG key ID: 722287396A903BC5
17 changed files with 80 additions and 33 deletions

View file

@ -185,11 +185,11 @@ impl Assists {
return None; return None;
} }
let mut trigger_signature_help = false; let mut command = None;
let source_change = if self.resolve.should_resolve(&id) { let source_change = if self.resolve.should_resolve(&id) {
let mut builder = SourceChangeBuilder::new(self.file); let mut builder = SourceChangeBuilder::new(self.file);
f(&mut builder); f(&mut builder);
trigger_signature_help = builder.trigger_signature_help; command = builder.command.take();
Some(builder.finish()) Some(builder.finish())
} else { } else {
None None
@ -197,7 +197,7 @@ impl Assists {
let label = Label::new(label); let label = Label::new(label);
let group = group.cloned(); let group = group.cloned();
self.buf.push(Assist { id, label, group, target, source_change, trigger_signature_help }); self.buf.push(Assist { id, label, group, target, source_change, command });
Some(()) Some(())
} }

View file

@ -135,6 +135,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
} }
} }
} }
edit.rename();
} }
Anchor::Replace(stmt) => { Anchor::Replace(stmt) => {
cov_mark::hit!(test_extract_var_expr_stmt); cov_mark::hit!(test_extract_var_expr_stmt);
@ -149,6 +150,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
} }
} }
} }
edit.rename();
} }
Anchor::WrapInBlock(to_wrap) => { Anchor::WrapInBlock(to_wrap) => {
let indent_to = to_wrap.indent_level(); let indent_to = to_wrap.indent_level();
@ -192,6 +194,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
} }
} }
} }
edit.rename();
// fixup indentation of block // fixup indentation of block
block.indent(indent_to); block.indent(indent_to);

View file

@ -454,7 +454,7 @@ pub fn test_some_range(a: int) -> bool {
group: None, group: None,
target: 59..60, target: 59..60,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_variable_assist); .assert_debug_eq(&extract_into_variable_assist);
@ -470,7 +470,7 @@ pub fn test_some_range(a: int) -> bool {
group: None, group: None,
target: 59..60, target: 59..60,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_function_assist); .assert_debug_eq(&extract_into_function_assist);
@ -500,7 +500,7 @@ pub fn test_some_range(a: int) -> bool {
group: None, group: None,
target: 59..60, target: 59..60,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_variable_assist); .assert_debug_eq(&extract_into_variable_assist);
@ -516,7 +516,7 @@ pub fn test_some_range(a: int) -> bool {
group: None, group: None,
target: 59..60, target: 59..60,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_function_assist); .assert_debug_eq(&extract_into_function_assist);
@ -587,7 +587,9 @@ pub fn test_some_range(a: int) -> bool {
is_snippet: true, is_snippet: true,
}, },
), ),
trigger_signature_help: false, command: Some(
Rename,
),
} }
"#]] "#]]
.assert_debug_eq(&extract_into_variable_assist); .assert_debug_eq(&extract_into_variable_assist);
@ -603,7 +605,7 @@ pub fn test_some_range(a: int) -> bool {
group: None, group: None,
target: 59..60, target: 59..60,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_function_assist); .assert_debug_eq(&extract_into_function_assist);
@ -666,7 +668,9 @@ pub fn test_some_range(a: int) -> bool {
is_snippet: true, is_snippet: true,
}, },
), ),
trigger_signature_help: false, command: Some(
Rename,
),
} }
"#]] "#]]
.assert_debug_eq(&extract_into_variable_assist); .assert_debug_eq(&extract_into_variable_assist);
@ -715,7 +719,7 @@ pub fn test_some_range(a: int) -> bool {
is_snippet: true, is_snippet: true,
}, },
), ),
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&extract_into_function_assist); .assert_debug_eq(&extract_into_function_assist);

View file

@ -29,7 +29,16 @@ pub struct Assist {
/// cumbersome, especially if you want to embed an assist into another data /// cumbersome, especially if you want to embed an assist into another data
/// structure, such as a diagnostic. /// structure, such as a diagnostic.
pub source_change: Option<SourceChange>, pub source_change: Option<SourceChange>,
pub trigger_signature_help: bool, /// The command to execute after the assist is applied.
pub command: Option<Command>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Command {
/// Show the parameter hints popup.
TriggerSignatureHelp,
/// Rename the just inserted item.
Rename,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]

View file

@ -5,7 +5,7 @@
use std::{collections::hash_map::Entry, iter, mem}; use std::{collections::hash_map::Entry, iter, mem};
use crate::SnippetCap; use crate::{assists::Command, SnippetCap};
use base_db::{AnchoredPathBuf, FileId}; use base_db::{AnchoredPathBuf, FileId};
use itertools::Itertools; use itertools::Itertools;
use nohash_hasher::IntMap; use nohash_hasher::IntMap;
@ -194,7 +194,7 @@ pub struct SourceChangeBuilder {
pub edit: TextEditBuilder, pub edit: TextEditBuilder,
pub file_id: FileId, pub file_id: FileId,
pub source_change: SourceChange, pub source_change: SourceChange,
pub trigger_signature_help: bool, pub command: Option<Command>,
/// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin. /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin.
pub mutated_tree: Option<TreeMutator>, pub mutated_tree: Option<TreeMutator>,
@ -236,7 +236,7 @@ impl SourceChangeBuilder {
edit: TextEdit::builder(), edit: TextEdit::builder(),
file_id, file_id,
source_change: SourceChange::default(), source_change: SourceChange::default(),
trigger_signature_help: false, command: None,
mutated_tree: None, mutated_tree: None,
snippet_builder: None, snippet_builder: None,
} }
@ -304,8 +304,15 @@ impl SourceChangeBuilder {
let file_system_edit = FileSystemEdit::MoveFile { src, dst }; let file_system_edit = FileSystemEdit::MoveFile { src, dst };
self.source_change.push_file_system_edit(file_system_edit); self.source_change.push_file_system_edit(file_system_edit);
} }
/// Triggers the parameter hint popup after the assist is applied
pub fn trigger_signature_help(&mut self) { pub fn trigger_signature_help(&mut self) {
self.trigger_signature_help = true; self.command = Some(Command::TriggerSignatureHelp);
}
/// Renames the item at the cursor position after the assist is applied
pub fn rename(&mut self) {
self.command = Some(Command::Rename);
} }
/// Adds a tabstop snippet to place the cursor before `node` /// Adds a tabstop snippet to place the cursor before `node`

View file

@ -98,7 +98,7 @@ fn quickfix_for_redundant_assoc_item(
group: None, group: None,
target: range, target: range,
source_change: Some(source_change_builder.finish()), source_change: Some(source_change_builder.finish()),
trigger_signature_help: false, command: None,
}]) }])
} }

View file

@ -82,7 +82,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
original_range.file_id, original_range.file_id,
TextEdit::replace(original_range.range, code), TextEdit::replace(original_range.range, code),
)), )),
trigger_signature_help: false, command: None,
}) })
.collect(); .collect();

View file

@ -130,7 +130,7 @@ fn add_variant_to_union(
group: None, group: None,
target: error_range.range, target: error_range.range,
source_change: Some(src_change_builder.finish()), source_change: Some(src_change_builder.finish()),
trigger_signature_help: false, command: None,
}) })
} }
@ -173,7 +173,7 @@ fn add_field_to_struct_fix(
group: None, group: None,
target: error_range.range, target: error_range.range,
source_change: Some(src_change_builder.finish()), source_change: Some(src_change_builder.finish()),
trigger_signature_help: false, command: None,
}) })
} }
None => { None => {
@ -204,7 +204,7 @@ fn add_field_to_struct_fix(
group: None, group: None,
target: error_range.range, target: error_range.range,
source_change: Some(src_change_builder.finish()), source_change: Some(src_change_builder.finish()),
trigger_signature_help: false, command: None,
}) })
} }
Some(FieldList::TupleFieldList(_tuple)) => { Some(FieldList::TupleFieldList(_tuple)) => {
@ -266,7 +266,7 @@ fn method_fix(
file_id, file_id,
TextEdit::insert(range.end(), "()".to_owned()), TextEdit::insert(range.end(), "()".to_owned()),
)), )),
trigger_signature_help: false, command: None,
}) })
} }
#[cfg(test)] #[cfg(test)]

View file

@ -108,7 +108,7 @@ fn field_fix(
(file_id, TextEdit::insert(range.start(), "(".to_owned())), (file_id, TextEdit::insert(range.start(), "(".to_owned())),
(file_id, TextEdit::insert(range.end(), ")".to_owned())), (file_id, TextEdit::insert(range.end(), ")".to_owned())),
])), ])),
trigger_signature_help: false, command: None,
}) })
} }
@ -191,7 +191,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
file_id, file_id,
TextEdit::replace(range, assoc_func_call_expr_string), TextEdit::replace(range, assoc_func_call_expr_string),
)), )),
trigger_signature_help: false, command: None,
}) })
} else { } else {
None None

View file

@ -73,7 +73,7 @@ fn fixes(
diagnostic_range.file_id, diagnostic_range.file_id,
TextEdit::replace(name_range, format!("_{}", var_name.display(db))), TextEdit::replace(name_range, format!("_{}", var_name.display(db))),
)), )),
trigger_signature_help: false, command: None,
}]) }])
} }

View file

@ -613,7 +613,7 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
group: None, group: None,
target, target,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
} }

View file

@ -45,7 +45,7 @@ pub(crate) fn ssr_assists(
group: Some(GroupLabel("Apply SSR".into())), group: Some(GroupLabel("Apply SSR".into())),
target: comment_range, target: comment_range,
source_change, source_change,
trigger_signature_help: false, command: None,
}; };
ssr_assists.push(assist); ssr_assists.push(assist);
@ -143,7 +143,7 @@ mod tests {
is_snippet: false, is_snippet: false,
}, },
), ),
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&apply_in_file_assist); .assert_debug_eq(&apply_in_file_assist);
@ -196,7 +196,7 @@ mod tests {
is_snippet: false, is_snippet: false,
}, },
), ),
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&apply_in_workspace_assist); .assert_debug_eq(&apply_in_workspace_assist);
@ -236,7 +236,7 @@ mod tests {
), ),
target: 10..21, target: 10..21,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&apply_in_file_assist); .assert_debug_eq(&apply_in_file_assist);
@ -256,7 +256,7 @@ mod tests {
), ),
target: 10..21, target: 10..21,
source_change: None, source_change: None,
trigger_signature_help: false, command: None,
} }
"#]] "#]]
.assert_debug_eq(&apply_in_workspace_assist); .assert_debug_eq(&apply_in_workspace_assist);

View file

@ -1135,6 +1135,7 @@ pub struct ClientCommandsConfig {
pub show_reference: bool, pub show_reference: bool,
pub goto_location: bool, pub goto_location: bool,
pub trigger_parameter_hints: bool, pub trigger_parameter_hints: bool,
pub rename: bool,
} }
#[derive(Debug)] #[derive(Debug)]
@ -1901,6 +1902,7 @@ impl Config {
show_reference: get("rust-analyzer.showReferences"), show_reference: get("rust-analyzer.showReferences"),
goto_location: get("rust-analyzer.gotoLocation"), goto_location: get("rust-analyzer.gotoLocation"),
trigger_parameter_hints: get("editor.action.triggerParameterHints"), trigger_parameter_hints: get("editor.action.triggerParameterHints"),
rename: get("editor.action.rename"),
} }
} }

View file

@ -13,7 +13,7 @@ use ide::{
NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
}; };
use ide_db::{rust_doc::format_docs, FxHasher}; use ide_db::{assists, rust_doc::format_docs, FxHasher};
use itertools::Itertools; use itertools::Itertools;
use paths::{Utf8Component, Utf8Prefix}; use paths::{Utf8Component, Utf8Prefix};
use semver::VersionReq; use semver::VersionReq;
@ -1336,8 +1336,14 @@ pub(crate) fn code_action(
command: None, command: None,
}; };
if assist.trigger_signature_help && snap.config.client_commands().trigger_parameter_hints { if assist.command == Some(assists::Command::TriggerSignatureHelp)
&& snap.config.client_commands().trigger_parameter_hints
{
res.command = Some(command::trigger_parameter_hints()); res.command = Some(command::trigger_parameter_hints());
} else if assist.command == Some(assists::Command::Rename)
&& snap.config.client_commands().rename
{
res.command = Some(command::rename());
} }
match (assist.source_change, resolve_data) { match (assist.source_change, resolve_data) {
@ -1715,6 +1721,14 @@ pub(crate) mod command {
arguments: None, arguments: None,
} }
} }
pub(crate) fn rename() -> lsp_types::Command {
lsp_types::Command {
title: "rename".into(),
command: "rust-analyzer.rename".into(),
arguments: None,
}
}
} }
pub(crate) fn implementation_title(count: usize) -> String { pub(crate) fn implementation_title(count: usize) -> String {

View file

@ -348,6 +348,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
"rust-analyzer.showReferences", "rust-analyzer.showReferences",
"rust-analyzer.gotoLocation", "rust-analyzer.gotoLocation",
"editor.action.triggerParameterHints", "editor.action.triggerParameterHints",
"editor.action.rename",
], ],
}, },
...capabilities.experimental, ...capabilities.experimental,

View file

@ -118,6 +118,12 @@ export function triggerParameterHints(_: CtxInit): Cmd {
}; };
} }
export function rename(_: CtxInit): Cmd {
return async () => {
await vscode.commands.executeCommand("editor.action.rename");
};
}
export function openLogs(ctx: CtxInit): Cmd { export function openLogs(ctx: CtxInit): Cmd {
return async () => { return async () => {
if (ctx.client.outputChannel) { if (ctx.client.outputChannel) {

View file

@ -190,6 +190,7 @@ function createCommands(): Record<string, CommandFactory> {
runSingle: { enabled: commands.runSingle }, runSingle: { enabled: commands.runSingle },
showReferences: { enabled: commands.showReferences }, showReferences: { enabled: commands.showReferences },
triggerParameterHints: { enabled: commands.triggerParameterHints }, triggerParameterHints: { enabled: commands.triggerParameterHints },
rename: { enabled: commands.rename },
openLogs: { enabled: commands.openLogs }, openLogs: { enabled: commands.openLogs },
revealDependency: { enabled: commands.revealDependency }, revealDependency: { enabled: commands.revealDependency },
}; };