multilint 0.3.0

A driver of multiple linters
Documentation
use crate::{config, format::OutputFormat, linter::Linter};
use anyhow::Result;
use std::path::Path;

pub fn run_linters(
    config_path: impl AsRef<Path>,
    format: &dyn OutputFormat,
    linters: Option<&[String]>,
) -> Result<bool> {
    let config = config::from_path(&config_path)?;
    let mut ok = true;
    for (name, linter_config) in &config.linter {
        if let Some(linters) = linters {
            if !linters.contains(name) {
                continue;
            }
        }
        format.start(name);
        let linter = Linter::from_config(linter_config.clone(), &config.global);
        if !linter.is_executable() {
            format.no_command(name);
            continue;
        }
        match linter.run(".")? {
            None => format.no_file(name),
            Some(output) => {
                format.status(name, &output)?;
                ok &= output.success();
            }
        }
    }
    Ok(ok)
}

#[cfg(test)]
mod tests {
    use crate::format::TextFormat;

    use super::run_linters;
    use std::{fs::File, io::Write};
    use tempfile::tempdir;
    use test_log::test;

    #[test]
    fn run() {
        let root = tempdir().unwrap();
        let config = root.path().join("multilint.toml");
        let format = TextFormat::default();

        {
            let mut config = File::create(&config).unwrap();
            writeln!(config, "[linter.test]").unwrap();
            writeln!(config, "command = 'true'").unwrap();
            writeln!(config, "includes = ['*']").unwrap();
        }
        assert!(run_linters(&root.path(), &format, None).unwrap());

        {
            let mut config = File::create(&config).unwrap();
            writeln!(config, "[linter.test]").unwrap();
            writeln!(config, "command = 'false'").unwrap();
            writeln!(config, "includes = ['*']").unwrap();
        }
        assert!(!run_linters(&root.path(), &format, None).unwrap());
    }

    #[test]
    fn run_selected() {
        let root = tempdir().unwrap();
        let config = root.path().join("multilint.toml");
        let format = TextFormat::default();

        {
            let mut config = File::create(&config).unwrap();
            writeln!(config, "[linter.test]").unwrap();
            writeln!(config, "command = 'false'").unwrap();
            writeln!(config, "includes = ['*']").unwrap();
        }
        assert!(run_linters(&root.path(), &format, Some(&[])).unwrap());
    }
}