use super::super::timeline::VersionTimeline;
use super::super::{IntervalKind, MemberInterval};
use super::availability::{Availability, Site, SiteKind, VersionVisitor, availability};
use crate::error::ParserResult;
use crate::hir::Definition;
struct IntervalCollector<'a> {
timeline: &'a VersionTimeline,
version_enum: String,
intervals: Vec<MemberInterval>,
}
impl VersionVisitor for IntervalCollector<'_> {
fn enter(&mut self, site: &Site<'_>, parent: Availability) -> ParserResult<Availability> {
let interval = availability(site, parent, self.timeline)?;
let in_version_enum = site.path == self.version_enum
|| site.path.starts_with(&format!("{}::", self.version_enum));
if !in_version_enum {
if let Some(kind) = interval_kind(site.kind) {
self.intervals.push(MemberInterval {
path: site.path.clone(),
kind,
from: interval.from,
until: interval.until,
});
}
}
Ok(interval)
}
}
fn interval_kind(kind: SiteKind) -> Option<IntervalKind> {
match kind {
SiteKind::Type => Some(IntervalKind::Type),
SiteKind::Member => Some(IntervalKind::Member),
SiteKind::Enumerator => Some(IntervalKind::Enumerator),
SiteKind::BitmaskValue => Some(IntervalKind::BitmaskValue),
SiteKind::Operation => Some(IntervalKind::Operation),
SiteKind::Parameter => Some(IntervalKind::Parameter),
SiteKind::Attribute => Some(IntervalKind::Attribute),
SiteKind::Module | SiteKind::Interface | SiteKind::Bitfield | SiteKind::Unsupported => None,
}
}
pub(crate) fn collect_intervals(
definitions: &[Definition],
timeline: &VersionTimeline,
) -> ParserResult<Vec<MemberInterval>> {
let mut visitor = IntervalCollector {
timeline,
version_enum: timeline.enum_ident().to_string(),
intervals: Vec::new(),
};
visitor.walk(definitions, "", Availability::full())?;
Ok(visitor.intervals)
}