luau_parser/impl/
list.rs

1//! All `impl` blocks for [`List`].
2
3use lsp_types::Range;
4use luau_lexer::prelude::{Error, Lexer, Symbol, Token, TokenType};
5use std::ops::{Deref, DerefMut};
6
7use crate::types::{
8    GetRange, GetRangeError, List, ListItem, Parse, ParseWithArgs, Print, TryParse,
9};
10
11impl<T> List<T> {
12    /// Create a new empty list.
13    #[inline]
14    pub const fn new() -> Self {
15        Self { items: Vec::new() }
16    }
17
18    /// The main parsing logic.
19    fn parse<C: FnMut(Token, &mut Lexer) -> Option<T>>(
20        mut token: Token,
21        lexer: &mut Lexer,
22        mut parse: C,
23    ) -> Option<Self> {
24        let mut items = Vec::new();
25        let mut state = lexer.save_state();
26
27        while let Some(item) = parse(token, lexer) {
28            maybe_next_token!(lexer, maybe_comma, TokenType::Symbol(Symbol::Comma));
29            state = lexer.save_state();
30
31            if let Some(comma) = maybe_comma {
32                items.push(ListItem::Trailing {
33                    item,
34                    separator: comma,
35                });
36            } else {
37                items.push(ListItem::NonTrailing(item));
38
39                break;
40            }
41
42            token = lexer.next_token();
43        }
44
45        lexer.set_state(state);
46
47        Some(Self { items })
48    }
49}
50
51impl<T> Default for List<T> {
52    #[inline]
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl<T: Parse> Parse for List<T> {
59    #[inline]
60    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<Self> {
61        Self::parse(token, lexer, |token, lexer| T::parse(token, lexer, errors))
62    }
63}
64impl<T: Parse> TryParse for List<T> {}
65
66impl<A: Clone, T: ParseWithArgs<A>> ParseWithArgs<A> for List<T> {
67    #[inline]
68    fn parse_with(
69        token: Token,
70        lexer: &mut Lexer,
71        errors: &mut Vec<Error>,
72        args: A,
73    ) -> Option<Self> {
74        Self::parse(token, lexer, |token, lexer| {
75            T::parse_with(token, lexer, errors, args.clone())
76        })
77    }
78}
79
80impl<T> Deref for List<T> {
81    type Target = Vec<ListItem<T>>;
82
83    fn deref(&self) -> &Self::Target {
84        &self.items
85    }
86}
87impl<T> DerefMut for List<T> {
88    fn deref_mut(&mut self) -> &mut Self::Target {
89        &mut self.items
90    }
91}
92
93impl<T> Deref for ListItem<T> {
94    type Target = T;
95
96    fn deref(&self) -> &Self::Target {
97        match self {
98            Self::Trailing { item, .. } => item,
99            Self::NonTrailing(item) => item,
100        }
101    }
102}
103impl<T> DerefMut for ListItem<T> {
104    fn deref_mut(&mut self) -> &mut Self::Target {
105        match self {
106            Self::Trailing { item, .. } => item,
107            Self::NonTrailing(item) => item,
108        }
109    }
110}
111
112impl<T: GetRange> GetRange for List<T> {
113    fn get_range(&self) -> Result<Range, GetRangeError> {
114        (**self).get_range()
115    }
116}
117
118impl<T: GetRange> GetRange for ListItem<T> {
119    fn get_range(&self) -> Result<Range, GetRangeError> {
120        match self {
121            Self::Trailing { item, separator } => Ok(Range::new(
122                item.get_range()?.start,
123                separator.get_range()?.end,
124            )),
125            Self::NonTrailing(item) => item.get_range(),
126        }
127    }
128}
129
130impl<T: Print> Print for List<T> {
131    #[inline]
132    fn print(&self) -> String {
133        self.items.print()
134    }
135
136    #[inline]
137    fn print_final_trivia(&self) -> String {
138        self.items.print_final_trivia()
139    }
140
141    #[inline]
142    fn print_without_final_trivia(&self) -> String {
143        self.items.print_without_final_trivia()
144    }
145}
146
147impl<T: Print> Print for ListItem<T> {
148    #[inline]
149    fn print(&self) -> String {
150        match self {
151            Self::Trailing { item, separator } => {
152                item.print_without_final_trivia() + &separator.print()
153            }
154            Self::NonTrailing(item) => item.print(),
155        }
156    }
157
158    #[inline]
159    fn print_final_trivia(&self) -> String {
160        match self {
161            Self::Trailing { separator, .. } => separator.print_final_trivia(),
162            Self::NonTrailing(item) => item.print_final_trivia(),
163        }
164    }
165
166    #[inline]
167    fn print_without_final_trivia(&self) -> String {
168        match self {
169            Self::Trailing { item, separator } => {
170                item.print_without_final_trivia() + &separator.print_without_final_trivia()
171            }
172            Self::NonTrailing(item) => item.print_without_final_trivia(),
173        }
174    }
175}