1- use emmylua_parser:: { LuaAst , LuaAstNode , LuaCallExpr , LuaDocTagType } ;
1+ use emmylua_parser:: { LuaAst , LuaAstNode , LuaAstToken , LuaCallExpr , LuaDocTagType } ;
22use rowan:: TextRange ;
33
44use crate :: diagnostic:: { checker:: Checker , lua_diagnostic:: DiagnosticContext } ;
55use crate :: semantic:: {
66 CallConstraintContext , build_call_constraint_context, normalize_constraint_type,
77} ;
88use crate :: {
9- DiagnosticCode , DocTypeInferContext , GenericTplId , LuaMemberOwner , LuaSemanticDeclId ,
10- LuaSignature , LuaStringTplType , LuaType , RenderLevel , SemanticDeclLevel , SemanticModel ,
11- TypeCheckFailReason , TypeCheckResult , TypeSubstitutor , humanize_type, infer_doc_type,
12- instantiate_type_generic,
9+ DiagnosticCode , DocTypeInferContext , LuaStringTplType , LuaType , RenderLevel , SemanticModel ,
10+ TypeCheckFailReason , TypeCheckResult , TypeSubstitutor , VariadicType , humanize_type,
11+ infer_doc_type, instantiate_type_generic,
1312} ;
1413
1514pub struct GenericConstraintMismatchChecker ;
@@ -38,47 +37,72 @@ fn check_call_expr(
3837 semantic_model : & SemanticModel ,
3938 call_expr : LuaCallExpr ,
4039) -> Option < ( ) > {
41- let function = semantic_model
42- . infer_expr ( call_expr. get_prefix_expr ( ) ?. clone ( ) )
43- . ok ( ) ?;
44- if let LuaType :: Signature ( signature_id) = function {
45- let signature = semantic_model
46- . get_db ( )
47- . get_signature_index ( )
48- . get ( & signature_id) ?;
49- let Some ( CallConstraintContext {
40+ let Some ( (
41+ CallConstraintContext {
5042 params,
5143 arg_infos,
5244 substitutor,
53- } ) = build_call_constraint_context ( semantic_model, & call_expr, signature)
54- else {
55- return Some ( ( ) ) ;
56- } ;
45+ } ,
46+ doc_func,
47+ ) ) = build_call_constraint_context ( semantic_model, & call_expr)
48+ else {
49+ return Some ( ( ) ) ;
50+ } ;
5751
58- for ( i, ( _, param_type) ) in params. iter ( ) . enumerate ( ) {
59- let param_type = if let Some ( param_type) = param_type {
60- param_type
61- } else {
62- continue ;
63- } ;
52+ let mut arg_ranges = collect_arg_ranges ( semantic_model, & call_expr) ;
53+ if call_expr. is_colon_call ( ) && !doc_func. is_colon_define ( ) {
54+ let colon_range = call_expr. get_colon_token ( ) ?. get_range ( ) ;
55+ arg_ranges. insert ( 0 , colon_range) ;
56+ }
6457
65- check_param (
66- context,
67- semantic_model,
68- & call_expr,
69- i,
70- param_type,
71- signature,
72- & arg_infos,
73- false ,
74- & substitutor,
75- ) ;
76- }
58+ for ( i, ( _, param_type) ) in params. iter ( ) . enumerate ( ) {
59+ let param_type = if let Some ( param_type) = param_type {
60+ param_type
61+ } else {
62+ continue ;
63+ } ;
64+
65+ check_param (
66+ context,
67+ semantic_model,
68+ & call_expr,
69+ i,
70+ param_type,
71+ & arg_infos,
72+ & arg_ranges,
73+ false ,
74+ & substitutor,
75+ ) ;
7776 }
7877
7978 Some ( ( ) )
8079}
8180
81+ fn collect_arg_ranges ( semantic_model : & SemanticModel , call_expr : & LuaCallExpr ) -> Vec < TextRange > {
82+ let Some ( arg_list) = call_expr. get_args_list ( ) else {
83+ return Vec :: new ( ) ;
84+ } ;
85+ let arg_exprs = arg_list. get_args ( ) . collect :: < Vec < _ > > ( ) ;
86+ let mut ranges = Vec :: new ( ) ;
87+ for expr in arg_exprs {
88+ let expr_type = semantic_model
89+ . infer_expr ( expr. clone ( ) )
90+ . unwrap_or ( LuaType :: Unknown ) ;
91+ match expr_type {
92+ LuaType :: Variadic ( variadic) => match variadic. as_ref ( ) {
93+ VariadicType :: Base ( _) => ranges. push ( expr. get_range ( ) ) ,
94+ VariadicType :: Multi ( values) => {
95+ for _ in values {
96+ ranges. push ( expr. get_range ( ) ) ;
97+ }
98+ }
99+ } ,
100+ _ => ranges. push ( expr. get_range ( ) ) ,
101+ }
102+ }
103+ ranges
104+ }
105+
82106fn check_doc_tag_type (
83107 context : & mut DiagnosticContext ,
84108 semantic_model : & SemanticModel ,
@@ -122,31 +146,20 @@ fn check_param(
122146 call_expr : & LuaCallExpr ,
123147 param_index : usize ,
124148 param_type : & LuaType ,
125- signature : & LuaSignature ,
126- arg_infos : & [ ( LuaType , TextRange ) ] ,
149+ arg_infos : & [ LuaType ] ,
150+ arg_ranges : & [ TextRange ] ,
127151 from_union : bool ,
128152 substitutor : & TypeSubstitutor ,
129153) -> Option < ( ) > {
130154 // 应该先通过泛型体操约束到唯一类型再进行检查
131155 match param_type {
132156 LuaType :: StrTplRef ( str_tpl_ref) => {
133- let extend_type = str_tpl_ref
134- . get_constraint ( )
135- . cloned ( )
136- . or_else ( || {
137- get_extend_type (
138- semantic_model,
139- call_expr,
140- str_tpl_ref. get_tpl_id ( ) ,
141- signature,
142- )
143- } )
144- . map ( |ty| {
145- normalize_constraint_type (
146- semantic_model. get_db ( ) ,
147- instantiate_type_generic ( semantic_model. get_db ( ) , & ty, substitutor) ,
148- )
149- } ) ;
157+ let extend_type = str_tpl_ref. get_constraint ( ) . cloned ( ) . map ( |ty| {
158+ normalize_constraint_type (
159+ semantic_model. get_db ( ) ,
160+ instantiate_type_generic ( semantic_model. get_db ( ) , & ty, substitutor) ,
161+ )
162+ } ) ;
150163 let arg_expr = call_expr. get_args_list ( ) ?. get_args ( ) . nth ( param_index) ?;
151164 let arg_type = semantic_model. infer_expr ( arg_expr. clone ( ) ) . ok ( ) ?;
152165
@@ -164,24 +177,15 @@ fn check_param(
164177 ) ;
165178 }
166179 LuaType :: TplRef ( tpl_ref) | LuaType :: ConstTplRef ( tpl_ref) => {
167- let extend_type = tpl_ref
168- . get_constraint ( )
169- . cloned ( )
170- . or_else ( || {
171- get_extend_type ( semantic_model, call_expr, tpl_ref. get_tpl_id ( ) , signature)
172- } )
173- . map ( |ty| {
174- normalize_constraint_type (
175- semantic_model. get_db ( ) ,
176- instantiate_type_generic ( semantic_model. get_db ( ) , & ty, substitutor) ,
177- )
178- } ) ;
179- validate_tpl_ref (
180- context,
181- semantic_model,
182- & extend_type,
183- arg_infos. get ( param_index) ,
184- ) ;
180+ let extend_type = tpl_ref. get_constraint ( ) . cloned ( ) . map ( |ty| {
181+ normalize_constraint_type (
182+ semantic_model. get_db ( ) ,
183+ instantiate_type_generic ( semantic_model. get_db ( ) , & ty, substitutor) ,
184+ )
185+ } ) ;
186+ let arg_type = arg_infos. get ( param_index) ;
187+ let arg_range = arg_ranges. get ( param_index) . copied ( ) ;
188+ validate_tpl_ref ( context, semantic_model, & extend_type, arg_type, arg_range) ;
185189 }
186190 LuaType :: Union ( union_type) => {
187191 // 如果不是来自 union, 才展开 union 中的每个类型进行检查
@@ -193,8 +197,8 @@ fn check_param(
193197 call_expr,
194198 param_index,
195199 union_member_type,
196- signature,
197200 arg_infos,
201+ arg_ranges,
198202 true ,
199203 substitutor,
200204 ) ;
@@ -206,45 +210,6 @@ fn check_param(
206210 Some ( ( ) )
207211}
208212
209- fn get_extend_type (
210- semantic_model : & SemanticModel ,
211- call_expr : & LuaCallExpr ,
212- tpl_id : GenericTplId ,
213- signature : & LuaSignature ,
214- ) -> Option < LuaType > {
215- match tpl_id {
216- GenericTplId :: Func ( tpl_id) => signature
217- . generic_params
218- . get ( tpl_id as usize ) ?
219- . type_constraint
220- . clone ( ) ,
221- GenericTplId :: Type ( tpl_id) => {
222- let prefix_expr = call_expr. get_prefix_expr ( ) ?;
223- let semantic_decl = semantic_model. find_decl (
224- prefix_expr. syntax ( ) . clone ( ) . into ( ) ,
225- SemanticDeclLevel :: default ( ) ,
226- ) ?;
227- let member_index = semantic_model. get_db ( ) . get_member_index ( ) ;
228- match semantic_decl {
229- LuaSemanticDeclId :: Member ( member_id) => {
230- let owner = member_index. get_current_owner ( & member_id) ?;
231- match owner {
232- LuaMemberOwner :: Type ( type_id) => {
233- let generic_params = semantic_model
234- . get_db ( )
235- . get_type_index ( )
236- . get_generic_params ( type_id) ?;
237- generic_params. get ( tpl_id as usize ) ?. type_constraint . clone ( )
238- }
239- _ => None ,
240- }
241- }
242- _ => None ,
243- }
244- }
245- }
246- }
247-
248213fn validate_str_tpl_ref (
249214 context : & mut DiagnosticContext ,
250215 semantic_model : & SemanticModel ,
@@ -309,18 +274,20 @@ fn validate_tpl_ref(
309274 context : & mut DiagnosticContext ,
310275 semantic_model : & SemanticModel ,
311276 extend_type : & Option < LuaType > ,
312- arg_info : Option < & ( LuaType , TextRange ) > ,
277+ arg_type : Option < & LuaType > ,
278+ range : Option < TextRange > ,
313279) -> Option < ( ) > {
314280 let extend_type = extend_type. clone ( ) ?;
315- let arg_info = arg_info?;
316- let result = semantic_model. type_check_detail ( & extend_type, & arg_info. 0 ) ;
281+ let arg_type = arg_type?;
282+ let range = range?;
283+ let result = semantic_model. type_check_detail ( & extend_type, arg_type) ;
317284 if result. is_err ( ) {
318285 add_type_check_diagnostic (
319286 context,
320287 semantic_model,
321- arg_info . 1 ,
288+ range ,
322289 & extend_type,
323- & arg_info . 0 ,
290+ arg_type ,
324291 result,
325292 ) ;
326293 }
0 commit comments