Repository: rust-lang/rust-analyzer
Pull request #12032 (2022-04-19 16:46:24)

feat: display signature help when applying "Add `::<>`" assist
Closes https://github.com/rust-lang/rust-analyzer/issues/12031


Patch:
diff --git a/crates/ide/src/ssr.rs b/crates/ide/src/ssr.rs
index 6142a0eafd..ba9a7f62e6 100644
--- a/crates/ide/src/ssr.rs
+++ b/crates/ide/src/ssr.rs
@@ -45,6 +45,7 @@ pub(crate) fn ssr_assists(
             group: Some(GroupLabel("Apply SSR".into())),
             target: comment_range,
             source_change,
+            trigger_signature_help: false,
         };
 
         ssr_assists.push(assist);
@@ -140,6 +141,7 @@ mod tests {
                         is_snippet: false,
                     },
                 ),
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&apply_in_file_assist);
@@ -186,6 +188,7 @@ mod tests {
                         is_snippet: false,
                     },
                 ),
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&apply_in_workspace_assist);
@@ -225,6 +228,7 @@ mod tests {
                 ),
                 target: 10..21,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&apply_in_file_assist);
@@ -244,6 +248,7 @@ mod tests {
                 ),
                 target: 10..21,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&apply_in_workspace_assist);
diff --git a/crates/ide_assists/src/assist_context.rs b/crates/ide_assists/src/assist_context.rs
index fd46aa2479..ec85faaf46 100644
--- a/crates/ide_assists/src/assist_context.rs
+++ b/crates/ide_assists/src/assist_context.rs
@@ -193,9 +193,11 @@ impl Assists {
             return None;
         }
 
+        let mut trigger_signature_help = false;
         let source_change = if self.resolve.should_resolve(&id) {
             let mut builder = AssistBuilder::new(self.file);
             f(&mut builder);
+            trigger_signature_help = builder.trigger_signature_help;
             Some(builder.finish())
         } else {
             None
@@ -203,7 +205,7 @@ impl Assists {
 
         let label = Label::new(label);
         let group = group.cloned();
-        self.buf.push(Assist { id, label, group, target, source_change });
+        self.buf.push(Assist { id, label, group, target, source_change, trigger_signature_help });
         Some(())
     }
 
@@ -219,6 +221,7 @@ pub(crate) struct AssistBuilder {
     edit: TextEditBuilder,
     file_id: FileId,
     source_change: SourceChange,
+    trigger_signature_help: bool,
 
     /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin.
     mutated_tree: Option<TreeMutator>,
@@ -252,6 +255,7 @@ impl AssistBuilder {
             edit: TextEdit::builder(),
             file_id,
             source_change: SourceChange::default(),
+            trigger_signature_help: false,
             mutated_tree: None,
         }
     }
@@ -332,6 +336,9 @@ impl AssistBuilder {
         let file_system_edit = FileSystemEdit::MoveFile { src, dst };
         self.source_change.push_file_system_edit(file_system_edit);
     }
+    pub(crate) fn trigger_signature_help(&mut self) {
+        self.trigger_signature_help = true;
+    }
 
     fn finish(mut self) -> SourceChange {
         self.commit();
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index c3d27f7ea6..a82dca9db0 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -89,15 +89,18 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
         AssistId("add_turbo_fish", AssistKind::RefactorRewrite),
         "Add `::<>`",
         ident.text_range(),
-        |builder| match ctx.config.snippet_cap {
-            Some(cap) => {
-                let snip = format!("::<{}>", get_snippet_fish_head(number_of_arguments));
-                builder.insert_snippet(cap, ident.text_range().end(), snip)
-            }
-            None => {
-                let fish_head = std::iter::repeat("_").take(number_of_arguments).format(", ");
-                let snip = format!("::<{}>", fish_head);
-                builder.insert(ident.text_range().end(), snip);
+        |builder| {
+            builder.trigger_signature_help();
+            match ctx.config.snippet_cap {
+                Some(cap) => {
+                    let snip = format!("::<{}>", get_snippet_fish_head(number_of_arguments));
+                    builder.insert_snippet(cap, ident.text_range().end(), snip)
+                }
+                None => {
+                    let fish_head = std::iter::repeat("_").take(number_of_arguments).format(", ");
+                    let snip = format!("::<{}>", fish_head);
+                    builder.insert(ident.text_range().end(), snip);
+                }
             }
         },
     )
diff --git a/crates/ide_db/src/assists.rs b/crates/ide_db/src/assists.rs
index be5f063f0f..da23763dc2 100644
--- a/crates/ide_db/src/assists.rs
+++ b/crates/ide_db/src/assists.rs
@@ -29,6 +29,7 @@ pub struct Assist {
     /// cumbersome, especially if you want to embed an assist into another data
     /// structure, such as a diagnostic.
     pub source_change: Option<SourceChange>,
+    pub trigger_signature_help: bool,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
diff --git a/crates/ide_diagnostics/src/handlers/unresolved_module.rs b/crates/ide_diagnostics/src/handlers/unresolved_module.rs
index 587a3ee26d..b8f2a9e94a 100644
--- a/crates/ide_diagnostics/src/handlers/unresolved_module.rs
+++ b/crates/ide_diagnostics/src/handlers/unresolved_module.rs
@@ -117,6 +117,7 @@ mod baz {}
                                             is_snippet: false,
                                         },
                                     ),
+                                    trigger_signature_help: false,
                                 },
                                 Assist {
                                     id: AssistId(
@@ -143,6 +144,7 @@ mod baz {}
                                             is_snippet: false,
                                         },
                                     ),
+                                    trigger_signature_help: false,
                                 },
                             ],
                         ),
