use super::{Annotation, AstAlloc, MergePriority, record::FieldMetadata};
pub trait Combine<'ast>: Default {
fn combine(alloc: &'ast AstAlloc, left: Self, right: Self) -> Self;
}
impl<'ast> Combine<'ast> for FieldMetadata<'ast> {
fn combine(alloc: &'ast AstAlloc, left: Self, right: Self) -> Self {
let priority = match (left.priority, right.priority) {
(MergePriority::Neutral, p) | (p, MergePriority::Neutral) => p,
(p1, p2) => std::cmp::max(p1, p2),
};
FieldMetadata {
doc: merge_doc(left.doc, right.doc),
annotation: Combine::combine(alloc, left.annotation, right.annotation),
opt: left.opt || right.opt,
not_exported: left.not_exported || right.not_exported,
priority,
}
}
}
impl<'ast> Combine<'ast> for Annotation<'ast> {
fn combine(alloc: &'ast AstAlloc, left: Self, right: Self) -> Self {
let (typ, leftover) = match (left.typ, right.typ) {
(left_ty @ Some(_), right_ty @ Some(_)) => (left_ty, right_ty),
(left_ty, right_ty) => (left_ty.or(right_ty), None),
};
let contracts: Vec<_> = left
.contracts
.iter()
.cloned()
.chain(leftover)
.chain(right.contracts.iter().cloned())
.collect();
alloc.annotation(typ, contracts)
}
}
pub(crate) fn merge_doc<'ast>(
doc1: Option<&'ast str>,
doc2: Option<&'ast str>,
) -> Option<&'ast str> {
doc1.or(doc2)
}