11use emmylua_parser:: {
2- BinaryOperator , LuaAst , LuaAstNode , LuaBinaryExpr , LuaCallArgList , LuaCallExpr , LuaExpr ,
3- LuaIndexKey , LuaLiteralToken , LuaNameExpr , LuaSyntaxId , LuaSyntaxKind ,
2+ BinaryOperator , LuaAst , LuaAstNode , LuaBinaryExpr , LuaBlock , LuaCallArgList , LuaCallExpr ,
3+ LuaExpr , LuaIndexKey , LuaLiteralToken , LuaNameExpr , LuaStat , LuaSyntaxId , LuaSyntaxKind ,
4+ UnaryOperator ,
45} ;
56use rowan:: TextRange ;
67
@@ -20,8 +21,9 @@ pub fn analyze(analyzer: &mut FlowAnalyzer) -> Option<()> {
2021 let mut flow_chains = LuaFlowChain :: new ( decl_id) ;
2122 for range in ranges {
2223 let syntax_id = LuaSyntaxId :: new ( LuaSyntaxKind :: NameExpr . into ( ) , range. clone ( ) ) ;
23- let node = LuaNameExpr :: cast ( syntax_id. to_node_from_root ( root) ?) ?;
24- infer_name_expr ( analyzer, & mut flow_chains, node) ;
24+ if let Some ( node) = LuaNameExpr :: cast ( syntax_id. to_node_from_root ( root) ?) {
25+ infer_name_expr ( analyzer, & mut flow_chains, node) ;
26+ }
2527 }
2628 analyzer
2729 . db
@@ -32,84 +34,63 @@ pub fn analyze(analyzer: &mut FlowAnalyzer) -> Option<()> {
3234 Some ( ( ) )
3335}
3436
35- fn get_effect_range ( check_expr : LuaExpr ) -> Option < TextRange > {
36- let parent = check_expr. get_parent :: < LuaAst > ( ) ?;
37- match parent {
38- LuaAst :: LuaIfStat ( if_stat) => {
39- let range = if_stat. get_block ( ) ?. get_range ( ) ;
40- Some ( range)
41- }
42- LuaAst :: LuaWhileStat ( while_stat) => {
43- let range = while_stat. get_block ( ) ?. get_range ( ) ;
44- Some ( range)
45- }
46- LuaAst :: LuaElseIfClauseStat ( else_if_clause_stat) => {
47- let range = else_if_clause_stat. get_block ( ) ?. get_range ( ) ;
48- Some ( range)
49- }
50- LuaAst :: LuaParenExpr ( paren_expr) => get_effect_range ( LuaExpr :: ParenExpr ( paren_expr) ) ,
51- LuaAst :: LuaBinaryExpr ( binary_expr) => {
52- let op = binary_expr. get_op_token ( ) ?;
53- let basic_range = match op. get_op ( ) {
54- BinaryOperator :: OpAnd => {
55- let range = binary_expr. get_range ( ) ;
56- let check_range = check_expr. get_range ( ) ;
57- if check_range. start ( ) == range. start ( ) {
58- let start = check_range. end ( ) ;
59- let end = range. end ( ) ;
60- if start < end {
61- Some ( TextRange :: new ( start, end) )
62- } else {
63- None
64- }
65- } else {
66- None
67- }
68- }
69- _ => return None ,
70- } ;
71-
72- let parent_effect_range = get_effect_range ( LuaExpr :: BinaryExpr ( binary_expr) ) ;
73- match ( basic_range, parent_effect_range) {
74- ( Some ( basic_range) , Some ( parent_effect_range) ) => {
75- let start = basic_range. start ( ) . min ( parent_effect_range. start ( ) ) ;
76- let end = basic_range. end ( ) . max ( parent_effect_range. end ( ) ) ;
77- Some ( TextRange :: new ( start, end) )
78- }
79- ( Some ( basic_range) , None ) => Some ( basic_range) ,
80- ( None , Some ( parent_effect_range) ) => Some ( parent_effect_range) ,
81- _ => None ,
82- }
83- }
84- _ => None ,
85- }
86- }
87-
8837fn infer_name_expr (
8938 analyzer : & FlowAnalyzer ,
9039 flow_chains : & mut LuaFlowChain ,
9140 name_expr : LuaNameExpr ,
9241) -> Option < ( ) > {
9342 let parent = name_expr. get_parent :: < LuaAst > ( ) ?;
43+ broadcast_up (
44+ analyzer,
45+ flow_chains,
46+ parent,
47+ LuaAst :: LuaNameExpr ( name_expr) ,
48+ TypeAssertion :: Exist ,
49+ ) ;
50+ Some ( ( ) )
51+ }
52+
53+ fn broadcast_up (
54+ analyzer : & FlowAnalyzer ,
55+ flow_chains : & mut LuaFlowChain ,
56+ parent : LuaAst ,
57+ origin : LuaAst ,
58+ type_assert : TypeAssertion ,
59+ ) -> Option < ( ) > {
9460 match parent {
9561 LuaAst :: LuaIfStat ( if_stat) => {
9662 // this mean the name_expr is a condition and the name_expr is not nil and is not false
97- let block = if_stat. get_block ( ) ?;
98- flow_chains. add_type_assert ( TypeAssertion :: Exist , block. get_range ( ) ) ;
63+ if let Some ( block) = if_stat. get_block ( ) {
64+ flow_chains. add_type_assert ( type_assert. clone ( ) , block. get_range ( ) ) ;
65+ }
66+
67+ if let Some ( ne_type_assert) = type_assert. get_negation ( ) {
68+ if let Some ( else_stat) = if_stat. get_else_clause ( ) {
69+ let range = else_stat. get_range ( ) ;
70+ flow_chains. add_type_assert ( ne_type_assert, range) ;
71+ } else if is_block_has_return ( if_stat. get_block ( ) ?) . unwrap_or ( false ) {
72+ let parent_block = if_stat. get_parent :: < LuaBlock > ( ) ?;
73+ let parent_range = parent_block. get_range ( ) ;
74+ let if_range = if_stat. get_range ( ) ;
75+ if if_range. end ( ) < parent_range. end ( ) {
76+ let range = TextRange :: new ( if_range. end ( ) , parent_range. end ( ) ) ;
77+ flow_chains. add_type_assert ( ne_type_assert, range) ;
78+ }
79+ }
80+ }
9981 }
10082 LuaAst :: LuaWhileStat ( while_stat) => {
10183 // this mean the name_expr is a condition and the name_expr is not nil and is not false
10284 let block = while_stat. get_block ( ) ?;
103- flow_chains. add_type_assert ( TypeAssertion :: Exist , block. get_range ( ) ) ;
85+ flow_chains. add_type_assert ( type_assert , block. get_range ( ) ) ;
10486 }
10587 LuaAst :: LuaElseIfClauseStat ( else_if_clause_stat) => {
10688 // this mean the name_expr is a condition and the name_expr is not nil and is not false
10789 let block = else_if_clause_stat. get_block ( ) ?;
108- flow_chains. add_type_assert ( TypeAssertion :: Exist , block. get_range ( ) ) ;
90+ flow_chains. add_type_assert ( type_assert , block. get_range ( ) ) ;
10991 }
11092 LuaAst :: LuaIndexExpr ( index_expr) => {
11193 let key = index_expr. get_index_key ( ) ?;
112- let range = get_effect_range ( LuaExpr :: IndexExpr ( index_expr) ) ?;
11394 let reference_key = match key {
11495 LuaIndexKey :: Integer ( i) => {
11596 if i. is_int ( ) {
@@ -125,24 +106,59 @@ fn infer_name_expr(
125106 _ => return None ,
126107 } ;
127108
128- flow_chains. add_type_assert ( TypeAssertion :: FieldExist ( reference_key. into ( ) ) , range) ;
109+ let type_assert = TypeAssertion :: FieldExist ( reference_key. into ( ) ) ;
110+ broadcast_up (
111+ analyzer,
112+ flow_chains,
113+ index_expr. get_parent :: < LuaAst > ( ) ?,
114+ LuaAst :: LuaIndexExpr ( index_expr) ,
115+ type_assert,
116+ ) ;
129117 }
130118 LuaAst :: LuaBinaryExpr ( binary_expr) => {
131119 let op = binary_expr. get_op_token ( ) ?;
132120 match op. get_op ( ) {
133121 BinaryOperator :: OpAnd => {
134- let range = get_effect_range ( LuaExpr :: NameExpr ( name_expr) ) ?;
135- flow_chains. add_type_assert ( TypeAssertion :: Exist , range) ;
122+ let ( left, right) = binary_expr. get_exprs ( ) ?;
123+ if left. get_position ( ) == origin. get_position ( ) {
124+ flow_chains. add_type_assert ( type_assert. clone ( ) , right. get_range ( ) ) ;
125+ }
126+
127+ broadcast_up (
128+ analyzer,
129+ flow_chains,
130+ binary_expr. get_parent :: < LuaAst > ( ) ?,
131+ LuaAst :: LuaBinaryExpr ( binary_expr) ,
132+ type_assert,
133+ ) ;
136134 }
137135 _ => { }
138136 }
139137 }
140138 LuaAst :: LuaCallArgList ( call_args_list) => {
141- infer_call_arg_list ( analyzer, flow_chains, call_args_list) ?;
139+ if type_assert == TypeAssertion :: Exist {
140+ infer_call_arg_list ( analyzer, flow_chains, call_args_list) ?;
141+ }
142+ }
143+ LuaAst :: LuaUnaryExpr ( unary_expr) => {
144+ let op = unary_expr. get_op_token ( ) ?;
145+ match op. get_op ( ) {
146+ UnaryOperator :: OpNot => {
147+ if let Some ( ne_type_assert) = type_assert. get_negation ( ) {
148+ broadcast_up (
149+ analyzer,
150+ flow_chains,
151+ unary_expr. get_parent :: < LuaAst > ( ) ?,
152+ LuaAst :: LuaUnaryExpr ( unary_expr) ,
153+ ne_type_assert,
154+ ) ;
155+ }
156+ }
157+ _ => { }
158+ }
142159 }
143160 _ => { }
144161 }
145-
146162 Some ( ( ) )
147163}
148164
@@ -168,18 +184,18 @@ fn infer_call_arg_list(
168184}
169185
170186fn infer_lua_type_assert (
171- _ : & FlowAnalyzer ,
187+ analyzer : & FlowAnalyzer ,
172188 flow_chains : & mut LuaFlowChain ,
173189 call_expr : LuaCallExpr ,
174190) -> Option < ( ) > {
175- let parent = call_expr. get_parent :: < LuaBinaryExpr > ( ) ?;
176- let op = parent . get_op_token ( ) ?;
191+ let binary_expr = call_expr. get_parent :: < LuaBinaryExpr > ( ) ?;
192+ let op = binary_expr . get_op_token ( ) ?;
177193 match op. get_op ( ) {
178194 BinaryOperator :: OpEq => { }
179195 _ => return None ,
180196 } ;
181197
182- let operands = parent . get_exprs ( ) ?;
198+ let operands = binary_expr . get_exprs ( ) ?;
183199 let literal_expr = if let LuaExpr :: LiteralExpr ( literal) = operands. 0 {
184200 literal
185201 } else if let LuaExpr :: LiteralExpr ( literal) = operands. 1 {
@@ -194,21 +210,42 @@ fn infer_lua_type_assert(
194210 } ;
195211
196212 let type_assert = match type_literal. as_str ( ) {
197- "number" => TypeAssertion :: IsNativeLuaType ( LuaType :: Number ) ,
198- "string" => TypeAssertion :: IsNativeLuaType ( LuaType :: String ) ,
199- "boolean" => TypeAssertion :: IsNativeLuaType ( LuaType :: Boolean ) ,
200- "table" => TypeAssertion :: IsNativeLuaType ( LuaType :: Table ) ,
201- "function" => TypeAssertion :: IsNativeLuaType ( LuaType :: Function ) ,
202- "thread" => TypeAssertion :: IsNativeLuaType ( LuaType :: Thread ) ,
203- "userdata" => TypeAssertion :: IsNativeLuaType ( LuaType :: Userdata ) ,
204- "nil" => TypeAssertion :: IsNativeLuaType ( LuaType :: Nil ) ,
213+ "number" => TypeAssertion :: Force ( LuaType :: Number ) ,
214+ "string" => TypeAssertion :: Force ( LuaType :: String ) ,
215+ "boolean" => TypeAssertion :: Force ( LuaType :: Boolean ) ,
216+ "table" => TypeAssertion :: Force ( LuaType :: Table ) ,
217+ "function" => TypeAssertion :: Force ( LuaType :: Function ) ,
218+ "thread" => TypeAssertion :: Force ( LuaType :: Thread ) ,
219+ "userdata" => TypeAssertion :: Force ( LuaType :: Userdata ) ,
220+ "nil" => TypeAssertion :: Force ( LuaType :: Nil ) ,
205221 _ => {
206222 return None ;
207223 }
208224 } ;
209225
210- let range = get_effect_range ( LuaExpr :: BinaryExpr ( parent) ) ?;
211- flow_chains. add_type_assert ( type_assert, range) ;
226+ broadcast_up (
227+ analyzer,
228+ flow_chains,
229+ binary_expr. get_parent :: < LuaAst > ( ) ?,
230+ LuaAst :: LuaBinaryExpr ( binary_expr) ,
231+ type_assert,
232+ ) ;
212233
213234 Some ( ( ) )
214235}
236+
237+ fn is_block_has_return ( block : LuaBlock ) -> Option < bool > {
238+ for stat in block. get_stats ( ) {
239+ match stat {
240+ LuaStat :: ReturnStat ( _) => return Some ( true ) ,
241+ LuaStat :: DoStat ( do_stat) => {
242+ if is_block_has_return ( do_stat. get_block ( ) ?) . unwrap_or ( false ) {
243+ return Some ( true ) ;
244+ }
245+ }
246+ _ => { }
247+ }
248+ }
249+
250+ Some ( false )
251+ }
0 commit comments