Skip to content

Commit e835c32

Browse files
authored
Merge pull request #494 from xuhuanzy/fix
update
2 parents e785b7d + 158777c commit e835c32

Some content is hidden

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

70 files changed

+3086
-347
lines changed

crates/emmylua_code_analysis/locales/lint.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,7 @@ Cannot use `...` outside a vararg function.:
241241
en: "Duplicate index `%{name}`."
242242
zh_CN: "重复定义的索引 `%{name}`."
243243
zh_HK: "重複定義的索引 `%{name}`."
244-
244+
"the generic constraint must be a subclass of `%{source}`. %{reason}":
245+
en: "the generic constraint must be a subclass of `%{source}`. %{reason}"
246+
zh_CN: "泛型约束要求类型为 `%{source}` 子类。%{reason}"
247+
zh_HK: "泛型約束要求類型為 `%{source}` 子類。%{reason}"

crates/emmylua_code_analysis/resources/schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,13 @@
499499
"enum": [
500500
"duplicate-index"
501501
]
502+
},
503+
{
504+
"description": "generic-constraint-mismatch",
505+
"type": "string",
506+
"enum": [
507+
"generic-constraint-mismatch"
508+
]
502509
}
503510
]
504511
},

crates/emmylua_code_analysis/resources/std/global.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ function getmetatable(object) end
112112
--- will iterate over the key–value pairs (1,`t[1]`), (2,`t[2]`), ..., up to
113113
--- the first absent index.
114114
---@generic V
115-
---@param t V[] | table<any, V> | {[any]: V}
115+
---@param t V[] | table<int, V> | {[int]: V}
116116
---@return fun(tbl: any):int, V
117117
function ipairs(t) end
118118

@@ -268,7 +268,7 @@ function rawequal(v1, v2) end
268268
---
269269
--- Gets the real value of `table[index]`, the `__index` metamethod. `table`
270270
--- must be a table; `index` may be any value.
271-
---@generic T, K: integer
271+
---@generic T, K
272272
---@param table T
273273
---@param index K
274274
---@return std.RawGet<T, K>

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ fn resolve_closure_member_type(
300300
.get(&closure_params.signature_id)
301301
.ok_or(InferFailReason::None)?;
302302
let mut final_params = signature.get_type_params().to_vec();
303+
let mut final_ret = LuaType::Unknown;
303304

304305
let mut multi_function_type = Vec::new();
305306
for typ in union_types.get_types() {
@@ -374,6 +375,8 @@ fn resolve_closure_member_type(
374375
final_params.push((param.0.clone(), param.1.clone()));
375376
}
376377
}
378+
379+
final_ret = TypeOps::Union.apply(db, &final_ret, doc_func.get_ret());
377380
}
378381

379382
if !variadic_type.is_unknown() {
@@ -389,7 +392,7 @@ fn resolve_closure_member_type(
389392
signature.is_async,
390393
signature.is_colon_define,
391394
final_params,
392-
signature.get_return_type(),
395+
final_ret,
393396
),
394397
self_type,
395398
)
@@ -472,14 +475,13 @@ fn resolve_doc_function(
472475
if signature.resolve_return == SignatureReturnStatus::UnResolve
473476
|| signature.resolve_return == SignatureReturnStatus::InferResolve
474477
{
475-
if signature.return_docs.is_empty() && !doc_func.get_ret().is_nil() {
476-
signature.resolve_return = SignatureReturnStatus::DocResolve;
477-
signature.return_docs.push(LuaDocReturnInfo {
478-
name: None,
479-
type_ref: doc_func.get_ret().clone(),
480-
description: None,
481-
});
482-
}
478+
signature.resolve_return = SignatureReturnStatus::DocResolve;
479+
signature.return_docs.clear();
480+
signature.return_docs.push(LuaDocReturnInfo {
481+
name: None,
482+
type_ref: doc_func.get_ret().clone(),
483+
description: None,
484+
});
483485
}
484486

485487
Ok(())

crates/emmylua_code_analysis/src/compilation/test/annotation_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ mod test {
3838
let ty = ws.expr_ty("GG.fun");
3939
assert_eq!(
4040
format!("{:?}", ty),
41-
"Signature(LuaSignatureId { file_id: FileId { id: 14 }, position: 76 })"
41+
"Signature(LuaSignatureId { file_id: FileId { id: 13 }, position: 76 })"
4242
);
4343
}
4444

crates/emmylua_code_analysis/src/compilation/test/closure_return_test.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,38 @@ mod test {
4646
"#,
4747
));
4848
}
49+
50+
#[test]
51+
fn test_issue_464() {
52+
let mut ws = VirtualWorkspace::new();
53+
assert!(!ws.check_code_for_namespace(
54+
DiagnosticCode::ReturnTypeMismatch,
55+
r#"
56+
---@class D31
57+
---@field func? fun(a:number, b:string):number
58+
59+
---@type D31
60+
local f = {
61+
func = function(a, b)
62+
return "a"
63+
end,
64+
}
65+
"#,
66+
));
67+
68+
assert!(ws.check_code_for_namespace(
69+
DiagnosticCode::ReturnTypeMismatch,
70+
r#"
71+
---@class D31
72+
---@field func? fun(a:number, b:string):number
73+
74+
---@type D31
75+
local f = {
76+
func = function(a, b)
77+
return a
78+
end,
79+
}
80+
"#,
81+
));
82+
}
4983
}

