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