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
use hir::{Mutability, Semantics};
use ide_db::RootDatabase;

use syntax::ast::{self, AstNode};

use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};

pub(super) fn hints(
    acc: &mut Vec<InlayHint>,
    sema: &Semantics<'_, RootDatabase>,
    config: &InlayHintsConfig,
    pat: &ast::Pat,
) -> Option<()> {
    if !config.binding_mode_hints {
        return None;
    }

    let outer_paren_pat = pat
        .syntax()
        .ancestors()
        .skip(1)
        .map_while(ast::Pat::cast)
        .map_while(|pat| match pat {
            ast::Pat::ParenPat(pat) => Some(pat),
            _ => None,
        })
        .last();
    let range =
        outer_paren_pat.as_ref().map_or_else(|| pat.syntax(), |it| it.syntax()).text_range();
    sema.pattern_adjustments(&pat).iter().for_each(|ty| {
        let reference = ty.is_reference();
        let mut_reference = ty.is_mutable_reference();
        let r = match (reference, mut_reference) {
            (true, true) => "&mut",
            (true, false) => "&",
            _ => return,
        };
        acc.push(InlayHint {
            range,
            kind: InlayKind::BindingModeHint,
            label: r.to_string().into(),
            tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
        });
    });
    match pat {
        ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
            let bm = sema.binding_mode_of_pat(pat)?;
            let bm = match bm {
                hir::BindingMode::Move => return None,
                hir::BindingMode::Ref(Mutability::Mut) => "ref mut",
                hir::BindingMode::Ref(Mutability::Shared) => "ref",
            };
            acc.push(InlayHint {
                range: pat.syntax().text_range(),
                kind: InlayKind::BindingModeHint,
                label: bm.to_string().into(),
                tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
            });
        }
        ast::Pat::OrPat(pat) if outer_paren_pat.is_none() => {
            acc.push(InlayHint {
                range: pat.syntax().text_range(),
                kind: InlayKind::OpeningParenthesis,
                label: "(".into(),
                tooltip: None,
            });
            acc.push(InlayHint {
                range: pat.syntax().text_range(),
                kind: InlayKind::ClosingParenthesis,
                label: ")".into(),
                tooltip: None,
            });
        }
        _ => (),
    }

    Some(())
}