use super::error::Error;
use crate::parsers::hcl::{
Pair, Rule,
ast::{Attribute, Block},
};
#[derive(Debug, Clone)]
pub struct Body<'i> {
pub attributes: Vec<Attribute<'i>>,
pub blocks: Vec<Block<'i>>,
}
impl<'i> Body<'i> {
pub fn find_blocks<'s, 'j>(&'s self, id: &'j str) -> impl Iterator<Item = &'s Block<'i>> + 'j
where
's: 'j,
{
self.blocks.iter().filter(|block| block.id == id)
}
pub fn get_block(&self, id: &str, args: Option<&[&str]>) -> Option<&Block<'i>> {
self.find_blocks(id)
.find(|block| args.is_none_or(|args| block.args == args))
}
pub fn get_attribute(&self, name: &str) -> Option<&Attribute<'i>> {
self.attributes.iter().find(|attr| attr.name == name)
}
pub fn get_attributes_with_inline_hints(&self) -> Vec<&Attribute<'i>> {
self.attributes
.iter()
.filter(|attr| attr.hint.is_some())
.collect()
}
}
impl<'i> Body<'i> {
pub(super) fn process(pair: Pair<'i>) -> (Self, Vec<Error>) {
let mut attributes = vec![];
let mut blocks = vec![];
let mut errors = vec![];
for item in pair.into_inner() {
match item.as_rule() {
Rule::Attribute => match Attribute::process(item) {
Ok(processed_item) => attributes.push(processed_item),
Err(e) => errors.push(e),
},
Rule::AttributeError => {
let (l, _) = item.line_col();
errors.push(Error::MultipleInlineHint {
hint: item.as_str().to_string(),
line: l.to_string(),
});
}
Rule::Block => {
let (block, errs) = Block::process(item);
blocks.push(block);
errors.extend(errs);
}
rule => unreachable!("{rule:?}"),
}
}
(Self { attributes, blocks }, errors)
}
}