Skip to main content

forge_lint/sol/info/
pascal_case.rs

1use crate::{
2    linter::{EarlyLintPass, LintContext},
3    sol::{
4        Severity, SolLint,
5        naming::{check_pascal_case, emit_rename, has_acronym_exception},
6    },
7};
8use foundry_config::lint::LintSpecificConfig;
9use solar::ast::ItemStruct;
10use std::sync::Arc;
11
12declare_forge_lint!(
13    PASCAL_CASE_STRUCT,
14    Severity::Info,
15    "pascal-case-struct",
16    "struct name is not `PascalCase`"
17);
18
19#[derive(Debug)]
20pub(super) struct PascalCaseStructPass {
21    config: Arc<LintSpecificConfig>,
22}
23
24impl PascalCaseStructPass {
25    pub(super) const fn new(config: Arc<LintSpecificConfig>) -> Self {
26        Self { config }
27    }
28}
29
30impl<'ast> EarlyLintPass<'ast> for PascalCaseStructPass {
31    fn check_item_struct(&mut self, ctx: &LintContext, strukt: &'ast ItemStruct<'ast>) {
32        let name = strukt.name.as_str();
33        // The acronym exceptions shared with the `mixed-case-*` lints keep `ERC20Data` valid.
34        if has_acronym_exception(name, &self.config.mixed_case_exceptions, |pre| {
35            pre == heck::AsUpperCamelCase(pre).to_string()
36        }) {
37            return;
38        }
39        if let Some(expected) = check_pascal_case(name) {
40            emit_rename(ctx, &PASCAL_CASE_STRUCT, strukt.name.span, expected);
41        }
42    }
43}