]> git.lizzy.rs Git - rust.git/commitdiff
Add snippet support for some assists
authorAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 17 May 2020 12:21:24 +0000 (14:21 +0200)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Tue, 19 May 2020 18:28:27 +0000 (20:28 +0200)
crates/ra_assists/src/handlers/add_custom_impl.rs
crates/ra_assists/src/handlers/add_derive.rs
crates/ra_assists/src/handlers/add_impl.rs
crates/ra_assists/src/tests/generated.rs
docs/user/assists.md

index 2baeb8607f82b5fa98870b41e81174f1ff2bb303..fa70c849684a625b70989b0684358911f664ba0c 100644 (file)
@@ -25,7 +25,7 @@
 // struct S;
 //
 // impl Debug for S {
-//
+//     $0
 // }
 // ```
 pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -52,7 +52,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<
         format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name);
 
     let target = attr.syntax().text_range();
-    acc.add(AssistId("add_custom_impl"), label, target, |edit| {
+    acc.add(AssistId("add_custom_impl"), label, target, |builder| {
         let new_attr_input = input
             .syntax()
             .descendants_with_tokens()
@@ -63,20 +63,11 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<
         let has_more_derives = !new_attr_input.is_empty();
         let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string();
 
-        let mut buf = String::new();
-        buf.push_str("\n\nimpl ");
-        buf.push_str(trait_token.text().as_str());
-        buf.push_str(" for ");
-        buf.push_str(annotated_name.as_str());
-        buf.push_str(" {\n");
-
-        let cursor_delta = if has_more_derives {
-            let delta = input.syntax().text_range().len() - TextSize::of(&new_attr_input);
-            edit.replace(input.syntax().text_range(), new_attr_input);
-            delta
+        if has_more_derives {
+            builder.replace(input.syntax().text_range(), new_attr_input);
         } else {
             let attr_range = attr.syntax().text_range();
-            edit.delete(attr_range);
+            builder.delete(attr_range);
 
             let line_break_range = attr
                 .syntax()
@@ -84,14 +75,24 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<
                 .filter(|t| t.kind() == WHITESPACE)
                 .map(|t| t.text_range())
                 .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0)));
-            edit.delete(line_break_range);
-
-            attr_range.len() + line_break_range.len()
-        };
-
-        edit.set_cursor(start_offset + TextSize::of(&buf) - cursor_delta);
-        buf.push_str("\n}");
-        edit.insert(start_offset, buf);
+            builder.delete(line_break_range);
+        }
+
+        match ctx.config.snippet_cap {
+            Some(cap) => {
+                builder.insert_snippet(
+                    cap,
+                    start_offset,
+                    format!("\n\nimpl {} for {} {{\n    $0\n}}", trait_token, annotated_name),
+                );
+            }
+            None => {
+                builder.insert(
+                    start_offset,
+                    format!("\n\nimpl {} for {} {{\n\n}}", trait_token, annotated_name),
+                );
+            }
+        }
     })
 }
 
@@ -117,7 +118,7 @@ struct Foo {
 }
 
 impl Debug for Foo {
-<|>
+    $0
 }
             ",
         )
@@ -139,7 +140,7 @@ pub struct Foo {
 }
 
 impl Debug for Foo {
-<|>
+    $0
 }
             ",
         )
@@ -158,7 +159,7 @@ struct Foo {}
 struct Foo {}
 
 impl Debug for Foo {
-<|>
+    $0
 }
             ",
         )
index fb08c19e936145203eeb5955848434ce96d2a4bb..b123b84988cf4e730a9a68b1488b69ddc16463dd 100644 (file)
 // ```
 // ->
 // ```
-// #[derive()]
+// #[derive($0)]
 // struct Point {
 //     x: u32,
 //     y: u32,
 // }
 // ```
 pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
+    let cap = ctx.config.snippet_cap?;
     let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
     let node_start = derive_insertion_offset(&nominal)?;
     let target = nominal.syntax().text_range();
-    acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |edit| {
+    acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| {
         let derive_attr = nominal
             .attrs()
             .filter_map(|x| x.as_simple_call())
             .filter(|(name, _arg)| name == "derive")
             .map(|(_name, arg)| arg)
             .next();
-        let offset = match derive_attr {
+        match derive_attr {
             None => {
-                edit.insert(node_start, "#[derive()]\n");
-                node_start + TextSize::of("#[derive(")
+                builder.insert_snippet(cap, node_start, "#[derive($0)]\n");
+            }
+            Some(tt) => {
+                // Just move the cursor.
+                builder.insert_snippet(
+                    cap,
+                    tt.syntax().text_range().end() - TextSize::of(')'),
+                    "$0",
+                )
             }
-            Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'),
         };
-        edit.set_cursor(offset)
     })
 }
 
