forge_lint/sol/info/
multi_contract_file.rs1use crate::{
2 linter::{EarlyLintPass, Lint, LintContext},
3 sol::{Severity, SolLint},
4};
5use foundry_config::lint::LintSpecificConfig;
6use solar::ast;
7use std::sync::Arc;
8
9declare_forge_lint!(
10 MULTI_CONTRACT_FILE,
11 Severity::Info,
12 "multi-contract-file",
13 "file contains multiple contracts, interfaces or libraries"
14);
15
16#[derive(Debug)]
17pub(super) struct MultiContractFilePass {
18 config: Arc<LintSpecificConfig>,
19}
20
21impl MultiContractFilePass {
22 pub(super) const fn new(config: Arc<LintSpecificConfig>) -> Self {
23 Self { config }
24 }
25}
26
27impl<'ast> EarlyLintPass<'ast> for MultiContractFilePass {
28 fn check_full_source_unit(
29 &mut self,
30 ctx: &LintContext<'ast, '_>,
31 unit: &'ast ast::SourceUnit<'ast>,
32 ) {
33 if !ctx.is_lint_enabled(MULTI_CONTRACT_FILE.id()) {
34 return;
35 }
36 let spans: Vec<_> = unit
38 .items
39 .iter()
40 .filter_map(|item| match &item.kind {
41 ast::ItemKind::Contract(c) if !self.config.is_exempted(&c.kind) => {
42 Some(c.name.span)
43 }
44 _ => None,
45 })
46 .collect();
47 if spans.len() > 1 {
48 for span in spans {
49 ctx.emit(&MULTI_CONTRACT_FILE, span);
50 }
51 }
52 }
53}