diff options
Diffstat (limited to 'crates/assists/src/handlers')
-rw-r--r-- | crates/assists/src/handlers/replace_string_with_char.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/crates/assists/src/handlers/replace_string_with_char.rs b/crates/assists/src/handlers/replace_string_with_char.rs new file mode 100644 index 000000000..4ca87a8ec --- /dev/null +++ b/crates/assists/src/handlers/replace_string_with_char.rs | |||
@@ -0,0 +1,141 @@ | |||
1 | use syntax::{ | ||
2 | ast::{self, HasStringValue}, | ||
3 | AstToken, | ||
4 | SyntaxKind::STRING, | ||
5 | }; | ||
6 | |||
7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
8 | |||
9 | // Assist: replace_string_with_char | ||
10 | // | ||
11 | // Replace string with char. | ||
12 | // | ||
13 | // ``` | ||
14 | // fn main() { | ||
15 | // find("{<|>"); | ||
16 | // } | ||
17 | // ``` | ||
18 | // -> | ||
19 | // ``` | ||
20 | // fn main() { | ||
21 | // find('{'); | ||
22 | // } | ||
23 | // ``` | ||
24 | pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
25 | let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; | ||
26 | let value = token.value()?; | ||
27 | let target = token.syntax().text_range(); | ||
28 | |||
29 | if value.chars().take(2).count() != 1 { | ||
30 | return None; | ||
31 | } | ||
32 | |||
33 | acc.add( | ||
34 | AssistId("replace_string_with_char", AssistKind::RefactorRewrite), | ||
35 | "Replace string with char", | ||
36 | target, | ||
37 | |edit| { | ||
38 | edit.replace(token.syntax().text_range(), format!("'{}'", value)); | ||
39 | }, | ||
40 | ) | ||
41 | } | ||
42 | |||
43 | #[cfg(test)] | ||
44 | mod tests { | ||
45 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
46 | |||
47 | use super::*; | ||
48 | |||
49 | #[test] | ||
50 | fn replace_string_with_char_target() { | ||
51 | check_assist_target( | ||
52 | replace_string_with_char, | ||
53 | r#" | ||
54 | fn f() { | ||
55 | let s = "<|>c"; | ||
56 | } | ||
57 | "#, | ||
58 | r#""c""#, | ||
59 | ); | ||
60 | } | ||
61 | |||
62 | #[test] | ||
63 | fn replace_string_with_char_assist() { | ||
64 | check_assist( | ||
65 | replace_string_with_char, | ||
66 | r#" | ||
67 | fn f() { | ||
68 | let s = "<|>c"; | ||
69 | } | ||
70 | "#, | ||
71 | r##" | ||
72 | fn f() { | ||
73 | let s = 'c'; | ||
74 | } | ||
75 | "##, | ||
76 | ) | ||
77 | } | ||
78 | |||
79 | #[test] | ||
80 | fn replace_string_with_char_assist_with_emoji() { | ||
81 | check_assist( | ||
82 | replace_string_with_char, | ||
83 | r#" | ||
84 | fn f() { | ||
85 | let s = "<|>😀"; | ||
86 | } | ||
87 | "#, | ||
88 | r##" | ||
89 | fn f() { | ||
90 | let s = '😀'; | ||
91 | } | ||
92 | "##, | ||
93 | ) | ||
94 | } | ||
95 | |||
96 | #[test] | ||
97 | fn replace_string_with_char_assist_not_applicable() { | ||
98 | check_assist_not_applicable( | ||
99 | replace_string_with_char, | ||
100 | r#" | ||
101 | fn f() { | ||
102 | let s = "<|>test"; | ||
103 | } | ||
104 | "#, | ||
105 | ) | ||
106 | } | ||
107 | |||
108 | #[test] | ||
109 | fn replace_string_with_char_works_inside_macros() { | ||
110 | check_assist( | ||
111 | replace_string_with_char, | ||
112 | r#" | ||
113 | fn f() { | ||
114 | format!(<|>"x", 92) | ||
115 | } | ||
116 | "#, | ||
117 | r##" | ||
118 | fn f() { | ||
119 | format!('x', 92) | ||
120 | } | ||
121 | "##, | ||
122 | ) | ||
123 | } | ||
124 | |||
125 | #[test] | ||
126 | fn replace_string_with_char_works_func_args() { | ||
127 | check_assist( | ||
128 | replace_string_with_char, | ||
129 | r#" | ||
130 | fn f() { | ||
131 | find(<|>"x"); | ||
132 | } | ||
133 | "#, | ||
134 | r##" | ||
135 | fn f() { | ||
136 | find('x'); | ||
137 | } | ||
138 | "##, | ||
139 | ) | ||
140 | } | ||
141 | } | ||