use super::evidence::definition_semantic_fingerprint;
use super::fingerprints::relative_path;
use super::pairs::PairRelationships;
use crate::model::{Rule, StepDefinition};
use serde::Serialize;
use std::collections::HashMap;
use std::io::Write;
use std::path::Path;
const PAIR_SCHEMA_VERSION: &str = "1";
pub(crate) struct PairRecord {
pub(super) left: usize,
pub(super) right: usize,
pub(super) sources: Vec<&'static str>,
pub(super) owner: &'static str,
pub(super) positional: bool,
pub(super) relationships: PairRelationships,
pub(super) meaningful_handlers: bool,
pub(super) matcher_similarity: Option<f64>,
pub(super) handler_similarity: Option<f64>,
pub(super) rules: Vec<Rule>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct PairLine<'a> {
schema_version: &'static str,
left: &'a Side,
right: &'a Side,
candidate_sources: &'a [&'static str],
owner: &'static str,
positional: bool,
relationships: PairRelationships,
meaningful_handlers: bool,
matcher_similarity: Option<f64>,
handler_similarity: Option<f64>,
rules: &'a [Rule],
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct Side {
path: String,
line: usize,
column: usize,
definition_fingerprint: String,
}
fn side(definition: &StepDefinition, root: &Path) -> Side {
let location = &definition.location;
Side {
path: relative_path(definition, root),
line: location.line,
column: location.column,
definition_fingerprint: definition_semantic_fingerprint(definition),
}
}
pub(crate) fn write_pairs(
definitions: &[StepDefinition],
records: &[PairRecord],
root: &Path,
out: &mut dyn Write,
) -> anyhow::Result<()> {
let mut sides: HashMap<usize, Side> = HashMap::new();
for record in records {
for index in [record.left, record.right] {
sides
.entry(index)
.or_insert_with(|| side(&definitions[index], root));
}
let line = PairLine {
schema_version: PAIR_SCHEMA_VERSION,
left: &sides[&record.left],
right: &sides[&record.right],
candidate_sources: &record.sources,
owner: record.owner,
positional: record.positional,
relationships: record.relationships,
meaningful_handlers: record.meaningful_handlers,
matcher_similarity: record.matcher_similarity,
handler_similarity: record.handler_similarity,
rules: &record.rules,
};
serde_json::to_writer(&mut *out, &line)?;
out.write_all(b"\n")?;
}
Ok(())
}