Simplify bind pat filtering
This commit is contained in:
parent
730286b523
commit
edd60f7b0d
@ -3,7 +3,7 @@
|
|||||||
//! fn f(a: i32, b: i32) -> i32 { a + b }
|
//! fn f(a: i32, b: i32) -> i32 { a + b }
|
||||||
//! let _x /* i32 */= f(4, 4);
|
//! let _x /* i32 */= f(4, 4);
|
||||||
//! ```
|
//! ```
|
||||||
use hir::{Semantics, TypeInfo};
|
use hir::Semantics;
|
||||||
use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
|
use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -28,11 +28,41 @@ pub(super) fn hints(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let parent = pat.syntax().parent()?;
|
||||||
|
let type_ascriptable = match_ast! {
|
||||||
|
match parent {
|
||||||
|
ast::Param(it) => {
|
||||||
|
if it.ty().is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(it.colon_token())
|
||||||
|
},
|
||||||
|
ast::LetStmt(it) => {
|
||||||
|
if config.hide_closure_initialization_hints {
|
||||||
|
if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
|
||||||
|
if closure_has_block_body(&closure) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if it.ty().is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(it.colon_token())
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let descended = sema.descend_node_into_attributes(pat.clone()).pop();
|
let descended = sema.descend_node_into_attributes(pat.clone()).pop();
|
||||||
let desc_pat = descended.as_ref().unwrap_or(pat);
|
let desc_pat = descended.as_ref().unwrap_or(pat);
|
||||||
let ty = sema.type_of_binding_in_pat(desc_pat)?;
|
let ty = sema.type_of_binding_in_pat(desc_pat)?;
|
||||||
|
|
||||||
if should_not_display_type_hint(sema, config, pat, &ty) {
|
if ty.is_unknown() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if sema.resolve_bind_pat_to_const(pat).is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,11 +74,6 @@ pub(super) fn hints(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_ascriptable = desc_pat.syntax().parent().and_then(|it| {
|
|
||||||
ast::LetStmt::cast(it.clone())
|
|
||||||
.map(|it| it.colon_token())
|
|
||||||
.or_else(|| ast::Param::cast(it).map(|it| it.colon_token()))
|
|
||||||
});
|
|
||||||
let text_edit = if let Some(colon_token) = &type_ascriptable {
|
let text_edit = if let Some(colon_token) = &type_ascriptable {
|
||||||
ty_to_text_edit(
|
ty_to_text_edit(
|
||||||
sema,
|
sema,
|
||||||
@ -89,57 +114,6 @@ pub(super) fn hints(
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_not_display_type_hint(
|
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
|
||||||
config: &InlayHintsConfig,
|
|
||||||
bind_pat: &ast::IdentPat,
|
|
||||||
pat_ty: &hir::Type,
|
|
||||||
) -> bool {
|
|
||||||
let db = sema.db;
|
|
||||||
|
|
||||||
if pat_ty.is_unknown() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if sema.resolve_bind_pat_to_const(bind_pat).is_some() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for node in bind_pat.syntax().ancestors() {
|
|
||||||
match_ast! {
|
|
||||||
match node {
|
|
||||||
ast::LetStmt(it) => {
|
|
||||||
if config.hide_closure_initialization_hints {
|
|
||||||
if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
|
|
||||||
if closure_has_block_body(&closure) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return it.ty().is_some()
|
|
||||||
},
|
|
||||||
// FIXME: We might wanna show type hints in parameters for non-top level patterns as well
|
|
||||||
ast::Param(it) => return it.ty().is_some(),
|
|
||||||
ast::MatchArm(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
|
|
||||||
ast::LetExpr(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
|
|
||||||
ast::IfExpr(_) => return false,
|
|
||||||
ast::WhileExpr(_) => return false,
|
|
||||||
ast::ForExpr(it) => {
|
|
||||||
// We *should* display hint only if user provided "in {expr}" and we know the type of expr (and it's not unit).
|
|
||||||
// Type of expr should be iterable.
|
|
||||||
return it.in_token().is_none() ||
|
|
||||||
it.iterable()
|
|
||||||
.and_then(|iterable_expr| sema.type_of_expr(&iterable_expr))
|
|
||||||
.map(TypeInfo::original)
|
|
||||||
.map_or(true, |iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit())
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_named_constructor(
|
fn is_named_constructor(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
pat: &ast::IdentPat,
|
pat: &ast::IdentPat,
|
||||||
@ -193,19 +167,6 @@ fn is_named_constructor(
|
|||||||
(ctor_name == ty_name).then_some(())
|
(ctor_name == ty_name).then_some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir::Type) -> bool {
|
|
||||||
if let Some(hir::Adt::Enum(enum_data)) = pat_ty.as_adt() {
|
|
||||||
let pat_text = bind_pat.to_string();
|
|
||||||
enum_data
|
|
||||||
.variants(db)
|
|
||||||
.into_iter()
|
|
||||||
.map(|variant| variant.name(db).to_smol_str())
|
|
||||||
.any(|enum_name| enum_name == pat_text)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
// This module also contains tests for super::closure_ret
|
// This module also contains tests for super::closure_ret
|
||||||
|
Loading…
Reference in New Issue
Block a user