From c1712e55c6d7fbb9d7ccef5de0be0b1c41033219 Mon Sep 17 00:00:00 2001 From: Sebastian Ziebell Date: Mon, 17 Apr 2023 11:34:04 +0200 Subject: [PATCH] Restrict "sort items" assist inside Impl & Trait This fixes the applicability of the "sort items alphabetically" assist when the selection is inside a `Trait` or `Impl`. It's now tested if the selection is inside or overlaps with an inner node, e.g. associated const or type alias, function. --- crates/ide-assists/src/handlers/sort_items.rs | 109 +++++++++++++++++- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/crates/ide-assists/src/handlers/sort_items.rs b/crates/ide-assists/src/handlers/sort_items.rs index 63e350e155fc8..3a0121f55fa02 100644 --- a/crates/ide-assists/src/handlers/sort_items.rs +++ b/crates/ide-assists/src/handlers/sort_items.rs @@ -87,11 +87,7 @@ pub(crate) fn sort_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( return None; } - if let Some(trait_ast) = ctx.find_node_at_offset::() { - add_sort_methods_assist(acc, trait_ast.assoc_item_list()?) - } else if let Some(impl_ast) = ctx.find_node_at_offset::() { - add_sort_methods_assist(acc, impl_ast.assoc_item_list()?) - } else if let Some(struct_ast) = ctx.find_node_at_offset::() { + if let Some(struct_ast) = ctx.find_node_at_offset::() { add_sort_field_list_assist(acc, struct_ast.field_list()) } else if let Some(union_ast) = ctx.find_node_at_offset::() { add_sort_fields_assist(acc, union_ast.record_field_list()?) @@ -103,6 +99,10 @@ pub(crate) fn sort_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( add_sort_fields_assist(acc, enum_struct_variant_ast) } else if let Some(enum_ast) = ctx.find_node_at_offset::() { add_sort_variants_assist(acc, enum_ast.variant_list()?) + } else if let Some(trait_ast) = ctx.find_node_at_offset::() { + add_sort_methods_assist(acc, ctx, trait_ast.assoc_item_list()?) + } else if let Some(impl_ast) = ctx.find_node_at_offset::() { + add_sort_methods_assist(acc, ctx, impl_ast.assoc_item_list()?) } else { None } @@ -148,7 +148,19 @@ fn add_sort_field_list_assist(acc: &mut Assists, field_list: Option Option<()> { +fn add_sort_methods_assist( + acc: &mut Assists, + ctx: &AssistContext<'_>, + item_list: ast::AssocItemList, +) -> Option<()> { + let selection = ctx.selection_trimmed(); + + // ignore assist if the selection intersects with an associated item. + if item_list.assoc_items().any(|item| item.syntax().text_range().intersect(selection).is_some()) + { + return None; + } + let methods = get_methods(&item_list); let sorted = sort_by_name(&methods); @@ -218,6 +230,51 @@ mod tests { use super::*; + #[test] + fn not_applicable_if_selection_in_fn_body() { + check_assist_not_applicable( + sort_items, + r#" +struct S; +impl S { + fn func2() { + $0 bar $0 + } + fn func() {} +} + "#, + ) + } + + #[test] + fn not_applicable_if_selection_at_associated_const() { + check_assist_not_applicable( + sort_items, + r#" +struct S; +impl S { + fn func2() {} + fn func() {} + const C: () = $0()$0; +} + "#, + ) + } + + #[test] + fn not_applicable_if_selection_overlaps_nodes() { + check_assist_not_applicable( + sort_items, + r#" +struct S; +impl $0S { + fn$0 func2() {} + fn func() {} +} + "#, + ) + } + #[test] fn not_applicable_if_no_selection() { cov_mark::check!(not_applicable_if_no_selection); @@ -233,6 +290,21 @@ t$0rait Bar { ) } + #[test] + fn not_applicable_if_selection_in_trait_fn_body() { + check_assist_not_applicable( + sort_items, + r#" +trait Bar { + fn b() { + $0 hello $0 + } + fn a(); +} + "#, + ) + } + #[test] fn not_applicable_if_trait_empty() { cov_mark::check!(not_applicable_if_sorted_or_empty_or_single); @@ -460,6 +532,31 @@ struct Bar { ) } + #[test] + fn sort_struct_inside_a_function() { + check_assist( + sort_items, + r#" +fn hello() { + $0struct Bar$0 { + b: u8, + a: u32, + c: u64, + } +} + "#, + r#" +fn hello() { + struct Bar { + a: u32, + b: u8, + c: u64, + } +} + "#, + ) + } + #[test] fn sort_generic_struct_with_lifetime() { check_assist(