emmylua_parser/syntax/node/lua/
mod.rs1mod expr;
2mod path_trait;
3mod stat;
4mod test;
5
6use crate::{
7 kind::{LuaSyntaxKind, LuaTokenKind},
8 syntax::traits::{LuaAstChildren, LuaAstNode, LuaAstToken},
9 LuaCommentOwner, LuaSyntaxNode,
10};
11
12pub use expr::*;
13pub use path_trait::*;
14use rowan::TextRange;
15pub use stat::*;
16
17use super::{LuaLiteralToken, LuaNameToken, LuaNumberToken, LuaStringToken};
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct LuaChunk {
21 syntax: LuaSyntaxNode,
22}
23
24impl LuaAstNode for LuaChunk {
25 fn syntax(&self) -> &LuaSyntaxNode {
26 &self.syntax
27 }
28
29 fn can_cast(kind: LuaSyntaxKind) -> bool
30 where
31 Self: Sized,
32 {
33 kind == LuaSyntaxKind::Chunk
34 }
35
36 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
37 where
38 Self: Sized,
39 {
40 if syntax.kind() == LuaSyntaxKind::Chunk.into() {
41 Some(Self { syntax })
42 } else {
43 None
44 }
45 }
46}
47
48impl LuaChunk {
49 pub fn get_block(&self) -> Option<LuaBlock> {
50 self.child()
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55pub struct LuaBlock {
56 syntax: LuaSyntaxNode,
57}
58
59impl LuaAstNode for LuaBlock {
60 fn syntax(&self) -> &LuaSyntaxNode {
61 &self.syntax
62 }
63
64 fn can_cast(kind: LuaSyntaxKind) -> bool
65 where
66 Self: Sized,
67 {
68 kind == LuaSyntaxKind::Block
69 }
70
71 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
72 where
73 Self: Sized,
74 {
75 if syntax.kind() == LuaSyntaxKind::Block.into() {
76 Some(Self { syntax })
77 } else {
78 None
79 }
80 }
81}
82
83impl LuaBlock {
84 pub fn get_stats(&self) -> LuaAstChildren<LuaStat> {
85 self.children()
86 }
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub struct LuaLocalName {
91 syntax: LuaSyntaxNode,
92}
93
94impl LuaAstNode for LuaLocalName {
95 fn syntax(&self) -> &LuaSyntaxNode {
96 &self.syntax
97 }
98
99 fn can_cast(kind: LuaSyntaxKind) -> bool
100 where
101 Self: Sized,
102 {
103 kind == LuaSyntaxKind::LocalName
104 }
105
106 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
107 where
108 Self: Sized,
109 {
110 if Self::can_cast(syntax.kind().into()) {
111 Some(Self { syntax })
112 } else {
113 None
114 }
115 }
116}
117
118impl LuaLocalName {
119 pub fn get_name_token(&self) -> Option<LuaNameToken> {
120 self.token()
121 }
122
123 pub fn get_attrib(&self) -> Option<LuaLocalAttribute> {
124 self.child()
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Hash)]
129pub struct LuaCallArgList {
130 syntax: LuaSyntaxNode,
131}
132
133impl LuaAstNode for LuaCallArgList {
134 fn syntax(&self) -> &LuaSyntaxNode {
135 &self.syntax
136 }
137
138 fn can_cast(kind: LuaSyntaxKind) -> bool
139 where
140 Self: Sized,
141 {
142 kind == LuaSyntaxKind::CallArgList
143 }
144
145 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
146 where
147 Self: Sized,
148 {
149 if Self::can_cast(syntax.kind().into()) {
150 Some(Self { syntax })
151 } else {
152 None
153 }
154 }
155}
156
157impl LuaCallArgList {
158 pub fn is_single_arg_no_parens(&self) -> bool {
159 self.token_by_kind(LuaTokenKind::TkLeftParen).is_none()
160 }
161
162 pub fn get_args(&self) -> LuaAstChildren<LuaExpr> {
163 self.children()
164 }
165
166 pub fn get_single_arg_expr(&self) -> Option<LuaSingleArgExpr> {
167 self.child()
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Hash)]
172pub struct LuaLocalAttribute {
173 syntax: LuaSyntaxNode,
174}
175
176impl LuaAstNode for LuaLocalAttribute {
177 fn syntax(&self) -> &LuaSyntaxNode {
178 &self.syntax
179 }
180
181 fn can_cast(kind: LuaSyntaxKind) -> bool
182 where
183 Self: Sized,
184 {
185 kind == LuaSyntaxKind::Attribute
186 }
187
188 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
189 where
190 Self: Sized,
191 {
192 if Self::can_cast(syntax.kind().into()) {
193 Some(Self { syntax })
194 } else {
195 None
196 }
197 }
198}
199
200impl LuaLocalAttribute {
201 pub fn get_name_token(&self) -> Option<LuaNameToken> {
202 self.token()
203 }
204
205 pub fn is_close(&self) -> bool {
206 match self.get_name_token() {
207 None => false,
208 Some(name_token) => name_token.get_name_text() == "close",
209 }
210 }
211
212 pub fn is_const(&self) -> bool {
213 match self.get_name_token() {
214 None => false,
215 Some(name_token) => name_token.get_name_text() == "const",
216 }
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq, Hash)]
221pub struct LuaTableField {
222 syntax: LuaSyntaxNode,
223}
224
225impl LuaAstNode for LuaTableField {
226 fn syntax(&self) -> &LuaSyntaxNode {
227 &self.syntax
228 }
229
230 fn can_cast(kind: LuaSyntaxKind) -> bool
231 where
232 Self: Sized,
233 {
234 kind == LuaSyntaxKind::TableFieldAssign || kind == LuaSyntaxKind::TableFieldValue
235 }
236
237 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
238 where
239 Self: Sized,
240 {
241 if Self::can_cast(syntax.kind().into()) {
242 Some(Self { syntax })
243 } else {
244 None
245 }
246 }
247}
248
249impl LuaCommentOwner for LuaTableField {}
250
251impl LuaTableField {
252 pub fn is_assign_field(&self) -> bool {
254 self.syntax().kind() == LuaSyntaxKind::TableFieldAssign.into()
255 }
256
257 pub fn is_value_field(&self) -> bool {
259 self.syntax().kind() == LuaSyntaxKind::TableFieldValue.into()
260 }
261
262 pub fn get_field_key(&self) -> Option<LuaIndexKey> {
263 if !self.is_assign_field() {
264 let parent_table = self.get_parent::<LuaTableExpr>()?;
265 let fields = parent_table.get_fields();
266 let mut idx = 1;
267 for field in fields {
268 if field.is_value_field() {
269 if field.syntax() == self.syntax() {
270 return Some(LuaIndexKey::Idx(idx));
271 }
272 idx += 1;
273 }
274 }
275
276 return None;
277 }
278
279 let mut meet_left_bracket = false;
280 for child in self.syntax.children_with_tokens() {
281 if meet_left_bracket {
282 match child {
283 rowan::NodeOrToken::Node(node) => {
284 if LuaLiteralExpr::can_cast(node.kind().into()) {
285 let literal_expr = LuaLiteralExpr::cast(node.clone()).unwrap();
286 if let Some(literal_token) = literal_expr.get_literal() {
287 match literal_token {
288 LuaLiteralToken::String(token) => {
289 return Some(LuaIndexKey::String(token.clone()));
290 }
291 LuaLiteralToken::Number(token) => {
292 return Some(LuaIndexKey::Integer(token.clone()));
293 }
294 _ => {}
295 }
296 }
297 }
298
299 return Some(LuaIndexKey::Expr(LuaExpr::cast(node).unwrap()));
300 }
301 _ => return None,
302 }
303 } else if let Some(token) = child.as_token() {
304 if token.kind() == LuaTokenKind::TkLeftBracket.into() {
305 meet_left_bracket = true;
306 } else if token.kind() == LuaTokenKind::TkName.into() {
307 return Some(LuaIndexKey::Name(
308 LuaNameToken::cast(token.clone()).unwrap(),
309 ));
310 }
311 }
312 }
313
314 None
315 }
316
317 pub fn get_value_expr(&self) -> Option<LuaExpr> {
318 if self.is_assign_field() {
319 self.children().last()
320 } else {
321 self.child()
322 }
323 }
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, Hash)]
327pub enum LuaIndexKey {
328 Name(LuaNameToken),
329 String(LuaStringToken),
330 Integer(LuaNumberToken),
331 Expr(LuaExpr),
332 Idx(usize),
333}
334
335impl LuaIndexKey {
336 pub fn is_name(&self) -> bool {
337 matches!(self, LuaIndexKey::Name(_))
338 }
339
340 pub fn is_string(&self) -> bool {
341 matches!(self, LuaIndexKey::String(_))
342 }
343
344 pub fn is_integer(&self) -> bool {
345 matches!(self, LuaIndexKey::Integer(_))
346 }
347
348 pub fn is_expr(&self) -> bool {
349 matches!(self, LuaIndexKey::Expr(_))
350 }
351
352 pub fn get_name(&self) -> Option<&LuaNameToken> {
353 match self {
354 LuaIndexKey::Name(token) => Some(token),
355 _ => None,
356 }
357 }
358
359 pub fn get_string(&self) -> Option<&LuaStringToken> {
360 match self {
361 LuaIndexKey::String(token) => Some(token),
362 _ => None,
363 }
364 }
365
366 pub fn get_integer(&self) -> Option<&LuaNumberToken> {
367 match self {
368 LuaIndexKey::Integer(token) => Some(token),
369 _ => None,
370 }
371 }
372
373 pub fn get_expr(&self) -> Option<&LuaExpr> {
374 match self {
375 LuaIndexKey::Expr(expr) => Some(expr),
376 _ => None,
377 }
378 }
379
380 pub fn get_path_part(&self) -> String {
381 match self {
382 LuaIndexKey::String(s) => s.get_value(),
383 LuaIndexKey::Name(name) => name.get_name_text().to_string(),
384 LuaIndexKey::Integer(i) => {
385 format!("[{}]", i.get_int_value())
386 }
387 LuaIndexKey::Expr(expr) => {
388 format!("[{}]", expr.syntax().text())
389 }
390 LuaIndexKey::Idx(i) => {
391 format!("[{}]", i)
392 }
393 }
394 }
395
396 pub fn get_range(&self) -> Option<TextRange> {
397 match self {
398 LuaIndexKey::Name(token) => Some(token.get_range()),
399 LuaIndexKey::String(token) => Some(token.get_range()),
400 LuaIndexKey::Integer(token) => Some(token.get_range()),
401 LuaIndexKey::Expr(expr) => Some(expr.syntax().text_range()),
402 LuaIndexKey::Idx(_) => None,
403 }
404 }
405}
406
407#[derive(Debug, Clone, PartialEq, Eq, Hash)]
408pub struct LuaParamName {
409 syntax: LuaSyntaxNode,
410}
411
412impl LuaAstNode for LuaParamName {
413 fn syntax(&self) -> &LuaSyntaxNode {
414 &self.syntax
415 }
416
417 fn can_cast(kind: LuaSyntaxKind) -> bool
418 where
419 Self: Sized,
420 {
421 kind == LuaSyntaxKind::ParamName
422 }
423
424 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
425 where
426 Self: Sized,
427 {
428 if Self::can_cast(syntax.kind().into()) {
429 Some(Self { syntax })
430 } else {
431 None
432 }
433 }
434}
435
436impl LuaParamName {
437 pub fn get_name_token(&self) -> Option<LuaNameToken> {
438 self.token()
439 }
440
441 pub fn is_dots(&self) -> bool {
442 self.token_by_kind(LuaTokenKind::TkDots).is_some()
443 }
444}
445
446#[derive(Debug, Clone, PartialEq, Eq, Hash)]
447pub struct LuaParamList {
448 syntax: LuaSyntaxNode,
449}
450
451impl LuaAstNode for LuaParamList {
452 fn syntax(&self) -> &LuaSyntaxNode {
453 &self.syntax
454 }
455
456 fn can_cast(kind: LuaSyntaxKind) -> bool
457 where
458 Self: Sized,
459 {
460 kind == LuaSyntaxKind::ParamList
461 }
462
463 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
464 where
465 Self: Sized,
466 {
467 if Self::can_cast(syntax.kind().into()) {
468 Some(Self { syntax })
469 } else {
470 None
471 }
472 }
473}
474
475impl LuaParamList {
476 pub fn get_params(&self) -> LuaAstChildren<LuaParamName> {
477 self.children()
478 }
479}
480
481#[derive(Debug, Clone, PartialEq, Eq, Hash)]
482pub enum LuaIndexMemberExpr {
483 IndexExpr(LuaIndexExpr),
484 TableField(LuaTableField),
485}
486
487impl LuaAstNode for LuaIndexMemberExpr {
488 fn syntax(&self) -> &LuaSyntaxNode {
489 match self {
490 LuaIndexMemberExpr::IndexExpr(expr) => expr.syntax(),
491 LuaIndexMemberExpr::TableField(field) => field.syntax(),
492 }
493 }
494
495 fn can_cast(kind: LuaSyntaxKind) -> bool
496 where
497 Self: Sized,
498 {
499 LuaIndexExpr::can_cast(kind) || LuaTableField::can_cast(kind)
500 }
501
502 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
503 where
504 Self: Sized,
505 {
506 if LuaIndexExpr::can_cast(syntax.kind().into()) {
507 Some(Self::IndexExpr(LuaIndexExpr::cast(syntax).unwrap()))
508 } else if LuaTableField::can_cast(syntax.kind().into()) {
509 Some(Self::TableField(LuaTableField::cast(syntax).unwrap()))
510 } else {
511 None
512 }
513 }
514}
515
516impl LuaIndexMemberExpr {
517 pub fn get_index_expr(&self) -> Option<LuaIndexExpr> {
518 match self {
519 LuaIndexMemberExpr::IndexExpr(expr) => Some(expr.clone()),
520 _ => None,
521 }
522 }
523
524 pub fn get_table_field(&self) -> Option<LuaTableField> {
525 match self {
526 LuaIndexMemberExpr::TableField(field) => Some(field.clone()),
527 _ => None,
528 }
529 }
530
531 pub fn get_index_key(&self) -> Option<LuaIndexKey> {
532 match self {
533 LuaIndexMemberExpr::IndexExpr(expr) => expr.get_index_key(),
534 LuaIndexMemberExpr::TableField(field) => field.get_field_key(),
535 }
536 }
537
538 pub fn get_prefix_expr(&self) -> Option<LuaExpr> {
539 match self {
540 LuaIndexMemberExpr::IndexExpr(expr) => expr.get_prefix_expr(),
541 LuaIndexMemberExpr::TableField(field) => field.get_parent(),
542 }
543 }
544}