Omit type hints for enum variant bind pats

This commit is contained in:
Kirill Bulatov 2020-02-24 10:29:34 +03:00
parent cd01e72a9e
commit 7f3c0e8564

View file

@ -1,6 +1,6 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use hir::{HirDisplay, SourceAnalyzer, SourceBinder}; use hir::{Adt, HirDisplay, SourceAnalyzer, SourceBinder, Type};
use once_cell::unsync::Lazy; use once_cell::unsync::Lazy;
use ra_ide_db::RootDatabase; use ra_ide_db::RootDatabase;
use ra_prof::profile; use ra_prof::profile;
@ -57,12 +57,10 @@ fn get_inlay_hints(
get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it)); get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it));
}, },
ast::BindPat(it) => { ast::BindPat(it) => {
if should_not_display_type_hint(&it) { let pat = ast::Pat::from(it.clone());
return None;
}
let pat = ast::Pat::from(it);
let ty = analyzer.type_of_pat(db, &pat)?; let ty = analyzer.type_of_pat(db, &pat)?;
if ty.is_unknown() {
if should_not_display_type_hint(db, &it, &ty) {
return None; return None;
} }
@ -80,7 +78,24 @@ fn get_inlay_hints(
Some(()) Some(())
} }
fn should_not_display_type_hint(bind_pat: &ast::BindPat) -> bool { fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool {
if let Some(Adt::Enum(enum_data)) = pat_ty.as_adt() {
let pat_text = bind_pat.syntax().to_string();
enum_data
.variants(db)
.into_iter()
.map(|variant| variant.name(db).to_string())
.any(|enum_name| enum_name == pat_text)
} else {
false
}
}
fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool {
if pat_ty.is_unknown() {
return true;
}
for node in bind_pat.syntax().ancestors() { for node in bind_pat.syntax().ancestors() {
match_ast! { match_ast! {
match node { match node {
@ -90,6 +105,17 @@ fn should_not_display_type_hint(bind_pat: &ast::BindPat) -> bool {
ast::Param(it) => { ast::Param(it) => {
return it.ascribed_type().is_some() return it.ascribed_type().is_some()
}, },
ast::MatchArm(_it) => {
return pat_is_enum_variant(db, bind_pat, pat_ty);
},
ast::IfExpr(it) => {
return it.condition().and_then(|condition| condition.pat()).is_some()
&& pat_is_enum_variant(db, bind_pat, pat_ty);
},
ast::WhileExpr(it) => {
return it.condition().and_then(|condition| condition.pat()).is_some()
&& pat_is_enum_variant(db, bind_pat, pat_ty);
},
_ => (), _ => (),
} }
} }
@ -119,13 +145,12 @@ fn get_param_name_hints(
} else { } else {
0 0
}; };
let parameters = fn_signature.parameter_names.iter().skip(n_params_to_skip); let hints = fn_signature
.parameter_names
let hints = parameters .iter()
.skip(n_params_to_skip)
.zip(args) .zip(args)
.filter(|(param, arg)| { .filter(|(param, arg)| should_show_param_hint(&fn_signature, param, &arg))
should_show_param_hint(&fn_signature, param, &arg.syntax().to_string())
})
.map(|(param_name, arg)| InlayHint { .map(|(param_name, arg)| InlayHint {
range: arg.syntax().text_range(), range: arg.syntax().text_range(),
kind: InlayKind::ParameterHint, kind: InlayKind::ParameterHint,
@ -139,8 +164,9 @@ fn get_param_name_hints(
fn should_show_param_hint( fn should_show_param_hint(
fn_signature: &FunctionSignature, fn_signature: &FunctionSignature,
param_name: &str, param_name: &str,
argument_string: &str, argument: &ast::Expr,
) -> bool { ) -> bool {
let argument_string = argument.syntax().to_string();
if param_name.is_empty() || argument_string.ends_with(param_name) { if param_name.is_empty() || argument_string.ends_with(param_name) {
return false; return false;
} }
@ -440,75 +466,77 @@ struct Test {
b: u8, b: u8,
} }
fn main() { use CustomOption::*;
let test = CustomOption::Some(Test { a: CustomOption::Some(3), b: 1 });
if let CustomOption::None = &test {};
if let test = &test {};
if let CustomOption::Some(test) = &test {};
if let CustomOption::Some(Test { a, b }) = &test {};
if let CustomOption::Some(Test { a: x, b: y }) = &test {};
if let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {};
if let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {};
if let CustomOption::Some(Test { b: y, .. }) = &test {};
if test == CustomOption::None {} fn main() {
let test = Some(Test { a: Some(3), b: 1 });
if let None = &test {};
if let test = &test {};
if let Some(test) = &test {};
if let Some(Test { a, b }) = &test {};
if let Some(Test { a: x, b: y }) = &test {};
if let Some(Test { a: Some(x), b: y }) = &test {};
if let Some(Test { a: None, b: y }) = &test {};
if let Some(Test { b: y, .. }) = &test {};
if test == None {}
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [166; 170), range: [188; 192),
kind: TypeHint, kind: TypeHint,
label: "CustomOption<Test>", label: "CustomOption<Test>",
}, },
InlayHint { InlayHint {
range: [287; 291), range: [267; 271),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<Test>", label: "&CustomOption<Test>",
}, },
InlayHint { InlayHint {
range: [334; 338), range: [300; 304),
kind: TypeHint, kind: TypeHint,
label: "&Test", label: "&Test",
}, },
InlayHint { InlayHint {
range: [389; 390), range: [341; 342),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<u32>", label: "&CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [392; 393), range: [344; 345),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [449; 450), range: [387; 388),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<u32>", label: "&CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [455; 456), range: [393; 394),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [531; 532), range: [441; 442),
kind: TypeHint, kind: TypeHint,
label: "&u32", label: "&u32",
}, },
InlayHint { InlayHint {
range: [538; 539), range: [448; 449),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [618; 619), range: [500; 501),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [675; 676), range: [543; 544),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
@ -533,75 +561,77 @@ struct Test {
b: u8, b: u8,
} }
fn main() { use CustomOption::*;
let test = CustomOption::Some(Test { a: CustomOption::Some(3), b: 1 });
while let CustomOption::None = &test {};
while let test = &test {};
while let CustomOption::Some(test) = &test {};
while let CustomOption::Some(Test { a, b }) = &test {};
while let CustomOption::Some(Test { a: x, b: y }) = &test {};
while let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {};
while let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {};
while let CustomOption::Some(Test { b: y, .. }) = &test {};
while test == CustomOption::None {} fn main() {
let test = Some(Test { a: Some(3), b: 1 });
while let None = &test {};
while let test = &test {};
while let Some(test) = &test {};
while let Some(Test { a, b }) = &test {};
while let Some(Test { a: x, b: y }) = &test {};
while let Some(Test { a: Some(x), b: y }) = &test {};
while let Some(Test { a: None, b: y }) = &test {};
while let Some(Test { b: y, .. }) = &test {};
while test == None {}
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [166; 170), range: [188; 192),
kind: TypeHint, kind: TypeHint,
label: "CustomOption<Test>", label: "CustomOption<Test>",
}, },
InlayHint { InlayHint {
range: [293; 297), range: [273; 277),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<Test>", label: "&CustomOption<Test>",
}, },
InlayHint { InlayHint {
range: [343; 347), range: [309; 313),
kind: TypeHint, kind: TypeHint,
label: "&Test", label: "&Test",
}, },
InlayHint { InlayHint {
range: [401; 402), range: [353; 354),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<u32>", label: "&CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [404; 405), range: [356; 357),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [464; 465), range: [402; 403),
kind: TypeHint, kind: TypeHint,
label: "&CustomOption<u32>", label: "&CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [470; 471), range: [408; 409),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [549; 550), range: [459; 460),
kind: TypeHint, kind: TypeHint,
label: "&u32", label: "&u32",
}, },
InlayHint { InlayHint {
range: [556; 557), range: [466; 467),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [639; 640), range: [521; 522),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
InlayHint { InlayHint {
range: [699; 700), range: [567; 568),
kind: TypeHint, kind: TypeHint,
label: "&u8", label: "&u8",
}, },
@ -626,16 +656,18 @@ struct Test {
b: u8, b: u8,
} }
use CustomOption::*;
fn main() { fn main() {
match CustomOption::Some(Test { a: CustomOption::Some(3), b: 1 }) { match Some(Test { a: Some(3), b: 1 }) {
CustomOption::None => (), None => (),
test => (), test => (),
CustomOption::Some(test) => (), Some(test) => (),
CustomOption::Some(Test { a, b }) => (), Some(Test { a, b }) => (),
CustomOption::Some(Test { a: x, b: y }) => (), Some(Test { a: x, b: y }) => (),
CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) => (), Some(Test { a: Some(x), b: y }) => (),
CustomOption::Some(Test { a: CustomOption::None, b: y }) => (), Some(Test { a: None, b: y }) => (),
CustomOption::Some(Test { b: y, .. }) => (), Some(Test { b: y, .. }) => (),
_ => {} _ => {}
} }
}"#, }"#,
@ -644,52 +676,52 @@ fn main() {
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [272; 276), range: [252; 256),
kind: TypeHint, kind: TypeHint,
label: "CustomOption<Test>", label: "CustomOption<Test>",
}, },
InlayHint { InlayHint {
range: [311; 315), range: [277; 281),
kind: TypeHint, kind: TypeHint,
label: "Test", label: "Test",
}, },
InlayHint { InlayHint {
range: [358; 359), range: [310; 311),
kind: TypeHint, kind: TypeHint,
label: "CustomOption<u32>", label: "CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [361; 362), range: [313; 314),
kind: TypeHint, kind: TypeHint,
label: "u8", label: "u8",
}, },
InlayHint { InlayHint {
range: [410; 411), range: [348; 349),
kind: TypeHint, kind: TypeHint,
label: "CustomOption<u32>", label: "CustomOption<u32>",
}, },
InlayHint { InlayHint {
range: [416; 417), range: [354; 355),
kind: TypeHint, kind: TypeHint,
label: "u8", label: "u8",
}, },
InlayHint { InlayHint {
range: [484; 485), range: [394; 395),
kind: TypeHint, kind: TypeHint,
label: "u32", label: "u32",
}, },
InlayHint { InlayHint {
range: [491; 492), range: [401; 402),
kind: TypeHint, kind: TypeHint,
label: "u8", label: "u8",
}, },
InlayHint { InlayHint {
range: [563; 564), range: [445; 446),
kind: TypeHint, kind: TypeHint,
label: "u8", label: "u8",
}, },
InlayHint { InlayHint {
range: [612; 613), range: [480; 481),
kind: TypeHint, kind: TypeHint,
label: "u8", label: "u8",
}, },
@ -743,6 +775,7 @@ enum CustomOption<T> {
None, None,
Some(T), Some(T),
} }
use CustomOption::*;
struct FileId {} struct FileId {}
struct SmolStr {} struct SmolStr {}
@ -791,11 +824,11 @@ fn main() {
Test::from_syntax( Test::from_syntax(
FileId {}, FileId {},
"impl".into(), "impl".into(),
CustomOption::None, None,
TextRange {}, TextRange {},
SyntaxKind {}, SyntaxKind {},
CustomOption::None, None,
CustomOption::None, None,
); );
}"#, }"#,
); );
@ -803,77 +836,77 @@ fn main() {
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [777; 788), range: [798; 809),
kind: TypeHint, kind: TypeHint,
label: "i32", label: "i32",
}, },
InlayHint { InlayHint {
range: [821; 822), range: [842; 843),
kind: ParameterHint, kind: ParameterHint,
label: "foo", label: "foo",
}, },
InlayHint { InlayHint {
range: [824; 825), range: [845; 846),
kind: ParameterHint, kind: ParameterHint,
label: "bar", label: "bar",
}, },
InlayHint { InlayHint {
range: [827; 834), range: [848; 855),
kind: ParameterHint, kind: ParameterHint,
label: "msg", label: "msg",
}, },
InlayHint { InlayHint {
range: [839; 850), range: [860; 871),
kind: ParameterHint, kind: ParameterHint,
label: "last", label: "last",
}, },
InlayHint { InlayHint {
range: [893; 896), range: [914; 917),
kind: ParameterHint, kind: ParameterHint,
label: "param", label: "param",
}, },
InlayHint { InlayHint {
range: [916; 918), range: [937; 939),
kind: ParameterHint, kind: ParameterHint,
label: "&self", label: "&self",
}, },
InlayHint { InlayHint {
range: [920; 924), range: [941; 945),
kind: ParameterHint, kind: ParameterHint,
label: "param", label: "param",
}, },
InlayHint { InlayHint {
range: [959; 968), range: [980; 989),
kind: ParameterHint, kind: ParameterHint,
label: "file_id", label: "file_id",
}, },
InlayHint { InlayHint {
range: [978; 991), range: [999; 1012),
kind: ParameterHint, kind: ParameterHint,
label: "name", label: "name",
}, },
InlayHint { InlayHint {
range: [1001; 1019), range: [1022; 1026),
kind: ParameterHint, kind: ParameterHint,
label: "focus_range", label: "focus_range",
}, },
InlayHint { InlayHint {
range: [1029; 1041), range: [1036; 1048),
kind: ParameterHint, kind: ParameterHint,
label: "full_range", label: "full_range",
}, },
InlayHint { InlayHint {
range: [1051; 1064), range: [1058; 1071),
kind: ParameterHint, kind: ParameterHint,
label: "kind", label: "kind",
}, },
InlayHint { InlayHint {
range: [1074; 1092), range: [1081; 1085),
kind: ParameterHint, kind: ParameterHint,
label: "docs", label: "docs",
}, },
InlayHint { InlayHint {
range: [1102; 1120), range: [1095; 1099),
kind: ParameterHint, kind: ParameterHint,
label: "description", label: "description",
}, },