use crate::def::DefId;
use crate::types::{
CallableShapeId, ConditionalTypeId, FunctionShapeId, IntrinsicKind, LiteralValue, MappedTypeId,
ObjectShapeId, OrderedFloat, StringIntrinsicKind, TemplateLiteralId, TupleListId,
TypeApplicationId, TypeListId, TypeParamInfo,
};
use crate::visitor::TypeVisitor;
use crate::{SymbolRef, TypeData, TypeDatabase, TypeId};
use tsz_common::interner::Atom;
struct TypeDataDataVisitor<F, T>
where
F: Fn(&TypeData) -> Option<T>,
{
extractor: F,
}
impl<F, T> TypeDataDataVisitor<F, T>
where
F: Fn(&TypeData) -> Option<T>,
{
const fn new(extractor: F) -> Self {
Self { extractor }
}
}
impl<F, T> TypeVisitor for TypeDataDataVisitor<F, T>
where
F: Fn(&TypeData) -> Option<T>,
{
type Output = Option<T>;
fn visit_type_key(&mut self, _types: &dyn TypeDatabase, type_key: &TypeData) -> Self::Output {
(self.extractor)(type_key)
}
fn visit_intrinsic(&mut self, _kind: IntrinsicKind) -> Self::Output {
Self::default_output()
}
fn visit_literal(&mut self, _value: &LiteralValue) -> Self::Output {
Self::default_output()
}
fn default_output() -> Self::Output {
None
}
}
fn extract_type_data<T, F>(types: &dyn TypeDatabase, type_id: TypeId, extractor: F) -> Option<T>
where
F: Fn(&TypeData) -> Option<T>,
{
let mut visitor = TypeDataDataVisitor::new(extractor);
visitor.visit_type(types, type_id)
}
pub fn union_list_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeListId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Union(list_id) => Some(*list_id),
_ => None,
})
}
pub fn intersection_list_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeListId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Intersection(list_id) => Some(*list_id),
_ => None,
})
}
pub fn object_shape_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<ObjectShapeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Object(shape_id) => Some(*shape_id),
_ => None,
})
}
pub fn object_with_index_shape_id(
types: &dyn TypeDatabase,
type_id: TypeId,
) -> Option<ObjectShapeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::ObjectWithIndex(shape_id) => Some(*shape_id),
_ => None,
})
}
pub fn array_element_type(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Array(element) => Some(*element),
_ => None,
})
}
pub fn tuple_list_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TupleListId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Tuple(list_id) => Some(*list_id),
_ => None,
})
}
pub fn intrinsic_kind(types: &dyn TypeDatabase, type_id: TypeId) -> Option<IntrinsicKind> {
extract_type_data(types, type_id, |key| match key {
TypeData::Intrinsic(kind) => Some(*kind),
_ => None,
})
}
pub fn literal_value(types: &dyn TypeDatabase, type_id: TypeId) -> Option<LiteralValue> {
extract_type_data(types, type_id, |key| match key {
TypeData::Literal(value) => Some(value.clone()),
_ => None,
})
}
pub fn literal_string(types: &dyn TypeDatabase, type_id: TypeId) -> Option<Atom> {
match literal_value(types, type_id) {
Some(LiteralValue::String(atom)) => Some(atom),
_ => None,
}
}
pub fn literal_number(types: &dyn TypeDatabase, type_id: TypeId) -> Option<OrderedFloat> {
match literal_value(types, type_id) {
Some(LiteralValue::Number(value)) => Some(value),
_ => None,
}
}
pub fn template_literal_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TemplateLiteralId> {
extract_type_data(types, type_id, |key| match key {
TypeData::TemplateLiteral(list_id) => Some(*list_id),
_ => None,
})
}
pub fn type_param_info(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeParamInfo> {
extract_type_data(types, type_id, |key| match key {
TypeData::TypeParameter(info) | TypeData::Infer(info) => Some(info.clone()),
_ => None,
})
}
pub fn ref_symbol(types: &dyn TypeDatabase, type_id: TypeId) -> Option<SymbolRef> {
extract_type_data(types, type_id, |key| match key {
TypeData::Lazy(_def_id) => {
None
}
_ => None,
})
}
pub fn lazy_def_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<DefId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Lazy(def_id) => Some(*def_id),
_ => None,
})
}
pub fn bound_parameter_index(types: &dyn TypeDatabase, type_id: TypeId) -> Option<u32> {
extract_type_data(types, type_id, |key| match key {
TypeData::BoundParameter(index) => Some(*index),
_ => None,
})
}
pub fn recursive_index(types: &dyn TypeDatabase, type_id: TypeId) -> Option<u32> {
extract_type_data(types, type_id, |key| match key {
TypeData::Recursive(index) => Some(*index),
_ => None,
})
}
pub fn is_enum_type(types: &dyn TypeDatabase, type_id: TypeId) -> bool {
matches!(types.lookup(type_id), Some(TypeData::Enum(_, _)))
}
pub fn enum_components(types: &dyn TypeDatabase, type_id: TypeId) -> Option<(DefId, TypeId)> {
extract_type_data(types, type_id, |key| match key {
TypeData::Enum(def_id, member_type) => Some((*def_id, *member_type)),
_ => None,
})
}
pub fn application_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeApplicationId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Application(app_id) => Some(*app_id),
_ => None,
})
}
pub fn mapped_type_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<MappedTypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Mapped(mapped_id) => Some(*mapped_id),
_ => None,
})
}
pub fn conditional_type_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<ConditionalTypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Conditional(cond_id) => Some(*cond_id),
_ => None,
})
}
pub fn index_access_parts(types: &dyn TypeDatabase, type_id: TypeId) -> Option<(TypeId, TypeId)> {
extract_type_data(types, type_id, |key| match key {
TypeData::IndexAccess(object_type, index_type) => Some((*object_type, *index_type)),
_ => None,
})
}
pub fn type_query_symbol(types: &dyn TypeDatabase, type_id: TypeId) -> Option<SymbolRef> {
extract_type_data(types, type_id, |key| match key {
TypeData::TypeQuery(sym_ref) => Some(*sym_ref),
_ => None,
})
}
pub fn keyof_inner_type(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::KeyOf(inner) => Some(*inner),
_ => None,
})
}
pub fn readonly_inner_type(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::ReadonlyType(inner) => Some(*inner),
_ => None,
})
}
pub fn no_infer_inner_type(types: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::NoInfer(inner) => Some(*inner),
_ => None,
})
}
pub fn string_intrinsic_components(
types: &dyn TypeDatabase,
type_id: TypeId,
) -> Option<(StringIntrinsicKind, TypeId)> {
extract_type_data(types, type_id, |key| match key {
TypeData::StringIntrinsic { kind, type_arg } => Some((*kind, *type_arg)),
_ => None,
})
}
pub fn unique_symbol_ref(types: &dyn TypeDatabase, type_id: TypeId) -> Option<SymbolRef> {
extract_type_data(types, type_id, |key| match key {
TypeData::UniqueSymbol(sym_ref) => Some(*sym_ref),
_ => None,
})
}
pub fn module_namespace_symbol_ref(types: &dyn TypeDatabase, type_id: TypeId) -> Option<SymbolRef> {
extract_type_data(types, type_id, |key| match key {
TypeData::ModuleNamespace(sym_ref) => Some(*sym_ref),
_ => None,
})
}
pub fn is_this_type(types: &dyn TypeDatabase, type_id: TypeId) -> bool {
extract_type_data(types, type_id, |key| match key {
TypeData::ThisType => Some(true),
_ => None,
})
.unwrap_or(false)
}
pub fn is_error_type(types: &dyn TypeDatabase, type_id: TypeId) -> bool {
extract_type_data(types, type_id, |key| match key {
TypeData::Error => Some(true),
_ => None,
})
.unwrap_or(false)
}
pub fn function_shape_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<FunctionShapeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Function(shape_id) => Some(*shape_id),
_ => None,
})
}
pub fn callable_shape_id(types: &dyn TypeDatabase, type_id: TypeId) -> Option<CallableShapeId> {
extract_type_data(types, type_id, |key| match key {
TypeData::Callable(shape_id) => Some(*shape_id),
_ => None,
})
}