luaur_analysis/functions/
lint.rs1use alloc::vec::Vec;
4
5use luaur_ast::records::ast_name_table::AstNameTable;
6use luaur_ast::records::ast_stat::AstStat;
7use luaur_ast::records::hot_comment::HotComment;
8use luaur_config::enums::code::Code;
9use luaur_config::records::lint_options::LintOptions;
10use luaur_config::records::lint_warning::LintWarning;
11
12use crate::functions::fill_builtin_globals::fill_builtin_globals;
13use crate::functions::has_native_comment_directive::has_native_comment_directive;
14use crate::functions::lint_comments::lint_comments;
15use crate::records::lint_context::LintContext;
16use crate::records::lint_deprecated_api::LintDeprecatedApi;
17use crate::records::lint_duplicate_condition::LintDuplicateCondition;
18use crate::records::lint_duplicate_function::LintDuplicateFunction;
19use crate::records::lint_duplicate_local::LintDuplicateLocal;
20use crate::records::lint_for_range::LintForRange;
21use crate::records::lint_format_string::LintFormatString;
22use crate::records::lint_global_local::LintGlobalLocal;
23use crate::records::lint_integer_parsing::LintIntegerParsing;
24use crate::records::lint_misleading_and_or::LintMisleadingAndOr;
25use crate::records::lint_multi_line_statement::LintMultiLineStatement;
26use crate::records::lint_same_line_statement::LintSameLineStatement;
27use crate::records::lint_table_literal::LintTableLiteral;
28use crate::records::lint_table_operations::LintTableOperations;
29use crate::records::lint_uninitialized_local::LintUninitializedLocal;
30use crate::records::lint_unreachable_code::LintUnreachableCode;
31use crate::records::lint_unused_function::LintUnusedFunction;
32use crate::records::warning_comparator::WarningComparator;
33use crate::type_aliases::scope_ptr_type::ScopePtr;
34
35use crate::methods::lint_implicit_return_process::lint_implicit_return_process;
36use crate::methods::lint_local_hygiene_process::lint_local_hygiene_process;
37use crate::methods::lint_redundant_native_attribute_process::lint_redundant_native_attribute_process;
38use crate::methods::lint_unbalanced_assignment_process::lint_unbalanced_assignment_process;
39use crate::methods::lint_unknown_type_process::lint_unknown_type_process;
40use crate::records::lint_comparison_precedence::LintComparisonPrecedence;
41
42use crate::records::module::Module;
43
44pub fn lint(
45 root: *mut AstStat,
46 names: &AstNameTable,
47 env: &ScopePtr,
48 module: *const Module,
49 hotcomments: &[HotComment],
50 options: &LintOptions,
51) -> Vec<LintWarning> {
52 let mut context = LintContext {
53 result: Vec::new(),
54 options: *options,
55 root,
56 placeholder: names.get(c"_".as_ptr()),
57 builtin_globals: luaur_common::records::dense_hash_map::DenseHashMap::new(
58 luaur_ast::records::ast_name::AstName::new(),
59 ),
60 scope: env.clone(),
61 module,
62 };
63
64 fill_builtin_globals(&mut context, names, env);
65
66 if context.warning_enabled(Code::Code_UnknownGlobal)
67 || context.warning_enabled(Code::Code_DeprecatedGlobal)
68 || context.warning_enabled(Code::Code_GlobalUsedAsLocal)
69 || context.warning_enabled(Code::Code_PlaceholderRead)
70 || context.warning_enabled(Code::Code_BuiltinGlobalWrite)
71 {
72 LintGlobalLocal::process(&mut context);
73 }
74
75 if context.warning_enabled(Code::Code_MultiLineStatement) {
76 LintMultiLineStatement::new(core::ptr::null_mut()).process(&mut context);
77 }
78
79 if context.warning_enabled(Code::Code_SameLineStatement) {
80 LintSameLineStatement::new(core::ptr::null_mut()).process(&mut context);
81 }
82
83 if context.warning_enabled(Code::Code_LocalShadow)
84 || context.warning_enabled(Code::Code_FunctionUnused)
85 || context.warning_enabled(Code::Code_ImportUnused)
86 || context.warning_enabled(Code::Code_LocalUnused)
87 {
88 lint_local_hygiene_process(&mut context);
89 }
90
91 if context.warning_enabled(Code::Code_FunctionUnused) {
92 LintUnusedFunction::new().process(&mut context);
93 }
94
95 if context.warning_enabled(Code::Code_UnreachableCode) {
96 LintUnreachableCode::process(&mut context);
97 }
98
99 if context.warning_enabled(Code::Code_UnknownType) {
100 lint_unknown_type_process(&mut context);
101 }
102
103 if context.warning_enabled(Code::Code_ForRange) {
104 LintForRange::process(&mut context);
105 }
106
107 if context.warning_enabled(Code::Code_UnbalancedAssignment) {
108 lint_unbalanced_assignment_process(&mut context);
109 }
110
111 if context.warning_enabled(Code::Code_ImplicitReturn) {
112 lint_implicit_return_process(&mut context);
113 }
114
115 if context.warning_enabled(Code::Code_FormatString) {
116 LintFormatString {
117 context: core::ptr::null_mut(),
118 }
119 .process(&mut context);
120 }
121
122 if context.warning_enabled(Code::Code_TableLiteral) {
123 LintTableLiteral {
124 context: core::ptr::null_mut(),
125 }
126 .process(&mut context);
127 }
128
129 if context.warning_enabled(Code::Code_UninitializedLocal) {
130 LintUninitializedLocal::process(&mut context);
131 }
132
133 if context.warning_enabled(Code::Code_DuplicateFunction) {
134 LintDuplicateFunction::new(&mut context as *mut LintContext).process();
135 }
136
137 if context.warning_enabled(Code::Code_DeprecatedApi) {
138 LintDeprecatedApi {
139 context: core::ptr::null_mut(),
140 function_type_scope_stack: Vec::new(),
141 }
142 .process(&mut context);
143 }
144
145 if context.warning_enabled(Code::Code_TableOperations) {
146 LintTableOperations::process(&mut context);
147 }
148
149 if context.warning_enabled(Code::Code_DuplicateCondition) {
150 LintDuplicateCondition {
151 context: &mut context as *mut LintContext,
152 }
153 .process();
154 }
155
156 if context.warning_enabled(Code::Code_DuplicateLocal) {
157 LintDuplicateLocal::process(&mut context);
158 }
159
160 if context.warning_enabled(Code::Code_MisleadingAndOr) {
161 LintMisleadingAndOr {
162 context: core::ptr::null_mut(),
163 }
164 .process(&mut context);
165 }
166
167 if context.warning_enabled(Code::Code_CommentDirective) {
168 lint_comments(&mut context, hotcomments);
169 }
170
171 if context.warning_enabled(Code::Code_IntegerParsing) {
172 LintIntegerParsing::process(&mut context);
173 }
174
175 if context.warning_enabled(Code::Code_ComparisonPrecedence) {
176 LintComparisonPrecedence::process(&mut context);
177 }
178
179 if context.warning_enabled(Code::Code_RedundantNativeAttribute) {
180 if has_native_comment_directive(hotcomments) {
181 lint_redundant_native_attribute_process(&mut context);
182 }
183 }
184
185 let comparator = WarningComparator::default();
186 context.result.sort_by(|lhs, rhs| {
187 let c = comparator.compare_location_location(&lhs.location, &rhs.location);
188 if c != 0 {
189 return c.cmp(&0);
190 }
191 (lhs.code as i32).cmp(&(rhs.code as i32))
192 });
193
194 context.result
195}