Skip to content

Commit 1952445

Browse files
committed
fix select function
1 parent 8be78e1 commit 1952445

File tree

8 files changed

+121
-36
lines changed

8 files changed

+121
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
`FIX` custom operator infer
1919

20-
20+
`FIX` Fix select function and add std.Select type
2121

2222
# 0.5.1
2323

crates/emmylua_code_analysis/resources/std/builtin.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@
106106

107107
---@class function
108108

109-
---@alias NotNull<T> T - ?
109+
---@alias std.NotNull<T> T - ?
110110

111-
---@alias Nullable<T> T + ?
111+
---@alias std.Nullable<T> T + ?
112112

113113
--- built-in type for Select function
114-
---@alias Select<T, StartOrLen> unknown
114+
---@alias std.Select<T, StartOrLen> unknown
115115
---
116116
--- built-in type for Unpack function
117-
---@alias Unpack<T, Start, End> unknown
117+
---@alias std.Unpack<T, Start, End> unknown

crates/emmylua_code_analysis/resources/std/global.lua

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
---@generic T
2222
---@param v T
2323
---@param message? string
24-
---@return NotNull<T>
24+
---@return std.NotNull<T>
2525
function assert(v, message) end
2626

2727
---
@@ -105,7 +105,7 @@ function getmetatable(object) end
105105
--- the first absent index.
106106
---@generic V
107107
---@param t table<any, V> | V[]
108-
---@return fun(tbl: any):int, NotNull<V>
108+
---@return fun(tbl: any):int, std.NotNull<V>
109109
function ipairs(t) end
110110

111111
---
@@ -216,7 +216,7 @@ function next(table, index) end
216216
--- traversal.
217217
---@generic K, V
218218
---@param t table<K, V> | V[]
219-
---@return fun(tbl: any):K, NotNull<V>
219+
---@return fun(tbl: any):K, std.NotNull<V>
220220
function pairs(t) end
221221
---
222222
--- Calls function `f` with the given arguments in *protected mode*. This
@@ -311,8 +311,8 @@ function require(modname) end
311311
--- the total number of extra arguments it received.
312312
---@generic T, Num: integer | '#'
313313
---@param index Num
314-
---@param ... T
315-
---@return Select<T, Num>
314+
---@param ... T...
315+
---@return std.Select<T..., Num>
316316
function select(index, ...) end
317317

318318
---
@@ -343,15 +343,12 @@ function setmetatable(table, metatable) end
343343
--- represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. If
344344
--- the string `e` is not a valid numeral in the given base, the function
345345
--- returns **nil**.
346-
---@overload fun(e:number):number
347-
---@overload fun(e:number, base: int):number
348-
---@overload fun(e:string):number|nil
349-
---@overload fun(e:string, base: int):number|nil
350-
---@overload fun(e:any):nil
351-
---@overload fun(e:any, base:int):nil
346+
---@overload fun(e:number, base?: int):number
347+
---@overload fun(e:string, base?: int):number?
348+
---@overload fun(e:any, base?:int):nil
352349
---@param e any
353350
---@param base? int
354-
---@return number|nil
351+
---@return number?
355352
function tonumber(e, base) end
356353

357354
---

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

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,49 @@ impl LuaMultiReturn {
756756
}
757757
}
758758

