Repository: rust-analyzer/rust-analyzer
Pull request #7896 (2021-03-06 20:22:22)

Only replace quotes in replace_string_with_char assist
bors r+


Patch:
diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs
deleted file mode 100644
index fa12545792..0000000000
--- a/crates/ide_assists/src/handlers/generate_default_from_new.rs
+++ /dev/null
@@ -1,374 +0,0 @@
-use crate::{
-    assist_context::{AssistContext, Assists},
-    AssistId,
-};
-use ide_db::helpers::FamousDefs;
-use syntax::{
-    ast::{self, Impl, NameOwner},
-    AstNode,
-};
-use test_utils::mark;
-
-// Assist: generate_default_from_new
-//
-// Generates default implementation from new method.
-//
-// ```
-// struct Example { _inner: () }
-//
-// impl Example {
-//     pub fn n$0ew() -> Self {
-//         Self { _inner: () }
-//     }
-// }
-// ```
-// ->
-// ```
-// struct Example { _inner: () }
-//
-// impl Example {
-//     pub fn new() -> Self {
-//         Self { _inner: () }
-//     }
-// }
-//
-// impl Default for Example {
-//     fn default() -> Self {
-//         Self::new()
-//     }
-// }
-// ```
-pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
-    let fn_name = fn_node.name()?;
-
-    if fn_name.text() != "new" {
-        mark::hit!(other_function_than_new);
-        return None;
-    }
-
-    if fn_node.param_list()?.params().next().is_some() {
-        mark::hit!(new_function_with_parameters);
-        return None;
-    }
-
-    let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
-    if is_default_implemented(ctx, &impl_) {
-        mark::hit!(default_block_is_already_present);
-        mark::hit!(struct_in_module_with_default);
-        return None;
-    }
-
-    let insert_location = impl_.syntax().text_range();
-
-    acc.add(
-        AssistId("generate_default_from_new", crate::AssistKind::Generate),
-        "Generate a Default impl from a new fn",
-        insert_location,
-        move |builder| {
-            let code = default_fn_node_for_new(impl_);
-            builder.insert(insert_location.end(), code);
-        },
-    )
-}
-
-fn default_fn_node_for_new(impl_: Impl) -> String {
-    format!(
-        "
-
-impl Default for {} {{
-    fn default() -> Self {{
-        Self::new()
-    }}
-}}",
-        impl_.self_ty().unwrap().syntax().text()
-    )
-}
-
-fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
-    let db = ctx.sema.db;
-    let impl_ = ctx.sema.to_def(impl_);
-    let impl_def = match impl_ {
-        Some(value) => value,
-        None => return false,
-    };
-
-    let ty = impl_def.target_ty(db);
-    let krate = impl_def.module(db).krate();
-    let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default();
-    let default_trait = match default {
-        Some(value) => value,
-        None => return false,
-    };
-
-    ty.impls_trait(db, default_trait, &[])
-}
-
-#[cfg(test)]
-mod tests {
-    use ide_db::helpers::FamousDefs;
-
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn generate_default() {
-        check_pass(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn ne$0w() -> Self {
-        Self { _inner: () }
-    }
-}
-
-fn main() {}
-"#,
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-fn main() {}
-"#,
-        );
-    }
-
-    #[test]
-    fn generate_default2() {
-        check_pass(
-            r#"
-struct Test { value: u32 }
-
-impl Test {
-    pub fn ne$0w() -> Self {
-        Self { value: 0 }
-    }
-}
-"#,
-            r#"
-struct Test { value: u32 }
-
-impl Test {
-    pub fn new() -> Self {
-        Self { value: 0 }
-    }
-}
-
-impl Default for Test {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn new_function_with_parameters() {
-        mark::check!(new_function_with_parameters);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn $0new(value: ()) -> Self {
-        Self { _inner: value }
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn other_function_than_new() {
-        mark::check!(other_function_than_new);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn a$0dd() -> Self {
-        Self { _inner: () }
-    }
-}
-
-"#,
-        );
-    }
-
-    #[test]
-    fn default_block_is_already_present() {
-        mark::check!(default_block_is_already_present);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn n$0ew() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn standalone_new_function() {
-        check_not_applicable(
-            r#"
-fn n$0ew() -> u32 {
-    0
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn multiple_struct_blocks() {
-        check_pass(
-            r#"
-struct Example { _inner: () }
-struct Test { value: u32 }
-
-impl Example {
-    pub fn new$0() -> Self {
-        Self { _inner: () }
-    }
-}
-"#,
-            r#"
-struct Example { _inner: () }
-struct Test { value: u32 }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn when_struct_is_after_impl() {
-        check_pass(
-            r#"
-impl Example {
-    pub fn $0new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-struct Example { _inner: () }
-"#,
-            r#"
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-struct Example { _inner: () }
-"#,
-        );
-    }
-
-    #[test]
-    fn struct_in_module() {
-        check_pass(
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn n$0ew() -> Self {
-            Self { _inner: () }
-        }
-    }
-}
-"#,
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn new() -> Self {
-            Self { _inner: () }
-        }
-    }
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn struct_in_module_with_default() {
-        mark::check!(struct_in_module_with_default);
-        check_not_applicable(
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn n$0ew() -> Self {
-            Self { _inner: () }
-        }
-    }
-
-    impl Default for Example {
-        fn default() -> Self {
-            Self::new()
-        }
-    }
-}
-"#,
-        );
-    }
-
-    fn check_pass(before: &str, after: &str) {
-        let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
-        check_assist(generate_default_from_new, before, after);
-    }
-
-    fn check_not_applicable(before: &str) {
-        let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
-        check_assist_not_applicable(generate_default_from_new, before);
-    }
-}
diff --git a/crates/ide_assists/src/handlers/replace_string_with_char.rs b/crates/ide_assists/src/handlers/replace_string_with_char.rs
index 303c0dcbeb..634b9c0b79 100644
--- a/crates/ide_assists/src/handlers/replace_string_with_char.rs
+++ b/crates/ide_assists/src/handlers/replace_string_with_char.rs
@@ -25,15 +25,16 @@ pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext) -
     if value.chars().take(2).count() != 1 {
         return None;
     }
+    let quote_offets = token.quote_offsets()?;
 
     acc.add(
         AssistId("replace_string_with_char", AssistKind::RefactorRewrite),
         "Replace string with char",
         target,
         |edit| {
-            let token_text = token.syntax().text();
-            let inner_text = &token_text[1..token_text.len() - 1];
-            edit.replace(token.syntax().text_range(), format!("'{}'", inner_text));
+            let (left, right) = quote_offets.quotes;
+            edit.replace(left, String::from('\''));
+            edit.replace(right, String::from('\''));
         },
     )
 }
@@ -49,10 +50,10 @@ mod tests {
         check_assist_target(
             replace_string_with_char,
             r#"
-            fn f() {
-                let s = "$0c";
-            }
-            "#,
+fn f() {
+    let s = "$0c";
+}
+"#,
             r#""c""#,
         );
     }
@@ -62,15 +63,15 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-    fn f() {
-        let s = "$0c";
-    }
-    "#,
+fn f() {
+    let s = "$0c";
+}
+"#,
             r##"
-    fn f() {
-        let s = 'c';
-    }
-    "##,
+fn f() {
+    let s = 'c';
+}
+"##,
         )
     }
 
@@ -79,15 +80,15 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-    fn f() {
-        let s = "$0😀";
-    }
-    "#,
+fn f() {
+    let s = "$0😀";
+}
+"#,
             r##"
-    fn f() {
-        let s = '😀';
-    }
-    "##,
+fn f() {
+    let s = '😀';
+}
+"##,
         )
     }
 
