emmylua_parser/syntax/node/lua/
expr.rs1use crate::{
2 LuaAstToken, LuaIndexToken, LuaLiteralToken, LuaSyntaxNode, LuaSyntaxToken, LuaTokenKind,
3 kind::LuaSyntaxKind,
4 syntax::{
5 node::{LuaBinaryOpToken, LuaNameToken, LuaUnaryOpToken},
6 traits::{LuaAstChildren, LuaAstNode, LuaCommentOwner},
7 },
8};
9
10use super::{
11 LuaBlock, LuaCallArgList, LuaIndexKey, LuaParamList, LuaTableField, path_trait::PathTrait,
12};
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub enum LuaExpr {
16 CallExpr(LuaCallExpr),
17 TableExpr(LuaTableExpr),
18 LiteralExpr(LuaLiteralExpr),
19 BinaryExpr(LuaBinaryExpr),
20 UnaryExpr(LuaUnaryExpr),
21 ClosureExpr(LuaClosureExpr),
22 ParenExpr(LuaParenExpr),
23 NameExpr(LuaNameExpr),
24 IndexExpr(LuaIndexExpr),
25}
26
27impl LuaAstNode for LuaExpr {
28 fn syntax(&self) -> &LuaSyntaxNode {
29 match self {
30 LuaExpr::CallExpr(node) => node.syntax(),
31 LuaExpr::TableExpr(node) => node.syntax(),
32 LuaExpr::LiteralExpr(node) => node.syntax(),
33 LuaExpr::BinaryExpr(node) => node.syntax(),
34 LuaExpr::UnaryExpr(node) => node.syntax(),
35 LuaExpr::ClosureExpr(node) => node.syntax(),
36 LuaExpr::ParenExpr(node) => node.syntax(),
37 LuaExpr::NameExpr(node) => node.syntax(),
38 LuaExpr::IndexExpr(node) => node.syntax(),
39 }
40 }
41
42 fn can_cast(kind: LuaSyntaxKind) -> bool
43 where
44 Self: Sized,
45 {
46 matches!(
47 kind,
48 LuaSyntaxKind::CallExpr
49 | LuaSyntaxKind::AssertCallExpr
50 | LuaSyntaxKind::ErrorCallExpr
51 | LuaSyntaxKind::RequireCallExpr
52 | LuaSyntaxKind::TypeCallExpr
53 | LuaSyntaxKind::SetmetatableCallExpr
54 | LuaSyntaxKind::TableArrayExpr
55 | LuaSyntaxKind::TableObjectExpr
56 | LuaSyntaxKind::TableEmptyExpr
57 | LuaSyntaxKind::LiteralExpr
58 | LuaSyntaxKind::BinaryExpr
59 | LuaSyntaxKind::UnaryExpr
60 | LuaSyntaxKind::ClosureExpr
61 | LuaSyntaxKind::ParenExpr
62 | LuaSyntaxKind::NameExpr
63 | LuaSyntaxKind::IndexExpr
64 )
65 }
66
67 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
68 where
69 Self: Sized,
70 {
71 match syntax.kind().into() {
72 LuaSyntaxKind::CallExpr
73 | LuaSyntaxKind::AssertCallExpr
74 | LuaSyntaxKind::ErrorCallExpr
75 | LuaSyntaxKind::RequireCallExpr
76 | LuaSyntaxKind::TypeCallExpr
77 | LuaSyntaxKind::SetmetatableCallExpr => {
78 LuaCallExpr::cast(syntax).map(LuaExpr::CallExpr)
79 }
80 LuaSyntaxKind::TableArrayExpr
81 | LuaSyntaxKind::TableObjectExpr
82 | LuaSyntaxKind::TableEmptyExpr => LuaTableExpr::cast(syntax).map(LuaExpr::TableExpr),
83 LuaSyntaxKind::LiteralExpr => LuaLiteralExpr::cast(syntax).map(LuaExpr::LiteralExpr),
84 LuaSyntaxKind::BinaryExpr => LuaBinaryExpr::cast(syntax).map(LuaExpr::BinaryExpr),
85 LuaSyntaxKind::UnaryExpr => LuaUnaryExpr::cast(syntax).map(LuaExpr::UnaryExpr),
86 LuaSyntaxKind::ClosureExpr => LuaClosureExpr::cast(syntax).map(LuaExpr::ClosureExpr),
87 LuaSyntaxKind::ParenExpr => LuaParenExpr::cast(syntax).map(LuaExpr::ParenExpr),
88 LuaSyntaxKind::NameExpr => LuaNameExpr::cast(syntax).map(LuaExpr::NameExpr),
89 LuaSyntaxKind::IndexExpr => LuaIndexExpr::cast(syntax).map(LuaExpr::IndexExpr),
90 _ => None,
91 }
92 }
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Hash)]
96pub enum LuaVarExpr {
97 NameExpr(LuaNameExpr),
98 IndexExpr(LuaIndexExpr),
99}
100
101impl LuaAstNode for LuaVarExpr {
102 fn syntax(&self) -> &LuaSyntaxNode {
103 match self {
104 LuaVarExpr::NameExpr(node) => node.syntax(),
105 LuaVarExpr::IndexExpr(node) => node.syntax(),
106 }
107 }
108
109 fn can_cast(kind: LuaSyntaxKind) -> bool
110 where
111 Self: Sized,
112 {
113 matches!(kind, LuaSyntaxKind::NameExpr | LuaSyntaxKind::IndexExpr)
114 }
115
116 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
117 where
118 Self: Sized,
119 {
120 match syntax.kind().into() {
121 LuaSyntaxKind::NameExpr => LuaNameExpr::cast(syntax).map(LuaVarExpr::NameExpr),
122 LuaSyntaxKind::IndexExpr => LuaIndexExpr::cast(syntax).map(LuaVarExpr::IndexExpr),
123 _ => None,
124 }
125 }
126}
127
128impl LuaVarExpr {
129 pub fn to_expr(&self) -> LuaExpr {
130 match self {
131 LuaVarExpr::NameExpr(node) => LuaExpr::NameExpr(node.clone()),
132 LuaVarExpr::IndexExpr(node) => LuaExpr::IndexExpr(node.clone()),
133 }
134 }
135}
136
137impl From<LuaVarExpr> for LuaExpr {
138 fn from(expr: LuaVarExpr) -> Self {
139 match expr {
140 LuaVarExpr::NameExpr(node) => LuaExpr::NameExpr(node),
141 LuaVarExpr::IndexExpr(node) => LuaExpr::IndexExpr(node),
142 }
143 }
144}
145
146impl PathTrait for LuaVarExpr {}
147
148#[derive(Debug, Clone, PartialEq, Eq, Hash)]
149pub enum LuaSingleArgExpr {
150 TableExpr(LuaTableExpr),
151 LiteralExpr(LuaLiteralExpr),
152}
153
154impl LuaAstNode for LuaSingleArgExpr {
155 fn syntax(&self) -> &LuaSyntaxNode {
156 match self {
157 LuaSingleArgExpr::TableExpr(node) => node.syntax(),
158 LuaSingleArgExpr::LiteralExpr(node) => node.syntax(),
159 }
160 }
161
162 fn can_cast(kind: LuaSyntaxKind) -> bool
163 where
164 Self: Sized,
165 {
166 matches!(
167 kind,
168 LuaSyntaxKind::TableArrayExpr
169 | LuaSyntaxKind::TableObjectExpr
170 | LuaSyntaxKind::TableEmptyExpr
171 | LuaSyntaxKind::LiteralExpr
172 )
173 }
174
175 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
176 where
177 Self: Sized,
178 {
179 match syntax.kind().into() {
180 LuaSyntaxKind::TableArrayExpr
181 | LuaSyntaxKind::TableObjectExpr
182 | LuaSyntaxKind::TableEmptyExpr => {
183 LuaTableExpr::cast(syntax).map(LuaSingleArgExpr::TableExpr)
184 }
185 LuaSyntaxKind::LiteralExpr => {
186 LuaLiteralExpr::cast(syntax).map(LuaSingleArgExpr::LiteralExpr)
187 }
188 _ => None,
189 }
190 }
191}
192
193impl From<LuaSingleArgExpr> for LuaExpr {
194 fn from(expr: LuaSingleArgExpr) -> Self {
195 match expr {
196 LuaSingleArgExpr::TableExpr(node) => LuaExpr::TableExpr(node),
197 LuaSingleArgExpr::LiteralExpr(node) => LuaExpr::LiteralExpr(node),
198 }
199 }
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
203pub struct LuaNameExpr {
204 syntax: LuaSyntaxNode,
205}
206
207impl LuaAstNode for LuaNameExpr {
208 fn syntax(&self) -> &LuaSyntaxNode {
209 &self.syntax
210 }
211
212 fn can_cast(kind: LuaSyntaxKind) -> bool
213 where
214 Self: Sized,
215 {
216 kind == LuaSyntaxKind::NameExpr
217 }
218
219 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
220 where
221 Self: Sized,
222 {
223 if Self::can_cast(syntax.kind().into()) {
224 Some(Self { syntax })
225 } else {
226 None
227 }
228 }
229}
230
231impl LuaCommentOwner for LuaNameExpr {}
232
233impl LuaNameExpr {
234 pub fn get_name_token(&self) -> Option<LuaNameToken> {
235 self.token()
236 }
237
238 pub fn get_name_text(&self) -> Option<String> {
239 self.get_name_token()
240 .map(|it| it.get_name_text().to_string())
241 }
242}
243
244impl PathTrait for LuaNameExpr {}
245
246impl From<LuaNameExpr> for LuaVarExpr {
247 fn from(expr: LuaNameExpr) -> Self {
248 LuaVarExpr::NameExpr(expr)
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, Hash)]
253pub struct LuaIndexExpr {
254 syntax: LuaSyntaxNode,
255}
256
257impl LuaAstNode for LuaIndexExpr {
258 fn syntax(&self) -> &LuaSyntaxNode {
259 &self.syntax
260 }
261
262 fn can_cast(kind: LuaSyntaxKind) -> bool
263 where
264 Self: Sized,
265 {
266 kind == LuaSyntaxKind::IndexExpr
267 }
268
269 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
270 where
271 Self: Sized,
272 {
273 if Self::can_cast(syntax.kind().into()) {
274 Some(Self { syntax })
275 } else {
276 None
277 }
278 }
279}
280
281impl LuaIndexExpr {
282 pub fn get_prefix_expr(&self) -> Option<LuaExpr> {
283 self.child()
284 }
285
286 pub fn get_index_token(&self) -> Option<LuaIndexToken> {
287 self.token()
288 }
289
290 pub fn get_index_key(&self) -> Option<LuaIndexKey> {
291 let mut meet_left_bracket = false;
292 for child in self.syntax.children_with_tokens() {
293 if meet_left_bracket {
294 match child {
295 rowan::NodeOrToken::Node(node) => {
296 if LuaLiteralExpr::can_cast(node.kind().into()) {
297 let literal_expr = LuaLiteralExpr::cast(node.clone()).unwrap();
298 if let Some(literal_token) = literal_expr.get_literal() {
299 match literal_token {
300 LuaLiteralToken::String(token) => {
301 return Some(LuaIndexKey::String(token.clone()));
302 }
303 LuaLiteralToken::Number(token) => {
304 return Some(LuaIndexKey::Integer(token.clone()));
305 }
306 _ => {}
307 }
308 }
309 }
310
311 return Some(LuaIndexKey::Expr(LuaExpr::cast(node).unwrap()));
312 }
313 _ => return None,
314 }
315 } else if let Some(token) = child.as_token() {
316 if token.kind() == LuaTokenKind::TkLeftBracket.into() {
317 meet_left_bracket = true;
318 } else if token.kind() == LuaTokenKind::TkName.into() {
319 return Some(LuaIndexKey::Name(
320 LuaNameToken::cast(token.clone()).unwrap(),
321 ));
322 }
323 }
324 }
325
326 None
327 }
328
329 pub fn get_index_name_token(&self) -> Option<LuaSyntaxToken> {
330 let index_token = self.get_index_token()?;
331 index_token.syntax().next_token()
332 }
333
334 pub fn get_name_token(&self) -> Option<LuaNameToken> {
335 self.token()
336 }
337}
338
339impl PathTrait for LuaIndexExpr {}
340
341impl From<LuaIndexExpr> for LuaVarExpr {
342 fn from(expr: LuaIndexExpr) -> Self {
343 LuaVarExpr::IndexExpr(expr)
344 }
345}
346
347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
348pub struct LuaCallExpr {
349 syntax: LuaSyntaxNode,
350}
351
352impl LuaAstNode for LuaCallExpr {
353 fn syntax(&self) -> &LuaSyntaxNode {
354 &self.syntax
355 }
356
357 fn can_cast(kind: LuaSyntaxKind) -> bool
358 where
359 Self: Sized,
360 {
361 kind == LuaSyntaxKind::CallExpr
362 || kind == LuaSyntaxKind::AssertCallExpr
363 || kind == LuaSyntaxKind::ErrorCallExpr
364 || kind == LuaSyntaxKind::RequireCallExpr
365 || kind == LuaSyntaxKind::TypeCallExpr
366 || kind == LuaSyntaxKind::SetmetatableCallExpr
367 }
368
369 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
370 where
371 Self: Sized,
372 {
373 if Self::can_cast(syntax.kind().into()) {
374 Some(Self { syntax })
375 } else {
376 None
377 }
378 }
379}
380
381impl LuaCallExpr {
382 pub fn get_prefix_expr(&self) -> Option<LuaExpr> {
383 self.child()
384 }
385
386 pub fn get_args_list(&self) -> Option<LuaCallArgList> {
387 self.child()
388 }
389
390 pub fn get_args_count(&self) -> Option<usize> {
391 self.get_args_list().map(|it| it.get_args().count())
392 }
393
394 pub fn is_colon_call(&self) -> bool {
395 if let Some(index_token) = self.get_colon_token() {
396 return index_token.is_colon();
397 }
398 false
399 }
400
401 pub fn get_colon_token(&self) -> Option<LuaIndexToken> {
402 self.get_prefix_expr().and_then(|prefix| match prefix {
403 LuaExpr::IndexExpr(index_expr) => index_expr.get_index_token(),
404 _ => None,
405 })
406 }
407
408 pub fn is_require(&self) -> bool {
409 self.syntax().kind() == LuaSyntaxKind::RequireCallExpr.into()
410 }
411
412 pub fn is_error(&self) -> bool {
413 self.syntax().kind() == LuaSyntaxKind::ErrorCallExpr.into()
414 }
415
416 pub fn is_assert(&self) -> bool {
417 self.syntax().kind() == LuaSyntaxKind::AssertCallExpr.into()
418 }
419
420 pub fn is_type(&self) -> bool {
421 self.syntax().kind() == LuaSyntaxKind::TypeCallExpr.into()
422 }
423
424 pub fn is_setmetatable(&self) -> bool {
425 self.syntax().kind() == LuaSyntaxKind::SetmetatableCallExpr.into()
426 }
427}
428
429impl PathTrait for LuaCallExpr {}
430
431impl From<LuaCallExpr> for LuaExpr {
432 fn from(expr: LuaCallExpr) -> Self {
433 LuaExpr::CallExpr(expr)
434 }
435}
436
437#[derive(Debug, Clone, PartialEq, Eq, Hash)]
448pub struct LuaTableExpr {
449 syntax: LuaSyntaxNode,
450}
451
452impl LuaAstNode for LuaTableExpr {
453 fn syntax(&self) -> &LuaSyntaxNode {
454 &self.syntax
455 }
456
457 fn can_cast(kind: LuaSyntaxKind) -> bool
458 where
459 Self: Sized,
460 {
461 kind == LuaSyntaxKind::TableArrayExpr
462 || kind == LuaSyntaxKind::TableObjectExpr
463 || kind == LuaSyntaxKind::TableEmptyExpr
464 }
465
466 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
467 where
468 Self: Sized,
469 {
470 if Self::can_cast(syntax.kind().into()) {
471 Some(Self { syntax })
472 } else {
473 None
474 }
475 }
476}
477
478impl LuaCommentOwner for LuaTableExpr {}
479
480impl LuaTableExpr {
481 pub fn is_empty(&self) -> bool {
482 self.syntax().kind() == LuaSyntaxKind::TableEmptyExpr.into()
483 }
484
485 pub fn is_array(&self) -> bool {
486 self.syntax().kind() == LuaSyntaxKind::TableArrayExpr.into()
487 }
488
489 pub fn is_object(&self) -> bool {
490 self.syntax().kind() == LuaSyntaxKind::TableObjectExpr.into()
491 }
492
493 pub fn get_fields(&self) -> LuaAstChildren<LuaTableField> {
494 self.children()
495 }
496}
497
498impl From<LuaTableExpr> for LuaSingleArgExpr {
499 fn from(expr: LuaTableExpr) -> Self {
500 LuaSingleArgExpr::TableExpr(expr)
501 }
502}
503
504#[derive(Debug, Clone, PartialEq, Eq, Hash)]
505pub struct LuaLiteralExpr {
506 syntax: LuaSyntaxNode,
507}
508
509impl LuaAstNode for LuaLiteralExpr {
510 fn syntax(&self) -> &LuaSyntaxNode {
511 &self.syntax
512 }
513
514 fn can_cast(kind: LuaSyntaxKind) -> bool
515 where
516 Self: Sized,
517 {
518 kind == LuaSyntaxKind::LiteralExpr
519 }
520
521 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
522 where
523 Self: Sized,
524 {
525 if Self::can_cast(syntax.kind().into()) {
526 Some(Self { syntax })
527 } else {
528 None
529 }
530 }
531}
532
533impl LuaLiteralExpr {
534 pub fn get_literal(&self) -> Option<LuaLiteralToken> {
535 self.token()
536 }
537}
538
539impl From<LuaLiteralExpr> for LuaSingleArgExpr {
540 fn from(expr: LuaLiteralExpr) -> Self {
541 LuaSingleArgExpr::LiteralExpr(expr)
542 }
543}
544
545#[derive(Debug, Clone, PartialEq, Eq, Hash)]
546pub struct LuaBinaryExpr {
547 syntax: LuaSyntaxNode,
548}
549
550impl LuaAstNode for LuaBinaryExpr {
551 fn syntax(&self) -> &LuaSyntaxNode {
552 &self.syntax
553 }
554
555 fn can_cast(kind: LuaSyntaxKind) -> bool
556 where
557 Self: Sized,
558 {
559 kind == LuaSyntaxKind::BinaryExpr
560 }
561
562 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
563 where
564 Self: Sized,
565 {
566 if Self::can_cast(syntax.kind().into()) {
567 Some(Self { syntax })
568 } else {
569 None
570 }
571 }
572}
573
574impl LuaBinaryExpr {
575 pub fn get_exprs(&self) -> Option<(LuaExpr, LuaExpr)> {
576 let exprs = self.children::<LuaExpr>().collect::<Vec<_>>();
577 if exprs.len() == 2 {
578 Some((exprs[0].clone(), exprs[1].clone()))
579 } else {
580 None
581 }
582 }
583
584 pub fn get_op_token(&self) -> Option<LuaBinaryOpToken> {
585 self.token()
586 }
587
588 pub fn get_left_expr(&self) -> Option<LuaExpr> {
589 self.child()
590 }
591}
592
593impl From<LuaBinaryExpr> for LuaExpr {
594 fn from(expr: LuaBinaryExpr) -> Self {
595 LuaExpr::BinaryExpr(expr)
596 }
597}
598
599#[derive(Debug, Clone, PartialEq, Eq, Hash)]
600pub struct LuaUnaryExpr {
601 syntax: LuaSyntaxNode,
602}
603
604impl LuaAstNode for LuaUnaryExpr {
605 fn syntax(&self) -> &LuaSyntaxNode {
606 &self.syntax
607 }
608
609 fn can_cast(kind: LuaSyntaxKind) -> bool
610 where
611 Self: Sized,
612 {
613 kind == LuaSyntaxKind::UnaryExpr
614 }
615
616 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
617 where
618 Self: Sized,
619 {
620 if Self::can_cast(syntax.kind().into()) {
621 Some(Self { syntax })
622 } else {
623 None
624 }
625 }
626}
627
628impl LuaUnaryExpr {
629 pub fn get_expr(&self) -> Option<LuaExpr> {
630 self.child()
631 }
632
633 pub fn get_op_token(&self) -> Option<LuaUnaryOpToken> {
634 self.token()
635 }
636}
637
638impl From<LuaUnaryExpr> for LuaExpr {
639 fn from(expr: LuaUnaryExpr) -> Self {
640 LuaExpr::UnaryExpr(expr)
641 }
642}
643
644#[derive(Debug, Clone, PartialEq, Eq, Hash)]
645pub struct LuaClosureExpr {
646 syntax: LuaSyntaxNode,
647}
648
649impl LuaAstNode for LuaClosureExpr {
650 fn syntax(&self) -> &LuaSyntaxNode {
651 &self.syntax
652 }
653
654 fn can_cast(kind: LuaSyntaxKind) -> bool
655 where
656 Self: Sized,
657 {
658 kind == LuaSyntaxKind::ClosureExpr
659 }
660
661 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
662 where
663 Self: Sized,
664 {
665 if Self::can_cast(syntax.kind().into()) {
666 Some(Self { syntax })
667 } else {
668 None
669 }
670 }
671}
672
673impl LuaClosureExpr {
674 pub fn get_block(&self) -> Option<LuaBlock> {
675 self.child()
676 }
677
678 pub fn get_params_list(&self) -> Option<LuaParamList> {
679 self.child()
680 }
681}
682
683impl From<LuaClosureExpr> for LuaExpr {
684 fn from(expr: LuaClosureExpr) -> Self {
685 LuaExpr::ClosureExpr(expr)
686 }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690pub struct LuaParenExpr {
691 syntax: LuaSyntaxNode,
692}
693
694impl LuaAstNode for LuaParenExpr {
695 fn syntax(&self) -> &LuaSyntaxNode {
696 &self.syntax
697 }
698
699 fn can_cast(kind: LuaSyntaxKind) -> bool
700 where
701 Self: Sized,
702 {
703 kind == LuaSyntaxKind::ParenExpr
704 }
705
706 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
707 where
708 Self: Sized,
709 {
710 if Self::can_cast(syntax.kind().into()) {
711 Some(Self { syntax })
712 } else {
713 None
714 }
715 }
716}
717
718impl LuaParenExpr {
719 pub fn get_expr(&self) -> Option<LuaExpr> {
720 self.child()
721 }
722}
723
724impl From<LuaParenExpr> for LuaExpr {
725 fn from(expr: LuaParenExpr) -> Self {
726 LuaExpr::ParenExpr(expr)
727 }
728}