//! This module contains structures for filtering the expected types.
//! Use case for structures in this module is, for example, situation when you need to process
//! only certain `Enum`s.
use std::iter;
use hir::Semantics;
use syntax::ast::{self, Pat, make};
use crate::RootDatabase;
/// Enum types that implement `std::ops::Try` trait.
#[derive(Clone, Copy, Debug)]
pub enum TryEnum {
Result,
Option,
}
impl TryEnum {
const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result];
/// Returns `Some(..)` if the provided `ty.strip_references()` is an enum that implements `std::ops::Try`.
pub fn from_ty(sema: &Semantics<'_, RootDatabase>, ty: &hir::Type<'_>) -> Option<TryEnum> {
Self::from_ty_without_strip(sema, &ty.strip_references())
}
/// Returns `Some(..)` if the provided type is an enum that implements `std::ops::Try`.
pub fn from_ty_without_strip(
sema: &Semantics<'_, RootDatabase>,
ty: &hir::Type<'_>,
) -> Option<TryEnum> {
let enum_ = match ty.as_adt() {
Some(hir::Adt::Enum(it)) => it,
_ => return None,
};
TryEnum::ALL.iter().find_map(|&var| {
if enum_.name(sema.db).as_str() == var.type_name() {
return Some(var);
}
None
})
}
pub fn happy_case(self) -> &'static str {
match self {
TryEnum::Result => "Ok",
TryEnum::Option => "Some",
}
}
pub fn sad_pattern(self) -> ast::Pat {
match self {
TryEnum::Result => make::tuple_struct_pat(
make::ext::ident_path("Err"),
iter::once(make::wildcard_pat().into()),
)
.into(),
TryEnum::Option => make::ext::simple_ident_pat(make::name("None")).into(),
}
}
pub fn happy_pattern(self, pat: Pat) -> ast::Pat {
match self {
TryEnum::Result => {
make::tuple_struct_pat(make::ext::ident_path("Ok"), iter::once(pat)).into()
}
TryEnum::Option => {
make::tuple_struct_pat(make::ext::ident_path("Some"), iter::once(pat)).into()
}
}
}
pub fn happy_pattern_wildcard(self) -> ast::Pat {
match self {
TryEnum::Result => make::tuple_struct_pat(
make::ext::ident_path("Ok"),
iter::once(make::wildcard_pat().into()),
)
.into(),
TryEnum::Option => make::tuple_struct_pat(
make::ext::ident_path("Some"),
iter::once(make::wildcard_pat().into()),
)
.into(),
}
}
fn type_name(self) -> &'static str {
match self {
TryEnum::Result => "Result",
TryEnum::Option => "Option",
}
}
}