Skip to content

Commit 9e68126

Browse files
authored
Merge pull request #404 from xuhuanzy/completion
update
2 parents 8d6b25a + a39122d commit 9e68126

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2706
-740
lines changed

crates/emmylua_code_analysis/locales/lint.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,12 @@ Cannot use `...` outside a vararg function.:
233233
en: "Duplicate class constructor '%{name}'. constructor must have only one."
234234
zh_CN: "类有重复的 (constructor) 定义 '%{name}'。(constructor) 必须只有一个。"
235235
zh_HK: "類有重複的 (constructor) 定義 '%{name}'。(constructor) 必須只有一個。"
236+
"Duplicate field `%{name}`.":
237+
en: "Duplicate field `%{name}`."
238+
zh_CN: "重复定义的字段 `%{name}`."
239+
zh_HK: "重複定義的字段 `%{name}`."
240+
"Duplicate index `%{name}`.":
241+
en: "Duplicate index `%{name}`."
242+
zh_CN: "重复定义的索引 `%{name}`."
243+
zh_HK: "重複定義的索引 `%{name}`."
236244

crates/emmylua_code_analysis/resources/schema.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,20 @@
474474
"enum": [
475475
"unnecessary-if"
476476
]
477+
},
478+
{
479+
"description": "duplicate-set-field",
480+
"type": "string",
481+
"enum": [
482+
"duplicate-set-field"
483+
]
484+
},
485+
{
486+
"description": "duplicate-index",
487+
"type": "string",
488+
"enum": [
489+
"duplicate-index"
490+
]
477491
}
478492
]
479493
},

crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option<
5858
};
5959

6060
if nullable && !field_type.is_nullable() {
61-
field_type = TypeOps::Union.apply(&field_type, &LuaType::Nil);
61+
field_type = TypeOps::Union.apply(analyzer.db, &field_type, &LuaType::Nil);
6262
}
6363

6464
let description = if let Some(description) = tag.get_description() {

crates/emmylua_code_analysis/src/compilation/analyzer/doc/infer_type.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn infer_type(analyzer: &mut DocAnalyzer, node: LuaDocType) -> LuaType {
3535
}
3636

3737
if !t.is_nullable() {
38-
return TypeOps::Union.apply(&t, &LuaType::Nil);
38+
return TypeOps::Union.apply(analyzer.db, &t, &LuaType::Nil);
3939
}
4040

4141
return t;
@@ -408,7 +408,7 @@ fn infer_func_type(analyzer: &mut DocAnalyzer, func: &LuaDocFuncType) -> LuaType
408408
let type_ref = if let Some(type_ref) = param.get_type() {
409409
let mut typ = infer_type(analyzer, type_ref);
410410
if nullable && !typ.is_nullable() {
411-
typ = TypeOps::Union.apply(&typ, &LuaType::Nil);
411+
typ = TypeOps::Union.apply(analyzer.db, &typ, &LuaType::Nil);
412412
}
413413
Some(typ)
414414
} else {
@@ -505,7 +505,7 @@ fn infer_object_type(analyzer: &mut DocAnalyzer, object_type: &LuaDocObjectType)
505505
};
506506

507507
if field.is_nullable() {
508-
type_ref = TypeOps::Union.apply(&type_ref, &LuaType::Nil);
508+
type_ref = TypeOps::Union.apply(analyzer.db, &type_ref, &LuaType::Nil);
509509
}
510510

511511
fields.push((key, type_ref));

crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub fn analyze_param(analyzer: &mut DocAnalyzer, tag: LuaDocTagParam) -> Option<
109109
};
110110

111111
if nullable && !type_ref.is_nullable() {
112-
type_ref = TypeOps::Union.apply(&type_ref, &LuaType::Nil);
112+
type_ref = TypeOps::Union.apply(analyzer.db, &type_ref, &LuaType::Nil);
113113
}
114114