@@ -96,10 +97,10 @@ mod tests {
         check_assist_not_applicable(
             replace_string_with_char,
             r#"
-    fn f() {
-        let s = "$0test";
-    }
-    "#,
+fn f() {
+    let s = "$0test";
+}
+"#,
         )
     }
 
@@ -108,15 +109,15 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-                fn f() {
-                    format!($0"x", 92)
-                }
-                "#,
+fn f() {
+    format!($0"x", 92)
+}
+"#,
             r##"
-                fn f() {
-                    format!('x', 92)
-                }
-                "##,
+fn f() {
+    format!('x', 92)
+}
+"##,
         )
     }
 
@@ -125,15 +126,15 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-                fn f() {
-                    find($0"x");
-                }
-                "#,
+fn f() {
+    find($0"x");
+}
+"#,
             r##"
-                fn f() {
-                    find('x');
-                }
-                "##,
+fn f() {
+    find('x');
+}
+"##,
         )
     }
 
@@ -142,15 +143,15 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-                fn f() {
-                    find($0"\n");
-                }
-                "#,
+fn f() {
+    find($0"\n");
+}
+"#,
             r##"
-                fn f() {
-                    find('\n');
-                }
-                "##,
+fn f() {
+    find('\n');
+}
+"##,
         )
     }
 
@@ -159,15 +160,32 @@ mod tests {
         check_assist(
             replace_string_with_char,
             r#"
-                fn f() {
-                    find($0"\u{7FFF}");
-                }
-                "#,
+fn f() {
+    find($0"\u{7FFF}");
+}
+"#,
+            r##"
+fn f() {
+    find('\u{7FFF}');
+}
+"##,
+        )
+    }
+
+    #[test]
+    fn replace_raw_string_with_char() {
+        check_assist(
+            replace_string_with_char,
             r##"
-                fn f() {
-                    find('\u{7FFF}');
-                }
-                "##,
+fn f() {
+    $0r#"X"#
+}
+"##,
+            r##"
+fn f() {
+    'X'
+}
+"##,
         )
     }
 }
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index ea62d5f5da..9c8148462c 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -127,7 +127,6 @@ mod handlers {
     mod flip_comma;
     mod flip_trait_bound;
     mod generate_default_from_enum_variant;
-    mod generate_default_from_new;
     mod generate_derive;
     mod generate_enum_is_method;
     mod generate_enum_projection_method;
@@ -190,7 +189,6 @@ mod handlers {
             flip_comma::flip_comma,
             flip_trait_bound::flip_trait_bound,
             generate_default_from_enum_variant::generate_default_from_enum_variant,
-            generate_default_from_new::generate_default_from_new,
             generate_derive::generate_derive,
             generate_enum_is_method::generate_enum_is_method,
             generate_enum_projection_method::generate_enum_as_method,


Test patch:
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 304b5798f2..4f007aa48b 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -439,37 +439,6 @@ impl Default for Version {
     )
 }
 
-#[test]
-fn doctest_generate_default_from_new() {
-    check_doc_test(
-        "generate_default_from_new",
-        r#####"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn n$0ew() -> Self {
-        Self { _inner: () }
-    }
-}
-"#####,
-        r#####"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_generate_derive() {
     check_doc_test(