use std::collections::HashSet;
use crate::error::{ErrorCode, RuleError};
use crate::locator::YamlLocator;
use crate::path::PathToken;
#[derive(Debug, Clone)]
pub struct V2Scope {
let_bindings: HashSet<String>,
item_available: bool,
acc_available: bool,
pipe_available: bool,
parent: Option<Box<V2Scope>>,
}
impl V2Scope {
pub fn new() -> Self {
Self {
let_bindings: HashSet::new(),
item_available: false,
acc_available: false,
pipe_available: false,
parent: None,
}
}
pub fn with_parent(parent: &V2Scope) -> Self {
Self {
let_bindings: HashSet::new(),
item_available: parent.item_available,
acc_available: parent.acc_available,
pipe_available: parent.pipe_available,
parent: Some(Box::new(parent.clone())),
}
}
pub fn with_item(mut self) -> Self {
self.item_available = true;
self
}
pub fn with_acc(mut self) -> Self {
self.acc_available = true;
self
}
pub fn with_pipe(mut self) -> Self {
self.pipe_available = true;
self
}
pub fn add_binding(&mut self, name: String) {
self.let_bindings.insert(name);
}
pub fn has_binding(&self, name: &str) -> bool {
if self.let_bindings.contains(name) {
return true;
}
if let Some(ref parent) = self.parent {
return parent.has_binding(name);
}
false
}
pub fn allows_item(&self) -> bool {
self.item_available
}
pub fn allows_acc(&self) -> bool {
self.acc_available
}
pub fn allows_pipe(&self) -> bool {
self.pipe_available
}
}
impl Default for V2Scope {
fn default() -> Self {
Self::new()
}
}
pub struct V2ValidationCtx<'a> {
locator: Option<&'a YamlLocator>,
errors: Vec<RuleError>,
pub(super) produced_targets: HashSet<Vec<PathToken>>,
pub(super) allow_any_out_ref: bool,
pub context_referenced: bool,
pub(super) custom_op_names: HashSet<String>,
}
impl<'a> V2ValidationCtx<'a> {
pub fn new(locator: Option<&'a YamlLocator>) -> Self {
Self {
locator,
errors: Vec::new(),
produced_targets: HashSet::new(),
allow_any_out_ref: false,
context_referenced: false,
custom_op_names: HashSet::new(),
}
}
pub fn with_produced_targets(
locator: Option<&'a YamlLocator>,
produced_targets: HashSet<Vec<PathToken>>,
allow_any_out_ref: bool,
) -> Self {
Self {
locator,
errors: Vec::new(),
produced_targets,
allow_any_out_ref,
context_referenced: false,
custom_op_names: HashSet::new(),
}
}
pub(crate) fn with_custom_op_names(mut self, names: HashSet<String>) -> Self {
self.custom_op_names = names;
self
}
pub(crate) fn is_custom_op(&self, name: &str) -> bool {
self.custom_op_names.contains(name)
}
pub fn push_error(&mut self, code: ErrorCode, message: impl Into<String>, path: &str) {
let mut err = RuleError::new(code, message).with_path(path);
if let Some(locator) = self.locator {
if let Some(location) = locator.location_for(path) {
err = err.with_location(location.line, location.column);
}
}
self.errors.push(err);
}
pub fn add_produced_target(&mut self, tokens: Vec<PathToken>) {
self.produced_targets.insert(tokens);
}
pub fn produced_targets(&self) -> &HashSet<Vec<PathToken>> {
&self.produced_targets
}
pub fn finish(self) -> Result<(), Vec<RuleError>> {
if self.errors.is_empty() {
Ok(())
} else {
Err(self.errors)
}
}
pub fn has_errors(&self) -> bool {
!self.errors.is_empty()
}
pub fn errors(&self) -> &[RuleError] {
&self.errors
}
}