rust-doctor 0.5.0

Local-first health audit for Cargo workspaces: curated Clippy lints and native detectors, scored out of 100
Documentation
#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]

use std::path::{Path, PathBuf};
use std::process::{Command, Output};

use serde_json::Value;

struct Oracle {
    fixture: &'static str,
    code: &'static str,
    primary_lines: &'static [u64],
}

const ORACLES: [Oracle; 3] = [
    Oracle {
        fixture: "dbg-macro",
        code: "clippy::dbg_macro",
        primary_lines: &[4, 8, 12],
    },
    Oracle {
        fixture: "todo",
        code: "clippy::todo",
        primary_lines: &[4, 8, 12],
    },
    Oracle {
        fixture: "unimplemented",
        code: "clippy::unimplemented",
        primary_lines: &[4, 8, 12],
    },
];

fn fixture_root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/kernel-contract")
}

fn target_root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR")).join("target/kernel-contract")
}

fn clippy(fixture: &str, arguments: &[&str]) -> Output {
    Command::new("cargo")
        .current_dir(fixture_root().join(fixture))
        .env("CARGO_TARGET_DIR", target_root())
        .args(arguments)
        .output()
        .expect("Clippy contract process should start")
}

fn records(output: &Output) -> Vec<Value> {
    String::from_utf8_lossy(&output.stdout)
        .lines()
        .filter_map(|line| serde_json::from_str(line).ok())
        .collect()
}

fn diagnostics<'a>(records: &'a [Value], code: &str) -> Vec<&'a Value> {
    records
        .iter()
        .filter(|record| {
            record["reason"] == "compiler-message" && record["message"]["code"]["code"] == code
        })
        .collect()
}

#[test]
fn target_clippy_contract_matches_the_curated_oracle_matrix() {
    let version = Command::new("cargo")
        .args(["clippy", "--version"])
        .output()
        .expect("Clippy version process should start");
    assert!(version.status.success());
    assert!(
        String::from_utf8_lossy(&version.stdout).starts_with("clippy 0.1.97 "),
        "unexpected target toolchain: {}",
        String::from_utf8_lossy(&version.stdout)
    );

    for oracle in ORACLES {
        let output = clippy(
            oracle.fixture,
            &["clippy", "--message-format=json", "--", "-W", oracle.code],
        );
        assert!(
            output.status.success(),
            "{}: {}",
            oracle.fixture,
            String::from_utf8_lossy(&output.stderr)
        );
        let records = records(&output);
        let findings = diagnostics(&records, oracle.code);
        let mut primary_lines: Vec<_> = findings
            .iter()
            .map(|finding| {
                finding["message"]["spans"]
                    .as_array()
                    .and_then(|spans| spans.iter().find(|span| span["is_primary"] == true))
                    .and_then(|span| span["line_start"].as_u64())
                    .expect("curated diagnostic should carry a primary span")
            })
            .collect();
        primary_lines.sort_unstable();

        assert_eq!(findings.len(), 3, "{}", oracle.fixture);
        assert!(
            findings
                .iter()
                .all(|finding| finding["message"]["level"] == "warning"),
            "{}",
            oracle.fixture
        );
        assert_eq!(primary_lines, oracle.primary_lines, "{}", oracle.fixture);
    }

    let allowed = clippy(
        "allowed",
        &[
            "clippy",
            "--message-format=json",
            "--",
            "-W",
            "clippy::dbg_macro",
            "-W",
            "clippy::todo",
            "-W",
            "clippy::unimplemented",
        ],
    );
    assert!(
        allowed.status.success(),
        "{}",
        String::from_utf8_lossy(&allowed.stderr)
    );
    let allowed_records = records(&allowed);
    assert!(
        ORACLES
            .iter()
            .all(|oracle| { diagnostics(&allowed_records, oracle.code).is_empty() })
    );

    let denied = clippy(
        "denied",
        &[
            "clippy",
            "--message-format=json",
            "--",
            "-W",
            "clippy::todo",
        ],
    );
    assert!(!denied.status.success());
    let denied_records = records(&denied);
    let finding_position = denied_records
        .iter()
        .position(|record| {
            record["reason"] == "compiler-message"
                && record["message"]["code"]["code"] == "clippy::todo"
                && record["message"]["level"] == "error"
        })
        .expect("denied lint should emit a structured error");
    let completion_position = denied_records
        .iter()
        .position(|record| record["reason"] == "build-finished" && record["success"] == false)
        .expect("denied lint should emit failed build completion");
    assert!(finding_position < completion_position);

    let dependency = clippy(
        "dependency-app",
        &[
            "clippy",
            "--no-deps",
            "--message-format=json",
            "--",
            "-W",
            "clippy::todo",
        ],
    );
    assert!(
        dependency.status.success(),
        "{}",
        String::from_utf8_lossy(&dependency.stderr)
    );
    assert!(diagnostics(&records(&dependency), "clippy::todo").is_empty());
}