ripr 0.3.0

Static RIPR mutation-exposure analysis for Rust workspaces
Documentation
use crate::domain::Finding;

use super::{array_field, field, number_field};
use crate::output::json::report::{related_test_json, stop_reason_values};

pub fn render_context_packet(finding: &Finding, max_related_tests: usize) -> String {
    let mut out = String::new();
    out.push_str("{\n");
    field(&mut out, 1, "version", "1.0", true);
    field(&mut out, 1, "tool", "ripr", true);
    out.push_str("  \"probe\": {\n");
    field(&mut out, 2, "id", &finding.probe.id.0, true);
    field(&mut out, 2, "family", finding.probe.family.as_str(), true);
    field(&mut out, 2, "delta", finding.probe.delta.as_str(), true);
    field(
        &mut out,
        2,
        "file",
        &finding.probe.location.file.display().to_string(),
        true,
    );
    number_field(&mut out, 2, "line", finding.probe.location.line, true);
    field(
        &mut out,
        2,
        "changed_expression",
        &finding.probe.expression,
        false,
    );
    out.push_str("  },\n");
    out.push_str("  \"ripr\": {\n");
    field(
        &mut out,
        2,
        "reach",
        finding.ripr.reach.state.as_str(),
        true,
    );
    field(
        &mut out,
        2,
        "infect",
        finding.ripr.infect.state.as_str(),
        true,
    );
    field(
        &mut out,
        2,
        "propagate",
        finding.ripr.propagate.state.as_str(),
        true,
    );
    field(
        &mut out,
        2,
        "observe",
        finding.ripr.reveal.observe.state.as_str(),
        true,
    );
    field(
        &mut out,
        2,
        "discriminate",
        finding.ripr.reveal.discriminate.state.as_str(),
        false,
    );
    out.push_str("  },\n");
    let related_test_count = finding.related_tests.len().min(max_related_tests);
    out.push_str("  \"related_tests\": [\n");
    for (idx, test) in finding
        .related_tests
        .iter()
        .take(max_related_tests)
        .enumerate()
    {
        related_test_json(&mut out, test, 2);
        if idx + 1 != related_test_count {
            out.push(',');
        }
        out.push('\n');
    }
    out.push_str("  ],\n");
    array_field(&mut out, 1, "missing", &finding.missing, true);
    let stop_reasons = stop_reason_values(finding);
    array_field(&mut out, 1, "stop_reasons", &stop_reasons, true);
    field(
        &mut out,
        1,
        "recommended_next_step",
        finding.recommended_next_step.as_deref().unwrap_or(""),
        false,
    );
    out.push_str("}\n");
    out
}