forge_lint/sol/info/
multi_contract_file.rs1use crate::{
2 linter::{EarlyLintPass, Lint, LintContext},
3 sol::{Severity, SolLint, info::MultiContractFile},
4};
5
6use solar::ast::{self as ast};
7
8declare_forge_lint!(
9 MULTI_CONTRACT_FILE,
10 Severity::Info,
11 "multi-contract-file",
12 "prefer having only one contract, interface or library per file"
13);
14
15impl<'ast> EarlyLintPass<'ast> for MultiContractFile {
16 fn check_full_source_unit(
17 &mut self,
18 ctx: &LintContext<'ast, '_>,
19 unit: &'ast ast::SourceUnit<'ast>,
20 ) {
21 if !ctx.is_lint_enabled(MULTI_CONTRACT_FILE.id()) {
22 return;
23 }
24
25 let relevant_spans: Vec<_> = unit
27 .items
28 .iter()
29 .filter_map(|item| match &item.kind {
30 ast::ItemKind::Contract(c) => {
31 (!ctx.config.lint_specific.is_exempted(&c.kind)).then_some(c.name.span)
32 }
33 _ => None,
34 })
35 .collect();
36
37 if relevant_spans.len() > 1 {
39 relevant_spans.into_iter().for_each(|span| ctx.emit(&MULTI_CONTRACT_FILE, span));
40 }
41 }
42}