grit_pattern_matcher/
binding.rs

1use crate::{
2    constant::Constant,
3    context::QueryContext,
4    effects::Effect,
5    pattern::{FileRegistry, Pattern, ResolvedPattern, State},
6};
7use grit_util::{
8    error::{GritPatternError, GritResult},
9    AnalysisLogs, ByteRange, CodeRange, Range,
10};
11use std::path::Path;
12use std::{borrow::Cow, collections::HashMap};
13
14pub trait Binding<'a, Q: QueryContext>: Clone + std::fmt::Debug + PartialEq + Sized {
15    fn from_constant(constant: &'a Constant) -> Self;
16
17    fn from_node(node: Q::Node<'a>) -> Self;
18
19    fn from_path(path: &'a Path) -> Self;
20
21    fn from_pattern(
22        pattern: &'a Pattern<Q>,
23        state: &mut State<'a, Q>,
24        context: &'a Q::ExecContext<'a>,
25        logs: &mut AnalysisLogs,
26    ) -> GritResult<Q::Binding<'a>> {
27        let resolved = Q::ResolvedPattern::from_pattern(pattern, state, context, logs)?;
28        if let Some(binding) = resolved.get_last_binding() {
29            Ok(binding.clone())
30        } else {
31            Err(GritPatternError::new(
32                "cannot create binding from pattern without binding",
33            ))
34        }
35    }
36
37    fn from_range(range: ByteRange, source: &'a str) -> Self;
38
39    fn singleton(&self) -> Option<Q::Node<'a>>;
40
41    fn get_sexp(&self) -> Option<String>;
42
43    fn position(&self, language: &Q::Language<'a>) -> Option<Range>;
44
45    fn range(&self, language: &Q::Language<'a>) -> Option<ByteRange>;
46
47    fn code_range(&self, language: &Q::Language<'a>) -> Option<CodeRange>;
48
49    /// Checks whether two bindings are equivalent.
50    ///
51    /// Bindings are considered equivalent if they refer to the same thing.
52    fn is_equivalent_to(&self, other: &Self, language: &Q::Language<'a>) -> bool;
53
54    fn is_suppressed(&self, language: &Q::Language<'a>, current_name: Option<&str>) -> bool;
55
56    /// Returns the padding to use for inserting the given text.
57    fn get_insertion_padding(
58        &self,
59        text: &str,
60        is_first: bool,
61        language: &Q::Language<'a>,
62    ) -> Option<String>;
63
64    fn linearized_text(
65        &self,
66        language: &Q::Language<'a>,
67        effects: &[Effect<'a, Q>],
68        files: &FileRegistry<'a, Q>,
69        memo: &mut HashMap<CodeRange, Option<String>>,
70        distributed_indent: Option<usize>,
71        logs: &mut AnalysisLogs,
72    ) -> GritResult<Cow<'a, str>>;
73
74    fn text(&self, language: &Q::Language<'a>) -> GritResult<Cow<str>>;
75
76    fn source(&self) -> Option<&'a str>;
77
78    /// Returns the constant this binding binds to, if and only if it is a
79    /// constant binding.
80    fn as_constant(&self) -> Option<&Constant>;
81
82    /// Returns the path of this binding, if and only if it is a filename
83    /// binding.
84    fn as_filename(&self) -> Option<&Path>;
85
86    /// Returns the node of this binding, if and only if it is a node binding.
87    fn as_node(&self) -> Option<Q::Node<'a>>;
88
89    /// Returns `true` if and only if this binding is bound to a list.
90    fn is_list(&self) -> bool;
91
92    /// Returns an iterator over the items in a list.
93    ///
94    /// Returns `None` if the binding is not bound to a list.
95    fn list_items(&self) -> Option<impl Iterator<Item = Q::Node<'a>> + Clone>;
96
97    /// Returns the parent node of this binding.
98    ///
99    /// Returns `None` if the binding has no relation to a node.
100    fn parent_node(&self) -> Option<Q::Node<'a>>;
101
102    fn is_truthy(&self) -> bool;
103
104    fn log_empty_field_rewrite_error(
105        &self,
106        language: &Q::Language<'a>,
107        logs: &mut AnalysisLogs,
108    ) -> GritResult<()>;
109}