115115
let description = if let Some(des) = tag.get_description() {

crates/emmylua_code_analysis/src/compilation/analyzer/lua/closure.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,11 @@ fn analyze_return(
160160
.db
161161
.get_signature_index_mut()
162162
.get_or_create(signature_id.clone());
163-
signature.return_docs = returns;
163+
164164
signature.resolve_return = SignatureReturnStatus::InferResolve;
165+
166+
signature.return_docs = returns;
167+
165168
Some(())
166169
}
167170

@@ -202,7 +205,7 @@ pub fn analyze_return_point(
202205
match point {
203206
LuaReturnPoint::Expr(expr) => {
204207
let expr_type = infer_expr(db, cache, expr.clone())?;
205-
return_type = TypeOps::Union.apply(&return_type, &expr_type);
208+
return_type = TypeOps::Union.apply(db, &return_type, &expr_type);
206209
}
207210
LuaReturnPoint::MuliExpr(exprs) => {
208211
let mut multi_return = vec![];
@@ -211,10 +214,10 @@ pub fn analyze_return_point(
211214
multi_return.push(expr_type);
212215
}
213216
let typ = LuaType::Variadic(VariadicType::Multi(multi_return).into());
214-
return_type = TypeOps::Union.apply(&return_type, &typ);
217+
return_type = TypeOps::Union.apply(db, &return_type, &typ);
215218
}
216219
LuaReturnPoint::Nil => {
217-
return_type = TypeOps::Union.apply(&return_type, &LuaType::Nil);
220+
return_type = TypeOps::Union.apply(db, &return_type, &LuaType::Nil);
218221
}
219222
_ => {}
220223
}

crates/emmylua_code_analysis/src/compilation/analyzer/lua/for_range_stat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn analyze_for_range_stat(
3131
.get_type(idx)
3232
.cloned()
3333
.unwrap_or(LuaType::Unknown);
34-
let ret_type = TypeOps::Remove.apply(&ret_type, &LuaType::Nil);
34+
let ret_type = TypeOps::Remove.apply(analyzer.db, &ret_type, &LuaType::Nil);
3535
analyzer
3636
.db
3737
.get_type_index_mut()

crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ pub fn try_resolve_iter_var(
286286
.get_type(iter_var.ret_idx)
287287
.cloned()
288288
.unwrap_or(LuaType::Unknown);
289-
iter_type = TypeOps::Remove.apply(&iter_type, &LuaType::Nil);
289+
iter_type = TypeOps::Remove.apply(db, &iter_type, &LuaType::Nil);
290290
let decl_id = iter_var.decl_id;
291291
bind_type(
292292
db,

crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve_closure.rs

Lines changed: 120 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use std::sync::Arc;
2+
13
use emmylua_parser::{LuaAstNode, LuaTableExpr, LuaVarExpr};
24

35
use crate::{
46
infer_call_expr_func, infer_expr, infer_member_map, infer_table_should_be, DbIndex,
57
InferFailReason, InferGuard, LuaDocParamInfo, LuaDocReturnInfo, LuaFunctionType, LuaInferCache,
6-
LuaMemberInfo, LuaSemanticDeclId, LuaSignatureId, LuaType, LuaTypeDeclId,
7-
SignatureReturnStatus,
8+
LuaMemberInfo, LuaSemanticDeclId, LuaSignatureId, LuaType, LuaTypeDeclId, LuaUnionType,
9+
SignatureReturnStatus, TypeOps,
810
};
911

1012
use super::{
@@ -232,7 +234,6 @@ pub fn try_resolve_closure_parent_params(
232234
}
233235
};
234236
self_type = Some(typ.clone());
235-
236237
find_best_function_type(db, cache, &typ, &closure_params.signature_id)
237238
}
238239
_ => return Some(true),
@@ -277,8 +278,9 @@ pub fn try_resolve_closure_parent_params(
277278
}
278279
};
279280

280-
let Some(member_type) = member_type else {
281-
return Some(true);
281+
let member_type = match member_type {
282+
Some(member_type) => member_type,
283+
None => return Some(true),
282284
};
283285

284286
match &member_type {
@@ -298,6 +300,59 @@ pub fn try_resolve_closure_parent_params(
298300
Some(true)
299301
}
300302
}
303+
LuaType::Union(union_types) => {
304+
let mut final_params = signature.get_type_params().to_vec();
305+
for typ in union_types.get_types() {
306+
let LuaType::DocFunction(doc_func) = typ else {
307+
continue;
308+
};
309+
let mut doc_params = doc_func.get_params().to_vec();
310+
match (doc_func.is_colon_define(), signature.is_colon_define) {
311+
(true, true) | (false, false) => {}
312+
(true, false) => {
313+
// 原始签名是冒号定义, 但未解析的签名不是冒号定义, 即要插入第一个参数
314+
doc_params.insert(0, ("self".to_string(), Some(LuaType::SelfInfer)));
315+
}
316+
(false, true) => {
317+
// 原始签名不是冒号定义, 但未解析的签名是冒号定义, 即要删除第一个参数
318+
doc_params.remove(0);
319+
}
320+
}
321+
// 如果第一个参数是 self, 则需要将 self 的类型设置为 self_type
322+
if doc_params.get(0).map_or(false, |(_, typ)| match typ {
323+
Some(LuaType::SelfInfer) => true,
324+
_ => false,
325+
}) {
326+
if let Some(self_type) = &self_type {
327+
doc_params[0].1 = Some(self_type.clone());
328+
}
329+
}
330+
for (idx, param) in doc_params.iter().enumerate() {
331+
if let Some(final_param) = final_params.get(idx) {
332+
if final_param.0 == "..." {
333+
continue;
334+
}
335+
let new_type = TypeOps::Union.apply(
336+
db,
337+
final_param.1.as_ref().unwrap_or(&LuaType::Unknown),
338+
param.1.as_ref().unwrap_or(&LuaType::Unknown),
339+
);
340+
final_params[idx] = (final_param.0.clone(), Some(new_type));
341+
}
342+
}
343+
}
344+
resolve_doc_function(
345+
db,
346+
closure_params,
347+
&LuaFunctionType::new(
348+
signature.is_async,
349+
signature.is_colon_define,
350+
final_params,
351+
signature.get_return_type(),
352+
),
353+
self_type,
354+
)
355+
}
301356
_ => Some(true),
302357
}
303358
}
@@ -363,7 +418,6 @@ fn resolve_doc_function(
363418
description: None,
364419
});
365420
}
366-
367421
Some(true)
368422
}
369423

