Skip to content

Commit f158266

Browse files
committed
check mut for preferred-local-alias check
1 parent 1b22ca7 commit f158266

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

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

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl Checker for PreferredLocalAliasChecker {
3333
LuaAst::LuaIndexExpr(index_expr) => {
3434
check_index_expr_preference(
3535
context,
36-
&local_alias_set,
36+
&mut local_alias_set,
3737
semantic_model,
3838
&index_expr,
3939
);
@@ -130,10 +130,17 @@ fn is_only_dot_index_expr(expr: &LuaExpr) -> Option<bool> {
130130

131131
#[derive(Debug)]
132132
struct LocalAliasSet {
133-
local_alias_stack: Vec<HashMap<String, (LuaSemanticDeclId, String)>>,
133+
local_alias_stack: Vec<HashMap<String, LocalAliasInfo>>,
134134
disable_check: HashSet<TextRange>,
135135
}
136136

137+
#[derive(Debug)]
138+
struct LocalAliasInfo {
139+
pub decl_id: LuaSemanticDeclId,
140+
pub preferred_name: String,
141+
pub invalid: bool,
142+
}
143+
137144
impl LocalAliasSet {
138145
fn new() -> Self {
139146
LocalAliasSet {
@@ -152,14 +159,21 @@ impl LocalAliasSet {
152159

153160
fn insert(&mut self, name: String, preferred_name: String, decl_id: LuaSemanticDeclId) {
154161
if let Some(map) = self.local_alias_stack.last_mut() {
155-
map.insert(name, (decl_id, preferred_name));
162+
map.insert(
163+
name,
164+
LocalAliasInfo {
165+
decl_id,
166+
preferred_name,
167+
invalid: false,
168+
},
169+
);
156170
}
157171
}
158172

159-
fn get(&self, name: &str) -> Option<(LuaSemanticDeclId, String)> {
160-
for map in self.local_alias_stack.iter().rev() {
161-
if let Some(item) = map.get(name) {
162-
return Some(item.clone());
173+
fn get(&mut self, name: &str) -> Option<&mut LocalAliasInfo> {
174+
for map in self.local_alias_stack.iter_mut().rev() {
175+
if let Some(item) = map.get_mut(name) {
176+
return Some(item);
163177
}
164178
}
165179
None
@@ -176,7 +190,7 @@ impl LocalAliasSet {
176190

177191
fn check_index_expr_preference(
178192
context: &mut DiagnosticContext,
179-
local_alias_set: &LocalAliasSet,
193+
local_alias_set: &mut LocalAliasSet,
180194
semantic_model: &SemanticModel,
181195
index_expr: &LuaIndexExpr,
182196
) -> Option<()> {
@@ -190,15 +204,16 @@ fn check_index_expr_preference(
190204
}
191205

192206
let parent = index_expr.get_parent::<LuaAst>()?;
207+
let mut mutable_index = false;
193208
match parent {
194209
LuaAst::LuaAssignStat(assign_stat) => {
195210
let eq = assign_stat.get_assign_op()?;
196211
if eq.get_position() > index_expr.get_position() {
197-
return Some(());
212+
mutable_index = true;
198213
}
199214
}
200215
LuaAst::LuaFuncStat(_) => {
201-
return Some(());
216+
mutable_index = true;
202217
}
203218
_ => {}
204219
}
@@ -209,18 +224,27 @@ fn check_index_expr_preference(
209224
_ => return Some(()),
210225
};
211226

212-
let (semantic_id, preferred_name) = local_alias_set.get(&name)?;
227+
let alias_info = local_alias_set.get(&name)?;
228+
if alias_info.invalid {
229+
return Some(());
230+
}
231+
213232
if semantic_model.is_reference_to(
214233
index_expr.syntax().clone(),
215-
semantic_id,
234+
alias_info.decl_id.clone(),
216235
SemanticDeclLevel::NoTrace,
217236
) {
237+
if mutable_index {
238+
alias_info.invalid = true;
239+
return Some(());
240+
}
241+
218242
context.add_diagnostic(
219243
DiagnosticCode::PreferredLocalAlias,
220244
index_expr.get_range(),
221245
t!(
222246
"Prefer use local alias variable '%{name}'",
223-
name = preferred_name
247+
name = alias_info.preferred_name
224248
)
225249
.to_string(),
226250
None,

crates/emmylua_code_analysis/src/diagnostic/test/code_style/preferred_local_alias_test.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,17 @@ mod test {
1313
print(string.gsub("hello", "l", "0"))
1414
"#,
1515
));
16+
17+
assert!(ws.check_code_for(
18+
DiagnosticCode::PreferredLocalAlias,
19+
r#"
20+
local t = {
21+
a = ""
22+
}
23+
local h = t.a
24+
t.a = 'h'
25+
print(t.a)
26+
"#,
27+
));
1628
}
1729
}

0 commit comments

Comments
 (0)