1use lsp_types::Range;
9use luau_lexer::prelude::{Error, Lexer, Symbol, Token, TokenType};
10use std::cell::Cell;
11
12use crate::{
13 safe_unwrap,
14 types::{
15 Bracketed, BracketedList, Expression, FunctionArguments, GetRange, GetRangeError, Parse,
16 ParseWithArgs, Pointer, Print, Table, TableAccessKey, TableField, TableFieldValue,
17 TableKey, TryParse, TryParseWithArgs, TypeValue,
18 },
19};
20
21#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
23struct ParseArgs {
24 is_type: bool,
26
27 inferred_keys: Cell<u32>,
29}
30impl ParseArgs {
31 #[inline]
33 const fn new(is_type: bool, inferred_keys: u32) -> Self {
34 Self {
35 is_type,
36 inferred_keys: Cell::new(inferred_keys),
37 }
38 }
39}
40
41impl TableKey {
42 #[inline]
44 fn undefined_number(parse_args: &ParseArgs) -> Self {
45 Self::UndefinedNumber(
46 parse_args
47 .inferred_keys
48 .replace(parse_args.inferred_keys.get() + 1),
49 )
50 }
51
52 #[inline]
54 fn undefined_string() -> Self {
55 Self::UndefinedString("number".into())
56 }
57}
58
59impl ParseWithArgs<bool> for TableKey {
60 fn parse_with(
61 token: Token,
62 lexer: &mut Lexer,
63 errors: &mut Vec<Error>,
64 is_type: bool,
65 ) -> Option<Self> {
66 match token.token_type {
67 TokenType::Identifier(_) | TokenType::PartialKeyword(_) => Some(Self::Simple(token)),
68 TokenType::Symbol(Symbol::OpeningBrackets) => {
69 if is_type {
70 Bracketed::<_>::parse_with(
71 token,
72 lexer,
73 errors,
74 ("Expected <type>", Symbol::ClosingBrackets),
75 )
76 .map(Self::Type)
77 } else {
78 Bracketed::<_>::parse_with(
79 token,
80 lexer,
81 errors,
82 ("Expected <expr>", Symbol::ClosingBrackets),
83 )
84 .map(Self::Expression)
85 }
86 }
87 _ => None,
88 }
89 }
90}
91
92impl ParseWithArgs<&ParseArgs> for TableField {
93 fn parse_with(
94 token: Token,
95 lexer: &mut Lexer,
96 errors: &mut Vec<Error>,
97 parse_args: &ParseArgs,
98 ) -> Option<Self> {
99 if token == TokenType::Symbol(Symbol::ClosingCurlyBrackets) {
100 return None;
103 }
104
105 let state = lexer.save_state();
106
107 let (key, equal_or_colon) =
108 TableKey::parse_with(token.clone(), lexer, errors, parse_args.is_type).map_or(
109 (None, None),
110 |key| {
111 #[allow(clippy::branches_sharing_code)]
114 let equal_or_colon = if parse_args.is_type {
115 maybe_next_token!(lexer, temp, TokenType::Symbol(Symbol::Colon));
116
117 temp
118 } else {
119 maybe_next_token!(lexer, temp, TokenType::Symbol(Symbol::Equal));
120
121 temp
122 };
123
124 (Some(Pointer::new(key)), equal_or_colon)
125 },
126 );
127
128 if key.is_none() || equal_or_colon.is_none() {
129 lexer.set_state(state);
130
131 return Some(Self {
132 key: if parse_args.is_type {
133 Pointer::new(TableKey::undefined_string())
134 } else {
135 Pointer::new(TableKey::undefined_number(parse_args))
136 },
137 equal_or_colon: None,
138 value: safe_unwrap!(
139 lexer,
140 errors,
141 "Expected <type>",
142 TableFieldValue::parse_with(token, lexer, errors, parse_args.is_type)
143 .map(Pointer::new)
144 ),
145 });
146 }
147
148 #[allow(clippy::unwrap_used)]
150 let key = key.unwrap();
151
152 let value = Pointer::new(TableFieldValue::try_parse_with(
153 lexer,
154 errors,
155 parse_args.is_type,
156 )?);
157
158 Some(Self {
159 key,
160 equal_or_colon,
161 value,
162 })
163 }
164}
165
166impl ParseWithArgs<bool> for TableFieldValue {
167 #[inline]
168 fn parse_with(
169 token: Token,
170 lexer: &mut Lexer,
171 errors: &mut Vec<Error>,
172 is_type: bool,
173 ) -> Option<Self> {
174 if is_type {
175 TypeValue::parse(token, lexer, errors).map(Self::Type)
176 } else if token == TokenType::Symbol(Symbol::Ellipses) {
177 Some(Self::VariadicValues(token))
178 } else {
179 Expression::parse(token, lexer, errors).map(Self::Expression)
180 }
181 }
182}
183
184impl ParseWithArgs<bool> for Table {
185 fn parse_with(
186 token: Token,
187 lexer: &mut Lexer,
188 errors: &mut Vec<Error>,
189 is_type: bool,
190 ) -> Option<Self> {
191 if !matches!(
192 token.token_type,
193 TokenType::Symbol(Symbol::OpeningCurlyBrackets)
194 ) {
195 return None;
196 }
197
198 BracketedList::<TableField>::parse_with(
199 token,
200 lexer,
201 errors,
202 (
203 "Expected <table-field>",
204 Symbol::ClosingCurlyBrackets,
205 &ParseArgs::new(is_type, 1),
206 ),
207 )
208 .map(Self)
209 }
210}
211
212impl Parse<FunctionArguments> for Table {
213 #[inline]
214 fn parse(
215 token: Token,
216 lexer: &mut Lexer,
217 errors: &mut Vec<Error>,
218 ) -> Option<FunctionArguments> {
219 Self::parse_with(token, lexer, errors, false).map(FunctionArguments::Table)
220 }
221}
222impl TryParse<FunctionArguments> for Table {}
223
224impl Parse<TableAccessKey> for TableKey {
225 #[inline]
226 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<TableAccessKey> {
227 Self::parse_with(token, lexer, errors, false)
228 .map(Pointer::new)
229 .map(TableAccessKey::Expression)
230 }
231}
232impl TryParse<TableAccessKey> for TableKey {}
233
234impl GetRange for TableKey {
235 #[inline]
236 fn get_range(&self) -> Result<Range, GetRangeError> {
237 match self {
238 Self::ERROR => Err(GetRangeError::ErrorVariant),
239 Self::UndefinedNumber(_) | Self::UndefinedString(_) => {
240 Err(GetRangeError::UndefinedKey)
241 }
242 Self::Simple(token) => token.get_range(),
243 Self::Expression(bracketed) => bracketed.get_range(),
244 Self::Type(bracketed) => bracketed.get_range(),
245 }
246 }
247}
248
249impl GetRange for TableField {
250 #[inline]
251 fn get_range(&self) -> Result<Range, GetRangeError> {
252 let value_range = self.value.get_range();
253
254 if let Ok(key_range) = self.key.get_range() {
255 Ok(Range::new(key_range.start, value_range?.end))
256 } else {
257 value_range
258 }
259 }
260}
261
262impl Print for TableKey {
263 #[inline]
264 fn print(&self) -> String {
265 match self {
266 Self::Simple(token) => token.print(),
267 Self::Expression(bracketed) => bracketed.print(),
268 Self::Type(bracketed) => bracketed.print(),
269 _ => "".to_string(),
270 }
271 }
272
273 #[inline]
274 fn print_final_trivia(&self) -> String {
275 match self {
276 Self::Simple(token) => token.print_final_trivia(),
277 Self::Expression(bracketed) => bracketed.print_final_trivia(),
278 Self::Type(bracketed) => bracketed.print_final_trivia(),
279 _ => "".to_string(),
280 }
281 }
282
283 #[inline]
284 fn print_without_final_trivia(&self) -> String {
285 match self {
286 Self::Simple(token) => token.print_without_final_trivia(),
287 Self::Expression(bracketed) => bracketed.print_without_final_trivia(),
288 Self::Type(bracketed) => bracketed.print_without_final_trivia(),
289 _ => "".to_string(),
290 }
291 }
292}
293
294impl Print for TableField {
295 #[inline]
296 fn print_without_final_trivia(&self) -> String {
297 self.key.print_without_final_trivia()
298 + &self.equal_or_colon.print_without_final_trivia()
299 + &self.value.print_without_final_trivia()
300 }
301
302 #[inline]
303 fn print_final_trivia(&self) -> String {
304 self.value.print_final_trivia()
305 }
306}