1- use emmylua_parser:: { BinaryOperator , LuaAstNode , LuaChunk , LuaDocOpType , LuaDocTagCast } ;
1+ use emmylua_parser:: {
2+ BinaryOperator , LuaAstNode , LuaCallExpr , LuaChunk , LuaDocOpType , LuaDocTagCast , LuaExpr ,
3+ } ;
24
35use crate :: {
46 semantic:: infer:: {
@@ -9,8 +11,8 @@ use crate::{
911 } ,
1012 VarRefId ,
1113 } ,
12- DbIndex , FileId , FlowNode , FlowTree , InFiled , InferFailReason , LuaInferCache , LuaType ,
13- LuaTypeOwner , TypeOps ,
14+ DbIndex , FileId , FlowId , FlowNode , FlowNodeKind , FlowTree , InFiled , InferFailReason ,
15+ LuaInferCache , LuaType , LuaTypeOwner , TypeOps ,
1416} ;
1517
1618pub fn get_type_at_cast_flow (
@@ -22,12 +24,24 @@ pub fn get_type_at_cast_flow(
2224 flow_node : & FlowNode ,
2325 tag_cast : LuaDocTagCast ,
2426) -> Result < ResultTypeOrContinue , InferFailReason > {
25- let key_expr = match tag_cast. get_key_expr ( ) {
26- Some ( expr) => expr,
27- None => return Ok ( ResultTypeOrContinue :: Continue ) ,
28- } ;
27+ match tag_cast. get_key_expr ( ) {
28+ Some ( expr) => {
29+ get_type_at_cast_expr ( db, tree, cache, root, var_ref_id, flow_node, tag_cast, expr)
30+ }
31+ None => get_type_at_inline_cast ( db, tree, cache, root, var_ref_id, flow_node, tag_cast) ,
32+ }
33+ }
2934
30- // todo support index_expr
35+ fn get_type_at_cast_expr (
36+ db : & DbIndex ,
37+ tree : & FlowTree ,
38+ cache : & mut LuaInferCache ,
39+ root : & LuaChunk ,
40+ var_ref_id : & VarRefId ,
41+ flow_node : & FlowNode ,
42+ tag_cast : LuaDocTagCast ,
43+ key_expr : LuaExpr ,
44+ ) -> Result < ResultTypeOrContinue , InferFailReason > {
3145 let Some ( maybe_ref_id) = get_var_expr_var_ref_id ( db, cache, key_expr) else {
3246 return Ok ( ResultTypeOrContinue :: Continue ) ;
3347 } ;
@@ -51,6 +65,62 @@ pub fn get_type_at_cast_flow(
5165 Ok ( ResultTypeOrContinue :: Result ( antecedent_type) )
5266}
5367
68+ fn get_type_at_inline_cast (
69+ db : & DbIndex ,
70+ tree : & FlowTree ,
71+ cache : & mut LuaInferCache ,
72+ root : & LuaChunk ,
73+ var_ref_id : & VarRefId ,
74+ flow_node : & FlowNode ,
75+ tag_cast : LuaDocTagCast ,
76+ ) -> Result < ResultTypeOrContinue , InferFailReason > {
77+ let antecedent_flow_id = get_single_antecedent ( tree, flow_node) ?;
78+ let mut antecedent_type =
79+ get_type_at_flow ( db, tree, cache, root, var_ref_id, antecedent_flow_id) ?;
80+ for cast_op_type in tag_cast. get_op_types ( ) {
81+ antecedent_type = cast_type (
82+ db,
83+ cache. get_file_id ( ) ,
84+ cast_op_type,
85+ antecedent_type,
86+ InferConditionFlow :: TrueCondition ,
87+ ) ?;
88+ }
89+ Ok ( ResultTypeOrContinue :: Result ( antecedent_type) )
90+ }
91+
92+ pub fn get_type_at_call_expr_inline_cast (
93+ db : & DbIndex ,
94+ cache : & mut LuaInferCache ,
95+ tree : & FlowTree ,
96+ call_expr : LuaCallExpr ,
97+ flow_id : FlowId ,
98+ mut return_type : LuaType ,
99+ ) -> Option < LuaType > {
100+ let flow_node = tree. get_flow_node ( flow_id) ?;
101+ let FlowNodeKind :: TagCast ( tag_cast_ptr) = & flow_node. kind else {
102+ return None ;
103+ } ;
104+
105+ let root = LuaChunk :: cast ( call_expr. get_root ( ) ) ?;
106+ let tag_cast = tag_cast_ptr. to_node ( & root) ?;
107+
108+ for cast_op_type in tag_cast. get_op_types ( ) {
109+ return_type = match cast_type (
110+ db,
111+ cache. get_file_id ( ) ,
112+ cast_op_type,
113+ return_type,
114+ InferConditionFlow :: TrueCondition ,
115+ ) {
116+ Ok ( typ) => typ,
117+ Err ( _) => return None ,
118+ } ;
119+ }
120+
121+ Some ( return_type)
122+ }
123+
54124enum CastAction {
55125 Add ,
56126 Remove ,
0 commit comments