1 use itertools::Itertools;
2 use rustc_hash::FxHashMap;
4 use hir::{PathResolution, Semantics};
5 use ide_db::RootDatabase;
7 ast::{self, NameOwner},
11 use crate::{utils::get_methods, AssistContext, AssistId, AssistKind, Assists};
13 // Assist: reorder_impl
15 // Reorder the methods of an `impl Trait`. The methods will be ordered
16 // in the same order as in the trait definition.
26 // $0impl Foo for Bar {
47 pub(crate) fn reorder_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
48 let impl_ast = ctx.find_node_at_offset::<ast::Impl>()?;
49 let items = impl_ast.assoc_item_list()?;
50 let methods = get_methods(&items);
54 .and_then(|t| match t {
55 ast::Type::PathType(path) => Some(path),
60 let ranks = compute_method_ranks(&path, ctx)?;
61 let sorted: Vec<_> = methods
65 f.name().and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::max_value())
69 // Don't edit already sorted methods:
70 if methods == sorted {
71 cov_mark::hit!(not_applicable_if_sorted);
75 let target = items.syntax().text_range();
77 AssistId("reorder_impl", AssistKind::RefactorRewrite),
78 "Sort methods by trait definition",
81 let methods = methods.into_iter().map(|fn_| builder.make_mut(fn_)).collect::<Vec<_>>();
85 .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax()));
90 fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> {
91 let td = trait_definition(path, &ctx.sema)?;
96 .flat_map(|i| match i {
97 hir::AssocItem::Function(f) => Some(f),
101 .map(|(idx, func)| (func.name(ctx.db()).to_string(), idx))
106 fn trait_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option<hir::Trait> {
107 match sema.resolve_path(path)? {
108 PathResolution::Def(hir::ModuleDef::Trait(trait_)) => Some(trait_),
115 use crate::tests::{check_assist, check_assist_not_applicable};
120 fn not_applicable_if_sorted() {
121 cov_mark::check!(not_applicable_if_sorted);
122 check_assist_not_applicable(
141 fn not_applicable_if_empty() {
142 check_assist_not_applicable(
147 $0impl Bar for Foo {}
153 fn reorder_impl_trait_functions() {
192 fn reorder_impl_trait_methods_uneven_ident_lengths() {
198 fn fooo(&mut self) {}
203 fn fooo(&mut self) {}
204 fn foo(&mut self) {$0}
209 fn fooo(&mut self) {}
215 fn fooo(&mut self) {}