759-
pub fn get_len(&self) -> usize {
759+
pub fn get_len(&self) -> Option<i64> {
760760
match self {
761-
LuaMultiReturn::Multi(types) => types.len(),
762-
LuaMultiReturn::Base(_) => 1,
761+
LuaMultiReturn::Base(_) => None,
762+
LuaMultiReturn::Multi(types) => {
763+
let basic_len = types.len() as i64;
764+
if basic_len == 0 {
765+
return Some(0);
766+
}
767+
768+
if let Some(LuaType::MuliReturn(last_multi)) = types.last() {
769+
let last_element_len = last_multi.get_len();
770+
return match last_element_len {
771+
Some(len) => Some(basic_len - 1 + len),
772+
None => None,
773+
};
774+
}
775+
776+
Some(basic_len)
777+
}
778+
}
779+
}
780+
781+
pub fn get_new_multi_from(&self, idx: usize) -> LuaMultiReturn {
782+
match self {
783+
LuaMultiReturn::Multi(types) => {
784+
if types.len() == 0 {
785+
return LuaMultiReturn::Multi(Vec::new());
786+
}
787+
788+
let mut new_types = Vec::new();
789+
if idx < types.len() {
790+
new_types.extend_from_slice(&types[idx..]);
791+
} else {
792+
let last = types.len() - 1;
793+
if let LuaType::MuliReturn(multi) = &types[last] {
794+
let rest_offset = idx - last;
795+
return multi.get_new_multi_from(rest_offset);
796+
}
797+
}
798+
799+
LuaMultiReturn::Multi(new_types)
800+
}
801+
LuaMultiReturn::Base(t) => LuaMultiReturn::Base(t.clone()),
763802
}
764803
}
765804

crates/emmylua_code_analysis/src/semantic/instantiate/instantiate_class_generic.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -443,25 +443,30 @@ fn instantiate_select_call(source: &LuaType, index: &LuaType) -> LuaType {
443443
match num_or_len {
444444
NumOrLen::Num(i) => match multi_return {
445445
LuaMultiReturn::Base(_) => LuaType::MuliReturn(multi_return.clone().into()),
446-
LuaMultiReturn::Multi(types) => {
447-
let start = if i < 0 { types.len() as i64 + i } else { i - 1 };
448-
if start < 0 || start as usize >= types.len() {
449-
return LuaType::Unknown;
446+
LuaMultiReturn::Multi(_) => {
447+
let total_len = multi_return.get_len();
448+
if total_len.is_none() {
449+
return source.clone();
450450
}
451451

452-
let new_types = types
453-
.iter()
454-
.skip(start as usize)
455-
.cloned()
456-
.collect::<Vec<_>>();
452+
let total_len = total_len.unwrap();
453+
let start = if i < 0 { total_len as i64 + i } else { i - 1 };
454+
if start < 0 || start >= total_len {
455+
return source.clone();
456+
}
457457

458-
LuaType::MuliReturn(LuaMultiReturn::Multi(new_types).into())
458+
let multi = multi_return.get_new_multi_from(start as usize);
459+
LuaType::MuliReturn(multi.into())
459460
}
460461
},
461-
NumOrLen::Len => match multi_return {
462-
LuaMultiReturn::Base(_) => LuaType::Integer,
463-
LuaMultiReturn::Multi(types) => LuaType::DocIntegerConst(types.len() as i64),
464-
},
462+
NumOrLen::Len => {
463+
let len = multi_return.get_len();
464+
if let Some(len) = len {
465+
LuaType::IntegerConst(len)
466+
} else {
467+
LuaType::Integer
468+
}
469+
}
465470
NumOrLen::LenUnknown => LuaType::Integer,
466471
}
467472
}

crates/emmylua_code_analysis/src/semantic/instantiate/instantiate_func_generic.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
};
1010

1111
use super::{
12-
instantiate_class_generic::instantiate_doc_function, tpl_pattern::tpl_pattern_match,
12+
instantiate_class_generic::instantiate_doc_function, tpl_pattern::{tpl_pattern_match, variadic_tpl_pattern_match},
1313
type_substitutor::TypeSubstitutor,
1414
};
1515

@@ -86,6 +86,12 @@ fn match_tpl_args(
8686
continue;
8787
};
8888

89+
if let LuaType::Variadic(inner) = func_param_type {
90+
let rest_arg_types = &arg_types[i..];
91+
variadic_tpl_pattern_match(&inner, rest_arg_types, &mut substitutor);
92+
break;
93+
}
94+
8995
tpl_pattern_match(
9096
db,
9197
infer_config,

crates/emmylua_code_analysis/src/semantic/instantiate/test.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,42 @@ mod test {
2525
let expected = ws.ty("async fun(a: number, b: string, c:boolean): number");
2626
assert_eq!(ty, expected);
2727
}
28+
29+
#[test]
30+
fn test_select_type() {
31+
let mut ws = crate::VirtualWorkspace::new_with_init_std_lib();
32+
ws.def(r#"
33+
---@param ... string
34+
function ffff(...)
35+
a, b, c = select(2, ...)
36+
end
37+
"#);
38+
39+
let a_ty = ws.expr_ty("a");
40+
let b_ty = ws.expr_ty("b");
41+
let c_ty = ws.expr_ty("c");
42+
let expected = ws.ty("string");
43+
assert_eq!(a_ty, expected);
44+
assert_eq!(b_ty, expected);
45+
assert_eq!(c_ty, expected);
46+
47+
ws.def(r#"
48+
e, f = select(2, "a", "b", "c")
49+
"#);
50+
51+
let e = ws.expr_ty("e");
52+
let expected = ws.expr_ty("'b'");
53+
let f = ws.expr_ty("f");
54+
let expected_f = ws.expr_ty("'c'");
55+
assert_eq!(e, expected);
56+
assert_eq!(f, expected_f);
57+
58+
ws.def(r#"
59+
h = select('#', "a", "b")
60+
"#);
61+
62+
let h = ws.expr_ty("h");
63+
let expected = ws.expr_ty("2");
64+
assert_eq!(h, expected);
65+
}
2866
}

crates/emmylua_code_analysis/src/semantic/instantiate/tpl_pattern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ fn func_varargs_tpl_pattern_match(
303303
Some(())
304304
}
305305

306-
fn variadic_tpl_pattern_match(
306+
pub fn variadic_tpl_pattern_match(
307307
tpl: &LuaType,
308308
target_rest_types: &[LuaType],
309309
substitutor: &mut TypeSubstitutor,

0 commit comments

Comments
 (0)