]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/convert_integer_literal.rs
Add macro test
[rust.git] / crates / ide_assists / src / handlers / convert_integer_literal.rs
1 use syntax::{ast, ast::Radix, AstToken};
2
3 use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
4
5 // Assist: convert_integer_literal
6 //
7 // Converts the base of integer literals to other bases.
8 //
9 // ```
10 // const _: i32 = 10$0;
11 // ```
12 // ->
13 // ```
14 // const _: i32 = 0b1010;
15 // ```
16 pub(crate) fn convert_integer_literal(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
17     let literal = ctx.find_node_at_offset::<ast::Literal>()?;
18     let literal = match literal.kind() {
19         ast::LiteralKind::IntNumber(it) => it,
20         _ => return None,
21     };
22     let radix = literal.radix();
23     let value = literal.value()?;
24     let suffix = literal.suffix();
25
26     let range = literal.syntax().text_range();
27     let group_id = GroupLabel("Convert integer base".into());
28
29     for &target_radix in Radix::ALL {
30         if target_radix == radix {
31             continue;
32         }
33
34         let mut converted = match target_radix {
35             Radix::Binary => format!("0b{:b}", value),
36             Radix::Octal => format!("0o{:o}", value),
37             Radix::Decimal => value.to_string(),
38             Radix::Hexadecimal => format!("0x{:X}", value),
39         };
40
41         let label = format!("Convert {} to {}{}", literal, converted, suffix.unwrap_or_default());
42
43         // Appends the type suffix back into the new literal if it exists.
44         if let Some(suffix) = suffix {
45             converted.push_str(suffix);
46         }
47
48         acc.add_group(
49             &group_id,
50             AssistId("convert_integer_literal", AssistKind::RefactorInline),
51             label,
52             range,
53             |builder| builder.replace(range, converted),
54         );
55     }
56
57     Some(())
58 }
59
60 #[cfg(test)]
61 mod tests {
62     use crate::tests::{check_assist_by_label, check_assist_not_applicable, check_assist_target};
63
64     use super::*;
65
66     #[test]
67     fn binary_target() {
68         check_assist_target(convert_integer_literal, "const _: i32 = 0b1010$0;", "0b1010");
69     }
70
71     #[test]
72     fn octal_target() {
73         check_assist_target(convert_integer_literal, "const _: i32 = 0o12$0;", "0o12");
74     }
75
76     #[test]
77     fn decimal_target() {
78         check_assist_target(convert_integer_literal, "const _: i32 = 10$0;", "10");
79     }
80
81     #[test]
82     fn hexadecimal_target() {
83         check_assist_target(convert_integer_literal, "const _: i32 = 0xA$0;", "0xA");
84     }
85
86     #[test]
87     fn binary_target_with_underscores() {
88         check_assist_target(convert_integer_literal, "const _: i32 = 0b10_10$0;", "0b10_10");
89     }
90
91     #[test]
92     fn octal_target_with_underscores() {
93         check_assist_target(convert_integer_literal, "const _: i32 = 0o1_2$0;", "0o1_2");
94     }
95
96     #[test]
97     fn decimal_target_with_underscores() {
98         check_assist_target(convert_integer_literal, "const _: i32 = 1_0$0;", "1_0");
99     }
100
101     #[test]
102     fn hexadecimal_target_with_underscores() {
103         check_assist_target(convert_integer_literal, "const _: i32 = 0x_A$0;", "0x_A");
104     }
105
106     #[test]
107     fn convert_decimal_integer() {
108         let before = "const _: i32 = 1000$0;";
109
110         check_assist_by_label(
111             convert_integer_literal,
112             before,
113             "const _: i32 = 0b1111101000;",
114             "Convert 1000 to 0b1111101000",
115         );
116
117         check_assist_by_label(
118             convert_integer_literal,
119             before,
120             "const _: i32 = 0o1750;",
121             "Convert 1000 to 0o1750",
122         );
123
124         check_assist_by_label(
125             convert_integer_literal,
126             before,
127             "const _: i32 = 0x3E8;",
128             "Convert 1000 to 0x3E8",
129         );
130     }
131
132     #[test]
133     fn convert_hexadecimal_integer() {
134         let before = "const _: i32 = 0xFF$0;";
135
136         check_assist_by_label(
137             convert_integer_literal,
138             before,
139             "const _: i32 = 0b11111111;",
140             "Convert 0xFF to 0b11111111",
141         );
142
143         check_assist_by_label(
144             convert_integer_literal,
145             before,
146             "const _: i32 = 0o377;",
147             "Convert 0xFF to 0o377",
148         );
149
150         check_assist_by_label(
151             convert_integer_literal,
152             before,
153             "const _: i32 = 255;",
154             "Convert 0xFF to 255",
155         );
156     }
157
158     #[test]
159     fn convert_binary_integer() {
160         let before = "const _: i32 = 0b11111111$0;";
161
162         check_assist_by_label(
163             convert_integer_literal,
164             before,
165             "const _: i32 = 0o377;",
166             "Convert 0b11111111 to 0o377",
167         );
168
169         check_assist_by_label(
170             convert_integer_literal,
171             before,
172             "const _: i32 = 255;",
173             "Convert 0b11111111 to 255",
174         );
175
176         check_assist_by_label(
177             convert_integer_literal,
178             before,
179             "const _: i32 = 0xFF;",
180             "Convert 0b11111111 to 0xFF",
181         );
182     }
183
184     #[test]
185     fn convert_octal_integer() {
186         let before = "const _: i32 = 0o377$0;";
187
188         check_assist_by_label(
189             convert_integer_literal,
190             before,
191             "const _: i32 = 0b11111111;",
192             "Convert 0o377 to 0b11111111",
193         );
194
195         check_assist_by_label(
196             convert_integer_literal,
197             before,
198             "const _: i32 = 255;",
199             "Convert 0o377 to 255",
200         );
201
202         check_assist_by_label(
203             convert_integer_literal,
204             before,
205             "const _: i32 = 0xFF;",
206             "Convert 0o377 to 0xFF",
207         );
208     }
209
210     #[test]
211     fn convert_integer_with_underscores() {
212         let before = "const _: i32 = 1_00_0$0;";
213
214         check_assist_by_label(
215             convert_integer_literal,
216             before,
217             "const _: i32 = 0b1111101000;",
218             "Convert 1_00_0 to 0b1111101000",
219         );
220
221         check_assist_by_label(
222             convert_integer_literal,
223             before,
224             "const _: i32 = 0o1750;",
225             "Convert 1_00_0 to 0o1750",
226         );
227
228         check_assist_by_label(
229             convert_integer_literal,
230             before,
231             "const _: i32 = 0x3E8;",
232             "Convert 1_00_0 to 0x3E8",
233         );
234     }
235
236     #[test]
237     fn convert_integer_with_suffix() {
238         let before = "const _: i32 = 1000i32$0;";
239
240         check_assist_by_label(
241             convert_integer_literal,
242             before,
243             "const _: i32 = 0b1111101000i32;",
244             "Convert 1000i32 to 0b1111101000i32",
245         );
246
247         check_assist_by_label(
248             convert_integer_literal,
249             before,
250             "const _: i32 = 0o1750i32;",
251             "Convert 1000i32 to 0o1750i32",
252         );
253
254         check_assist_by_label(
255             convert_integer_literal,
256             before,
257             "const _: i32 = 0x3E8i32;",
258             "Convert 1000i32 to 0x3E8i32",
259         );
260     }
261
262     #[test]
263     fn convert_overflowing_literal() {
264         let before = "const _: i32 =
265             111111111111111111111111111111111111111111111111111111111111111111111111$0;";
266         check_assist_not_applicable(convert_integer_literal, before);
267     }
268 }