1 //! Implementation of "binding mode" inlay hints:
3 //! let /* & */ (/* ref */ x,) = &(0,);
5 use hir::{Mutability, Semantics};
6 use ide_db::RootDatabase;
8 use syntax::ast::{self, AstNode};
10 use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
13 acc: &mut Vec<InlayHint>,
14 sema: &Semantics<'_, RootDatabase>,
15 config: &InlayHintsConfig,
18 if !config.binding_mode_hints {
22 let outer_paren_pat = pat
26 .map_while(ast::Pat::cast)
27 .map_while(|pat| match pat {
28 ast::Pat::ParenPat(pat) => Some(pat),
33 outer_paren_pat.as_ref().map_or_else(|| pat.syntax(), |it| it.syntax()).text_range();
34 sema.pattern_adjustments(&pat).iter().for_each(|ty| {
35 let reference = ty.is_reference();
36 let mut_reference = ty.is_mutable_reference();
37 let r = match (reference, mut_reference) {
38 (true, true) => "&mut",
44 kind: InlayKind::BindingModeHint,
45 label: r.to_string().into(),
46 tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
50 ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
51 let bm = sema.binding_mode_of_pat(pat)?;
53 hir::BindingMode::Move => return None,
54 hir::BindingMode::Ref(Mutability::Mut) => "ref mut",
55 hir::BindingMode::Ref(Mutability::Shared) => "ref",
58 range: pat.syntax().text_range(),
59 kind: InlayKind::BindingModeHint,
60 label: bm.to_string().into(),
61 tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
64 ast::Pat::OrPat(pat) if outer_paren_pat.is_none() => {
66 range: pat.syntax().text_range(),
67 kind: InlayKind::OpeningParenthesis,
72 range: pat.syntax().text_range(),
73 kind: InlayKind::ClosingParenthesis,
87 inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
92 fn hints_binding_modes() {
94 InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG },
109 let (x,) = &mut (0,);
112 let &mut (x,) = &mut (0,);
113 let (ref mut x,) = &mut (0,);
115 let &mut (ref mut x,) = &mut (0,);
116 let (mut x,) = &mut (0,);