Skip to content

Commit 58f4340

Browse files
committed
infer_index 优化, 允许 key 为 alias
1 parent 5da9a28 commit 58f4340

File tree

1 file changed

+166
-34
lines changed

1 file changed

+166
-34
lines changed

crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs

Lines changed: 166 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ fn infer_custom_type_member(
224224
let owner = LuaMemberOwner::Type(prefix_type_id.clone());
225225
let index_key = index_expr.get_index_key().ok_or(InferFailReason::None)?;
226226
let key: LuaMemberKey = index_key.clone().into();
227+
dbg!(&db.get_member_index().get_members(&owner));
227228
if let Some(member_item) = db.get_member_index().get_member_item(&owner, &key) {
228229
return member_item.resolve_type(db);
229230
}
@@ -254,9 +255,12 @@ fn infer_custom_type_member(
254255
if let LuaIndexKey::Expr(expr) = index_key {
255256
if let Some(keys) = expr_to_member_key(db, cache, &expr) {
256257
let mut result_type = Vec::new();
258+
dbg!(&keys);
257259
for key in keys {
258-
// 解决 enum[enum] 的情况
259-
if let Some(member_type) = get_enum_members(db, type_decl, &key, &owner) {
260+
// 解决 enum[enum] | class[class] 的情况
261+
if let Some(member_type) =
262+
get_expr_key_members(db, type_decl, &key, &owner, cache, infer_guard, &index_expr)
263+
{
260264
if !result_type.contains(&member_type) {
261265
result_type.push(member_type);
262266
}
@@ -282,65 +286,193 @@ fn infer_custom_type_member(
282286
Err(InferFailReason::FieldDotFound)
283287
}
284288

285-
fn get_enum_members(
289+
#[allow(unused)]
290+
fn get_expr_key_members(
286291
db: &DbIndex,
287292
type_decl: &LuaTypeDecl,
288293
key: &LuaMemberKey,
289294
owner: &LuaMemberOwner,
295+
cache: &mut LuaInferCache,
296+
infer_guard: &mut InferGuard,
297+
index_expr: &LuaIndexMemberExpr,
290298
) -> Option<LuaType> {
291-
if !type_decl.is_enum() {
292-
return None;
293-
}
294-
let LuaMemberKey::Expr(LuaType::Ref(id)) = key else {
299+
// if !type_decl.is_enum() {
300+
// return None;
301+
// }
302+
let LuaMemberKey::Expr(LuaType::Ref(index_id)) = key else {
295303
return None;
296304
};
297-
let index_type_decl = db.get_type_index().get_type_decl(id)?;
305+
let index_type_decl = db.get_type_index().get_type_decl(index_id)?;
298306
let mut result = Vec::new();
299307

300-
// 此时是 enum[enum] 的情况
301-
if index_type_decl == type_decl {
302-
// 只在包含 [key] 属性时才允许
303-
if !type_decl.is_enum_key() {
304-
return None;
305-
}
306-
307-
let members = &db.get_member_index().get_members(&owner)?;
308-
for member in members {
309-
db.get_type_index()
310-
.get_type_cache(&member.get_id().into())
311-
.map(|it| it.as_type())
312-
.map(|it| result.push(it.clone()));
308+
let origin_type = if index_type_decl.is_alias() {
309+
index_type_decl.get_alias_origin(db, None)?
310+
} else {
311+
LuaType::Ref(index_id.clone())
312+
};
313+
let mut member_keys = Vec::new();
314+
get_all_member_key(db, index_type_decl, &origin_type, &mut member_keys);
315+
for key in member_keys {
316+
if let Some(member_item) = db.get_member_index().get_member_item(&owner, &key) {
317+
if let Ok(member_type) = member_item.resolve_type(db) {
318+
if !result.contains(&member_type) {
319+
result.push(member_type);
320+
}
321+
}
313322
}
314323
}
315324

325+
// 此时是 enum[enum] 的情况
326+
// if index_type_decl == type_decl {
327+
// // 只在包含 [key] 属性时才允许
328+
// if !type_decl.is_enum_key() {
329+
// return None;
330+
// }
331+
332+
// match db.get_member_index().get_members(&owner) {
333+
// Some(members) => {
334+
// for member in members {
335+
// db.get_type_index()
336+
// .get_type_cache(&member.get_id().into())
337+
// .map(|it| it.as_type())
338+
// .map(|it| result.push(it.clone()));
339+
// }
340+
// }
341+
// // enum 没有成员时, 返回 unknown
342+
// None => {
343+
// result.push(LuaType::Unknown);
344+
// }
345+
// }
346+
// }
347+
316348
if index_type_decl.is_alias() {
317-
let origin_type = index_type_decl.get_alias_origin(db, None)?;
318-
if let LuaType::MultiLineUnion(types) = &origin_type {
349+
// let origin_type = index_type_decl.get_alias_origin(db, None)?;
350+
// let mut member_keys = Vec::new();
351+
// get_all_member_key(db, index_type_decl, &origin_type, &mut member_keys);
352+
// for key in member_keys {
353+
// if let Some(member_item) = db.get_member_index().get_member_item(&owner, &key) {
354+
// if let Ok(member_type) = member_item.resolve_type(db) {
355+
// if !result.contains(&member_type) {
356+
// result.push(member_type);
357+
// }
358+
// }
359+
// }
360+
// }
361+
// dbg!(&member_keys);
362+
// dbg!(&origin_type);
363+
// match &origin_type {
364+
// LuaType::Union(union_type) => {
365+
// for typ in union_type.get_types() {
366+
// match typ {
367+
// LuaType::Ref(id) => {
368+
// let type_decl = db.get_type_index().get_type_decl(id)?;
369+
// dbg!(&type_decl);
370+
// if type_decl.is_enum() {
371+
// let a = infer_member_by_member_key(
372+
// db,
373+
// cache,
374+
// typ,
375+
// index_expr.clone(),
376+
// infer_guard,
377+
// );
378+
// dbg!(&a);
379+
// }
380+
// }
381+
// _ => {}
382+
// }
383+
// }
384+
// }
385+
// _ => {}
386+
// }
387+
388+
// if let LuaType::MultiLineUnion(types) = &origin_type {
389+
// for (typ, _) in types.get_unions() {
390+
// let member_key: LuaMemberKey = match typ {
391+
// LuaType::DocStringConst(s) => (*s).to_string().into(),
392+
// LuaType::IntegerConst(i) => (*i).into(),
393+
// _ => continue,
394+
// };
395+
396+
// if let Some(member_item) =
397+
// db.get_member_index().get_member_item(&owner, &member_key)
398+
// {
399+
// if let Ok(member_type) = member_item.resolve_type(db) {
400+
// if !result.contains(&member_type) {
401+
// result.push(member_type);
402+
// }
403+
// }
404+
// }
405+
// }
406+
// }
407+
}
408+
409+
return match result.len() {
410+
0 => None,
411+
1 => Some(result[0].clone()),
412+
_ => Some(LuaType::Union(LuaUnionType::new(result).into())),
413+
};
414+
}
415+
416+
fn get_all_member_key(
417+
db: &DbIndex,
418+
index_type_decl: &LuaTypeDecl,
419+
origin_type: &LuaType,
420+
result: &mut Vec<LuaMemberKey>,
421+
) -> Option<()> {
422+
match &origin_type {
423+
LuaType::MultiLineUnion(types) => {
319424
for (typ, _) in types.get_unions() {
320425
let member_key: LuaMemberKey = match typ {
321426
LuaType::DocStringConst(s) => (*s).to_string().into(),
322427
LuaType::IntegerConst(i) => (*i).into(),
323428
_ => continue,
324429
};
325430

326-
if let Some(member_item) =
327-
db.get_member_index().get_member_item(&owner, &member_key)
328-
{
329-
if let Ok(member_type) = member_item.resolve_type(db) {
330-
if !result.contains(&member_type) {
331-
result.push(member_type);
431+
result.push(member_key);
432+
}
433+
}
434+
LuaType::Union(union_type) => {
435+
for typ in union_type.get_types() {
436+
if let LuaType::Ref(_) = typ {
437+
get_all_member_key(db, index_type_decl, typ, result)?;
438+
}
439+
}
440+
}
441+
LuaType::Ref(id) => {
442+
let type_decl = db.get_type_index().get_type_decl(id)?;
443+
if type_decl.is_enum() {
444+
let owner = LuaMemberOwner::Type(id.clone());
445+
if let Some(members) = db.get_member_index().get_members(&owner) {
446+
let is_enum_key = type_decl.is_enum_key();
447+
for member in members {
448+
if is_enum_key {
449+
result.push(member.get_key().clone());
450+
} else {
451+
let typ = db
452+
.get_type_index()
453+
.get_type_cache(&member.get_id().into())
454+
.map(|it| it.as_type());
455+
if let Some(typ) = typ {
456+
let member_key: LuaMemberKey = match typ {
457+
LuaType::DocStringConst(s) | LuaType::StringConst(s) => {
458+
(*s).to_string().into()
459+
}
460+
LuaType::DocIntegerConst(i) | LuaType::IntegerConst(i) => {
461+
(*i).into()
462+
}
463+
_ => continue,
464+
};
465+
result.push(member_key);
466+
}
332467
}
333468
}
334469
}
335470
}
336471
}
472+
_ => {}
337473
}
338474

339-
return match result.len() {
340-
0 => None,
341-
1 => Some(result[0].clone()),
342-
_ => Some(LuaType::Union(LuaUnionType::new(result).into())),
343-
};
475+
Some(())
344476
}
345477

346478
fn infer_tuple_member(tuple_type: &LuaTupleType, index_expr: LuaIndexMemberExpr) -> InferResult {

0 commit comments

Comments
 (0)