tsz_solver/type_queries/
iterable.rs1use crate::{TypeData, TypeDatabase, TypeId};
7
8#[derive(Debug, Clone)]
14pub enum IterableTypeKind {
15 Tuple(Vec<crate::types::TupleElement>),
17 Array(TypeId),
19 Other,
21}
22
23pub fn classify_iterable_type(db: &dyn TypeDatabase, type_id: TypeId) -> IterableTypeKind {
25 let Some(key) = db.lookup(type_id) else {
26 return IterableTypeKind::Other;
27 };
28
29 match key {
30 TypeData::Tuple(tuple_id) => {
31 let elements = db.tuple_list(tuple_id);
32 IterableTypeKind::Tuple(elements.to_vec())
33 }
34 TypeData::Array(elem_type) => IterableTypeKind::Array(elem_type),
35 _ => IterableTypeKind::Other,
36 }
37}
38
39#[derive(Debug, Clone)]
49pub enum FullIterableTypeKind {
50 Array(TypeId),
52 Tuple(Vec<crate::types::TupleElement>),
54 StringLiteral(tsz_common::interner::Atom),
56 Union(Vec<TypeId>),
58 Intersection(Vec<TypeId>),
60 Object(crate::types::ObjectShapeId),
62 Application { base: TypeId },
64 TypeParameter { constraint: Option<TypeId> },
66 Readonly(TypeId),
68 FunctionOrCallable,
70 ComplexType,
72 NotIterable,
74}
75
76pub fn classify_full_iterable_type(db: &dyn TypeDatabase, type_id: TypeId) -> FullIterableTypeKind {
80 let Some(key) = db.lookup(type_id) else {
81 return FullIterableTypeKind::NotIterable;
82 };
83
84 match key {
85 TypeData::Array(elem) => FullIterableTypeKind::Array(elem),
86 TypeData::Tuple(tuple_id) => {
87 let elements = db.tuple_list(tuple_id);
88 FullIterableTypeKind::Tuple(elements.to_vec())
89 }
90 TypeData::Literal(crate::LiteralValue::String(s)) => FullIterableTypeKind::StringLiteral(s),
91 TypeData::Union(members_id) => {
92 let members = db.type_list(members_id);
93 FullIterableTypeKind::Union(members.to_vec())
94 }
95 TypeData::Intersection(members_id) => {
96 let members = db.type_list(members_id);
97 FullIterableTypeKind::Intersection(members.to_vec())
98 }
99 TypeData::Object(shape_id) | TypeData::ObjectWithIndex(shape_id) => {
100 FullIterableTypeKind::Object(shape_id)
101 }
102 TypeData::Application(app_id) => {
103 let app = db.type_application(app_id);
104 FullIterableTypeKind::Application { base: app.base }
105 }
106 TypeData::TypeParameter(info) | TypeData::Infer(info) => {
107 FullIterableTypeKind::TypeParameter {
108 constraint: info.constraint,
109 }
110 }
111 TypeData::ReadonlyType(inner) | TypeData::NoInfer(inner) => {
112 FullIterableTypeKind::Readonly(inner)
113 }
114 TypeData::Function(_) | TypeData::Callable(_) => FullIterableTypeKind::FunctionOrCallable,
115 TypeData::IndexAccess(_, _) | TypeData::Conditional(_) | TypeData::Mapped(_) => {
116 FullIterableTypeKind::ComplexType
117 }
118 TypeData::BoundParameter(_)
120 | TypeData::Intrinsic(_)
121 | TypeData::Literal(_)
122 | TypeData::Lazy(_)
123 | TypeData::Recursive(_)
124 | TypeData::TemplateLiteral(_)
125 | TypeData::UniqueSymbol(_)
126 | TypeData::ThisType
127 | TypeData::TypeQuery(_)
128 | TypeData::KeyOf(_)
129 | TypeData::StringIntrinsic { .. }
130 | TypeData::ModuleNamespace(_)
131 | TypeData::Enum(_, _)
132 | TypeData::Error => FullIterableTypeKind::NotIterable,
133 }
134}
135
136#[derive(Debug, Clone)]
138pub enum AsyncIterableTypeKind {
139 Union(Vec<TypeId>),
141 Object(crate::types::ObjectShapeId),
143 Readonly(TypeId),
145 NotAsyncIterable,
147}
148
149pub fn classify_async_iterable_type(
151 db: &dyn TypeDatabase,
152 type_id: TypeId,
153) -> AsyncIterableTypeKind {
154 let Some(key) = db.lookup(type_id) else {
155 return AsyncIterableTypeKind::NotAsyncIterable;
156 };
157
158 match key {
159 TypeData::Union(members_id) => {
160 let members = db.type_list(members_id);
161 AsyncIterableTypeKind::Union(members.to_vec())
162 }
163 TypeData::Object(shape_id) | TypeData::ObjectWithIndex(shape_id) => {
164 AsyncIterableTypeKind::Object(shape_id)
165 }
166 TypeData::ReadonlyType(inner) => AsyncIterableTypeKind::Readonly(inner),
167 _ => AsyncIterableTypeKind::NotAsyncIterable,
168 }
169}
170
171#[derive(Debug, Clone)]
173pub enum ForOfElementKind {
174 Array(TypeId),
176 Tuple(Vec<crate::types::TupleElement>),
178 Union(Vec<TypeId>),
180 Readonly(TypeId),
182 String,
184 Other,
186}
187
188pub fn classify_for_of_element_type(db: &dyn TypeDatabase, type_id: TypeId) -> ForOfElementKind {
190 let Some(key) = db.lookup(type_id) else {
191 return ForOfElementKind::Other;
192 };
193
194 match key {
195 TypeData::Array(elem) => ForOfElementKind::Array(elem),
196 TypeData::Tuple(tuple_id) => {
197 let elements = db.tuple_list(tuple_id);
198 ForOfElementKind::Tuple(elements.to_vec())
199 }
200 TypeData::Union(members_id) => {
201 let members = db.type_list(members_id);
202 ForOfElementKind::Union(members.to_vec())
203 }
204 TypeData::ReadonlyType(inner) | TypeData::NoInfer(inner) => {
205 ForOfElementKind::Readonly(inner)
206 }
207 TypeData::Literal(crate::LiteralValue::String(_)) => ForOfElementKind::String,
209 _ => ForOfElementKind::Other,
210 }
211}