|
1 | 1 | use std::collections::HashSet; |
2 | 2 |
|
3 | | -use emmylua_parser::{LuaAst, LuaAstNode, LuaIndexExpr, LuaIndexKey, LuaVarExpr}; |
| 3 | +use emmylua_parser::{ |
| 4 | + LuaAst, LuaAstNode, LuaElseIfClauseStat, LuaForRangeStat, LuaForStat, LuaIfStat, LuaIndexExpr, |
| 5 | + LuaIndexKey, LuaRepeatStat, LuaSyntaxKind, LuaVarExpr, LuaWhileStat, |
| 6 | +}; |
4 | 7 |
|
5 | 8 | use crate::{DiagnosticCode, InferFailReason, LuaMemberKey, LuaType, SemanticModel}; |
6 | 9 |
|
@@ -64,6 +67,17 @@ fn check_index_expr( |
64 | 67 |
|
65 | 68 | let index_key = index_expr.get_index_key()?; |
66 | 69 |
|
| 70 | + // 检查是否为判断语句 |
| 71 | + if matches!(code, DiagnosticCode::UndefinedField) { |
| 72 | + if is_in_conditional_statement(index_expr) { |
| 73 | + return Some(()); |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + if is_in_conditional_statement(index_expr) { |
| 78 | + return Some(()); |
| 79 | + } |
| 80 | + |
67 | 81 | if is_valid_member(semantic_model, &prefix_typ, index_expr, &index_key, code).is_some() { |
68 | 82 | return Some(()); |
69 | 83 | } |
@@ -324,3 +338,84 @@ fn get_key_types(typ: &LuaType) -> HashSet<LuaType> { |
324 | 338 | } |
325 | 339 | type_set |
326 | 340 | } |
| 341 | + |
| 342 | +/// 判断给定的AST节点是否位于判断语句的条件表达式中 |
| 343 | +/// |
| 344 | +/// 该函数检查节点是否位于以下语句的条件部分: |
| 345 | +/// - if语句的条件表达式 |
| 346 | +/// - while循环的条件表达式 |
| 347 | +/// - for循环的迭代表达式 |
| 348 | +/// - repeat循环的条件表达式 |
| 349 | +/// - elseif子句的条件表达式 |
| 350 | +/// |
| 351 | +/// # 参数 |
| 352 | +/// * `node` - 要检查的AST节点 |
| 353 | +/// |
| 354 | +/// # 返回值 |
| 355 | +/// * `true` - 如果节点位于判断语句的条件表达式中 |
| 356 | +/// * `false` - 如果节点不在判断语句的条件表达式中 |
| 357 | +fn is_in_conditional_statement<T: LuaAstNode>(node: &T) -> bool { |
| 358 | + let node_range = node.get_range(); |
| 359 | + |
| 360 | + // 遍历所有祖先节点,查找条件语句 |
| 361 | + for ancestor in node.syntax().ancestors() { |
| 362 | + match ancestor.kind().into() { |
| 363 | + LuaSyntaxKind::IfStat => { |
| 364 | + if let Some(if_stat) = LuaIfStat::cast(ancestor) { |
| 365 | + if let Some(condition_expr) = if_stat.get_condition_expr() { |
| 366 | + if condition_expr.get_range().contains_range(node_range) { |
| 367 | + return true; |
| 368 | + } |
| 369 | + } |
| 370 | + } |
| 371 | + } |
| 372 | + LuaSyntaxKind::WhileStat => { |
| 373 | + if let Some(while_stat) = LuaWhileStat::cast(ancestor) { |
| 374 | + if let Some(condition_expr) = while_stat.get_condition_expr() { |
| 375 | + if condition_expr.get_range().contains_range(node_range) { |
| 376 | + return true; |
| 377 | + } |
| 378 | + } |
| 379 | + } |
| 380 | + } |
| 381 | + LuaSyntaxKind::ForStat => { |
| 382 | + if let Some(for_stat) = LuaForStat::cast(ancestor) { |
| 383 | + for iter_expr in for_stat.get_iter_expr() { |
| 384 | + if iter_expr.get_range().contains_range(node_range) { |
| 385 | + return true; |
| 386 | + } |
| 387 | + } |
| 388 | + } |
| 389 | + } |
| 390 | + LuaSyntaxKind::ForRangeStat => { |
| 391 | + if let Some(for_range_stat) = LuaForRangeStat::cast(ancestor) { |
| 392 | + for expr in for_range_stat.get_expr_list() { |
| 393 | + if expr.get_range().contains_range(node_range) { |
| 394 | + return true; |
| 395 | + } |
| 396 | + } |
| 397 | + } |
| 398 | + } |
| 399 | + LuaSyntaxKind::RepeatStat => { |
| 400 | + if let Some(repeat_stat) = LuaRepeatStat::cast(ancestor) { |
| 401 | + if let Some(condition_expr) = repeat_stat.get_condition_expr() { |
| 402 | + if condition_expr.get_range().contains_range(node_range) { |
| 403 | + return true; |
| 404 | + } |
| 405 | + } |
| 406 | + } |
| 407 | + } |
| 408 | + LuaSyntaxKind::ElseIfClauseStat => { |
| 409 | + if let Some(elseif_clause) = LuaElseIfClauseStat::cast(ancestor) { |
| 410 | + if let Some(condition_expr) = elseif_clause.get_condition_expr() { |
| 411 | + if condition_expr.get_range().contains_range(node_range) { |
| 412 | + return true; |
| 413 | + } |
| 414 | + } |
| 415 | + } |
| 416 | + } |
| 417 | + _ => {} |
| 418 | + } |
| 419 | + } |
| 420 | + false |
| 421 | +} |
0 commit comments