diff --git a/crates/ide_diagnostics/src/lib.rs b/crates/ide_diagnostics/src/lib.rs
index 13ac0a2450..b04da2e092 100644
--- a/crates/ide_diagnostics/src/lib.rs
+++ b/crates/ide_diagnostics/src/lib.rs
@@ -238,5 +238,6 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
         group: None,
         target,
         source_change: None,
+        trigger_signature_help: false,
     }
 }
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 45e46c1a06..e9a192cdfb 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -204,6 +204,7 @@ fn map_rust_child_diagnostic(
                     }),
                     is_preferred: Some(true),
                     data: None,
+                    command: None,
                 },
             }),
         })
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index fb64eeea4f..a1b71ab143 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1160,8 +1160,9 @@ pub(crate) fn handle_code_action_resolve(
         ))
         .into());
     }
-    let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit;
-    code_action.edit = edit;
+    let ca = to_proto::code_action(&snap, assist.clone(), None)?;
+    code_action.edit = ca.edit;
+    code_action.command = ca.command;
     Ok(code_action)
 }
 
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 489a233a0a..1cfaa13327 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -311,9 +311,8 @@ pub struct CodeAction {
     pub group: Option<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub kind: Option<CodeActionKind>,
-    // We don't handle commands on the client-side
-    // #[serde(skip_serializing_if = "Option::is_none")]
-    // pub command: Option<lsp_types::Command>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub command: Option<lsp_types::Command>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub edit: Option<SnippetWorkspaceEdit>,
     #[serde(skip_serializing_if = "Option::is_none")]
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index deea54cf7d..57b0e93765 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -1018,7 +1018,13 @@ pub(crate) fn code_action(
         edit: None,
         is_preferred: None,
         data: None,
+        command: None,
     };
+
+    if assist.trigger_signature_help && snap.config.client_commands().trigger_parameter_hints {
+        res.command = Some(command::trigger_parameter_hints());
+    }
+
     match (assist.source_change, resolve_data) {
         (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
         (None, Some((index, code_action_params))) => {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 46193a6ff3..2e1cee8955 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 326ad62235135223
+lsp_ext.rs hash: 7a34bc3f38e2a7d8
 
 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:
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 18f5b3aa10..a808d5ec6d 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -735,6 +735,9 @@ export function resolveCodeAction(ctx: Ctx): Cmd {
         const fileSystemEdit = await client.protocol2CodeConverter.asWorkspaceEdit(lcFileSystemEdit);
         await vscode.workspace.applyEdit(fileSystemEdit);
         await applySnippetWorkspaceEdit(edit);
+        if (item.command != null) {
+            await vscode.commands.executeCommand(item.command.command, item.command.arguments);
+        }
     };
 }
 


Test patch:
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index b3a0bd2773..6b57f9962c 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -341,6 +341,7 @@ pub fn test_some_range(a: int) -> bool {
                 group: None,
                 target: 59..60,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_variable_assist);
@@ -356,6 +357,7 @@ pub fn test_some_range(a: int) -> bool {
                 group: None,
                 target: 59..60,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_function_assist);
@@ -385,6 +387,7 @@ pub fn test_some_range(a: int) -> bool {
                 group: None,
                 target: 59..60,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_variable_assist);
@@ -400,6 +403,7 @@ pub fn test_some_range(a: int) -> bool {
                 group: None,
                 target: 59..60,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_function_assist);
@@ -450,6 +454,7 @@ pub fn test_some_range(a: int) -> bool {
                         is_snippet: true,
                     },
                 ),
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_variable_assist);
@@ -465,6 +470,7 @@ pub fn test_some_range(a: int) -> bool {
                 group: None,
                 target: 59..60,
                 source_change: None,
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_function_assist);
@@ -507,6 +513,7 @@ pub fn test_some_range(a: int) -> bool {
                         is_snippet: true,
                     },
                 ),
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_variable_assist);
@@ -543,6 +550,7 @@ pub fn test_some_range(a: int) -> bool {
                         is_snippet: true,
                     },
                 ),
+                trigger_signature_help: false,
             }
         "#]]
         .assert_debug_eq(&extract_into_function_assist);
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt
index 4610984acb..41c509452a 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt
@@ -318,6 +318,7 @@
                             "quickfix",
                         ),
                     ),
+                    command: None,
                     edit: Some(
                         SnippetWorkspaceEdit {
                             changes: Some(
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
index 46d44192c5..1c5c336223 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
@@ -165,6 +165,7 @@
                             "quickfix",
                         ),
                     ),
+                    command: None,
                     edit: Some(
                         SnippetWorkspaceEdit {
                             changes: Some(
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
index b595487e8f..3ab3412d97 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
@@ -165,6 +165,7 @@
                             "quickfix",
                         ),
                     ),
+                    command: None,
                     edit: Some(
                         SnippetWorkspaceEdit {
                             changes: Some(
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
index 3ee50392a7..0702420aa5 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
@@ -165,6 +165,7 @@
                             "quickfix",
                         ),
                     ),
+                    command: None,
                     edit: Some(
                         SnippetWorkspaceEdit {
                             changes: Some(
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
index d7987f65ed..4365e450df 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
@@ -328,6 +328,7 @@
                             "quickfix",
                         ),
                     ),
+                    command: None,
                     edit: Some(
                         SnippetWorkspaceEdit {
                             changes: Some(