rust/crates/ide-assists/src/handlers/convert_integer_literal.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

269 lines
6.9 KiB
Rust
Raw Normal View History

2020-11-06 12:01:25 -06:00
use syntax::{ast, ast::Radix, AstToken};
2020-09-29 13:48:43 -05:00
use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
// Assist: convert_integer_literal
//
// Converts the base of integer literals to other bases.
//
// ```
2021-01-06 14:15:48 -06:00
// const _: i32 = 10$0;
2020-09-29 13:48:43 -05:00
// ```
// ->
// ```
// const _: i32 = 0b1010;
// ```
2022-07-20 08:02:08 -05:00
pub(crate) fn convert_integer_literal(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
2020-11-06 15:52:22 -06:00
let literal = ctx.find_node_at_offset::<ast::Literal>()?;
let literal = match literal.kind() {
ast::LiteralKind::IntNumber(it) => it,
_ => return None,
};
2020-11-06 12:01:25 -06:00
let radix = literal.radix();
let value = literal.value()?;
let suffix = literal.suffix();
2020-09-29 13:48:43 -05:00
let range = literal.syntax().text_range();
let group_id = GroupLabel("Convert integer base".into());
for &target_radix in Radix::ALL {
if target_radix == radix {
2020-09-29 13:48:43 -05:00
continue;
}
let mut converted = match target_radix {
Radix::Binary => format!("0b{:b}", value),
Radix::Octal => format!("0o{:o}", value),
Radix::Decimal => value.to_string(),
Radix::Hexadecimal => format!("0x{:X}", value),
2020-09-29 13:48:43 -05:00
};
2020-11-06 12:01:25 -06:00
let label = format!("Convert {} to {}{}", literal, converted, suffix.unwrap_or_default());
2020-09-29 13:48:43 -05:00
// Appends the type suffix back into the new literal if it exists.
2020-11-06 12:01:25 -06:00
if let Some(suffix) = suffix {
converted.push_str(suffix);
2020-09-29 13:48:43 -05:00
}
acc.add_group(
&group_id,
AssistId("convert_integer_literal", AssistKind::RefactorInline),
label,
range,
|builder| builder.replace(range, converted),
);
}
Some(())
}
#[cfg(test)]
mod tests {
use crate::tests::{check_assist_by_label, check_assist_not_applicable, check_assist_target};
use super::*;
#[test]
fn binary_target() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0b1010$0;", "0b1010");
}
#[test]
fn octal_target() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0o12$0;", "0o12");
}
#[test]
fn decimal_target() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 10$0;", "10");
}
#[test]
fn hexadecimal_target() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0xA$0;", "0xA");
}
#[test]
fn binary_target_with_underscores() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0b10_10$0;", "0b10_10");
}
#[test]
fn octal_target_with_underscores() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0o1_2$0;", "0o1_2");
}
#[test]
fn decimal_target_with_underscores() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 1_0$0;", "1_0");
}
#[test]
fn hexadecimal_target_with_underscores() {
2021-01-06 14:15:48 -06:00
check_assist_target(convert_integer_literal, "const _: i32 = 0x_A$0;", "0x_A");
}
#[test]
fn convert_decimal_integer() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 1000$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0b1111101000;",
"Convert 1000 to 0b1111101000",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0o1750;",
"Convert 1000 to 0o1750",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0x3E8;",
"Convert 1000 to 0x3E8",
);
}
#[test]
fn convert_hexadecimal_integer() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 0xFF$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0b11111111;",
"Convert 0xFF to 0b11111111",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0o377;",
"Convert 0xFF to 0o377",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 255;",
"Convert 0xFF to 255",
);
}
#[test]
fn convert_binary_integer() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 0b11111111$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0o377;",
"Convert 0b11111111 to 0o377",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 255;",
"Convert 0b11111111 to 255",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0xFF;",
"Convert 0b11111111 to 0xFF",
);
}
#[test]
fn convert_octal_integer() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 0o377$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0b11111111;",
"Convert 0o377 to 0b11111111",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 255;",
"Convert 0o377 to 255",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0xFF;",
"Convert 0o377 to 0xFF",
);
}
#[test]
2020-11-07 03:47:25 -06:00
fn convert_integer_with_underscores() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 1_00_0$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0b1111101000;",
"Convert 1_00_0 to 0b1111101000",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0o1750;",
"Convert 1_00_0 to 0o1750",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0x3E8;",
"Convert 1_00_0 to 0x3E8",
);
}
#[test]
2020-11-07 03:47:25 -06:00
fn convert_integer_with_suffix() {
2021-01-06 14:15:48 -06:00
let before = "const _: i32 = 1000i32$0;";
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0b1111101000i32;",
"Convert 1000i32 to 0b1111101000i32",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0o1750i32;",
"Convert 1000i32 to 0o1750i32",
);
check_assist_by_label(
convert_integer_literal,
before,
"const _: i32 = 0x3E8i32;",
"Convert 1000i32 to 0x3E8i32",
);
}
#[test]
fn convert_overflowing_literal() {
let before = "const _: i32 =
2021-01-06 14:15:48 -06:00
111111111111111111111111111111111111111111111111111111111111111111111111$0;";
check_assist_not_applicable(convert_integer_literal, before);
}
}