use crate::{TypeData, TypeDatabase, TypeId};
#[derive(Debug, Clone)]
pub enum ExcessPropertiesKind {
Object(crate::types::ObjectShapeId),
ObjectWithIndex(crate::types::ObjectShapeId),
Union(Vec<TypeId>),
Intersection(Vec<TypeId>),
NotObject,
}
pub fn classify_for_excess_properties(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> ExcessPropertiesKind {
let Some(key) = db.lookup(type_id) else {
return ExcessPropertiesKind::NotObject;
};
match key {
TypeData::Object(shape_id) => ExcessPropertiesKind::Object(shape_id),
TypeData::ObjectWithIndex(shape_id) => ExcessPropertiesKind::ObjectWithIndex(shape_id),
TypeData::Union(list_id) => {
let members = db.type_list(list_id);
ExcessPropertiesKind::Union(members.to_vec())
}
TypeData::Intersection(list_id) => {
let members = db.type_list(list_id);
ExcessPropertiesKind::Intersection(members.to_vec())
}
_ => ExcessPropertiesKind::NotObject,
}
}
#[derive(Debug, Clone)]
pub enum ConstructorAccessKind {
SymbolRef(crate::types::SymbolRef),
Application(crate::types::TypeApplicationId),
Other,
}
pub fn classify_for_constructor_access(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> ConstructorAccessKind {
let Some(key) = db.lookup(type_id) else {
return ConstructorAccessKind::Other;
};
match key {
TypeData::TypeQuery(sym_ref) => ConstructorAccessKind::SymbolRef(sym_ref),
TypeData::Application(app_id) => ConstructorAccessKind::Application(app_id),
_ => ConstructorAccessKind::Other,
}
}
#[derive(Debug, Clone)]
pub enum AssignabilityEvalKind {
Application,
NeedsEnvEval,
Resolved,
}
pub fn classify_for_assignability_eval(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> AssignabilityEvalKind {
let Some(key) = db.lookup(type_id) else {
return AssignabilityEvalKind::Resolved;
};
match key {
TypeData::Application(_) | TypeData::Lazy(_) => AssignabilityEvalKind::Application,
TypeData::IndexAccess(_, _)
| TypeData::KeyOf(_)
| TypeData::Mapped(_)
| TypeData::Conditional(_) => AssignabilityEvalKind::NeedsEnvEval,
_ => AssignabilityEvalKind::Resolved,
}
}
#[derive(Debug, Clone)]
pub enum BindingElementTypeKind {
Array(TypeId),
Tuple(crate::types::TupleListId),
Object(crate::types::ObjectShapeId),
Other,
}
pub fn classify_for_binding_element(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> BindingElementTypeKind {
let Some(key) = db.lookup(type_id) else {
return BindingElementTypeKind::Other;
};
match key {
TypeData::Array(elem) => BindingElementTypeKind::Array(elem),
TypeData::Tuple(list_id) => BindingElementTypeKind::Tuple(list_id),
TypeData::Object(shape_id) => BindingElementTypeKind::Object(shape_id),
_ => BindingElementTypeKind::Other,
}
}
pub fn get_lazy_def_id(db: &dyn TypeDatabase, type_id: TypeId) -> Option<crate::def::DefId> {
match db.lookup(type_id) {
Some(TypeData::Lazy(def_id)) => Some(def_id),
_ => None,
}
}
pub fn get_def_id(db: &dyn TypeDatabase, type_id: TypeId) -> Option<crate::def::DefId> {
match db.lookup(type_id) {
Some(TypeData::Lazy(def_id)) => Some(def_id),
_ => None,
}
}
pub fn get_type_identity(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> (Option<crate::types::SymbolRef>, Option<crate::def::DefId>) {
match db.lookup(type_id) {
Some(TypeData::Lazy(def_id)) => (None, Some(def_id)),
_ => (None, None),
}
}
pub fn get_enum_components(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> Option<(crate::def::DefId, TypeId)> {
match db.lookup(type_id) {
Some(TypeData::Enum(def_id, member_type)) => Some((def_id, member_type)),
_ => None,
}
}
pub fn get_mapped_type_id(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> Option<crate::types::MappedTypeId> {
match db.lookup(type_id) {
Some(TypeData::Mapped(mapped_id)) => Some(mapped_id),
_ => None,
}
}
pub fn get_conditional_type_id(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> Option<crate::types::ConditionalTypeId> {
match db.lookup(type_id) {
Some(TypeData::Conditional(cond_id)) => Some(cond_id),
_ => None,
}
}
pub fn get_keyof_inner(db: &dyn TypeDatabase, type_id: TypeId) -> Option<TypeId> {
match db.lookup(type_id) {
Some(TypeData::KeyOf(inner)) => Some(inner),
_ => None,
}
}
#[derive(Debug, Clone)]
pub enum SymbolResolutionTraversalKind {
Application {
app_id: crate::types::TypeApplicationId,
base: TypeId,
args: Vec<TypeId>,
},
Lazy(crate::def::DefId),
TypeParameter {
constraint: Option<TypeId>,
default: Option<TypeId>,
},
Members(Vec<TypeId>),
Function(crate::types::FunctionShapeId),
Callable(crate::types::CallableShapeId),
Object(crate::types::ObjectShapeId),
Array(TypeId),
Tuple(crate::types::TupleListId),
Conditional(crate::types::ConditionalTypeId),
Mapped(crate::types::MappedTypeId),
Readonly(TypeId),
IndexAccess { object: TypeId, index: TypeId },
KeyOf(TypeId),
Terminal,
}
pub fn classify_for_symbol_resolution_traversal(
db: &dyn TypeDatabase,
type_id: TypeId,
) -> SymbolResolutionTraversalKind {
let Some(key) = db.lookup(type_id) else {
return SymbolResolutionTraversalKind::Terminal;
};
match key {
TypeData::Application(app_id) => {
let app = db.type_application(app_id);
SymbolResolutionTraversalKind::Application {
app_id,
base: app.base,
args: app.args.clone(),
}
}
TypeData::Lazy(def_id) => SymbolResolutionTraversalKind::Lazy(def_id),
TypeData::TypeParameter(param) | TypeData::Infer(param) => {
SymbolResolutionTraversalKind::TypeParameter {
constraint: param.constraint,
default: param.default,
}
}
TypeData::Union(members_id) | TypeData::Intersection(members_id) => {
let members = db.type_list(members_id);
SymbolResolutionTraversalKind::Members(members.to_vec())
}
TypeData::Function(shape_id) => SymbolResolutionTraversalKind::Function(shape_id),
TypeData::Callable(shape_id) => SymbolResolutionTraversalKind::Callable(shape_id),
TypeData::Object(shape_id) | TypeData::ObjectWithIndex(shape_id) => {
SymbolResolutionTraversalKind::Object(shape_id)
}
TypeData::Array(elem) => SymbolResolutionTraversalKind::Array(elem),
TypeData::Tuple(elems_id) => SymbolResolutionTraversalKind::Tuple(elems_id),
TypeData::Conditional(cond_id) => SymbolResolutionTraversalKind::Conditional(cond_id),
TypeData::Mapped(mapped_id) => SymbolResolutionTraversalKind::Mapped(mapped_id),
TypeData::ReadonlyType(inner) => SymbolResolutionTraversalKind::Readonly(inner),
TypeData::IndexAccess(obj, idx) => SymbolResolutionTraversalKind::IndexAccess {
object: obj,
index: idx,
},
TypeData::KeyOf(inner) => SymbolResolutionTraversalKind::KeyOf(inner),
_ => SymbolResolutionTraversalKind::Terminal,
}
}
#[derive(Debug, Clone)]
pub enum InterfaceMergeKind {
Callable(crate::types::CallableShapeId),
Object(crate::types::ObjectShapeId),
ObjectWithIndex(crate::types::ObjectShapeId),
Intersection,
Other,
}
pub fn classify_for_interface_merge(db: &dyn TypeDatabase, type_id: TypeId) -> InterfaceMergeKind {
let Some(key) = db.lookup(type_id) else {
return InterfaceMergeKind::Other;
};
match key {
TypeData::Callable(shape_id) => InterfaceMergeKind::Callable(shape_id),
TypeData::Object(shape_id) => InterfaceMergeKind::Object(shape_id),
TypeData::ObjectWithIndex(shape_id) => InterfaceMergeKind::ObjectWithIndex(shape_id),
TypeData::Intersection(_) => InterfaceMergeKind::Intersection,
TypeData::BoundParameter(_)
| TypeData::Intrinsic(_)
| TypeData::Literal(_)
| TypeData::Union(_)
| TypeData::Array(_)
| TypeData::Tuple(_)
| TypeData::Function(_)
| TypeData::TypeParameter(_)
| TypeData::Infer(_)
| TypeData::Lazy(_)
| TypeData::Recursive(_)
| TypeData::Application(_)
| TypeData::Conditional(_)
| TypeData::Mapped(_)
| TypeData::IndexAccess(_, _)
| TypeData::KeyOf(_)
| TypeData::TemplateLiteral(_)
| TypeData::UniqueSymbol(_)
| TypeData::ThisType
| TypeData::TypeQuery(_)
| TypeData::ReadonlyType(_)
| TypeData::NoInfer(_)
| TypeData::StringIntrinsic { .. }
| TypeData::ModuleNamespace(_)
| TypeData::Error
| TypeData::Enum(_, _) => InterfaceMergeKind::Other,
}
}
#[derive(Debug, Clone)]
pub enum AugmentationTargetKind {
Object(crate::types::ObjectShapeId),
ObjectWithIndex(crate::types::ObjectShapeId),
Callable(crate::types::CallableShapeId),
Other,
}
pub fn classify_for_augmentation(db: &dyn TypeDatabase, type_id: TypeId) -> AugmentationTargetKind {
let Some(key) = db.lookup(type_id) else {
return AugmentationTargetKind::Other;
};
match key {
TypeData::Object(shape_id) => AugmentationTargetKind::Object(shape_id),
TypeData::ObjectWithIndex(shape_id) => AugmentationTargetKind::ObjectWithIndex(shape_id),
TypeData::Callable(shape_id) => AugmentationTargetKind::Callable(shape_id),
_ => AugmentationTargetKind::Other,
}
}