1use lsp_types::Range;
8use luau_lexer::prelude::{Keyword, Lexer, ParseError, PartialKeyword, Symbol, Token, TokenType};
9
10use crate::{
11 force_parse_bracketed, parse_bracketed,
12 types::{
13 Attribute, Block, GetRange, GetRangeError, GlobalFunction, GlobalFunctionName,
14 LocalFunction, Parameter, Parse, ParseWithArgs, Pointer, TableAccessKey, TryParse,
15 TryParseWithArgs, TypeFunction, TypeValue,
16 },
17 utils::{get_token_type_display, get_token_type_display_extended},
18};
19
20impl Parse for LocalFunction {
21 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
22 let state = lexer.save_state();
23 let attributes;
24 let local_keyword;
25
26 match token.token_type {
27 TokenType::Keyword(Keyword::Local) => {
28 attributes = Vec::new();
29 local_keyword = token;
30 }
31 TokenType::Symbol(Symbol::At) => {
32 attributes = safe_unwrap!(
33 lexer,
34 errors,
35 "Expected <attribute>",
36 Vec::parse(token, lexer, errors)
37 );
38 local_keyword = lexer.next_token();
39 }
40 _ => return None,
41 }
42 if local_keyword != TokenType::Keyword(Keyword::Local) {
43 lexer.set_state(state);
44
45 return None;
46 }
47
48 parse_function!(
49 let attributes = attributes;
50 lexer.next_token(),
51 lexer,
52 errors,
53 let function_name = {
54 next_token_recoverable!(
55 lexer,
56 name,
57 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
58 TokenType::Identifier("*error*".into(),),
59 errors,
60 "Expected ".to_string()
61 + get_token_type_display(&TokenType::Identifier("".into(),))
62 );
63
64 name
65 },
66 { attributes, local_keyword, function_name }
67 )
68 }
69}
70impl TryParse for LocalFunction {}
71
72impl Parse for GlobalFunctionName {
73 fn parse(name: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
74 if !matches!(
75 name.token_type,
76 TokenType::Identifier(_) | TokenType::PartialKeyword(_)
77 ) {
78 return None;
79 }
80
81 maybe_next_token!(
82 lexer,
83 dot_or_colon,
84 TokenType::Symbol(Symbol::Dot) | TokenType::Symbol(Symbol::Colon)
85 );
86 if let Some(dot_or_colon) = dot_or_colon {
87 let is_dot = dot_or_colon == TokenType::Symbol(Symbol::Dot);
88
89 let keys = if is_dot {
90 Vec::<TableAccessKey>::parse_with(dot_or_colon.clone(), lexer, errors, false)
91 .unwrap_or_default()
92 } else {
93 Vec::new()
94 };
95
96 let method = if !is_dot {
97 next_token_recoverable!(
98 lexer,
99 parsed_method,
100 TokenType::Identifier(_),
101 TokenType::Identifier("*error*".into()),
102 errors,
103 "Expected ".to_string()
104 + get_token_type_display(&TokenType::Identifier("".into()),)
105 );
106
107 Some(Pointer::new((dot_or_colon, parsed_method)))
108 } else {
109 None
110 };
111
112 return Some(Self::Table {
113 table: name,
114 keys,
115 method,
116 });
117 }
118
119 Some(Self::SimpleName(name))
120 }
121}
122impl TryParse for GlobalFunctionName {}
123
124impl Parse for GlobalFunction {
125 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
126 let attributes;
127 let function_keyword;
128
129 match token.token_type {
130 TokenType::Keyword(Keyword::Function) => {
131 attributes = Vec::new();
132 function_keyword = token;
133 }
134 TokenType::Symbol(Symbol::At) => {
135 attributes = safe_unwrap!(
136 lexer,
137 errors,
138 "Expected <attribute>",
139 Vec::parse(token, lexer, errors)
140 );
141 function_keyword = lexer.next_token();
142 }
143 _ => return None,
144 }
145
146 parse_function!(
147 let attributes = attributes;
148 function_keyword,
149 lexer,
150 errors,
151 let function_name = {
152 GlobalFunctionName::try_parse(lexer, errors).unwrap_or_else(|| {
153 GlobalFunctionName::SimpleName(Token::empty(TokenType::Identifier(
154 "*error*".into(),
155 )))
156 })
157 },
158 { attributes, function_name }
159 )
160 }
161}
162impl TryParse for GlobalFunction {}
163
164impl Parse for Parameter {
165 fn parse(name: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
166 if !matches!(
167 name.token_type,
168 TokenType::Identifier(_)
169 | TokenType::PartialKeyword(_)
170 | TokenType::Symbol(Symbol::Ellipses)
171 ) {
172 return None;
173 }
174
175 maybe_next_token!(lexer, colon, TokenType::Symbol(Symbol::Colon));
176
177 let r#type = if colon.is_some() {
178 Pointer::<TypeValue>::try_parse(lexer, errors)
179 } else {
180 None
181 };
182
183 Some(Self {
184 name,
185 colon,
186 r#type,
187 })
188 }
189}
190
191impl Parse for Attribute {
192 fn parse(at: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
193 if at != TokenType::Symbol(Symbol::At) {
194 return None;
195 }
196
197 next_token_recoverable!(
198 lexer,
199 attribute,
200 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
201 TokenType::Identifier("*error*".into()),
202 errors,
203 "Expected ".to_string() + get_token_type_display(&TokenType::Identifier("".into()))
204 );
205
206 Some(Self { at, attribute })
207 }
208}
209impl TryParse for Attribute {}
210
211impl GetRange for GlobalFunctionName {
212 fn get_range(&self) -> Result<Range, GetRangeError> {
213 match self {
214 GlobalFunctionName::SimpleName(token) => token.get_range(),
215 GlobalFunctionName::Table {
216 table,
217 keys,
218 method,
219 } => {
220 let table_range = table.get_range();
221 let last_range = match method {
222 Some(method) => method.1.get_range(),
223 None => keys.get_range(),
224 };
225
226 if let Ok(last_range) = last_range {
227 Ok(Range::new(table_range?.start, last_range.end))
228 } else {
229 table_range
230 }
231 }
232 }
233 }
234}
235
236impl Parse for TypeFunction {
237 fn parse(
238 mut type_keyword: Token,
239 lexer: &mut Lexer,
240 errors: &mut Vec<ParseError>,
241 ) -> Option<Self> {
242 let state = lexer.save_state();
243
244 let export_keyword = if type_keyword == TokenType::PartialKeyword(PartialKeyword::Export) {
245 let temp = type_keyword;
246 type_keyword = lexer.next_token();
247
248 Some(temp)
249 } else {
250 None
251 };
252
253 let function_keyword = lexer.next_token();
254
255 if type_keyword != TokenType::PartialKeyword(PartialKeyword::Type)
256 || function_keyword != TokenType::Keyword(Keyword::Function)
257 {
258 lexer.set_state(state);
259
260 return None;
261 }
262
263 parse_function!(
264 function_keyword,
265 lexer,
266 errors,
267 let function_name = {
268 next_token_recoverable!(
269 lexer,
270 name,
271 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
272 TokenType::Identifier("*error*".into(),),
273 errors,
274 "Expected ".to_string()
275 + get_token_type_display(&TokenType::Identifier("".into(),))
276 );
277
278 name
279 },
280 { export_keyword, type_keyword, function_name }
281 )
282 }
283}
284impl TryParse for TypeFunction {}