@@ -66,12 +72,12 @@ fn add_derive_new() {
         check_assist(
             add_derive,
             "struct Foo { a: i32, <|>}",
-            "#[derive(<|>)]\nstruct Foo { a: i32, }",
+            "#[derive($0)]\nstruct Foo { a: i32, }",
         );
         check_assist(
             add_derive,
             "struct Foo { <|> a: i32, }",
-            "#[derive(<|>)]\nstruct Foo {  a: i32, }",
+            "#[derive($0)]\nstruct Foo {  a: i32, }",
         );
     }
 
@@ -80,7 +86,7 @@ fn add_derive_existing() {
         check_assist(
             add_derive,
             "#[derive(Clone)]\nstruct Foo { a: i32<|>, }",
-            "#[derive(Clone<|>)]\nstruct Foo { a: i32, }",
+            "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
         );
     }
 
@@ -96,7 +102,7 @@ struct Foo { a: i32<|>, }
             "
 /// `Foo` is a pretty important struct.
 /// It does stuff.
-#[derive(<|>)]
+#[derive($0)]
 struct Foo { a: i32, }
             ",
         );
index df114a0d84dd40cfc9791ca3c5760834e6fc7e81..eceba7d0ae671c11d8de5cb7aa29892762a2e4f7 100644 (file)
@@ -1,7 +1,4 @@
-use ra_syntax::{
-    ast::{self, AstNode, NameOwner, TypeParamsOwner},
-    TextSize,
-};
+use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
 use stdx::{format_to, SepBy};
 
 use crate::{AssistContext, AssistId, Assists};
 //
 // ```
 // struct Ctx<T: Clone> {
-//      data: T,<|>
+//     data: T,<|>
 // }
 // ```
 // ->
 // ```
 // struct Ctx<T: Clone> {
-//      data: T,
+//     data: T,
 // }
 //
 // impl<T: Clone> Ctx<T> {
-//
+//     $0
 // }
 // ```
 pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -50,30 +47,37 @@ pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
             let generic_params = lifetime_params.chain(type_params).sep_by(", ");
             format_to!(buf, "<{}>", generic_params)
         }
-        buf.push_str(" {\n");
-        edit.set_cursor(start_offset + TextSize::of(&buf));
-        buf.push_str("\n}");
-        edit.insert(start_offset, buf);
+        match ctx.config.snippet_cap {
+            Some(cap) => {
+                buf.push_str(" {\n    $0\n}");
+                edit.insert_snippet(cap, start_offset, buf);
+            }
+            None => {
+                buf.push_str(" {\n}");
+                edit.insert(start_offset, buf);
+            }
+        }
     })
 }
 
 #[cfg(test)]
 mod tests {
-    use super::*;
     use crate::tests::{check_assist, check_assist_target};
 
+    use super::*;
+
     #[test]
     fn test_add_impl() {
-        check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n<|>\n}\n");
+        check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n    $0\n}\n");
         check_assist(
             add_impl,
             "struct Foo<T: Clone> {<|>}",
-            "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}",
+            "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n    $0\n}",
         );
         check_assist(
             add_impl,
             "struct Foo<'a, T: Foo<'a>> {<|>}",
-            "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n<|>\n}",
+            "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n    $0\n}",
         );
     }
 
index 972dbd251d6a8ebb05071f26b38799cb28ca028a..9487c9239f010f8e7131682170bd92eb6131a227 100644 (file)
@@ -15,7 +15,7 @@ fn doctest_add_custom_impl() {
 struct S;
 
 impl Debug for S {
-
+    $0
 }
 "#####,
     )
@@ -32,7 +32,7 @@ struct Point {
 }
 "#####,
         r#####"
-#[derive()]
+#[derive($0)]
 struct Point {
     x: u32,
     y: u32,
@@ -108,16 +108,16 @@ fn doctest_add_impl() {
         "add_impl",
         r#####"
 struct Ctx<T: Clone> {
-     data: T,<|>
+    data: T,<|>
 }
 "#####,
         r#####"
 struct Ctx<T: Clone> {
-     data: T,
+    data: T,
 }
 
 impl<T: Clone> Ctx<T> {
-
+    $0
 }
 "#####,
     )
index 692fd4f52bacfabe4917646214565a8952053af4..41c5df5287c3f6e335517523de9469d233a288ee 100644 (file)
@@ -17,7 +17,7 @@ struct S;
 struct S;
 
 impl Debug for S {
-
+    $0
 }
 ```
 
@@ -33,7 +33,7 @@ struct Point {
 }
 
 // AFTER
-#[derive()]
+#[derive($0)]
 struct Point {
     x: u32,
     y: u32,
@@ -105,16 +105,16 @@ Adds a new inherent impl for a type.
 ```rust
 // BEFORE
 struct Ctx<T: Clone> {
-     data: T,┃
+    data: T,┃
 }
 
 // AFTER
 struct Ctx<T: Clone> {
-     data: T,
+    data: T,
 }
 
 impl<T: Clone> Ctx<T> {
-
+    $0
 }
 ```