forge_lint/sol/info/
screaming_snake_case.rs
1use super::ScreamingSnakeCase;
2use crate::{
3 linter::{EarlyLintPass, LintContext},
4 sol::{Severity, SolLint},
5};
6use solar_ast::{VarMut, VariableDefinition};
7
8declare_forge_lint!(
9 SCREAMING_SNAKE_CASE_CONSTANT,
10 Severity::Info,
11 "screaming-snake-case-const",
12 "constants should use SCREAMING_SNAKE_CASE"
13);
14
15declare_forge_lint!(
16 SCREAMING_SNAKE_CASE_IMMUTABLE,
17 Severity::Info,
18 "screaming-snake-case-immutable",
19 "immutables should use SCREAMING_SNAKE_CASE"
20);
21
22impl<'ast> EarlyLintPass<'ast> for ScreamingSnakeCase {
23 fn check_variable_definition(
24 &mut self,
25 ctx: &LintContext<'_>,
26 var: &'ast VariableDefinition<'ast>,
27 ) {
28 if let (Some(name), Some(mutability)) = (var.name, var.mutability) {
29 let name_str = name.as_str();
30 if name_str.len() < 2 || is_screaming_snake_case(name_str) {
31 return;
32 }
33
34 match mutability {
35 VarMut::Constant => ctx.emit(&SCREAMING_SNAKE_CASE_CONSTANT, name.span),
36 VarMut::Immutable => ctx.emit(&SCREAMING_SNAKE_CASE_IMMUTABLE, name.span),
37 }
38 }
39 }
40}
41
42pub fn is_screaming_snake_case(s: &str) -> bool {
44 if s.len() <= 1 {
45 return true;
46 }
47
48 s.trim_matches('_') == format!("{}", heck::AsShoutySnakeCase(s)).as_str()
50}