1
- use emmylua_parser:: { LuaAstNode , LuaClosureExpr , LuaReturnStat } ;
2
- use rowan:: TextRange ;
1
+ use emmylua_parser:: { LuaAstNode , LuaClosureExpr , LuaExpr , LuaReturnStat } ;
2
+ use rowan:: { NodeOrToken , TextRange } ;
3
3
4
4
use crate :: {
5
- humanize_type, DiagnosticCode , LuaSignatureId , LuaType , RenderLevel , SemanticModel ,
6
- SignatureReturnStatus , TypeCheckFailReason , TypeCheckResult ,
5
+ humanize_type, DiagnosticCode , LuaSemanticDeclId , LuaSignatureId , LuaType , RenderLevel ,
6
+ SemanticModel , SignatureReturnStatus , TypeCheckFailReason , TypeCheckResult ,
7
7
} ;
8
8
9
9
use super :: { get_own_return_stats, DiagnosticContext } ;
@@ -46,7 +46,12 @@ fn check_return_stat(
46
46
& return_stat. get_expr_list ( ) . collect :: < Vec < _ > > ( ) ,
47
47
None ,
48
48
) ?;
49
- let return_expr_types = infos. iter ( ) . map ( |( typ, _) | typ. clone ( ) ) . collect :: < Vec < _ > > ( ) ;
49
+ let mut return_expr_types = infos. iter ( ) . map ( |( typ, _) | typ. clone ( ) ) . collect :: < Vec < _ > > ( ) ;
50
+ // 解决 setmetatable 的返回值类型问题
51
+ let setmetatable_index = has_setmetatable ( semantic_model, return_stat) ;
52
+ if let Some ( setmetatable_index) = setmetatable_index {
53
+ return_expr_types[ setmetatable_index] = LuaType :: Any ;
54
+ }
50
55
let return_expr_ranges = infos
51
56
. iter ( )
52
57
. map ( |( _, range) | range. clone ( ) )
@@ -59,7 +64,6 @@ fn check_return_stat(
59
64
if return_expr_types. len ( ) < index {
60
65
break ;
61
66
}
62
-
63
67
check_variadic_return_type_match (
64
68
context,
65
69
semantic_model,
@@ -173,3 +177,31 @@ fn add_type_check_diagnostic(
173
177
} ,
174
178
}
175
179
}
180
+
181
+ fn has_setmetatable ( semantic_model : & SemanticModel , return_stat : & LuaReturnStat ) -> Option < usize > {
182
+ for ( index, expr) in return_stat. get_expr_list ( ) . enumerate ( ) {
183
+ if let LuaExpr :: CallExpr ( call_expr) = expr {
184
+ if let Some ( prefix_expr) = call_expr. get_prefix_expr ( ) {
185
+ let semantic_info = semantic_model
186
+ . get_semantic_info ( NodeOrToken :: Node ( prefix_expr. syntax ( ) . clone ( ) . into ( ) ) ) ?;
187
+
188
+ if let Some ( LuaSemanticDeclId :: LuaDecl ( decl_id) ) = semantic_info. semantic_decl {
189
+ let decl = semantic_model. get_db ( ) . get_decl_index ( ) . get_decl ( & decl_id) ;
190
+
191
+ if let Some ( decl) = decl {
192
+ if decl. is_global ( )
193
+ && semantic_model
194
+ . get_db ( )
195
+ . get_module_index ( )
196
+ . is_std ( & decl. get_file_id ( ) )
197
+ && decl. get_name ( ) == "setmetatable"
198
+ {
199
+ return Some ( index) ;
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+ None
207
+ }
0 commit comments