use tree_sitter::{Node, Tree};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ObligationScope {
Function,
Block,
Module,
Class,
Component,
}
impl ObligationScope {
#[must_use]
pub fn parse(name: &str) -> Option<Self> {
match name {
"function" => Some(Self::Function),
"block" => Some(Self::Block),
"module" => Some(Self::Module),
"class" => Some(Self::Class),
"component" => Some(Self::Component),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Keyed<'t> {
pub node: Node<'t>,
pub key: Option<Node<'t>>,
}
#[derive(Debug, Clone)]
pub struct UnmetObligation<'t> {
pub acquire: Node<'t>,
pub exit: Node<'t>,
pub partial: bool,
pub key: Option<Node<'t>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyCorrelation {
None,
Text,
Binding,
}
pub trait ObligationAnalyzer: Send + Sync {
fn analyze<'t>(
&self,
tree: &'t Tree,
source: &str,
scope: ObligationScope,
correlation: KeyCorrelation,
acquires: &[Keyed<'t>],
releases: &[Keyed<'t>],
) -> Vec<UnmetObligation<'t>>;
}
#[cfg(test)]
mod tests {
use super::ObligationScope;
#[test]
fn scope_parses_the_known_names_and_nothing_else() {
assert_eq!(
ObligationScope::parse("function"),
Some(ObligationScope::Function)
);
assert_eq!(
ObligationScope::parse("block"),
Some(ObligationScope::Block)
);
assert_eq!(
ObligationScope::parse("module"),
Some(ObligationScope::Module)
);
assert_eq!(
ObligationScope::parse("class"),
Some(ObligationScope::Class)
);
assert_eq!(
ObligationScope::parse("component"),
Some(ObligationScope::Component)
);
assert_eq!(ObligationScope::parse("loop"), None);
}
}