Skip to main content

luaur_analysis/methods/
lint_unbalanced_assignment_assign.rs

1use crate::records::lint_unbalanced_assignment::LintUnbalancedAssignment;
2use luaur_ast::records::ast_array::AstArray;
3use luaur_ast::records::ast_expr::AstExpr;
4use luaur_ast::records::ast_expr_call::AstExprCall;
5use luaur_ast::records::ast_expr_constant_nil::AstExprConstantNil;
6use luaur_ast::records::ast_expr_varargs::AstExprVarargs;
7use luaur_ast::records::ast_node::AstNode;
8use luaur_ast::records::ast_stat_assign::AstStatAssign;
9use luaur_ast::records::ast_stat_local::AstStatLocal;
10use luaur_ast::records::location::Location;
11use luaur_ast::rtti::ast_node_as;
12use luaur_config::enums::code::Code;
13
14impl LintUnbalancedAssignment {
15    pub fn assign(&mut self, vars: usize, values: &AstArray<*mut AstExpr>, location: Location) {
16        if vars != values.size && values.size > 0 {
17            let last = unsafe { *values.data.add(values.size - 1) };
18
19            if vars < values.size {
20                let msg = format!(
21                    "Assigning {} values to {} variables leaves some values unused",
22                    values.size, vars
23                );
24                crate::functions::emit_warning::emit_warning(
25                    unsafe { &mut *self.context },
26                    Code::Code_UnbalancedAssignment,
27                    location,
28                    format_args!("{}", msg),
29                );
30            } else if !unsafe { ast_node_as::<AstExprCall>(last as *mut AstNode) }.is_null()
31                || !unsafe { ast_node_as::<AstExprVarargs>(last as *mut AstNode) }.is_null()
32                || !unsafe { ast_node_as::<AstExprConstantNil>(last as *mut AstNode) }.is_null()
33            {
34                // we don't know how many values the last expression returns
35                // or last expression is nil which explicitly silences the nil-init warning
36            } else {
37                let msg = format!(
38                    "Assigning {} values to {} variables initializes extra variables with nil; add 'nil' to value list to silence",
39                    values.size, vars
40                );
41                crate::functions::emit_warning::emit_warning(
42                    unsafe { &mut *self.context },
43                    Code::Code_UnbalancedAssignment,
44                    location,
45                    format_args!("{}", msg),
46                );
47            }
48        }
49    }
50
51    pub fn visit_stat_local(&mut self, node: *mut core::ffi::c_void) -> bool {
52        let node = node as *mut AstStatLocal;
53        unsafe {
54            self.assign(
55                (*node).vars.size,
56                &(*node).values,
57                (*node).base.base.location,
58            );
59        }
60
61        true
62    }
63
64    pub fn visit_stat_assign(&mut self, node: *mut core::ffi::c_void) -> bool {
65        let node = node as *mut AstStatAssign;
66        unsafe {
67            self.assign(
68                (*node).vars.size,
69                &(*node).values,
70                (*node).base.base.location,
71            );
72        }
73
74        true
75    }
76}