mago_cli/commands/
lint.rs1use clap::Parser;
2
3use mago_interner::ThreadedInterner;
4use mago_reporting::reporter::Reporter;
5use mago_reporting::reporter::ReportingFormat;
6use mago_reporting::reporter::ReportingTarget;
7use mago_reporting::Level;
8use mago_service::config::Configuration;
9use mago_service::linter::LintService;
10use mago_service::source::SourceService;
11
12use crate::enum_variants;
13use crate::utils::bail;
14
15#[derive(Parser, Debug)]
16#[command(
17 name = "lint",
18 about = "Lint the project according to the `mago.toml` configuration or default settings",
19 long_about = r#"
20Lint the project according to the `mago.toml` configuration or default settings.
21
22This command analyzes the project's source code and highlights issues based on the defined linting rules.
23
24If `mago.toml` is not found, the default configuration is used. The command outputs the issues found in the project."
25 "#
26)]
27pub struct LintCommand {
28 #[arg(long, short, help = "Only show fixable issues", default_value_t = false)]
29 pub only_fixable: bool,
30
31 #[arg(long, default_value_t, help = "The issue reporting target to use.", ignore_case = true, value_parser = enum_variants!(ReportingTarget))]
32 pub reporting_target: ReportingTarget,
33
34 #[arg(long, default_value_t, help = "The issue reporting format to use.", ignore_case = true, value_parser = enum_variants!(ReportingFormat))]
35 pub reporting_format: ReportingFormat,
36}
37
38pub async fn execute(command: LintCommand, configuration: Configuration) -> i32 {
39 let interner = ThreadedInterner::new();
40
41 let source_service = SourceService::new(interner.clone(), configuration.source);
42 let source_manager = source_service.load().await.unwrap_or_else(bail);
43
44 let lint_service = LintService::new(configuration.linter, interner.clone(), source_manager.clone());
45 let issues = lint_service.run().await.unwrap_or_else(bail);
46 let issues_contain_errors = issues.get_highest_level().is_some_and(|level| level >= Level::Error);
47
48 let reporter = Reporter::new(interner, source_manager, command.reporting_target);
49
50 if command.only_fixable {
51 reporter.report(issues.only_fixable(), command.reporting_format).unwrap_or_else(bail);
52 } else {
53 reporter.report(issues, command.reporting_format).unwrap_or_else(bail);
54 }
55
56 if issues_contain_errors {
57 1
58 } else {
59 0
60 }
61}