@@ -385,47 +439,80 @@ fn find_best_function_type(
385439
prefix_type: &LuaType,
386440
signature_id: &LuaSignatureId,
387441
) -> Option<LuaType> {
388-
let member_info_map = infer_member_map(db, &prefix_type)?;
442+
let member_info_map = infer_member_map(db, prefix_type)?;
389443
let mut current_type_id = None;
390-
// 如果找不到证明是重定义
444+
391445
let target_infos = member_info_map.into_values().find(|infos| {
392-
infos.iter().any(|info| match &info.typ {
393-
LuaType::Signature(id) => {
446+
infos.iter().any(|info| {
447+
if let LuaType::Signature(id) = &info.typ {
394448
if id == signature_id {
395449
current_type_id = get_owner_type_id(db, info);
396450
return true;
397451
}
398-
false
399452
}
400-
_ => false,
453+
false
401454
})
402455
})?;
403-
// 找到第一个具有实际参数类型的签名
404-
target_infos.iter().find_map(|info| {
405-
// 所有者类型一致, 但我们找的是父类型
406-
if get_owner_type_id(db, info) == current_type_id {
407-
return None;
408-
}
456+
457+
let mut current_function_types = Vec::with_capacity(target_infos.len());
458+
// 父类或许也应该返回联合类型
459+
let mut parent_function_type = None;
460+
461+
for info in target_infos {
409462
let function_type =
410-
get_final_function_type(db, cache, &info.typ).unwrap_or(info.typ.clone());
411-
let param_type_len = match &function_type {
463+
get_final_function_type(db, cache, &info.typ).unwrap_or_else(|| info.typ.clone());
464+
465+
// 所有者类型一致, 不是父类
466+
if get_owner_type_id(db, &info) == current_type_id {
467+
match &function_type {
468+
LuaType::Signature(id) => {
469+
if let Some(cur_signature) = db.get_signature_index().get(id) {
470+
// 只需要重载声明
471+
if cur_signature.param_docs.is_empty() {
472+
current_function_types.extend(cur_signature.overloads.iter().cloned());
473+
}
474+
}
475+
}
476+
LuaType::DocFunction(doc_func) => {
477+
// 使用迭代器优化参数计数
478+
if doc_func.get_params().iter().any(|(_, typ)| typ.is_some()) {
479+
current_function_types.push(doc_func.clone());
480+
}
481+
}
482+
_ => {}
483+
}
484+
continue;
485+
}
486+
487+
// 父类处理
488+
let has_params = match &function_type {
412489
LuaType::Signature(id) => db
413490
.get_signature_index()
414-
.get(&id)
415-
.map(|sig| sig.param_docs.len())
416-
.unwrap_or(0),
417-
LuaType::DocFunction(doc_func) => doc_func
418-
.get_params()
419-
.iter()
420-
.filter(|(_, typ)| typ.is_some())
421-
.count(),
422-
_ => 0, // 跳过其他类型
491+
.get(id)
492+
.map_or(false, |sig| !sig.param_docs.is_empty()),
493+
LuaType::DocFunction(doc_func) => {
494+
doc_func.get_params().iter().any(|(_, typ)| typ.is_some())
495+
}
496+
_ => false,
423497
};
424-
if param_type_len > 0 {
425-
return Some(function_type.clone());
498+
499+
if has_params {
500+
parent_function_type = Some(function_type);
426501
}
427-
None
428-
})
502+
}
503+
match current_function_types.len() {
504+
0 => parent_function_type,
505+
1 => current_function_types
506+
.into_iter()
507+
.next()
508+
.map(LuaType::DocFunction),
509+
_ => Some(LuaType::Union(Arc::new(LuaUnionType::new(
510+
current_function_types
511+
.into_iter()
512+
.map(LuaType::DocFunction)
513+
.collect(),
514+
)))),
515+
}
429516
}
430517

431518
fn get_final_function_type(

0 commit comments

Comments
 (0)