grit_pattern_matcher/pattern/
file_pattern.rs1use super::{
2 patterns::{Matcher, Pattern},
3 resolved_pattern::ResolvedPattern,
4 state::State,
5};
6use crate::{
7 constants::{ABSOLUTE_PATH_INDEX, FILENAME_INDEX, GLOBAL_VARS_SCOPE_INDEX, PROGRAM_INDEX},
8 context::ExecContext,
9};
10use crate::{context::QueryContext, pattern::resolved_pattern::File};
11use grit_util::{error::GritResult, AnalysisLogs};
12
13#[derive(Debug, Clone)]
14pub struct FilePattern<Q: QueryContext> {
15 pub name: Pattern<Q>,
16 pub body: Pattern<Q>,
17}
18
19impl<Q: QueryContext> FilePattern<Q> {
20 pub fn new(name: Pattern<Q>, body: Pattern<Q>) -> Self {
21 Self { name, body }
22 }
23}
24
25impl<Q: QueryContext> Matcher<Q> for FilePattern<Q> {
26 fn execute<'a>(
27 &'a self,
28 resolved_pattern: &Q::ResolvedPattern<'a>,
29 state: &mut State<'a, Q>,
30 context: &'a Q::ExecContext<'a>,
31 logs: &mut AnalysisLogs,
32 ) -> GritResult<bool> {
33 let Some(file) = resolved_pattern.get_file() else {
34 return Ok(false);
35 };
36
37 let name = file.name(&state.files);
38
39 if !self.name.execute(&name, state, context, logs)? {
40 return Ok(false);
41 }
42
43 if !context.load_file(file, state, logs)? {
45 return Ok(false);
47 }
48
49 self.name
51 .execute(&file.name(&state.files), state, context, logs)?;
52
53 state.bindings[GLOBAL_VARS_SCOPE_INDEX as usize]
55 .last_mut()
56 .unwrap()[PROGRAM_INDEX]
57 .value = Some(file.binding(&state.files));
58 state.bindings[GLOBAL_VARS_SCOPE_INDEX as usize]
59 .last_mut()
60 .unwrap()[FILENAME_INDEX]
61 .value = Some(file.name(&state.files));
62 state.bindings[GLOBAL_VARS_SCOPE_INDEX as usize]
63 .last_mut()
64 .unwrap()[ABSOLUTE_PATH_INDEX]
65 .value = Some(file.name(&state.files));
66 state.bindings[GLOBAL_VARS_SCOPE_INDEX as usize]
67 .last_mut()
68 .unwrap()[ABSOLUTE_PATH_INDEX]
69 .value = Some(file.absolute_path(&state.files, context.language())?);
70
71 if !self
72 .body
73 .execute(&file.binding(&state.files), state, context, logs)?
74 {
75 return Ok(false);
76 }
77
78 Ok(true)
79 }
80}