Skip to content

Commit 62cf037

Browse files
committed
Fix #892
1 parent 0728705 commit 62cf037

File tree

1 file changed

+79
-22
lines changed

1 file changed

+79
-22
lines changed

crates/emmylua_code_analysis/src/diagnostic/checker/code_style/preferred_local_alias.rs

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,12 @@ fn collect_local_alias(
9898
{
9999
let name_token = local_name.get_name_token()?;
100100
let preferred_name = name_token.get_name_text();
101+
let ref_var = match find_ref_var_decl_id(semantic_model, value_expr) {
102+
Some(id) => id,
103+
None => continue,
104+
};
101105

102-
local_alias_set.insert(name, preferred_name.to_string(), semantic_id);
106+
local_alias_set.insert(name, preferred_name.to_string(), semantic_id, ref_var);
103107
local_alias_set.add_disable_check(value_expr.get_range());
104108
}
105109
}
@@ -108,6 +112,27 @@ fn collect_local_alias(
108112
Some(())
109113
}
110114

115+
fn find_ref_var_decl_id(
116+
semantic_model: &SemanticModel,
117+
expr: &LuaExpr,
118+
) -> Option<LuaSemanticDeclId> {
119+
let mut prefix = expr.clone();
120+
while let LuaExpr::IndexExpr(index_expr) = prefix {
121+
match index_expr.get_prefix_expr() {
122+
Some(LuaExpr::NameExpr(name_expr)) => {
123+
let node_or_token = NodeOrToken::Node(name_expr.syntax().clone());
124+
return semantic_model.find_decl(node_or_token, SemanticDeclLevel::NoTrace);
125+
}
126+
Some(LuaExpr::IndexExpr(prefix_index_expr)) => {
127+
prefix = LuaExpr::IndexExpr(prefix_index_expr);
128+
}
129+
_ => return None,
130+
}
131+
}
132+
133+
None
134+
}
135+
111136
fn is_only_dot_index_expr(expr: &LuaExpr) -> Option<bool> {
112137
let mut index_expr = match expr {
113138
LuaExpr::IndexExpr(index_expr) => index_expr.clone(),
@@ -129,6 +154,19 @@ fn is_only_dot_index_expr(expr: &LuaExpr) -> Option<bool> {
129154
}
130155
}
131156

157+
fn get_first_name_expr(expr: &LuaIndexExpr) -> Option<LuaExpr> {
158+
let mut index_expr = expr.clone();
159+
loop {
160+
match index_expr.get_prefix_expr() {
161+
Some(LuaExpr::NameExpr(name_expr)) => return Some(LuaExpr::NameExpr(name_expr)),
162+
Some(LuaExpr::IndexExpr(prefix_index_expr)) => {
163+
index_expr = prefix_index_expr;
164+
}
165+
_ => return None,
166+
}
167+
}
168+
}
169+
132170
#[derive(Debug)]
133171
struct LocalAliasSet {
134172
local_alias_stack: Vec<HashMap<String, LocalAliasInfo>>,
@@ -137,7 +175,8 @@ struct LocalAliasSet {
137175

138176
#[derive(Debug)]
139177
struct LocalAliasInfo {
140-
pub decl_id: LuaSemanticDeclId,
178+
pub ref_var: LuaSemanticDeclId,
179+
pub ref_field: LuaSemanticDeclId,
141180
pub preferred_name: String,
142181
pub invalid: bool,
143182
}
@@ -158,12 +197,19 @@ impl LocalAliasSet {
158197
self.local_alias_stack.pop();
159198
}
160199

161-
fn insert(&mut self, name: String, preferred_name: String, decl_id: LuaSemanticDeclId) {
200+
fn insert(
201+
&mut self,
202+
name: String,
203+
preferred_name: String,
204+
decl_id: LuaSemanticDeclId,
205+
ref_var: LuaSemanticDeclId,
206+
) {
162207
if let Some(map) = self.local_alias_stack.last_mut() {
163208
map.insert(
164209
name,
165210
LocalAliasInfo {
166-
decl_id,
211+
ref_var,
212+
ref_field: decl_id,
167213
preferred_name,
168214
invalid: false,
169215
},
@@ -230,29 +276,40 @@ fn check_index_expr_preference(
230276
return Some(());
231277
}
232278

233-
if semantic_model.is_reference_to(
279+
let var_expr = get_first_name_expr(index_expr)?;
280+
if !semantic_model.is_reference_to(
281+
var_expr.syntax().clone(),
282+
alias_info.ref_var.clone(),
283+
SemanticDeclLevel::NoTrace,
284+
) {
285+
return Some(());
286+
}
287+
288+
if !semantic_model.is_reference_to(
234289
index_expr.syntax().clone(),
235-
alias_info.decl_id.clone(),
290+
alias_info.ref_field.clone(),
236291
SemanticDeclLevel::NoTrace,
237292
) {
238-
if mutable_index {
239-
alias_info.invalid = true;
240-
return Some(());
241-
}
293+
return Some(());
294+
}
242295

243-
context.add_diagnostic(
244-
DiagnosticCode::PreferredLocalAlias,
245-
index_expr.get_range(),
246-
t!(
247-
"Prefer use local alias variable '%{name}'",
248-
name = alias_info.preferred_name
249-
)
250-
.to_string(),
251-
Some(json!({
252-
"preferredAlias": alias_info.preferred_name.clone(),
253-
})),
254-
);
296+
if mutable_index {
297+
alias_info.invalid = true;
298+
return Some(());
255299
}
256300

301+
context.add_diagnostic(
302+
DiagnosticCode::PreferredLocalAlias,
303+
index_expr.get_range(),
304+
t!(
305+
"Prefer use local alias variable '%{name}'",
306+
name = alias_info.preferred_name
307+
)
308+
.to_string(),
309+
Some(json!({
310+
"preferredAlias": alias_info.preferred_name.clone(),
311+
})),
312+
);
313+
257314
Some(())
258315
}

0 commit comments

Comments
 (0)