Skip to main content

lux_cli/
check.rs

1use clap::Args;
2use emmylua_check::OutputDestination;
3use eyre::{eyre, Result};
4use itertools::Itertools;
5use lux_lib::{config::Config, progress::MultiProgress, workspace::Workspace};
6
7use crate::{
8    args::OutputFormat,
9    workspace::{sync_dependencies_if_locked, sync_test_dependencies_if_locked},
10};
11
12#[derive(Args)]
13pub struct Check {
14    /// Comma-separated list of ignore patterns.
15    /// Patterns must follow glob syntax.
16    /// Lux will automatically add top-level ignored project files.
17    #[arg(short, long, value_delimiter = ',')]
18    ignore: Option<Vec<String>>,
19
20    /// The output format.
21    #[arg(long, default_value = "text", value_enum, ignore_case = true)]
22    output_format: OutputFormat,
23
24    /// Output destination.{n}
25    /// (stdout or a file path, only used when the output format is json).
26    #[arg(long, default_value = "stdout")]
27    output: OutputDestination,
28
29    /// Treat warnings as errors.
30    #[arg(long)]
31    warnings_as_errors: bool,
32}
33
34impl From<OutputFormat> for emmylua_check::OutputFormat {
35    fn from(value: OutputFormat) -> Self {
36        match value {
37            OutputFormat::Json => emmylua_check::OutputFormat::Json,
38            OutputFormat::Text => emmylua_check::OutputFormat::Text,
39        }
40    }
41}
42
43pub async fn check(args: Check, config: Config) -> Result<()> {
44    let workspace = Workspace::current_or_err()?;
45
46    let progress = MultiProgress::new_arc(&config);
47    sync_dependencies_if_locked(&workspace, progress.clone(), &config).await?;
48    sync_test_dependencies_if_locked(&workspace, progress, &config).await?;
49
50    let workspace_dirs = workspace
51        .members()
52        .iter()
53        .map(|project| project.root())
54        .flat_map(|project_root| {
55            vec![
56                project_root.join("src"),
57                project_root.join("lua"),
58                // For now, we don't include tests
59                // because they require LLS_Addons definitions for busted
60
61                // project_root.join("test"),
62                // project_root.join("tests"),
63                // project_root.join("spec"),
64            ]
65        })
66        .filter(|dir| dir.is_dir())
67        .collect_vec();
68
69    if workspace_dirs.is_empty() {
70        println!("Nothing to check!");
71        return Ok(());
72    }
73
74    let luarc_path = workspace.luarc_path(&config);
75    let rc_files = if luarc_path.is_file() {
76        Some(vec![luarc_path])
77    } else {
78        None
79    };
80    let emmylua_check_args = emmylua_check::CmdArgs {
81        config: rc_files,
82        workspace: workspace_dirs,
83        ignore: args.ignore,
84        output_format: args.output_format.into(),
85        output: args.output,
86        warnings_as_errors: args.warnings_as_errors,
87        verbose: config.verbose(),
88    };
89
90    emmylua_check::run_check(emmylua_check_args)
91        .await
92        .map_err(|err| eyre!(err.to_string()))?;
93    Ok(())
94}