Skip to content

Add structured editing API to insert snipperts #11638

@matklad

Description

@matklad

Some of our assists don't place cursor correctly:

Peek.2022-03-06.17-00.mp4

Here, I'd really want the cursor to end up on A, such that I can rename it. I've looked into quickly fixing this, and it seems we simply don't have an API for that!

What I'd love the API to look like is either this:

diff --git a/crates/ide_assists/src/handlers/introduce_named_generic.rs b/crates/ide_assists/src/handlers/introduce_named_generic.rs
index 636b05dca..8eb9a462e 100644
--- a/crates/ide_assists/src/handlers/introduce_named_generic.rs
+++ b/crates/ide_assists/src/handlers/introduce_named_generic.rs
@@ -1,5 +1,5 @@
 use syntax::{
-    ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode},
+    ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, HasGenericParams},
     ted,
 };
 
@@ -39,7 +39,10 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext) ->
             let new_ty = make::ty(&type_param_name).clone_for_update();
 
             ted::replace(impl_trait_type.syntax(), new_ty.syntax());
-            fn_.get_or_create_generic_param_list().add_generic_param(type_param.into())
+            fn_.get_or_create_generic_param_list().add_generic_param(type_param.into());
+            if let Some(generic_param) = fn_.generic_param_list().and_then(|it| it.generic_params().last()) {
+                edit.move_cursor_to(generic_param)
+            }
         },
     )
 }

or this

diff --git a/crates/ide_assists/src/handlers/introduce_named_generic.rs b/crates/ide_assists/src/handlers/introduce_named_generic.rs
index 636b05dca..f361148cb 100644
--- a/crates/ide_assists/src/handlers/introduce_named_generic.rs
+++ b/crates/ide_assists/src/handlers/introduce_named_generic.rs
@@ -34,7 +34,9 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext) ->
 
             let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type);
 
-            let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list))
+            let name: ast::Name = make::name(&type_param_name); // A
+            let name: ast::Name = add_snippert(name); // /*$0*/A
+            let type_param = make::type_param(name, Some(type_bound_list))
                 .clone_for_update();
             let new_ty = make::ty(&type_param_name).clone_for_update();
 

After we have this API, we should

  • check that it is used by all "introduce/generate" assits
  • audit the usages of string-based render_snippet API and see if we can replace that with structured editing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-assistsS-actionableSomeone could pick this issue up and work on it right now

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions