Skip to content

Commit 5111207

Browse files
committed
Auto merge of rust-lang#14591 - justahero:rust-langgh-14516, r=Veykril
Restrict "sort items" assist for traits & impls This restricts the "sort items alphabetically" assist when the selection is inside a `Impl` or `Trait` node & intersects with one of the associated items. It re-orders the conditional checks of AST nodes in the `sort_items` function to check for more specific nodes first before checking `Trait` or `Impl` nodes. The `AssistContext` is passed into the `add_sort_methods_assist` function to check if the selection intersects with any inner items, e.g. associated const or type alias, function. In this case the assist does not apply. Fixes: rust-lang#14516
2 parents bab80da + c1712e5 commit 5111207

File tree

1 file changed

+103
-6
lines changed

1 file changed

+103
-6
lines changed

crates/ide-assists/src/handlers/sort_items.rs

+103-6
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ pub(crate) fn sort_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
8787
return None;
8888
}
8989

90-
if let Some(trait_ast) = ctx.find_node_at_offset::<ast::Trait>() {
91-
add_sort_methods_assist(acc, trait_ast.assoc_item_list()?)
92-
} else if let Some(impl_ast) = ctx.find_node_at_offset::<ast::Impl>() {
93-
add_sort_methods_assist(acc, impl_ast.assoc_item_list()?)
94-
} else if let Some(struct_ast) = ctx.find_node_at_offset::<ast::Struct>() {
90+
if let Some(struct_ast) = ctx.find_node_at_offset::<ast::Struct>() {
9591
add_sort_field_list_assist(acc, struct_ast.field_list())
9692
} else if let Some(union_ast) = ctx.find_node_at_offset::<ast::Union>() {
9793
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<(
10399
add_sort_fields_assist(acc, enum_struct_variant_ast)
104100
} else if let Some(enum_ast) = ctx.find_node_at_offset::<ast::Enum>() {
105101
add_sort_variants_assist(acc, enum_ast.variant_list()?)
102+
} else if let Some(trait_ast) = ctx.find_node_at_offset::<ast::Trait>() {
103+
add_sort_methods_assist(acc, ctx, trait_ast.assoc_item_list()?)
104+
} else if let Some(impl_ast) = ctx.find_node_at_offset::<ast::Impl>() {
105+
add_sort_methods_assist(acc, ctx, impl_ast.assoc_item_list()?)
106106
} else {
107107
None
108108
}
@@ -148,7 +148,19 @@ fn add_sort_field_list_assist(acc: &mut Assists, field_list: Option<ast::FieldLi
148148
}
149149
}
150150

151-
fn add_sort_methods_assist(acc: &mut Assists, item_list: ast::AssocItemList) -> Option<()> {
151+
fn add_sort_methods_assist(
152+
acc: &mut Assists,
153+
ctx: &AssistContext<'_>,
154+
item_list: ast::AssocItemList,
155+
) -> Option<()> {
156+
let selection = ctx.selection_trimmed();
157+
158+
// ignore assist if the selection intersects with an associated item.
159+
if item_list.assoc_items().any(|item| item.syntax().text_range().intersect(selection).is_some())
160+
{
161+
return None;
162+
}
163+
152164
let methods = get_methods(&item_list);
153165
let sorted = sort_by_name(&methods);
154166

@@ -218,6 +230,51 @@ mod tests {
218230

219231
use super::*;
220232

233+
#[test]
234+
fn not_applicable_if_selection_in_fn_body() {
235+
check_assist_not_applicable(
236+
sort_items,
237+
r#"
238+
struct S;
239+
impl S {
240+
fn func2() {
241+
$0 bar $0
242+
}
243+
fn func() {}
244+
}
245+
"#,
246+
)
247+
}
248+
249+
#[test]
250+
fn not_applicable_if_selection_at_associated_const() {
251+
check_assist_not_applicable(
252+
sort_items,
253+
r#"
254+
struct S;
255+
impl S {
256+
fn func2() {}
257+
fn func() {}
258+
const C: () = $0()$0;
259+
}
260+
"#,
261+
)
262+
}
263+
264+
#[test]
265+
fn not_applicable_if_selection_overlaps_nodes() {
266+
check_assist_not_applicable(
267+
sort_items,
268+
r#"
269+
struct S;
270+
impl $0S {
271+
fn$0 func2() {}
272+
fn func() {}
273+
}
274+
"#,
275+
)
276+
}
277+
221278
#[test]
222279
fn not_applicable_if_no_selection() {
223280
cov_mark::check!(not_applicable_if_no_selection);
@@ -233,6 +290,21 @@ t$0rait Bar {
233290
)
234291
}
235292

293+
#[test]
294+
fn not_applicable_if_selection_in_trait_fn_body() {
295+
check_assist_not_applicable(
296+
sort_items,
297+
r#"
298+
trait Bar {
299+
fn b() {
300+
$0 hello $0
301+
}
302+
fn a();
303+
}
304+
"#,
305+
)
306+
}
307+
236308
#[test]
237309
fn not_applicable_if_trait_empty() {
238310
cov_mark::check!(not_applicable_if_sorted_or_empty_or_single);
@@ -460,6 +532,31 @@ struct Bar {
460532
)
461533
}
462534

535+
#[test]
536+
fn sort_struct_inside_a_function() {
537+
check_assist(
538+
sort_items,
539+
r#"
540+
fn hello() {
541+
$0struct Bar$0 {
542+
b: u8,
543+
a: u32,
544+
c: u64,
545+
}
546+
}
547+
"#,
548+
r#"
549+
fn hello() {
550+
struct Bar {
551+
a: u32,
552+
b: u8,
553+
c: u64,
554+
}
555+
}
556+
"#,
557+
)
558+
}
559+
463560
#[test]
464561
fn sort_generic_struct_with_lifetime() {
465562
check_assist(

0 commit comments

Comments
 (0)