|
1 | 1 | use emmylua_code_analysis::{ |
2 | | - InferGuard, LuaDeclLocation, LuaFunctionType, LuaMemberKey, LuaMemberOwner, LuaMultiLineUnion, |
3 | | - LuaPropertyOwnerId, LuaType, LuaTypeDeclId, LuaUnionType, RenderLevel, |
| 2 | + InferGuard, LuaDeclLocation, LuaFunctionType, LuaMember, LuaMemberKey, LuaMemberOwner, |
| 3 | + LuaMultiLineUnion, LuaPropertyOwnerId, LuaType, LuaTypeDeclId, LuaUnionType, RenderLevel, |
4 | 4 | }; |
5 | 5 | use emmylua_parser::{ |
6 | 6 | LuaAst, LuaAstNode, LuaAstToken, LuaCallArgList, LuaCallExpr, LuaComment, LuaNameToken, |
@@ -198,83 +198,130 @@ fn infer_call_arg_list( |
198 | 198 | let typ = call_expr_func.get_params().get(param_idx)?.1.clone()?; |
199 | 199 | let mut types = Vec::new(); |
200 | 200 | types.push(typ); |
201 | | - infer_call_arg_list_overload(builder, &call_expr, &call_expr_func, param_idx, &mut types); |
| 201 | + push_function_overloads_param( |
| 202 | + builder, |
| 203 | + &call_expr, |
| 204 | + call_expr_func.get_params(), |
| 205 | + param_idx, |
| 206 | + &mut types, |
| 207 | + ); |
202 | 208 | Some(types.into_iter().unique().collect()) // 需要去重 |
203 | 209 | } |
204 | 210 |
|
205 | | -fn infer_call_arg_list_overload( |
| 211 | +fn push_function_overloads_param( |
206 | 212 | builder: &mut CompletionBuilder, |
207 | 213 | call_expr: &LuaCallExpr, |
208 | | - call_expr_func: &LuaFunctionType, |
| 214 | + call_params: &[(String, Option<LuaType>)], |
209 | 215 | param_idx: usize, |
210 | 216 | types: &mut Vec<LuaType>, |
211 | 217 | ) -> Option<()> { |
| 218 | + let member_index = builder.semantic_model.get_db().get_member_index(); |
212 | 219 | let prefix_expr = call_expr.get_prefix_expr()?; |
213 | 220 | let property_owner_id = builder |
214 | 221 | .semantic_model |
215 | 222 | .get_property_owner_id(prefix_expr.syntax().clone().into())?; |
216 | 223 |
|
217 | | - let signature_id = match property_owner_id { |
| 224 | + // 收集函数类型 |
| 225 | + let functions = match property_owner_id { |
218 | 226 | LuaPropertyOwnerId::Member(member_id) => { |
219 | | - let member = builder |
220 | | - .semantic_model |
221 | | - .get_db() |
222 | | - .get_member_index() |
223 | | - .get_member(&member_id)?; |
224 | | - if let LuaType::Signature(signature_id) = member.get_decl_type() { |
225 | | - Some(signature_id) |
226 | | - } else { |
227 | | - None |
228 | | - } |
| 227 | + let member = member_index.get_member(&member_id)?; |
| 228 | + let key = member.get_key().to_path(); |
| 229 | + let members = member_index.get_members(&member.get_owner())?; |
| 230 | + let functions = filter_function_members(members, key); |
| 231 | + Some(functions) |
229 | 232 | } |
230 | 233 | LuaPropertyOwnerId::LuaDecl(decl_id) => { |
231 | 234 | let decl = builder |
232 | 235 | .semantic_model |
233 | 236 | .get_db() |
234 | 237 | .get_decl_index() |
235 | 238 | .get_decl(&decl_id)?; |
236 | | - if let LuaType::Signature(signature_id) = &decl.get_type()? { |
237 | | - Some(signature_id.clone()) |
238 | | - } else { |
239 | | - None |
| 239 | + |
| 240 | + let typ = decl.get_type()?; |
| 241 | + match typ { |
| 242 | + LuaType::Signature(_) | LuaType::DocFunction(_) => Some(vec![typ.clone()]), |
| 243 | + _ => { |
| 244 | + let key = decl.get_name(); |
| 245 | + let type_id = LuaTypeDeclId::new(decl.get_name()); |
| 246 | + let members = member_index.get_members(&LuaMemberOwner::Type(type_id))?; |
| 247 | + let functions = filter_function_members(members, key.to_string()); |
| 248 | + Some(functions) |
| 249 | + } |
240 | 250 | } |
241 | 251 | } |
242 | 252 | _ => None, |
243 | 253 | }?; |
244 | 254 |
|
245 | | - let signature = builder |
246 | | - .semantic_model |
247 | | - .get_db() |
248 | | - .get_signature_index() |
249 | | - .get(&signature_id)?; |
250 | | - |
251 | | - let call_params = call_expr_func.get_params(); |
252 | | - for overload in signature.overloads.iter() { |
253 | | - let overload_param = overload.get_params(); |
254 | | - // 前面的参数必须相同 |
255 | | - let mut is_match = true; |
256 | | - if param_idx != 0 { |
257 | | - for (i, param) in call_params.iter().enumerate() { |
258 | | - if i < param_idx { |
259 | | - if let Some(overload_param_type) = overload_param.get(i) { |
260 | | - if param.1 != overload_param_type.1 { |
261 | | - is_match = false; |
262 | | - break; |
263 | | - } |
264 | | - } |
265 | | - } else { |
266 | | - break; |
| 255 | + // 获取重载函数列表 |
| 256 | + let signature_index = builder.semantic_model.get_db().get_signature_index(); |
| 257 | + let mut overloads = Vec::new(); |
| 258 | + for function in functions { |
| 259 | + match function { |
| 260 | + LuaType::Signature(signature_id) => { |
| 261 | + if let Some(signature) = signature_index.get(&signature_id) { |
| 262 | + overloads.extend(signature.overloads.iter().cloned()); |
267 | 263 | } |
268 | 264 | } |
| 265 | + LuaType::DocFunction(doc_function) => { |
| 266 | + overloads.push(doc_function); |
| 267 | + } |
| 268 | + _ => {} |
269 | 269 | } |
270 | | - if !is_match { |
| 270 | + } |
| 271 | + |
| 272 | + // 筛选匹配的参数类型并添加到结果中 |
| 273 | + for overload in overloads.iter() { |
| 274 | + let overload_params = overload.get_params(); |
| 275 | + |
| 276 | + // 检查前面的参数是否匹配 |
| 277 | + if !params_match_prefix(call_params, overload_params, param_idx) { |
271 | 278 | continue; |
272 | 279 | } |
273 | | - if let Some(param_type) = overload.get_params().get(param_idx)?.1.clone() { |
| 280 | + |
| 281 | + // 添加匹配的参数类型 |
| 282 | + if let Some(param_type) = overload_params.get(param_idx).and_then(|p| p.1.clone()) { |
274 | 283 | types.push(param_type); |
275 | 284 | } |
276 | 285 | } |
277 | 286 |
|
| 287 | + /// 过滤出函数类型的成员 |
| 288 | + fn filter_function_members(members: Vec<&LuaMember>, key: String) -> Vec<LuaType> { |
| 289 | + members |
| 290 | + .into_iter() |
| 291 | + .filter(|it| { |
| 292 | + it.get_key().to_path() == key |
| 293 | + && matches!( |
| 294 | + it.get_decl_type(), |
| 295 | + LuaType::Signature(_) | LuaType::DocFunction(_) |
| 296 | + ) |
| 297 | + }) |
| 298 | + .map(|it| it.get_decl_type()) |
| 299 | + .collect() |
| 300 | + } |
| 301 | + |
| 302 | + /// 判断前面的参数是否匹配 |
| 303 | + fn params_match_prefix( |
| 304 | + call_params: &[(String, Option<LuaType>)], |
| 305 | + overload_params: &[(String, Option<LuaType>)], |
| 306 | + param_idx: usize, |
| 307 | + ) -> bool { |
| 308 | + if param_idx == 0 { |
| 309 | + return true; |
| 310 | + } |
| 311 | + |
| 312 | + for i in 0..param_idx { |
| 313 | + if let (Some(call_param), Some(overload_param)) = |
| 314 | + (call_params.get(i), overload_params.get(i)) |
| 315 | + { |
| 316 | + if call_param.1 != overload_param.1 { |
| 317 | + return false; |
| 318 | + } |
| 319 | + } |
| 320 | + } |
| 321 | + |
| 322 | + true |
| 323 | + } |
| 324 | + |
278 | 325 | Some(()) |
279 | 326 | } |
280 | 327 |
|
|
0 commit comments