Skip to content

Commit c2ef3e8

Browse files
committed
update keyof completion
1 parent 1c1a332 commit c2ef3e8

File tree

6 files changed

+49
-11
lines changed

6 files changed

+49
-11
lines changed

crates/emmylua_code_analysis/src/semantic/generic/instantiate_type/instantiate_special_generic.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ pub fn instantiate_alias_call(
4242
if operands.len() != 1 {
4343
return LuaType::Unknown;
4444
}
45-
// let is_tuple = operands.len() == 1 && operands[0].is_tuple();
4645

4746
let members = get_keyof_members(db, &operands[0]).unwrap_or_default();
4847
let member_key_types = members
@@ -54,13 +53,6 @@ pub fn instantiate_alias_call(
5453
})
5554
.collect::<Vec<_>>();
5655
LuaType::Tuple(LuaTupleType::new(member_key_types, LuaTupleStatus::InferResolve).into())
57-
// if is_tuple {
58-
// LuaType::Tuple(
59-
// LuaTupleType::new(member_key_types, LuaTupleStatus::InferResolve).into(),
60-
// )
61-
// } else {
62-
// LuaType::from_vec(member_key_types)
63-
// }
6456
}
6557
// 条件类型不在此处理
6658
LuaAliasCallKind::Extends => {
@@ -285,7 +277,7 @@ fn instantiate_index_call(db: &DbIndex, owner: &LuaType, key: &LuaType) -> LuaTy
285277
}
286278
}
287279

288-
fn get_keyof_members(db: &DbIndex, prefix_type: &LuaType) -> Option<Vec<LuaMemberInfo>> {
280+
pub fn get_keyof_members(db: &DbIndex, prefix_type: &LuaType) -> Option<Vec<LuaMemberInfo>> {
289281
match prefix_type {
290282
LuaType::Variadic(variadic) => match variadic.deref() {
291283
VariadicType::Base(base) => Some(vec![LuaMemberInfo {

crates/emmylua_code_analysis/src/semantic/generic/instantiate_type/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
use super::type_substitutor::{SubstitutorValue, TypeSubstitutor};
2121
use crate::TypeVisitTrait;
2222
pub use instantiate_func_generic::{build_self_type, infer_self_type, instantiate_func_generic};
23+
pub use instantiate_special_generic::get_keyof_members;
2324
pub use instantiate_special_generic::instantiate_alias_call;
2425

2526
pub fn instantiate_type_generic(

crates/emmylua_code_analysis/src/semantic/generic/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::SemanticDeclLevel;
2323
use crate::TypeOps;
2424
use crate::infer_node_semantic_decl;
2525
use crate::semantic::semantic_info::infer_token_semantic_decl;
26+
pub use instantiate_type::get_keyof_members;
2627

2728
pub fn get_tpl_ref_extend_type(
2829
db: &DbIndex,

crates/emmylua_code_analysis/src/semantic/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use overload_resolve::resolve_signature;
5858
pub use semantic_info::SemanticDeclLevel;
5959
pub use type_check::{TypeCheckFailReason, TypeCheckResult};
6060

61+
pub use generic::get_keyof_members;
6162
pub use infer::{DocTypeInferContext, infer_doc_type};
6263

6364
#[derive(Debug)]

crates/emmylua_ls/src/handlers/completion/add_completions/add_member_completion.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use emmylua_code_analysis::{
2-
DbIndex, LuaMemberInfo, LuaMemberKey, LuaSemanticDeclId, LuaType, SemanticModel,
3-
try_extract_signature_id_from_field,
2+
DbIndex, LuaAliasCallKind, LuaMemberInfo, LuaMemberKey, LuaSemanticDeclId, LuaType,
3+
SemanticModel, get_keyof_members, try_extract_signature_id_from_field,
44
};
55
use emmylua_parser::{
66
LuaAssignStat, LuaAstNode, LuaAstToken, LuaFuncStat, LuaGeneralToken, LuaIndexExpr,
@@ -44,6 +44,26 @@ pub fn add_member_completion(
4444
CompletionTriggerStatus::Dot => match member_key {
4545
LuaMemberKey::Name(name) => name.to_string(),
4646
LuaMemberKey::Integer(index) => format!("[{}]", index),
47+
LuaMemberKey::ExprType(typ) => {
48+
if let LuaType::Call(alias_call) = typ {
49+
if alias_call.get_call_kind() == LuaAliasCallKind::KeyOf
50+
&& alias_call.get_operands().len() == 1
51+
{
52+
let members = get_keyof_members(
53+
builder.semantic_model.get_db(),
54+
&alias_call.get_operands()[0],
55+
)
56+
.unwrap_or_default();
57+
let member_keys = members.iter().map(|m| m.key.clone()).collect::<Vec<_>>();
58+
for key in member_keys {
59+
let mut member_info = member_info.clone();
60+
member_info.key = key;
61+
add_member_completion(builder, member_info, status, None);
62+
}
63+
}
64+
}
65+
return None;
66+
}
4767
_ => return None,
4868
},
4969
CompletionTriggerStatus::Colon => match member_key {

crates/emmylua_ls/src/handlers/test/completion_test.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,4 +2243,27 @@ mod tests {
22432243
));
22442244
Ok(())
22452245
}
2246+
2247+
#[gtest]
2248+
fn test_keyof_enum() -> Result<()> {
2249+
let mut ws = ProviderVirtualWorkspace::new();
2250+
check!(ws.check_completion(
2251+
r#"
2252+
---@enum A
2253+
local styles = {
2254+
reset = 1
2255+
}
2256+
2257+
---@type table<keyof A, string>
2258+
local t
2259+
t.<??>
2260+
"#,
2261+
vec![VirtualCompletionItem {
2262+
label: "reset".to_string(),
2263+
kind: CompletionItemKind::VARIABLE,
2264+
..Default::default()
2265+
},],
2266+
));
2267+
Ok(())
2268+
}
22462269
}

0 commit comments

Comments
 (0)