Skip to content

Commit 45609a9

Browse files
committed
Auto merge of #17571 - winstxnhdw:bool-to-enum-no-dupe, r=Veykril
feat: do not add new enum if it already exists ## Summary This PR introduces a check for the existence of another enum within the current scope, and if it exist, we skip `add_enum_def`. ## Why? Currently, when using the `bool_to_enum` assist more than once, it is possible to add multiple enum definitions. For example, the following snippet, ```rs #[derive(PartialEq, Eq)] enum Bool { True, False, } fn main() { let a = Bool::True; let b = true; println!("Hello, world!"); } ``` will be transformed into, ```rs #[derive(PartialEq, Eq)] enum Bool { True, False, } #[derive(PartialEq, Eq)] enum Bool { True, False, } fn main() { let a = Bool::True; let b = Bool::True; println!("Hello, world!"); } ``` This can be annoying for users to clean up.
2 parents 0d6bd91 + d33e96b commit 45609a9

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct BoolNodeData {
9696

9797
/// Attempts to find an appropriate node to apply the action to.
9898
fn find_bool_node(ctx: &AssistContext<'_>) -> Option<BoolNodeData> {
99-
let name: ast::Name = ctx.find_node_at_offset()?;
99+
let name = ctx.find_node_at_offset::<ast::Name>()?;
100100

101101
if let Some(ident_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) {
102102
let def = ctx.sema.to_def(&ident_pat)?;
@@ -461,7 +461,20 @@ fn add_enum_def(
461461
usages: &UsageSearchResult,
462462
target_node: SyntaxNode,
463463
target_module: &hir::Module,
464-
) {
464+
) -> Option<()> {
465+
let insert_before = node_to_insert_before(target_node);
466+
467+
if ctx
468+
.sema
469+
.scope(&insert_before)?
470+
.module()
471+
.scope(ctx.db(), Some(*target_module))
472+
.iter()
473+
.any(|(name, _)| name.as_str() == Some("Bool"))
474+
{
475+
return None;
476+
}
477+
465478
let make_enum_pub = usages
466479
.iter()
467480
.flat_map(|(_, refs)| refs)
@@ -472,14 +485,15 @@ fn add_enum_def(
472485
.any(|module| module.nearest_non_block_module(ctx.db()) != *target_module);
473486
let enum_def = make_bool_enum(make_enum_pub);
474487

475-
let insert_before = node_to_insert_before(target_node);
476488
let indent = IndentLevel::from_node(&insert_before);
477489
enum_def.reindent_to(indent);
478490

479491
edit.insert(
480492
insert_before.text_range().start(),
481493
format!("{}\n\n{indent}", enum_def.syntax().text()),
482494
);
495+
496+
Some(())
483497
}
484498

485499
/// Finds where to put the new enum definition.
@@ -553,6 +567,33 @@ fn function(foo: Bool, bar: bool) {
553567
)
554568
}
555569

570+
#[test]
571+
fn no_duplicate_enums() {
572+
check_assist(
573+
bool_to_enum,
574+
r#"
575+
#[derive(PartialEq, Eq)]
576+
enum Bool { True, False }
577+
578+
fn function(foo: bool, $0bar: bool) {
579+
if bar {
580+
println!("bar");
581+
}
582+
}
583+
"#,
584+
r#"
585+
#[derive(PartialEq, Eq)]
586+
enum Bool { True, False }
587+
588+
fn function(foo: bool, bar: Bool) {
589+
if bar == Bool::True {
590+
println!("bar");
591+
}
592+
}
593+
"#,
594+
)
595+
}
596+
556597
#[test]
557598
fn parameter_with_last_param_usage() {
558599
check_assist(

0 commit comments

Comments
 (0)