Skip to content

Commit 0dc5f80

Browse files
committed
Fix enum crash issue
1 parent 2608aa1 commit 0dc5f80

File tree

3 files changed

+69
-45
lines changed

3 files changed

+69
-45
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
---
66
## [0.8.2] - Unreleased
77

8+
### 🐛 Fixed
9+
- **Enum Variable Parameter Issue**: Fixed a crash issue when checking enum variable as parameter
10+
811
## [0.8.1] - 2025-6-14
912

1013
### 🔧 Changed

crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -438,16 +438,10 @@ fn check_enum_is_param(
438438
prefix_typ: &LuaType,
439439
index_expr: &LuaIndexExpr,
440440
) -> Option<()> {
441-
if enum_variable_is_param(
441+
enum_variable_is_param(
442442
semantic_model.get_db(),
443443
&mut semantic_model.get_config().borrow_mut(),
444444
index_expr,
445445
prefix_typ,
446446
)
447-
.is_some()
448-
{
449-
return Some(());
450-
}
451-
452-
None
453447
}
Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashSet;
2+
13
use emmylua_parser::{LuaAstNode, LuaIndexExpr};
24
use rowan::NodeOrToken;
35

@@ -12,43 +14,6 @@ pub fn enum_variable_is_param(
1214
index_expr: &LuaIndexExpr,
1315
prefix_typ: &LuaType,
1416
) -> Option<()> {
15-
fn find_enum_origin(
16-
db: &DbIndex,
17-
cache: &mut LuaInferCache,
18-
decl_id: LuaDeclId,
19-
) -> Option<LuaDeclId> {
20-
let syntax_tree = db.get_vfs().get_syntax_tree(&decl_id.file_id)?;
21-
let root = syntax_tree.get_red_root();
22-
23-
let node = db
24-
.get_decl_index()
25-
.get_decl(&decl_id)?
26-
.get_value_syntax_id()?
27-
.to_node_from_root(&root)?;
28-
29-
let semantic_decl = match node.into() {
30-
NodeOrToken::Node(node) => {
31-
infer_node_semantic_decl(db, cache, node, SemanticDeclLevel::NoTrace)
32-
}
33-
NodeOrToken::Token(token) => {
34-
infer_token_semantic_decl(db, cache, token, SemanticDeclLevel::NoTrace)
35-
}
36-
};
37-
38-
match semantic_decl {
39-
Some(LuaSemanticDeclId::Member(_)) => None,
40-
Some(LuaSemanticDeclId::LuaDecl(new_decl_id)) => {
41-
let decl = db.get_decl_index().get_decl(&new_decl_id)?;
42-
if decl.get_value_syntax_id().is_some() {
43-
Some(find_enum_origin(db, cache, new_decl_id).unwrap_or(new_decl_id))
44-
} else {
45-
Some(new_decl_id)
46-
}
47-
}
48-
_ => None,
49-
}
50-
}
51-
5217
let LuaType::Ref(id) = prefix_typ else {
5318
return None;
5419
};
@@ -70,7 +35,8 @@ pub fn enum_variable_is_param(
7035
return None;
7136
};
7237

73-
let origin_decl_id = find_enum_origin(db, cache, decl_id).unwrap_or(decl_id);
38+
let mut decl_guard = DeclGuard::new();
39+
let origin_decl_id = find_enum_origin(db, cache, decl_id, &mut decl_guard).unwrap_or(decl_id);
7440
let decl = db.get_decl_index().get_decl(&origin_decl_id)?;
7541

7642
if decl.is_param() {
@@ -79,3 +45,64 @@ pub fn enum_variable_is_param(
7945
None
8046
}
8147
}
48+
49+
#[derive(Debug, Clone, PartialEq, Eq)]
50+
pub struct DeclGuard {
51+
decl_set: HashSet<LuaDeclId>,
52+
}
53+
54+
impl DeclGuard {
55+
pub fn new() -> Self {
56+
Self {
57+
decl_set: HashSet::new(),
58+
}
59+
}
60+
61+
pub fn check(&mut self, decl_id: LuaDeclId) -> Option<()> {
62+
if self.decl_set.contains(&decl_id) {
63+
None
64+
} else {
65+
self.decl_set.insert(decl_id);
66+
Some(())
67+
}
68+
}
69+
}
70+
71+
fn find_enum_origin(
72+
db: &DbIndex,
73+
cache: &mut LuaInferCache,
74+
decl_id: LuaDeclId,
75+
decl_guard: &mut DeclGuard,
76+
) -> Option<LuaDeclId> {
77+
decl_guard.check(decl_id)?;
78+
let syntax_tree = db.get_vfs().get_syntax_tree(&decl_id.file_id)?;
79+
let root = syntax_tree.get_red_root();
80+
81+
let node = db
82+
.get_decl_index()
83+
.get_decl(&decl_id)?
84+
.get_value_syntax_id()?
85+
.to_node_from_root(&root)?;
86+
87+
let semantic_decl = match node.into() {
88+
NodeOrToken::Node(node) => {
89+
infer_node_semantic_decl(db, cache, node, SemanticDeclLevel::NoTrace)
90+
}
91+
NodeOrToken::Token(token) => {
92+
infer_token_semantic_decl(db, cache, token, SemanticDeclLevel::NoTrace)
93+
}
94+
};
95+
96+
match semantic_decl {
97+
Some(LuaSemanticDeclId::Member(_)) => None,
98+
Some(LuaSemanticDeclId::LuaDecl(new_decl_id)) => {
99+
let decl = db.get_decl_index().get_decl(&new_decl_id)?;
100+
if decl.get_value_syntax_id().is_some() {
101+
Some(find_enum_origin(db, cache, new_decl_id, decl_guard).unwrap_or(new_decl_id))
102+
} else {
103+
Some(new_decl_id)
104+
}
105+
}
106+
_ => None,
107+
}
108+
}

0 commit comments

Comments
 (0)