lib_ruby_parser_ast/traverse/finder/pattern/
mod.rs

1mod item;
2pub use item::Item;
3
4mod error;
5pub use error::PatternError;
6
7/// Pattern that is used for matching.
8///
9/// Consists of multiple `finder::Item` elements
10///
11/// For example the following pattern:
12///
13/// ```text
14/// Pattern::new("args -> arglist -> 2 -> default")
15/// ```
16///
17/// can find a node that represents constant `FIND_ME` in the following code:
18///
19/// ```text
20/// def foo(a, b, c = FIND_ME)
21/// end
22/// ```
23///
24/// It means:
25/// 1. enter `.args` of the `Def` node (`(a, b, c = FIND_ME`))
26/// 2. enter its `.argslist` (`a, b, c = FIND_ME`)
27/// 3. enter element `[2]` (`c = FIND_ME`)
28/// 4. enter `.default` of the `Optarg` node (`FIND_ME`)
29#[derive(Debug, PartialEq, Eq)]
30pub struct Pattern {
31    pub(crate) parts: Vec<Item>,
32}
33
34impl Pattern {
35    /// Constructs a pattern from a string, returns an error on the first sub-pattern error
36    pub fn new(input: &str) -> Result<Self, PatternError> {
37        let mut parts: Vec<Item> = vec![];
38
39        for part in input.split(" -> ") {
40            let part = Item::new(part)?;
41            parts.push(part);
42        }
43
44        Ok(Self { parts })
45    }
46
47    /// Returns `true` if pattern is empty
48    pub fn empty() -> Self {
49        Self { parts: vec![] }
50    }
51
52    /// Pushes a new `Item` into a pattern
53    pub fn push(&mut self, item: Item) {
54        self.parts.push(item)
55    }
56
57    /// Pops an `Item` from a pattern
58    pub fn pop(&mut self) -> Option<Item> {
59        self.parts.pop()
60    }
61
62    pub(crate) fn unshift(&mut self) -> Option<Item> {
63        if self.parts.is_empty() {
64            None
65        } else {
66            Some(self.parts.remove(0))
67        }
68    }
69}