aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assists/flip_trait_bound.rs
blob: a2c954ec5fa9505a13eec4db7498cde436a102b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//! Assist for swapping traits inside of a trait bound list
//!
//! E.g. `A + B` => `B + A` when the cursor is placed by the `+` inside of a
//! trait bound list

use hir::db::HirDatabase;
use ra_syntax::{algo::non_trivia_sibling, ast::TypeBoundList, Direction, T};

use crate::{Assist, AssistCtx, AssistId};

/// Flip trait bound assist.
pub(crate) fn flip_trait_bound(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    // Make sure we're in a `TypeBoundList`
    ctx.node_at_offset::<TypeBoundList>()?;

    // We want to replicate the behavior of `flip_binexpr` by only suggesting
    // the assist when the cursor is on a `+`
    let plus = ctx.token_at_offset().find(|tkn| tkn.kind() == T![+])?;

    let (before, after) = (
        non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
        non_trivia_sibling(plus.clone().into(), Direction::Next)?,
    );

    ctx.add_action(AssistId("flip_trait_bound"), "flip trait bound", |edit| {
        edit.target(plus.text_range());
        edit.replace(before.text_range(), after.to_string());
        edit.replace(after.text_range(), before.to_string());
    });

    ctx.build()
}