Unnamed repository; edit this file 'description' to name the repository.
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use syntax::{
    algo::non_trivia_sibling,
    ast::{self, AstNode},
    Direction, T,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: flip_trait_bound
//
// Flips two trait bounds.
//
// ```
// fn foo<T: Clone +$0 Copy>() { }
// ```
// ->
// ```
// fn foo<T: Copy + Clone>() { }
// ```
pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    // We want to replicate the behavior of `flip_binexpr` by only suggesting
    // the assist when the cursor is on a `+`
    let plus = ctx.find_token_syntax_at_offset(T![+])?;

    // Make sure we're in a `TypeBoundList`
    if ast::TypeBoundList::cast(plus.parent()?).is_none() {
        return None;
    }

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

    let target = plus.text_range();
    acc.add(
        AssistId("flip_trait_bound", AssistKind::RefactorRewrite),
        "Flip trait bounds",
        target,
        |edit| {
            edit.replace(before.text_range(), after.to_string());
            edit.replace(after.text_range(), before.to_string());
        },
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn flip_trait_bound_assist_available() {
        check_assist_target(flip_trait_bound, "struct S<T> where T: A $0+ B + C { }", "+")
    }

    #[test]
    fn flip_trait_bound_not_applicable_for_single_trait_bound() {
        check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: $0A { }")
    }

    #[test]
    fn flip_trait_bound_works_for_struct() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A $0+ B { }",
            "struct S<T> where T: B + A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_trait_impl() {
        check_assist(
            flip_trait_bound,
            "impl X for S<T> where T: A +$0 B { }",
            "impl X for S<T> where T: B + A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_fn() {
        check_assist(flip_trait_bound, "fn f<T: A $0+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }")
    }

    #[test]
    fn flip_trait_bound_works_for_fn_where_clause() {
        check_assist(
            flip_trait_bound,
            "fn f<T>(t: T) where T: A +$0 B { }",
            "fn f<T>(t: T) where T: B + A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_lifetime() {
        check_assist(
            flip_trait_bound,
            "fn f<T>(t: T) where T: A $0+ 'static { }",
            "fn f<T>(t: T) where T: 'static + A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_complex_bounds() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A<T> $0+ b_mod::B<T> + C<T> { }",
            "struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_long_bounds() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A + B + C + D + E + F +$0 G + H + I + J { }",
            "struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }",
        )
    }
}
uot;, "parts" ], "flake-utils-pre-commit": [ "nci" ], "ghc-utils": [ "nci" ], "gomod2nix": [ "nci" ], "mach-nix": [ "nci" ], "nix-pypi-fetcher": [ "nci" ], "nixpkgs": [ "nci", "nixpkgs" ], "poetry2nix": [ "nci" ], "pre-commit-hooks": [ "nci" ], "pruned-racket-catalog": [ "nci" ] }, "locked": { "lastModified": 1677289985, "narHash": "sha256-lUp06cTTlWubeBGMZqPl9jODM99LpWMcwxRiscFAUJg=", "owner": "nix-community", "repo": "dream2nix", "rev": "28b973a8d4c30cc1cbb3377ea2023a76bc3fb889", "type": "github" }, "original": { "owner": "nix-community", "repo": "dream2nix", "type": "github" } }, "flake-utils": { "locked": { "lastModified": 1659877975, "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "owner": "numtide", "repo": "flake-utils", "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "mk-naked-shell": { "flake": false, "locked": { "lastModified": 1676572903, "narHash": "sha256-oQoDHHUTxNVSURfkFcYLuAK+btjs30T4rbEUtCUyKy8=", "owner": "yusdacra", "repo": "mk-naked-shell", "rev": "aeca9f8aa592f5e8f71f407d081cb26fd30c5a57", "type": "github" }, "original": { "owner": "yusdacra", "repo": "mk-naked-shell", "type": "github" } }, "nci": { "inputs": { "dream2nix": "dream2nix", "mk-naked-shell": "mk-naked-shell", "nixpkgs": [ "nixpkgs" ], "parts": "parts", "rust-overlay": [ "rust-overlay" ] }, "locked": { "lastModified": 1677297103, "narHash": "sha256-ArlJIbp9NGV9yvhZdV0SOUFfRlI/kHeKoCk30NbSiLc=", "owner": "yusdacra", "repo": "nix-cargo-integration", "rev": "a79272a2cb0942392bb3a5bf9a3ec6bc568795b2", "type": "github" }, "original": { "owner": "yusdacra", "repo": "nix-cargo-integration", "type": "github" } }, "nixpkgs": { "locked": { "lastModified": 1677063315, "narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=", "owner": "nixos", "repo": "nixpkgs", "rev": "988cc958c57ce4350ec248d2d53087777f9e1949", "type": "github" }, "original": { "owner": "nixos", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-lib": { "locked": { "dir": "lib", "lastModified": 1675183161, "narHash": "sha256-Zq8sNgAxDckpn7tJo7V1afRSk2eoVbu3OjI1QklGLNg=", "owner": "NixOS", "repo": "nixpkgs", "rev": "e1e1b192c1a5aab2960bf0a0bd53a2e8124fa18e", "type": "github" }, "original": { "dir": "lib", "owner": "NixOS", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "parts": { "inputs": { "nixpkgs-lib": [ "nci", "nixpkgs" ] }, "locked": { "lastModified": 1675933616, "narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=", "owner": "hercules-ci", "repo": "flake-parts", "rev": "47478a4a003e745402acf63be7f9a092d51b83d7", "type": "github" }, "original": { "owner": "hercules-ci", "repo": "flake-parts", "type": "github" } }, "parts_2": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { "lastModified": 1675933616, "narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=", "owner": "hercules-ci", "repo": "flake-parts", "rev": "47478a4a003e745402acf63be7f9a092d51b83d7", "type": "github" }, "original": { "owner": "hercules-ci", "repo": "flake-parts", "type": "github" } }, "root": { "inputs": { "nci": "nci", "nixpkgs": "nixpkgs", "parts": "parts_2", "rust-overlay": "rust-overlay" } }, "rust-overlay": { "inputs": { "flake-utils": "flake-utils", "nixpkgs": [ "nixpkgs" ] }, "locked": { "lastModified": 1677292251, "narHash": "sha256-D+6q5Z2MQn3UFJtqsM5/AvVHi3NXKZTIMZt1JGq/spA=", "owner": "oxalica", "repo": "rust-overlay", "rev": "34cdbf6ad480ce13a6a526f57d8b9e609f3d65dc", "type": "github" }, "original": { "owner": "oxalica", "repo": "rust-overlay", "type": "github" } } }, "root": "root", "version": 7 }