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