]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/inlay_hints/binding_mode.rs
Move inlay hints tests into implementation modules
[rust.git] / crates / ide / src / inlay_hints / binding_mode.rs
1 use hir::{Mutability, Semantics};
2 use ide_db::RootDatabase;
3
4 use syntax::ast::{self, AstNode};
5
6 use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
7
8 pub(super) fn hints(
9     acc: &mut Vec<InlayHint>,
10     sema: &Semantics<'_, RootDatabase>,
11     config: &InlayHintsConfig,
12     pat: &ast::Pat,
13 ) -> Option<()> {
14     if !config.binding_mode_hints {
15         return None;
16     }
17
18     let outer_paren_pat = pat
19         .syntax()
20         .ancestors()
21         .skip(1)
22         .map_while(ast::Pat::cast)
23         .map_while(|pat| match pat {
24             ast::Pat::ParenPat(pat) => Some(pat),
25             _ => None,
26         })
27         .last();
28     let range =
29         outer_paren_pat.as_ref().map_or_else(|| pat.syntax(), |it| it.syntax()).text_range();
30     sema.pattern_adjustments(&pat).iter().for_each(|ty| {
31         let reference = ty.is_reference();
32         let mut_reference = ty.is_mutable_reference();
33         let r = match (reference, mut_reference) {
34             (true, true) => "&mut",
35             (true, false) => "&",
36             _ => return,
37         };
38         acc.push(InlayHint {
39             range,
40             kind: InlayKind::BindingModeHint,
41             label: r.to_string().into(),
42             tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
43         });
44     });
45     match pat {
46         ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
47             let bm = sema.binding_mode_of_pat(pat)?;
48             let bm = match bm {
49                 hir::BindingMode::Move => return None,
50                 hir::BindingMode::Ref(Mutability::Mut) => "ref mut",
51                 hir::BindingMode::Ref(Mutability::Shared) => "ref",
52             };
53             acc.push(InlayHint {
54                 range: pat.syntax().text_range(),
55                 kind: InlayKind::BindingModeHint,
56                 label: bm.to_string().into(),
57                 tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
58             });
59         }
60         ast::Pat::OrPat(pat) if outer_paren_pat.is_none() => {
61             acc.push(InlayHint {
62                 range: pat.syntax().text_range(),
63                 kind: InlayKind::OpeningParenthesis,
64                 label: "(".into(),
65                 tooltip: None,
66             });
67             acc.push(InlayHint {
68                 range: pat.syntax().text_range(),
69                 kind: InlayKind::ClosingParenthesis,
70                 label: ")".into(),
71                 tooltip: None,
72             });
73         }
74         _ => (),
75     }
76
77     Some(())
78 }
79
80 #[cfg(test)]
81 mod tests {
82     use crate::{
83         inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
84         InlayHintsConfig,
85     };
86
87     #[test]
88     fn hints_binding_modes() {
89         check_with_config(
90             InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG },
91             r#"
92 fn __(
93     (x,): (u32,),
94     (x,): &(u32,),
95   //^^^^&
96    //^ ref
97     (x,): &mut (u32,)
98   //^^^^&mut
99    //^ ref mut
100 ) {
101     let (x,) = (0,);
102     let (x,) = &(0,);
103       //^^^^ &
104        //^ ref
105     let (x,) = &mut (0,);
106       //^^^^ &mut
107        //^ ref mut
108     let &mut (x,) = &mut (0,);
109     let (ref mut x,) = &mut (0,);
110       //^^^^^^^^^^^^ &mut
111     let &mut (ref mut x,) = &mut (0,);
112     let (mut x,) = &mut (0,);
113       //^^^^^^^^ &mut
114     match (0,) {
115         (x,) => ()
116     }
117     match &(0,) {
118         (x,) | (x,) => (),
119       //^^^^^^^^^^^&
120        //^ ref
121               //^ ref
122       //^^^^^^^^^^^(
123       //^^^^^^^^^^^)
124         ((x,) | (x,)) => (),
125       //^^^^^^^^^^^^^&
126         //^ ref
127                //^ ref
128     }
129     match &mut (0,) {
130         (x,) => ()
131       //^^^^ &mut
132        //^ ref mut
133     }
134 }"#,
135         );
136     }
137 }