@@ -3,13 +3,13 @@ use std::{ops::Deref, sync::Arc};
33use crate :: { infer_expr, DbIndex , LuaInferConfig } ;
44use emmylua_parser:: { LuaAstNode , LuaExpr , LuaSyntaxId , LuaSyntaxNode } ;
55
6- use super :: { LuaMemberPathExistType , LuaType , LuaUnionType } ;
6+ use super :: { type_ops :: TypeOps , LuaMemberPathExistType , LuaType } ;
77
88#[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
99pub enum TypeAssertion {
1010 Exist ,
1111 NotExist ,
12- Force ( LuaType ) ,
12+ Narrow ( LuaType ) ,
1313 MemberPathExist ( Arc < String > ) ,
1414 Add ( LuaType ) ,
1515 Remove ( LuaType ) ,
@@ -21,14 +21,14 @@ pub enum TypeAssertion {
2121impl TypeAssertion {
2222 pub fn simple_tighten_type ( & self , source : LuaType ) -> LuaType {
2323 match self {
24- TypeAssertion :: Exist => remove_nil_and_not_false ( source) ,
24+ TypeAssertion :: Exist => TypeOps :: Remove . apply ( & source, & LuaType :: Nil ) ,
2525 TypeAssertion :: NotExist => force_nil_or_false ( source) ,
26- TypeAssertion :: Force ( t) => narrow_down_type ( source, t. clone ( ) ) ,
26+ TypeAssertion :: Narrow ( t) => TypeOps :: Narrow . apply ( & source, t) ,
2727 TypeAssertion :: MemberPathExist ( key) => LuaType :: MemberPathExist (
2828 LuaMemberPathExistType :: new ( & key. deref ( ) , source, 0 ) . into ( ) ,
2929 ) ,
30- TypeAssertion :: Add ( lua_type) => add_type ( source, lua_type. clone ( ) ) ,
31- TypeAssertion :: Remove ( lua_type) => remove_type ( source, lua_type. clone ( ) ) ,
30+ TypeAssertion :: Add ( lua_type) => TypeOps :: Union . apply ( & source, lua_type) ,
31+ TypeAssertion :: Remove ( lua_type) => TypeOps :: Remove . apply ( & source, lua_type) ,
3232 _ => source,
3333 }
3434 }
@@ -37,7 +37,7 @@ impl TypeAssertion {
3737 match self {
3838 TypeAssertion :: Exist => Some ( TypeAssertion :: NotExist ) ,
3939 TypeAssertion :: NotExist => Some ( TypeAssertion :: Exist ) ,
40- TypeAssertion :: Force ( t) => Some ( TypeAssertion :: Remove ( t. clone ( ) ) ) ,
40+ TypeAssertion :: Narrow ( t) => Some ( TypeAssertion :: Remove ( t. clone ( ) ) ) ,
4141 _ => None ,
4242 }
4343 }
@@ -50,25 +50,25 @@ impl TypeAssertion {
5050 source : LuaType ,
5151 ) -> Option < LuaType > {
5252 match self {
53- TypeAssertion :: Exist => Some ( remove_nil_and_not_false ( source) ) ,
53+ TypeAssertion :: Exist => Some ( TypeOps :: Remove . apply ( & source, & LuaType :: Nil ) ) ,
5454 TypeAssertion :: NotExist => Some ( force_nil_or_false ( source) ) ,
55- TypeAssertion :: Force ( t) => Some ( narrow_down_type ( source, t. clone ( ) ) ) ,
55+ TypeAssertion :: Narrow ( t) => Some ( TypeOps :: Narrow . apply ( & source, t) ) ,
5656 TypeAssertion :: MemberPathExist ( key) => Some ( LuaType :: MemberPathExist (
5757 LuaMemberPathExistType :: new ( & key. deref ( ) , source, 0 ) . into ( ) ,
5858 ) ) ,
59- TypeAssertion :: Add ( lua_type) => Some ( add_type ( source, lua_type. clone ( ) ) ) ,
60- TypeAssertion :: Remove ( lua_type) => Some ( remove_type ( source, lua_type. clone ( ) ) ) ,
59+ TypeAssertion :: Add ( lua_type) => Some ( TypeOps :: Union . apply ( & source, lua_type) ) ,
60+ TypeAssertion :: Remove ( lua_type) => Some ( TypeOps :: Remove . apply ( & source, lua_type) ) ,
6161 TypeAssertion :: Reassign ( syntax_id) => {
6262 let expr = LuaExpr :: cast ( syntax_id. to_node_from_root ( root) ?) ?;
6363 let expr_type = infer_expr ( db, config, expr) ?;
64- Some ( narrow_down_type ( source, expr_type) )
64+ Some ( TypeOps :: Narrow . apply ( & source, & expr_type) )
6565 }
6666 TypeAssertion :: AddUnion ( syntax_ids) => {
6767 let mut typ = source;
6868 for syntax_id in syntax_ids {
6969 let expr = LuaExpr :: cast ( syntax_id. to_node_from_root ( root) ?) ?;
7070 let expr_type = infer_expr ( db, config, expr) ?;
71- typ = add_type ( typ, expr_type) ;
71+ typ = TypeOps :: Union . apply ( & typ, & expr_type) ;
7272 }
7373
7474 Some ( typ)
@@ -78,27 +78,6 @@ impl TypeAssertion {
7878 }
7979}
8080
81- fn remove_nil_and_not_false ( t : LuaType ) -> LuaType {
82- match t {
83- LuaType :: Nil => LuaType :: Unknown ,
84- LuaType :: Union ( types) => {
85- let mut new_types = Vec :: new ( ) ;
86- for t in types. get_types ( ) {
87- let t = remove_nil_and_not_false ( t. clone ( ) ) ;
88- if t != LuaType :: Unknown {
89- new_types. push ( t) ;
90- }
91- }
92- if new_types. len ( ) == 1 {
93- new_types. pop ( ) . unwrap ( )
94- } else {
95- LuaType :: Union ( LuaUnionType :: new ( new_types) . into ( ) )
96- }
97- }
98- LuaType :: Nullable ( t) => remove_nil_and_not_false ( ( * t) . clone ( ) ) ,
99- t => t,
100- }
101- }
10281
10382fn force_nil_or_false ( t : LuaType ) -> LuaType {
10483 if t. is_boolean ( ) {
@@ -108,169 +87,3 @@ fn force_nil_or_false(t: LuaType) -> LuaType {
10887 return LuaType :: Nil ;
10988}
11089
111- // need to be optimized
112- fn narrow_down_type ( source : LuaType , target : LuaType ) -> LuaType {
113- match & source {
114- LuaType :: Union ( union) => {
115- let mut types = union. get_types ( ) . to_vec ( ) ;
116- match target {
117- LuaType :: Number | LuaType :: FloatConst ( _) | LuaType :: IntegerConst ( _) => {
118- types. retain ( |t| t. is_number ( ) ) ;
119- if types. len ( ) == 1 {
120- types. pop ( ) . unwrap ( )
121- } else {
122- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
123- }
124- }
125- LuaType :: String | LuaType :: StringConst ( _) => {
126- types. retain ( |t| t. is_string ( ) ) ;
127- if types. len ( ) == 1 {
128- types. pop ( ) . unwrap ( )
129- } else {
130- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
131- }
132- }
133- LuaType :: Boolean | LuaType :: BooleanConst ( _) => {
134- types. retain ( |t| t. is_boolean ( ) ) ;
135- if types. len ( ) == 1 {
136- types. pop ( ) . unwrap ( )
137- } else {
138- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
139- }
140- }
141- LuaType :: Table | LuaType :: TableConst ( _) => {
142- types. retain ( |t| t. is_table ( ) ) ;
143- if types. len ( ) == 1 {
144- types. pop ( ) . unwrap ( )
145- } else {
146- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
147- }
148- }
149- LuaType :: Function => {
150- types. retain ( |t| t. is_function ( ) ) ;
151- if types. len ( ) == 1 {
152- types. pop ( ) . unwrap ( )
153- } else {
154- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
155- }
156- }
157- LuaType :: Thread => {
158- types. retain ( |t| t. is_thread ( ) ) ;
159- if types. len ( ) == 1 {
160- types. pop ( ) . unwrap ( )
161- } else {
162- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
163- }
164- }
165- LuaType :: Userdata => {
166- types. retain ( |t| t. is_userdata ( ) ) ;
167- if types. len ( ) == 1 {
168- types. pop ( ) . unwrap ( )
169- } else {
170- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
171- }
172- }
173- LuaType :: Nil => {
174- types. retain ( |t| t. is_nil ( ) ) ;
175- if types. len ( ) == 1 {
176- types. pop ( ) . unwrap ( )
177- } else {
178- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
179- }
180- }
181- _ => target,
182- }
183- }
184- LuaType :: Nullable ( inner) => {
185- if !target. is_nullable ( ) {
186- narrow_down_type ( target, ( * * inner) . clone ( ) )
187- } else {
188- LuaType :: Nil
189- }
190- }
191- LuaType :: BooleanConst ( _) => {
192- if target. is_boolean ( ) {
193- return LuaType :: Boolean ;
194- }
195-
196- target
197- }
198- LuaType :: FloatConst ( _) => {
199- if target. is_number ( ) {
200- return LuaType :: Number ;
201- }
202-
203- target
204- }
205- LuaType :: IntegerConst ( _) => {
206- if target. is_number ( ) {
207- return LuaType :: Number ;
208- }
209-
210- target
211- }
212- LuaType :: StringConst ( _) => {
213- if target. is_string ( ) {
214- return LuaType :: String ;
215- }
216-
217- target
218- }
219- _ => target,
220- }
221- }
222-
223- fn add_type ( source : LuaType , added_typ : LuaType ) -> LuaType {
224- if added_typ. is_nil ( ) {
225- return LuaType :: Nullable ( source. into ( ) ) ;
226- }
227-
228- match source {
229- LuaType :: Union ( union) => {
230- let mut types = union. get_types ( ) . to_vec ( ) ;
231- types. push ( added_typ) ;
232- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
233- }
234- LuaType :: Nullable ( inner) => {
235- let inner = add_type ( ( * inner) . clone ( ) , added_typ) ;
236- LuaType :: Nullable ( inner. into ( ) )
237- }
238- LuaType :: Unknown | LuaType :: Any => added_typ,
239- _ => {
240- if source. is_number ( ) && added_typ. is_number ( ) {
241- return LuaType :: Number ;
242- } else if source. is_string ( ) && added_typ. is_string ( ) {
243- return LuaType :: String ;
244- } else if source. is_boolean ( ) && added_typ. is_boolean ( ) {
245- return LuaType :: Boolean ;
246- } else if source. is_table ( ) && added_typ. is_table ( ) {
247- return LuaType :: Table ;
248- }
249-
250- LuaType :: Union ( LuaUnionType :: new ( vec ! [ source, added_typ] ) . into ( ) )
251- } ,
252- }
253- }
254-
255- fn remove_type ( source : LuaType , removed_type : LuaType ) -> LuaType {
256- if removed_type. is_nil ( ) {
257- return remove_nil_and_not_false ( source) ;
258- }
259-
260- match source {
261- LuaType :: Union ( union) => {
262- let mut types = union. get_types ( ) . to_vec ( ) ;
263- types. retain ( |t| t != & removed_type) ;
264- if types. len ( ) == 1 {
265- types. pop ( ) . unwrap ( )
266- } else {
267- LuaType :: Union ( LuaUnionType :: new ( types) . into ( ) )
268- }
269- }
270- LuaType :: Nullable ( inner) => {
271- let inner = remove_type ( ( * inner) . clone ( ) , removed_type) ;
272- LuaType :: Nullable ( inner. into ( ) )
273- }
274- _ => source,
275- }
276- }
0 commit comments