grit_pattern_matcher/pattern/
includes.rsuse super::{
patterns::{Matcher, Pattern, PatternName},
resolved_pattern::ResolvedPattern,
State,
};
use crate::context::{ExecContext, QueryContext};
use core::fmt::Debug;
use grit_util::{
error::{GritPatternError, GritResult},
AnalysisLogs,
};
#[derive(Debug, Clone)]
pub struct Includes<Q: QueryContext> {
pub includes: Pattern<Q>,
}
impl<Q: QueryContext> Includes<Q> {
pub fn new(includes: Pattern<Q>) -> Self {
Self { includes }
}
}
impl<Q: QueryContext> PatternName for Includes<Q> {
fn name(&self) -> &'static str {
"INCLUDES"
}
}
fn execute<'a, Q: QueryContext>(
pattern: &'a Pattern<Q>,
binding: &Q::ResolvedPattern<'a>,
state: &mut State<'a, Q>,
context: &'a Q::ExecContext<'a>,
logs: &mut AnalysisLogs,
) -> GritResult<bool> {
match &pattern {
Pattern::Regex(pattern) => pattern.execute_matching(binding, state, context, logs, false),
Pattern::Or(pattern) => {
for p in pattern.patterns.iter() {
if execute(p, binding, state, context, logs)? {
return Ok(true);
}
}
Ok(false)
}
Pattern::Any(pattern) => {
let mut any_matched = false;
for p in pattern.patterns.iter() {
if execute(p, binding, state, context, logs)? {
any_matched = true;
}
}
Ok(any_matched)
}
Pattern::And(pattern) => {
for p in pattern.patterns.iter() {
if !execute(p, binding, state, context, logs)? {
return Ok(false);
}
}
Ok(true)
}
Pattern::AstNode(_)
| Pattern::List(_)
| Pattern::ListIndex(_)
| Pattern::Map(_)
| Pattern::Accessor(_)
| Pattern::Call(_)
| Pattern::File(_)
| Pattern::Files(_)
| Pattern::Bubble(_)
| Pattern::Limit(_)
| Pattern::CallBuiltIn(_)
| Pattern::CallFunction(_)
| Pattern::CallForeignFunction(_)
| Pattern::Assignment(_)
| Pattern::Accumulate(_)
| Pattern::Maybe(_)
| Pattern::Not(_)
| Pattern::If(_)
| Pattern::Undefined
| Pattern::Top
| Pattern::Bottom
| Pattern::Underscore
| Pattern::StringConstant(_)
| Pattern::AstLeafNode(_)
| Pattern::IntConstant(_)
| Pattern::FloatConstant(_)
| Pattern::BooleanConstant(_)
| Pattern::Dynamic(_)
| Pattern::CodeSnippet(_)
| Pattern::Variable(_)
| Pattern::Rewrite(_)
| Pattern::Log(_)
| Pattern::Range(_)
| Pattern::Contains(_)
| Pattern::Includes(_)
| Pattern::Within(_)
| Pattern::After(_)
| Pattern::Before(_)
| Pattern::Where(_)
| Pattern::Some(_)
| Pattern::Every(_)
| Pattern::Add(_)
| Pattern::Subtract(_)
| Pattern::Multiply(_)
| Pattern::Divide(_)
| Pattern::Modulo(_)
| Pattern::Dots
| Pattern::Sequential(_)
| Pattern::Like(_)
| Pattern::CallbackPattern(_) => {
let resolved = Q::ResolvedPattern::from_pattern(pattern, state, context, logs)
.map_err(|err| {
GritPatternError::new(format!(
"{err} \n includes can only be used with patterns that can be resolved"
))
})?;
let substring = resolved.text(&state.files, context.language()).map_err(|err| {
GritPatternError::new(
format!("{err} \n includes can only be used with patterns that can be resolved to a string")
)
})?;
let string = binding.text(&state.files, context.language()).map_err(|err| {
GritPatternError::new(
format!("{err} \n includes can only be used with patterns that can be resolved to a string")
)
})?;
if string.contains(&*substring) {
Ok(true)
} else {
Ok(false)
}
}
}
}
impl<Q: QueryContext> Matcher<Q> for Includes<Q> {
fn execute<'a>(
&'a self,
binding: &Q::ResolvedPattern<'a>,
state: &mut State<'a, Q>,
context: &'a Q::ExecContext<'a>,
logs: &mut AnalysisLogs,
) -> GritResult<bool> {
execute(&self.includes, binding, state, context, logs)
}
}