Skip to main content

forge_lint/sol/info/
interface_naming.rs

1use crate::{
2    linter::{EarlyLintPass, Lint, LintContext},
3    sol::{Severity, SolLint, info::InterfaceFileNaming},
4};
5
6use solar::ast::{self as ast};
7
8declare_forge_lint!(
9    INTERFACE_FILE_NAMING,
10    Severity::Info,
11    "interface-file-naming",
12    "interface file names should be prefixed with 'I'"
13);
14
15declare_forge_lint!(
16    INTERFACE_NAMING,
17    Severity::Info,
18    "interface-naming",
19    "interface names should be prefixed with 'I'"
20);
21
22impl<'ast> EarlyLintPass<'ast> for InterfaceFileNaming {
23    fn check_full_source_unit(
24        &mut self,
25        ctx: &LintContext<'ast, '_>,
26        unit: &'ast ast::SourceUnit<'ast>,
27    ) {
28        if !ctx.is_lint_enabled(INTERFACE_FILE_NAMING.id()) {
29            return;
30        }
31
32        if let Some(file_name) = file_name(ctx, unit)
33            && !file_name.starts_with('I')
34            && unit.items.iter().all(|item| match &item.kind {
35                ast::ItemKind::Contract(c) => c.kind == ast::ContractKind::Interface,
36                _ => true,
37            })
38            && let Some(c) = unit.items.iter().find_map(|item| match &item.kind {
39                ast::ItemKind::Contract(c) => Some(c),
40                _ => None,
41            })
42        {
43            ctx.emit(&INTERFACE_FILE_NAMING, c.name.span);
44        }
45    }
46
47    fn check_item_contract(&mut self, ctx: &LintContext, contract: &'ast ast::ItemContract<'ast>) {
48        if ctx.is_lint_enabled(INTERFACE_NAMING.id())
49            && contract.kind == ast::ContractKind::Interface
50            && !contract.name.as_str().starts_with('I')
51        {
52            ctx.emit(&INTERFACE_NAMING, contract.name.span);
53        }
54    }
55}
56
57fn file_name(ctx: &LintContext, unit: &ast::SourceUnit) -> Option<String> {
58    let first_item_span = unit.items.first()?.span;
59    let file = ctx.session().source_map().lookup_source_file(first_item_span.lo());
60    let file_name = file.name.as_real()?.file_name()?.to_str()?;
61    Some(file_name.to_string())
62}