use crate::{ast::Comment, position::Position, position_map::PositionMap};
use alloc::collections::VecDeque;
use allocator_api2::alloc::Allocator;
use mfmt::Builder;
pub struct Context<'a, A: Allocator + Clone> {
builder: Builder<A>,
comments: VecDeque<&'a Comment<'a>>,
position_map: &'a PositionMap,
}
impl<'a, A: Allocator + Clone> Context<'a, A> {
pub fn new(
builder: Builder<A>,
comments: &'a [Comment<'a>],
position_map: &'a PositionMap,
) -> Self {
Self {
builder,
comments: comments.iter().collect(),
position_map,
}
}
pub const fn position_map(&self) -> &'a PositionMap {
self.position_map
}
pub const fn builder(&self) -> &Builder<A> {
&self.builder
}
pub fn drain_multi_line_comments(
&mut self,
line_index: usize,
) -> impl Iterator<Item = &'a Comment<'a>> + '_ {
self.comments.drain(
..self
.comments
.iter()
.position(|comment| self.line_index(comment.position()) >= line_index)
.unwrap_or(self.comments.len()),
)
}
pub fn drain_current_line_comment(
&mut self,
line_index: usize,
) -> impl Iterator<Item = &'a Comment<'a>> + '_ {
self.comments.drain(
..self
.comments
.iter()
.position(|comment| {
!matches!(comment, Comment::Line(_))
|| self.line_index(comment.position()) > line_index
})
.unwrap_or(self.comments.len()),
)
}
pub fn drain_inline_comments(
&mut self,
position: &Position,
) -> impl Iterator<Item = &'a Comment<'a>> + '_ {
self.comments.drain(
..self
.comments
.iter()
.position(|comment| comment.position().end() > position.start())
.unwrap_or(self.comments.len()),
)
}
pub fn peek_comments(&self, line_index: usize) -> impl Iterator<Item = &Comment<'a>> {
self.comments
.range(
..self
.comments
.iter()
.position(|comment| self.line_index(comment.position()) >= line_index)
.unwrap_or(self.comments.len()),
)
.copied()
}
fn line_index(&self, position: &Position) -> usize {
self.position_map()
.line_index(position.start())
.expect("valid offset")
}
}