1 use hir::{PathResolution, Semantics};
2 use ide_db::{FxHashMap, RootDatabase};
3 use itertools::Itertools;
9 use crate::{AssistContext, AssistId, AssistKind, Assists};
11 // Assist: reorder_impl_items
13 // Reorder the items of an `impl Trait`. The items will be ordered
14 // in the same order as in the trait definition.
24 // $0impl Foo for Bar {
45 pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
46 let impl_ast = ctx.find_node_at_offset::<ast::Impl>()?;
47 let items = impl_ast.assoc_item_list()?;
48 let assoc_items = items.assoc_items().collect::<Vec<_>>();
52 .and_then(|t| match t {
53 ast::Type::PathType(path) => Some(path),
58 let ranks = compute_item_ranks(&path, ctx)?;
59 let sorted: Vec<_> = assoc_items
64 ast::AssocItem::Const(c) => c.name(),
65 ast::AssocItem::Fn(f) => f.name(),
66 ast::AssocItem::TypeAlias(t) => t.name(),
67 ast::AssocItem::MacroCall(_) => None,
70 name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::max_value())
74 // Don't edit already sorted methods:
75 if assoc_items == sorted {
76 cov_mark::hit!(not_applicable_if_sorted);
80 let target = items.syntax().text_range();
82 AssistId("reorder_impl_items", AssistKind::RefactorRewrite),
83 "Sort items by trait definition",
87 assoc_items.into_iter().map(|item| builder.make_mut(item)).collect::<Vec<_>>();
91 .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax()));
96 fn compute_item_ranks(
98 ctx: &AssistContext<'_>,
99 ) -> Option<FxHashMap<String, usize>> {
100 let td = trait_definition(path, &ctx.sema)?;
105 .flat_map(|i| i.name(ctx.db()))
107 .map(|(idx, name)| (name.to_string(), idx))
112 fn trait_definition(path: &ast::Path, sema: &Semantics<'_, RootDatabase>) -> Option<hir::Trait> {
113 match sema.resolve_path(path)? {
114 PathResolution::Def(hir::ModuleDef::Trait(trait_)) => Some(trait_),
121 use crate::tests::{check_assist, check_assist_not_applicable};
126 fn not_applicable_if_sorted() {
127 cov_mark::check!(not_applicable_if_sorted);
128 check_assist_not_applicable(
151 fn reorder_impl_trait_functions() {
190 fn not_applicable_if_empty() {
191 check_assist_not_applicable(
196 $0impl Bar for Foo {}
202 fn reorder_impl_trait_items() {
257 fn reorder_impl_trait_items_uneven_ident_lengths() {