luau_parser/impl/
mod.rs

1//! All `impl` blocks for CST-related types.
2
3#[macro_use]
4mod macros;
5
6mod block;
7mod bracketed;
8mod cst;
9mod expression;
10mod list;
11mod name;
12mod value;
13
14use lsp_types::Range;
15use luau_lexer::prelude::{Comment, Error, Lexer, Token, TokenType, Trivia};
16
17use crate::types::{
18    GetRange, GetRangeError, Parse, ParseWithArgs, Pointer, Print, TryParse, TryParseWithArgs,
19};
20
21impl<T: Parse> Parse for Pointer<T> {
22    #[inline]
23    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<Self> {
24        T::parse(token, lexer, errors).map(Self::new)
25    }
26}
27impl<T: TryParse + Parse> TryParse for Pointer<T> {
28    #[inline]
29    fn try_parse(lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<Self> {
30        T::try_parse(lexer, errors).map(Self::new)
31    }
32}
33
34impl<T: Parse> Parse for Vec<T> {
35    #[inline]
36    fn parse(mut token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<Self> {
37        let mut values = Self::new();
38        let mut state = lexer.save_state();
39
40        while let Some(value) = T::parse(token, lexer, errors) {
41            values.push(value);
42            state = lexer.save_state();
43            token = lexer.next_token();
44        }
45
46        lexer.set_state(state);
47
48        (!values.is_empty()).then_some(values)
49    }
50}
51impl<T: TryParse + Parse> TryParse for Vec<T> {}
52
53impl<T: ParseWithArgs<A>, A: Clone> ParseWithArgs<A> for Vec<T> {
54    #[inline]
55    fn parse_with(
56        mut token: Token,
57        lexer: &mut Lexer,
58        errors: &mut Vec<Error>,
59        args: A,
60    ) -> Option<Self> {
61        let mut values = Self::new();
62        let mut state = lexer.save_state();
63
64        while let Some(value) = T::parse_with(token, lexer, errors, args.clone()) {
65            values.push(value);
66            state = lexer.save_state();
67            token = lexer.next_token();
68        }
69
70        lexer.set_state(state);
71
72        (!values.is_empty()).then_some(values)
73    }
74}
75impl<T: ParseWithArgs<A>, A: Clone> TryParseWithArgs<A> for T {}
76
77impl GetRange for Token {
78    #[inline]
79    fn get_range(&self) -> Result<Range, GetRangeError> {
80        Ok(Range::new(self.start, self.end))
81    }
82}
83
84impl Print for Comment {
85    #[inline]
86    fn print(&self) -> String {
87        match self {
88            Self::SingleLine(smol_str) | Self::MultiLine(smol_str) => smol_str.to_string(),
89        }
90    }
91
92    fn print_final_trivia(&self) -> String {
93        unreachable!()
94    }
95    fn print_without_final_trivia(&self) -> String {
96        unreachable!()
97    }
98}
99impl Print for Trivia {
100    #[inline]
101    fn print(&self) -> String {
102        match self {
103            Self::Spaces(smol_str) => smol_str.to_string(),
104            Self::Comment(comment) => comment.print(),
105        }
106    }
107
108    fn print_final_trivia(&self) -> String {
109        unreachable!()
110    }
111    fn print_without_final_trivia(&self) -> String {
112        unreachable!()
113    }
114}
115
116/// [`Print`] implementation for [`Vec<Trivia>`] as the default one won't work.
117/// It takes `&[Trivia]` so we don't need to `.clone()`.
118fn print_trivia(trivia: &[Trivia]) -> String {
119    trivia
120        .iter()
121        .fold("".to_string(), |str, item| str + &item.print())
122}
123
124impl Print for Token {
125    #[inline]
126    fn print_final_trivia(&self) -> String {
127        if self.token_type == TokenType::EndOfFile {
128            print_trivia(&self.leading_trivia)
129        } else {
130            print_trivia(&self.trailing_trivia)
131        }
132    }
133
134    #[inline]
135    fn print_without_final_trivia(&self) -> String {
136        self.token_type
137            .try_as_string()
138            .map(|token_type| print_trivia(&self.leading_trivia) + &token_type)
139            .unwrap_or_default()
140    }
141
142    #[inline]
143    fn print(&self) -> String {
144        self.token_type
145            .try_as_string()
146            .map(|token_type| {
147                print_trivia(&self.leading_trivia)
148                    + &token_type
149                    + &print_trivia(&self.trailing_trivia)
150            })
151            .unwrap_or_default()
152    }
153}
154
155impl<T: GetRange> GetRange for Pointer<T> {
156    #[inline]
157    fn get_range(&self) -> Result<Range, GetRangeError> {
158        (**self).get_range()
159    }
160}
161impl<T: Print> Print for Pointer<T> {
162    #[inline]
163    fn print(&self) -> String {
164        (**self).print()
165    }
166
167    #[inline]
168    fn print_final_trivia(&self) -> String {
169        (**self).print_final_trivia()
170    }
171
172    #[inline]
173    fn print_without_final_trivia(&self) -> String {
174        (**self).print_without_final_trivia()
175    }
176}
177
178impl<T: Print> Print for Option<T> {
179    #[inline]
180    fn print(&self) -> String {
181        self.as_ref()
182            .map_or_else(|| "".to_string(), |item| item.print())
183    }
184
185    fn print_final_trivia(&self) -> String {
186        self.as_ref()
187            .map_or_else(|| "".to_string(), |item| item.print_final_trivia())
188    }
189
190    fn print_without_final_trivia(&self) -> String {
191        self.as_ref()
192            .map_or_else(|| "".to_string(), |item| item.print_without_final_trivia())
193    }
194}
195
196impl<T: GetRange> GetRange for Vec<T> {
197    #[inline]
198    fn get_range(&self) -> Result<Range, GetRangeError> {
199        if self.is_empty() {
200            Err(GetRangeError::EmptyList)
201        } else if self.len() == 1 {
202            self[0].get_range()
203        } else {
204            // SAFETY: `self.last()` will never error as we know length is >= 2
205            #[allow(clippy::unwrap_used)]
206            Ok(Range::new(
207                self[0].get_range()?.start,
208                self.last().unwrap().get_range()?.end,
209            ))
210        }
211    }
212}
213impl<T: Print> Print for Vec<T> {
214    #[inline]
215    fn print_final_trivia(&self) -> String {
216        self.last()
217            .map(|item| item.print_final_trivia())
218            .unwrap_or_default()
219    }
220
221    #[inline]
222    fn print_without_final_trivia(&self) -> String {
223        self.iter().fold("".to_string(), |str, item| {
224            str + &item.print_without_final_trivia()
225        })
226    }
227}
228
229impl<T: Print, U: Print> Print for (T, U) {
230    #[inline]
231    fn print(&self) -> String {
232        let end = self.1.print();
233
234        if end.is_empty() {
235            self.0.print()
236        } else {
237            self.0.print_without_final_trivia() + &end
238        }
239    }
240
241    #[inline]
242    fn print_final_trivia(&self) -> String {
243        let maybe_final_trivia = self.1.print_final_trivia();
244        if maybe_final_trivia.is_empty() {
245            self.0.print_final_trivia()
246        } else {
247            maybe_final_trivia
248        }
249    }
250
251    #[inline]
252    fn print_without_final_trivia(&self) -> String {
253        self.0.print_without_final_trivia() + &self.1.print_without_final_trivia()
254    }
255}