crates/emmylua_code_analysis/src/compilation/test/flow.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,4 +782,24 @@ end
782782
"#
783783
));
784784
}
785+
786+
#[test]
787+
fn test_issue_288() {
788+
let mut ws = VirtualWorkspace::new_with_init_std_lib();
789+
790+
ws.def(
791+
r#"
792+
--- @alias MyFun fun(): string[]
793+
local f --- @type MyFun
794+
795+
if type(f) == 'function' then
796+
_, res = pcall(f)
797+
end
798+
"#,
799+
);
800+
801+
let res = ws.expr_ty("res");
802+
let res_desc = ws.humanize_type(res);
803+
assert_eq!(res_desc, "(string[]|string)");
804+
}
785805
}

crates/emmylua_code_analysis/src/compilation/test/for_range_var_infer_test.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#[cfg(test)]
22
mod test {
3-
use crate::{LuaType, VirtualWorkspace};
3+
use std::sync::Arc;
4+
5+
use crate::{LuaType, LuaUnionType, VirtualWorkspace};
46

57
#[test]
68
fn test_closure_param_infer() {
@@ -101,4 +103,51 @@ mod test {
101103
assert_eq!(a, LuaType::String);
102104
assert_eq!(b, LuaType::Integer);
103105
}
106+
107+
#[test]
108+
fn test_issue_291() {
109+
let mut ws = VirtualWorkspace::new_with_init_std_lib();
110+
111+
ws.def(
112+
r#"
113+
--- @class A
114+
--- @field [integer] string
115+
--- @field a boolean
116+
--- @field b number
117+
local a
118+
119+
for _, v in ipairs(a) do
120+
d = v
121+
end
122+
"#,
123+
);
124+
125+
assert_eq!(ws.expr_ty("d"), LuaType::String);
126+
}
127+
128+
#[test]
129+
fn test_issue_291_2() {
130+
let mut ws = VirtualWorkspace::new_with_init_std_lib();
131+
132+
ws.def(
133+
r#"
134+
--- @class A
135+
--- @field [1] string
136+
--- @field [2] number
137+
local a
138+
139+
for _, v in ipairs(a) do
140+
d = v
141+
end
142+
"#,
143+
);
144+
145+
assert_eq!(
146+
ws.expr_ty("d"),
147+
LuaType::Union(Arc::new(LuaUnionType::new(vec![
148+
LuaType::String,
149+
LuaType::Number,
150+
])))
151+
);
152+
}
104153
}

crates/emmylua_code_analysis/src/db_index/signature/signature.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use std::{collections::HashMap, sync::Arc};
66
use emmylua_parser::{LuaAstNode, LuaClosureExpr, LuaDocFuncType};
77
use rowan::TextSize;
88

9-
use crate::VariadicType;
109
use crate::{
1110
db_index::{LuaFunctionType, LuaType},
1211
FileId,
1312
};
13+
use crate::{SemanticModel, VariadicType};
1414

1515
#[derive(Debug)]
1616
pub struct LuaSignature {
@@ -117,13 +117,21 @@ impl LuaSignature {
117117
}
118118
}
119119

120-
pub fn is_method(&self) -> bool {
120+
pub fn is_method(&self, semantic_model: &SemanticModel, owner_type: Option<&LuaType>) -> bool {
121121
if self.is_colon_define {
122122
return true;
123123
}
124124

125-
if let Some(name) = self.params.first() {
126-
name == "self"
125+
if let Some(param_info) = self.get_param_info_by_id(0) {
126+
if param_info.type_ref.is_self_infer() {
127+
return true;
128+
}
129+
match owner_type {
130+
Some(owner_type) => semantic_model
131+
.type_check(owner_type, &param_info.type_ref)
132+
.is_ok(),
133+
None => param_info.name == "self",
134+
}
127135
} else {
128136
false
129137
}

crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ impl RenderLevel {
3030
}
3131
}
3232

33-
#[allow(unused)]
3433
pub fn humanize_type(db: &DbIndex, ty: &LuaType, level: RenderLevel) -> String {
3534
match ty {
3635
LuaType::Any => "any".to_string(),
@@ -80,11 +79,10 @@ pub fn humanize_type(db: &DbIndex, ty: &LuaType, level: RenderLevel) -> String {
8079
}
8180
LuaType::TplRef(tpl) => humanize_tpl_ref_type(tpl),
8281
LuaType::StrTplRef(str_tpl) => humanize_str_tpl_ref_type(str_tpl),
83-
LuaType::Variadic(multi) => humanize_multi_return_type(db, multi, level),
82+
LuaType::Variadic(multi) => humanize_variadic_type(db, multi, level),
8483
LuaType::Instance(ins) => humanize_instance_type(db, ins, level),
8584
LuaType::Signature(signature_id) => humanize_signature_type(db, signature_id, level),
8685
LuaType::Namespace(ns) => format!("{{ {} }}", ns),
87-
LuaType::Variadic(inner) => humanize_variadic_type(db, inner, level),
8886
LuaType::MultiLineUnion(multi_union) => {
8987
humanize_multi_line_union_type(db, multi_union, level)
9088
}
@@ -223,35 +221,6 @@ where
223221
}
224222
}
225223

226-
fn humanize_variadic_type(db: &DbIndex, multi: &VariadicType, level: RenderLevel) -> String {
227-
match multi {
228-
VariadicType::Base(base) => {
229-
let base_str = humanize_type(db, base, level.next_level());
230-
format!("{} ...", base_str)
231-
}
232-
VariadicType::Multi(types) => {
233-
let num = match level {
234-
RenderLevel::Detailed => 10,
235-
RenderLevel::Simple => 8,
236-
RenderLevel::Normal => 4,
237-
RenderLevel::Brief => 2,
238-
RenderLevel::Minimal => {
239-
return "multi<...>".to_string();
240-
}
241-
};
242-
243-
let dots = if types.len() > num { ", ..." } else { "" };
244-
let type_str = types
245-
.iter()
246-
.take(num)
247-
.map(|ty| humanize_type(db, ty, level.next_level()))
248-
.collect::<Vec<_>>()
249-
.join(",");
250-
format!("({}{})", type_str, dots)
251-
}
252-
}
253-
}
254-
255224
fn humanize_multi_line_union_type(
256225
db: &DbIndex,
257226
multi_union: &LuaMultiLineUnion,
@@ -372,8 +341,15 @@ fn humanize_doc_function_type(
372341
.join(", ");
373342

374343
let ret_type = lua_func.get_ret();
344+
let return_nil = match ret_type {
345+
LuaType::Variadic(variadic) => match variadic.get_type(0) {
346+
Some(LuaType::Nil) => true,
347+
_ => false,
348+
},
349+
_ => ret_type.is_nil(),
350+
};
375351

376-
if ret_type.is_nil() {
352+
if return_nil {
377353
return format!("{}({})", prev, params);
378354
}
379355

@@ -611,14 +587,14 @@ fn humanize_str_tpl_ref_type(str_tpl: &LuaStringTplType) -> String {
611587
}
612588
}
613589

614-
fn humanize_multi_return_type(db: &DbIndex, multi: &VariadicType, level: RenderLevel) -> String {
590+
fn humanize_variadic_type(db: &DbIndex, multi: &VariadicType, level: RenderLevel) -> String {
615591
match multi {
616592
VariadicType::Base(base) => {
617593
let base_str = humanize_type(db, base, level);
618594
format!("{} ...", base_str)
619595
}
620596
VariadicType::Multi(types) => {
621-
let num = match level {
597+
let max_num = match level {
622598
RenderLevel::Detailed => 10,
623599
RenderLevel::Simple => 8,
624600
RenderLevel::Normal => 4,
@@ -628,10 +604,10 @@ fn humanize_multi_return_type(db: &DbIndex, multi: &VariadicType, level: RenderL
628604
}
629605
};
630606

631-
let dots = if types.len() > num { ", ..." } else { "" };
607+
let dots = if types.len() > max_num { ", ..." } else { "" };
632608
let type_str = types
633609
.iter()
634-
.take(num)
610+
.take(max_num)
635611
.map(|ty| humanize_type(db, ty, level.next_level()))
636612
.collect::<Vec<_>>()
637613
.join(",");

0 commit comments

Comments
 (0)