1#![warn(missing_docs)]
2use std::{
3 borrow::Cow,
4 fmt::{self, Display},
5};
6
7use oxc_span::{Atom, GetSpan, Span};
8use oxc_syntax::{operator::UnaryOperator, scope::ScopeFlags};
9
10use crate::ast::*;
11
12impl Program<'_> {
13 pub fn is_empty(&self) -> bool {
15 self.body.is_empty() && self.directives.is_empty()
16 }
17
18 pub fn has_use_strict_directive(&self) -> bool {
20 self.directives.iter().any(Directive::is_use_strict)
21 }
22}
23
24impl<'a> Expression<'a> {
25 pub fn is_typescript_syntax(&self) -> bool {
27 matches!(
28 self,
29 Self::TSAsExpression(_)
30 | Self::TSSatisfiesExpression(_)
31 | Self::TSTypeAssertion(_)
32 | Self::TSNonNullExpression(_)
33 | Self::TSInstantiationExpression(_)
34 )
35 }
36
37 pub fn is_primary_expression(&self) -> bool {
39 self.is_literal()
40 || matches!(
41 self,
42 Self::Identifier(_)
43 | Self::ThisExpression(_)
44 | Self::FunctionExpression(_)
45 | Self::ClassExpression(_)
46 | Self::ParenthesizedExpression(_)
47 | Self::ArrayExpression(_)
48 | Self::ObjectExpression(_)
49 )
50 }
51
52 pub fn is_literal(&self) -> bool {
59 matches!(
61 self,
62 Self::BooleanLiteral(_)
63 | Self::NullLiteral(_)
64 | Self::NumericLiteral(_)
65 | Self::BigIntLiteral(_)
66 | Self::RegExpLiteral(_)
67 | Self::StringLiteral(_)
68 )
69 }
70
71 pub fn is_string_literal(&self) -> bool {
73 matches!(self, Self::StringLiteral(_) | Self::TemplateLiteral(_))
74 }
75
76 pub fn is_no_substitution_template(&self) -> bool {
78 matches!(self, Expression::TemplateLiteral(e) if e.is_no_substitution_template())
79 }
80
81 pub fn is_number_literal(&self) -> bool {
83 matches!(self, Self::NumericLiteral(_) | Self::BigIntLiteral(_))
84 }
85
86 pub fn is_big_int_literal(&self) -> bool {
88 matches!(self, Self::BigIntLiteral(_))
89 }
90
91 #[inline]
95 pub fn is_specific_string_literal(&self, string: &str) -> bool {
96 match self {
97 Self::StringLiteral(s) => s.value == string,
98 _ => false,
99 }
100 }
101
102 pub fn is_null(&self) -> bool {
104 matches!(self, Expression::NullLiteral(_))
105 }
106
107 pub fn is_undefined(&self) -> bool {
109 matches!(self, Self::Identifier(ident) if ident.name == "undefined")
110 }
111
112 pub fn is_void(&self) -> bool {
114 matches!(self, Self::UnaryExpression(expr) if expr.operator == UnaryOperator::Void)
115 }
116
117 pub fn is_void_0(&self) -> bool {
119 match self {
120 Self::UnaryExpression(expr) if expr.operator == UnaryOperator::Void => {
121 matches!(&expr.argument, Self::NumericLiteral(lit) if lit.value == 0.0)
122 }
123 _ => false,
124 }
125 }
126
127 pub fn is_number(&self) -> bool {
129 matches!(self, Self::NumericLiteral(_))
130 }
131
132 pub fn is_number_0(&self) -> bool {
134 matches!(self, Self::NumericLiteral(lit) if lit.value == 0.0)
135 }
136
137 pub fn is_number_value(&self, val: f64) -> bool {
139 matches!(self, Self::NumericLiteral(lit) if (lit.value - val).abs() < f64::EPSILON)
140 }
141
142 pub fn is_specific_raw_number_literal(&self, val: &str) -> bool {
144 matches!(self, Self::NumericLiteral(lit) if lit.raw.as_ref().is_some_and(|raw| raw == val))
145 }
146
147 pub fn evaluate_to_undefined(&self) -> bool {
149 self.is_undefined() || self.is_void()
150 }
151
152 pub fn is_null_or_undefined(&self) -> bool {
156 self.is_null() || self.evaluate_to_undefined()
157 }
158
159 pub fn is_nan(&self) -> bool {
161 matches!(self, Self::Identifier(ident) if ident.name == "NaN")
162 }
163
164 pub fn without_parentheses(&self) -> &Self {
166 let mut expr = self;
167 while let Expression::ParenthesizedExpression(paren_expr) = expr {
168 expr = &paren_expr.expression;
169 }
170 expr
171 }
172
173 pub fn without_parentheses_mut(&mut self) -> &mut Self {
175 let mut expr = self;
176 while let Expression::ParenthesizedExpression(paran_expr) = expr {
177 expr = &mut paran_expr.expression;
178 }
179 expr
180 }
181
182 pub fn is_specific_id(&self, name: &str) -> bool {
184 match self.get_inner_expression() {
185 Expression::Identifier(ident) => ident.name == name,
186 _ => false,
187 }
188 }
189
190 pub fn is_specific_member_access(&self, object: &str, property: &str) -> bool {
196 match self.get_inner_expression() {
197 expr if expr.is_member_expression() => {
198 expr.to_member_expression().is_specific_member_access(object, property)
199 }
200 Expression::ChainExpression(chain) => {
201 let Some(expr) = chain.expression.as_member_expression() else {
202 return false;
203 };
204 expr.is_specific_member_access(object, property)
205 }
206 _ => false,
207 }
208 }
209
210 #[must_use]
217 pub fn into_inner_expression(self) -> Expression<'a> {
218 let mut expr = self;
219 loop {
220 expr = match expr {
221 Expression::ParenthesizedExpression(e) => e.unbox().expression,
222 Expression::TSAsExpression(e) => e.unbox().expression,
223 Expression::TSSatisfiesExpression(e) => e.unbox().expression,
224 Expression::TSInstantiationExpression(e) => e.unbox().expression,
225 Expression::TSNonNullExpression(e) => e.unbox().expression,
226 Expression::TSTypeAssertion(e) => e.unbox().expression,
227 _ => break,
228 };
229 }
230 expr
231 }
232
233 pub fn get_inner_expression(&self) -> &Expression<'a> {
241 let mut expr = self;
242 loop {
243 expr = match expr {
244 Expression::ParenthesizedExpression(e) => &e.expression,
245 Expression::TSAsExpression(e) => &e.expression,
246 Expression::TSSatisfiesExpression(e) => &e.expression,
247 Expression::TSInstantiationExpression(e) => &e.expression,
248 Expression::TSNonNullExpression(e) => &e.expression,
249 Expression::TSTypeAssertion(e) => &e.expression,
250 _ => break,
251 };
252 }
253 expr
254 }
255
256 pub fn get_inner_expression_mut(&mut self) -> &mut Expression<'a> {
264 let mut expr = self;
265 loop {
266 expr = match expr {
267 Expression::ParenthesizedExpression(e) => &mut e.expression,
268 Expression::TSAsExpression(e) => &mut e.expression,
269 Expression::TSSatisfiesExpression(e) => &mut e.expression,
270 Expression::TSInstantiationExpression(e) => &mut e.expression,
271 Expression::TSNonNullExpression(e) => &mut e.expression,
272 Expression::TSTypeAssertion(e) => &mut e.expression,
273 _ => break,
274 };
275 }
276 expr
277 }
278
279 pub fn into_chain_element(self) -> Option<ChainElement<'a>> {
282 match self {
283 Expression::StaticMemberExpression(e) => Some(ChainElement::StaticMemberExpression(e)),
284 Expression::ComputedMemberExpression(e) => {
285 Some(ChainElement::ComputedMemberExpression(e))
286 }
287 Expression::PrivateFieldExpression(e) => Some(ChainElement::PrivateFieldExpression(e)),
288 Expression::CallExpression(e) => Some(ChainElement::CallExpression(e)),
289 Expression::TSNonNullExpression(e) => Some(ChainElement::TSNonNullExpression(e)),
290 _ => None,
291 }
292 }
293
294 pub fn is_identifier_reference(&self) -> bool {
296 matches!(self, Expression::Identifier(_))
297 }
298
299 pub fn get_identifier_reference(&self) -> Option<&IdentifierReference<'a>> {
302 match self.get_inner_expression() {
303 Expression::Identifier(ident) => Some(ident),
304 _ => None,
305 }
306 }
307
308 pub fn is_function(&self) -> bool {
311 matches!(self, Expression::FunctionExpression(_) | Expression::ArrowFunctionExpression(_))
312 }
313
314 pub fn is_anonymous_function_definition(&self) -> bool {
318 match self.without_parentheses() {
319 Self::ArrowFunctionExpression(_) => true,
320 Self::FunctionExpression(func) => func.name().is_none(),
321 Self::ClassExpression(class) => class.name().is_none(),
322 _ => false,
323 }
324 }
325
326 pub fn is_call_expression(&self) -> bool {
328 matches!(self, Expression::CallExpression(_))
329 }
330
331 pub fn is_super(&self) -> bool {
333 matches!(self, Expression::Super(_))
334 }
335
336 pub fn is_super_call_expression(&self) -> bool {
338 matches!(self, Expression::CallExpression(expr) if matches!(&expr.callee, Expression::Super(_)))
339 }
340
341 pub fn is_call_like_expression(&self) -> bool {
344 self.is_call_expression()
345 || matches!(self, Expression::NewExpression(_) | Expression::ImportExpression(_))
346 }
347
348 pub fn is_binaryish(&self) -> bool {
350 matches!(self, Expression::BinaryExpression(_) | Expression::LogicalExpression(_))
351 }
352
353 pub fn get_member_expr(&self) -> Option<&MemberExpression<'a>> {
357 match self.get_inner_expression() {
358 Expression::ChainExpression(chain_expr) => chain_expr.expression.as_member_expression(),
359 expr => expr.as_member_expression(),
360 }
361 }
362
363 pub fn is_require_call(&self) -> bool {
367 if let Self::CallExpression(call_expr) = self { call_expr.is_require_call() } else { false }
368 }
369
370 pub fn is_assignment(&self) -> bool {
372 matches!(self, Expression::AssignmentExpression(_))
373 }
374
375 pub fn is_entity_name_expression(&self) -> bool {
377 matches!(
379 self.without_parentheses(),
380 Expression::Identifier(_) | Expression::ThisExpression(_)
381 ) || self.is_property_access_entity_name_expression()
382 }
383
384 pub fn is_property_access_entity_name_expression(&self) -> bool {
386 if let Expression::StaticMemberExpression(e) = self {
387 e.object.is_entity_name_expression()
388 } else {
389 false
390 }
391 }
392}
393
394impl Display for IdentifierName<'_> {
395 #[inline]
396 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
397 self.name.fmt(f)
398 }
399}
400
401impl Display for IdentifierReference<'_> {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 self.name.fmt(f)
404 }
405}
406
407impl Display for BindingIdentifier<'_> {
408 #[inline]
409 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410 self.name.fmt(f)
411 }
412}
413
414impl ArrayExpressionElement<'_> {
415 pub fn is_elision(&self) -> bool {
419 matches!(self, Self::Elision(_))
420 }
421
422 #[inline]
424 pub fn is_spread(&self) -> bool {
425 matches!(self, Self::SpreadElement(_))
426 }
427}
428
429impl<'a> From<Argument<'a>> for ArrayExpressionElement<'a> {
430 fn from(argument: Argument<'a>) -> Self {
431 match argument {
432 Argument::SpreadElement(spread) => Self::SpreadElement(spread),
433 match_expression!(Argument) => Self::from(argument.into_expression()),
434 }
435 }
436}
437
438impl<'a> ObjectPropertyKind<'a> {
439 #[inline]
441 pub fn is_spread(&self) -> bool {
442 matches!(self, Self::SpreadProperty(_))
443 }
444
445 #[inline]
447 pub fn as_property(&self) -> Option<&ObjectProperty<'a>> {
448 match self {
449 Self::ObjectProperty(prop) => Some(prop),
450 Self::SpreadProperty(_) => None,
451 }
452 }
453}
454
455impl<'a> PropertyKey<'a> {
456 pub fn static_name(&self) -> Option<Cow<'a, str>> {
465 match self {
466 Self::StaticIdentifier(ident) => Some(Cow::Borrowed(ident.name.as_str())),
467 Self::StringLiteral(lit) => Some(Cow::Borrowed(lit.value.as_str())),
468 Self::RegExpLiteral(lit) => Some(Cow::Owned(lit.regex.to_string())),
469 Self::NumericLiteral(lit) => Some(Cow::Owned(lit.value.to_string())),
470 Self::BigIntLiteral(lit) => Some(Cow::Borrowed(lit.value.as_str())),
471 Self::NullLiteral(_) => Some(Cow::Borrowed("null")),
472 Self::TemplateLiteral(lit) => lit.single_quasi().map(Into::into),
473 _ => None,
474 }
475 }
476
477 pub fn is_specific_static_name(&self, name: &str) -> bool {
479 self.static_name().is_some_and(|n| n == name)
480 }
481
482 pub fn is_identifier(&self) -> bool {
485 matches!(self, Self::PrivateIdentifier(_) | Self::StaticIdentifier(_))
486 }
487
488 pub fn is_private_identifier(&self) -> bool {
491 matches!(self, Self::PrivateIdentifier(_))
492 }
493
494 pub fn private_name(&self) -> Option<Atom<'a>> {
501 match self {
502 Self::PrivateIdentifier(ident) => Some(ident.name),
503 _ => None,
504 }
505 }
506
507 pub fn name(&self) -> Option<Cow<'a, str>> {
516 if self.is_private_identifier() {
517 self.private_name().map(|name| Cow::Borrowed(name.as_str()))
518 } else {
519 self.static_name()
520 }
521 }
522
523 pub fn is_specific_id(&self, name: &str) -> bool {
525 match self {
526 PropertyKey::StaticIdentifier(ident) => ident.name == name,
527 _ => false,
528 }
529 }
530
531 pub fn is_specific_string_literal(&self, string: &str) -> bool {
533 matches!(self, Self::StringLiteral(s) if s.value == string)
534 }
535}
536
537impl PropertyKind {
538 pub fn is_accessor(self) -> bool {
542 matches!(self, Self::Get | Self::Set)
543 }
544}
545
546impl<'a> TemplateLiteral<'a> {
547 pub fn is_no_substitution_template(&self) -> bool {
555 self.quasis.len() == 1
556 }
557
558 pub fn single_quasi(&self) -> Option<Atom<'a>> {
560 if self.is_no_substitution_template() { self.quasis[0].value.cooked } else { None }
561 }
562}
563
564impl<'a> MemberExpression<'a> {
565 pub fn is_computed(&self) -> bool {
568 matches!(self, MemberExpression::ComputedMemberExpression(_))
569 }
570
571 pub fn optional(&self) -> bool {
574 match self {
575 MemberExpression::ComputedMemberExpression(expr) => expr.optional,
576 MemberExpression::StaticMemberExpression(expr) => expr.optional,
577 MemberExpression::PrivateFieldExpression(expr) => expr.optional,
578 }
579 }
580
581 pub fn object(&self) -> &Expression<'a> {
583 match self {
584 MemberExpression::ComputedMemberExpression(expr) => &expr.object,
585 MemberExpression::StaticMemberExpression(expr) => &expr.object,
586 MemberExpression::PrivateFieldExpression(expr) => &expr.object,
587 }
588 }
589
590 pub fn object_mut(&mut self) -> &mut Expression<'a> {
592 match self {
593 MemberExpression::ComputedMemberExpression(expr) => &mut expr.object,
594 MemberExpression::StaticMemberExpression(expr) => &mut expr.object,
595 MemberExpression::PrivateFieldExpression(expr) => &mut expr.object,
596 }
597 }
598
599 pub fn static_property_name(&self) -> Option<&'a str> {
610 match self {
611 MemberExpression::ComputedMemberExpression(expr) => {
612 expr.static_property_name().map(|name| name.as_str())
613 }
614 MemberExpression::StaticMemberExpression(expr) => Some(expr.property.name.as_str()),
615 MemberExpression::PrivateFieldExpression(_) => None,
616 }
617 }
618
619 pub fn static_property_info(&self) -> Option<(Span, &'a str)> {
624 match self {
625 MemberExpression::ComputedMemberExpression(expr) => match &expr.expression {
626 Expression::StringLiteral(lit) => Some((lit.span, lit.value.as_str())),
627 Expression::TemplateLiteral(lit) => {
628 if lit.quasis.len() == 1 {
629 lit.quasis[0].value.cooked.map(|cooked| (lit.span, cooked.as_str()))
630 } else {
631 None
632 }
633 }
634 _ => None,
635 },
636 MemberExpression::StaticMemberExpression(expr) => {
637 Some((expr.property.span, expr.property.name.as_str()))
638 }
639 MemberExpression::PrivateFieldExpression(_) => None,
640 }
641 }
642
643 pub fn through_optional_is_specific_member_access(&self, object: &str, property: &str) -> bool {
646 let object_matches = match self.object().without_parentheses() {
647 Expression::ChainExpression(x) => match x.expression.member_expression() {
648 None => false,
649 Some(member_expr) => {
650 member_expr.object().without_parentheses().is_specific_id(object)
651 }
652 },
653 x => x.is_specific_id(object),
654 };
655
656 let property_matches = self.static_property_name().is_some_and(|p| p == property);
657
658 object_matches && property_matches
659 }
660
661 pub fn is_specific_member_access(&self, object: &str, property: &str) -> bool {
663 self.object().is_specific_id(object)
664 && self.static_property_name().is_some_and(|p| p == property)
665 }
666}
667
668impl<'a> ComputedMemberExpression<'a> {
669 pub fn static_property_name(&self) -> Option<Atom<'a>> {
671 match &self.expression {
672 Expression::StringLiteral(lit) => Some(lit.value),
673 Expression::TemplateLiteral(lit) if lit.quasis.len() == 1 => lit.quasis[0].value.cooked,
674 Expression::RegExpLiteral(lit) => lit.raw,
675 _ => None,
676 }
677 }
678
679 pub fn static_property_info(&self) -> Option<(Span, &'a str)> {
683 match &self.expression {
684 Expression::StringLiteral(lit) => Some((lit.span, lit.value.as_str())),
685 Expression::TemplateLiteral(lit) if lit.quasis.len() == 1 => {
686 lit.quasis[0].value.cooked.map(|cooked| (lit.span, cooked.as_str()))
687 }
688 Expression::RegExpLiteral(lit) => lit.raw.map(|raw| (lit.span, raw.as_str())),
689 _ => None,
690 }
691 }
692}
693
694impl<'a> StaticMemberExpression<'a> {
695 pub fn get_first_object(&self) -> &Expression<'a> {
697 let mut object = &self.object;
698 loop {
699 match object {
700 Expression::StaticMemberExpression(member) => {
701 object = &member.object;
702 continue;
703 }
704 Expression::ChainExpression(chain) => {
705 if let ChainElement::StaticMemberExpression(member) = &chain.expression {
706 object = &member.object;
707 continue;
708 }
709 }
710 _ => {}
711 }
712
713 return object;
714 }
715 }
716
717 pub fn static_property_info(&self) -> (Span, &'a str) {
720 (self.property.span, self.property.name.as_str())
721 }
722}
723
724impl<'a> ChainElement<'a> {
725 pub fn member_expression(&self) -> Option<&MemberExpression<'a>> {
727 match self {
728 ChainElement::TSNonNullExpression(e) => match &e.expression {
729 match_member_expression!(Expression) => e.expression.as_member_expression(),
730 _ => None,
731 },
732 _ => self.as_member_expression(),
733 }
734 }
735}
736
737impl<'a> From<ChainElement<'a>> for Expression<'a> {
738 fn from(value: ChainElement<'a>) -> Self {
739 match value {
740 ChainElement::CallExpression(e) => Expression::CallExpression(e),
741 ChainElement::TSNonNullExpression(e) => Expression::TSNonNullExpression(e),
742 match_member_expression!(ChainElement) => {
743 Expression::from(value.into_member_expression())
744 }
745 }
746 }
747}
748
749impl CallExpression<'_> {
750 pub fn callee_name(&self) -> Option<&str> {
752 match &self.callee {
753 Expression::Identifier(ident) => Some(ident.name.as_str()),
754 expr => expr.as_member_expression().and_then(MemberExpression::static_property_name),
755 }
756 }
757
758 pub fn is_require_call(&self) -> bool {
765 if self.arguments.len() != 1 {
766 return false;
767 }
768 if let Expression::Identifier(id) = &self.callee {
769 id.name == "require"
770 && matches!(
771 self.arguments.first(),
772 Some(Argument::StringLiteral(_) | Argument::TemplateLiteral(_)),
773 )
774 } else {
775 false
776 }
777 }
778
779 pub fn is_symbol_or_symbol_for_call(&self) -> bool {
782 match &self.callee {
784 Expression::Identifier(id) => id.name == "Symbol",
785 expr => match expr.as_member_expression() {
786 Some(member) => {
787 matches!(member.object(), Expression::Identifier(id) if id.name == "Symbol")
788 && member.static_property_name() == Some("for")
789 }
790 None => false,
791 },
792 }
793 }
794
795 pub fn common_js_require(&self) -> Option<&StringLiteral<'_>> {
803 if !(self.callee.is_specific_id("require") && self.arguments.len() == 1) {
804 return None;
805 }
806 match &self.arguments[0] {
807 Argument::StringLiteral(str_literal) => Some(str_literal),
808 _ => None,
809 }
810 }
811
812 pub fn arguments_span(&self) -> Option<Span> {
825 self.arguments.first().map(|first| {
826 #[expect(clippy::missing_panics_doc)]
828 let last = self.arguments.last().unwrap();
829 Span::new(first.span().start, last.span().end)
830 })
831 }
832}
833
834impl NewExpression<'_> {
835 pub fn arguments_span(&self) -> Option<Span> {
848 self.arguments.first().map(|first| {
849 #[expect(clippy::missing_panics_doc)]
851 let last = self.arguments.last().unwrap();
852 Span::new(first.span().start, last.span().end)
853 })
854 }
855}
856
857impl Argument<'_> {
858 pub fn is_spread(&self) -> bool {
860 matches!(self, Self::SpreadElement(_))
861 }
862}
863
864impl<'a> AssignmentTarget<'a> {
865 pub fn get_identifier_name(&self) -> Option<&'a str> {
873 self.as_simple_assignment_target().and_then(SimpleAssignmentTarget::get_identifier_name)
874 }
875
876 pub fn get_expression(&self) -> Option<&Expression<'a>> {
885 self.as_simple_assignment_target().and_then(SimpleAssignmentTarget::get_expression)
886 }
887
888 pub fn get_expression_mut(&mut self) -> Option<&mut Expression<'a>> {
897 self.as_simple_assignment_target_mut().and_then(SimpleAssignmentTarget::get_expression_mut)
898 }
899}
900
901impl<'a> SimpleAssignmentTarget<'a> {
902 pub fn get_identifier_name(&self) -> Option<&'a str> {
911 match self {
912 Self::AssignmentTargetIdentifier(ident) => Some(ident.name.as_str()),
913 match_member_expression!(Self) => self.to_member_expression().static_property_name(),
914 _ => None,
915 }
916 }
917
918 pub fn get_expression(&self) -> Option<&Expression<'a>> {
925 match self {
926 Self::TSAsExpression(expr) => Some(&expr.expression),
927 Self::TSSatisfiesExpression(expr) => Some(&expr.expression),
928 Self::TSNonNullExpression(expr) => Some(&expr.expression),
929 Self::TSTypeAssertion(expr) => Some(&expr.expression),
930 _ => None,
931 }
932 }
933
934 pub fn get_expression_mut(&mut self) -> Option<&mut Expression<'a>> {
943 match self {
944 Self::TSAsExpression(expr) => Some(&mut expr.expression),
945 Self::TSSatisfiesExpression(expr) => Some(&mut expr.expression),
946 Self::TSNonNullExpression(expr) => Some(&mut expr.expression),
947 Self::TSTypeAssertion(expr) => Some(&mut expr.expression),
948 _ => None,
949 }
950 }
951}
952
953impl ObjectAssignmentTarget<'_> {
954 pub fn is_empty(&self) -> bool {
962 self.properties.is_empty() && self.rest.is_none()
963 }
964
965 pub fn len(&self) -> usize {
975 self.properties.len() + usize::from(self.rest.is_some())
976 }
977}
978
979impl<'a> AssignmentTargetMaybeDefault<'a> {
980 pub fn identifier(&self) -> Option<&IdentifierReference<'a>> {
987 match self {
988 AssignmentTargetMaybeDefault::AssignmentTargetIdentifier(id) => Some(id),
989 Self::AssignmentTargetWithDefault(target) => {
990 if let AssignmentTarget::AssignmentTargetIdentifier(id) = &target.binding {
991 Some(id)
992 } else {
993 None
994 }
995 }
996 _ => None,
997 }
998 }
999
1000 pub fn identifier_mut(&mut self) -> Option<&mut IdentifierReference<'a>> {
1002 match self {
1003 AssignmentTargetMaybeDefault::AssignmentTargetIdentifier(id) => Some(id),
1004 Self::AssignmentTargetWithDefault(target) => {
1005 if let AssignmentTarget::AssignmentTargetIdentifier(id) = &mut target.binding {
1006 Some(id)
1007 } else {
1008 None
1009 }
1010 }
1011 _ => None,
1012 }
1013 }
1014}
1015
1016impl Statement<'_> {
1017 pub fn is_typescript_syntax(&self) -> bool {
1019 match self {
1020 match_declaration!(Self) => {
1021 self.as_declaration().is_some_and(Declaration::is_typescript_syntax)
1022 }
1023 match_module_declaration!(Self) => {
1024 self.as_module_declaration().is_some_and(ModuleDeclaration::is_typescript_syntax)
1025 }
1026 _ => false,
1027 }
1028 }
1029
1030 pub fn is_iteration_statement(&self) -> bool {
1041 matches!(
1042 self,
1043 Statement::DoWhileStatement(_)
1044 | Statement::ForInStatement(_)
1045 | Statement::ForOfStatement(_)
1046 | Statement::ForStatement(_)
1047 | Statement::WhileStatement(_)
1048 )
1049 }
1050
1051 pub fn is_jump_statement(&self) -> bool {
1061 self.get_one_child().is_some_and(|stmt| {
1062 matches!(
1063 stmt,
1064 Self::ReturnStatement(_)
1065 | Self::ThrowStatement(_)
1066 | Self::BreakStatement(_)
1067 | Self::ContinueStatement(_)
1068 )
1069 })
1070 }
1071
1072 pub fn get_one_child(&self) -> Option<&Self> {
1074 if let Statement::BlockStatement(block_stmt) = self {
1075 return (block_stmt.body.len() == 1).then(|| &block_stmt.body[0]);
1076 }
1077 Some(self)
1078 }
1079
1080 pub fn get_one_child_mut(&mut self) -> Option<&mut Self> {
1082 if let Statement::BlockStatement(block_stmt) = self {
1083 return (block_stmt.body.len() == 1).then_some(&mut block_stmt.body[0]);
1084 }
1085 Some(self)
1086 }
1087}
1088
1089impl Directive<'_> {
1090 pub fn is_use_strict(&self) -> bool {
1094 self.directive == "use strict"
1095 }
1096}
1097
1098impl<'a> Declaration<'a> {
1099 pub fn is_typescript_syntax(&self) -> bool {
1101 match self {
1102 Self::VariableDeclaration(decl) => decl.is_typescript_syntax(),
1103 Self::FunctionDeclaration(func) => func.is_typescript_syntax(),
1104 Self::ClassDeclaration(class) => class.is_typescript_syntax(),
1105 _ => true,
1106 }
1107 }
1108
1109 pub fn id(&self) -> Option<&BindingIdentifier<'a>> {
1118 match self {
1119 Declaration::FunctionDeclaration(decl) => decl.id.as_ref(),
1120 Declaration::ClassDeclaration(decl) => decl.id.as_ref(),
1121 Declaration::TSTypeAliasDeclaration(decl) => Some(&decl.id),
1122 Declaration::TSInterfaceDeclaration(decl) => Some(&decl.id),
1123 Declaration::TSEnumDeclaration(decl) => Some(&decl.id),
1124 Declaration::TSImportEqualsDeclaration(decl) => Some(&decl.id),
1125 Declaration::TSModuleDeclaration(decl) => {
1126 if let TSModuleDeclarationName::Identifier(ident) = &decl.id {
1127 Some(ident)
1128 } else {
1129 None
1130 }
1131 }
1132 Declaration::VariableDeclaration(_) => None,
1133 }
1134 }
1135
1136 pub fn declare(&self) -> bool {
1138 match self {
1139 Declaration::VariableDeclaration(decl) => decl.declare,
1140 Declaration::FunctionDeclaration(decl) => decl.declare,
1141 Declaration::ClassDeclaration(decl) => decl.declare,
1142 Declaration::TSEnumDeclaration(decl) => decl.declare,
1143 Declaration::TSTypeAliasDeclaration(decl) => decl.declare,
1144 Declaration::TSModuleDeclaration(decl) => decl.declare,
1145 Declaration::TSInterfaceDeclaration(decl) => decl.declare,
1146 Declaration::TSImportEqualsDeclaration(_) => false,
1147 }
1148 }
1149
1150 pub fn is_type(&self) -> bool {
1152 matches!(self, Self::TSTypeAliasDeclaration(_) | Self::TSInterfaceDeclaration(_))
1153 }
1154}
1155
1156impl VariableDeclaration<'_> {
1157 pub fn is_typescript_syntax(&self) -> bool {
1159 self.declare
1160 }
1161
1162 pub fn has_init(&self) -> bool {
1164 self.declarations.iter().any(|decl| decl.init.is_some())
1165 }
1166}
1167
1168impl VariableDeclarationKind {
1169 pub fn is_var(self) -> bool {
1171 self == Self::Var
1172 }
1173
1174 pub fn is_const(self) -> bool {
1176 self == Self::Const
1177 }
1178
1179 pub fn is_lexical(self) -> bool {
1181 matches!(self, Self::Const | Self::Let | Self::Using | Self::AwaitUsing)
1182 }
1183
1184 pub fn is_using(self) -> bool {
1186 self == Self::Using || self == Self::AwaitUsing
1187 }
1188
1189 pub fn is_await(self) -> bool {
1191 self == Self::AwaitUsing
1192 }
1193
1194 pub fn as_str(self) -> &'static str {
1199 match self {
1200 Self::Var => "var",
1201 Self::Const => "const",
1202 Self::Let => "let",
1203 Self::Using => "using",
1204 Self::AwaitUsing => "await using",
1205 }
1206 }
1207}
1208
1209impl Display for VariableDeclarationKind {
1210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1211 self.as_str().fmt(f)
1212 }
1213}
1214
1215impl ForStatementInit<'_> {
1216 pub fn is_var_declaration(&self) -> bool {
1218 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_var())
1219 }
1220
1221 pub fn is_lexical_declaration(&self) -> bool {
1226 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_lexical())
1227 }
1228}
1229
1230impl ForStatementLeft<'_> {
1231 pub fn is_lexical_declaration(&self) -> bool {
1236 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_lexical())
1237 }
1238}
1239
1240impl SwitchCase<'_> {
1241 pub fn is_default_case(&self) -> bool {
1243 self.test.is_none()
1244 }
1245}
1246
1247impl<'a> BindingPattern<'a> {
1248 pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
1256 self.kind.get_identifier_name()
1257 }
1258
1259 pub fn get_binding_identifier(&self) -> Option<&BindingIdentifier<'a>> {
1269 self.kind.get_binding_identifier()
1270 }
1271
1272 pub fn get_binding_identifiers(&self) -> std::vec::Vec<&BindingIdentifier<'a>> {
1280 self.kind.get_binding_identifiers()
1281 }
1282}
1283
1284impl<'a> BindingPatternKind<'a> {
1285 pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
1293 match self {
1294 Self::BindingIdentifier(ident) => Some(ident.name),
1295 Self::AssignmentPattern(assign) => assign.left.get_identifier_name(),
1296 _ => None,
1297 }
1298 }
1299
1300 pub fn get_binding_identifier(&self) -> Option<&BindingIdentifier<'a>> {
1310 match self {
1311 Self::BindingIdentifier(ident) => Some(ident),
1312 Self::AssignmentPattern(assign) => assign.left.get_binding_identifier(),
1313 _ => None,
1314 }
1315 }
1316
1317 fn append_binding_identifiers<'b>(
1318 &'b self,
1319 idents: &mut std::vec::Vec<&'b BindingIdentifier<'a>>,
1320 ) {
1321 match self {
1322 Self::BindingIdentifier(ident) => idents.push(ident),
1323 Self::AssignmentPattern(assign) => assign.left.kind.append_binding_identifiers(idents),
1324 Self::ArrayPattern(pattern) => pattern
1325 .elements
1326 .iter()
1327 .filter_map(|item| item.as_ref())
1328 .for_each(|item| item.kind.append_binding_identifiers(idents)),
1329 Self::ObjectPattern(pattern) => pattern.properties.iter().for_each(|item| {
1330 item.value.kind.append_binding_identifiers(idents);
1331 }),
1332 }
1333 }
1334
1335 pub fn get_binding_identifiers(&self) -> std::vec::Vec<&BindingIdentifier<'a>> {
1343 let mut idents = vec![];
1344 self.append_binding_identifiers(&mut idents);
1345 idents
1346 }
1347
1348 pub fn is_destructuring_pattern(&self) -> bool {
1357 match self {
1358 Self::ObjectPattern(_) | Self::ArrayPattern(_) => true,
1359 Self::AssignmentPattern(pattern) => pattern.left.kind.is_destructuring_pattern(),
1360 Self::BindingIdentifier(_) => false,
1361 }
1362 }
1363
1364 pub fn is_binding_identifier(&self) -> bool {
1366 matches!(self, Self::BindingIdentifier(_))
1367 }
1368
1369 pub fn is_object_pattern(&self) -> bool {
1371 matches!(self, Self::ObjectPattern(_))
1372 }
1373
1374 pub fn is_array_pattern(&self) -> bool {
1376 matches!(self, Self::ArrayPattern(_))
1377 }
1378
1379 pub fn is_assignment_pattern(&self) -> bool {
1381 matches!(self, Self::AssignmentPattern(_))
1382 }
1383}
1384
1385impl ObjectPattern<'_> {
1386 pub fn is_empty(&self) -> bool {
1388 self.properties.is_empty() && self.rest.is_none()
1389 }
1390
1391 pub fn len(&self) -> usize {
1393 self.properties.len() + usize::from(self.rest.is_some())
1394 }
1395}
1396
1397impl ArrayPattern<'_> {
1398 pub fn is_empty(&self) -> bool {
1400 self.elements.is_empty() && self.rest.is_none()
1401 }
1402
1403 pub fn len(&self) -> usize {
1405 self.elements.len() + usize::from(self.rest.is_some())
1406 }
1407}
1408
1409impl<'a> Function<'a> {
1410 #[inline]
1412 pub fn name(&self) -> Option<Atom<'a>> {
1413 self.id.as_ref().map(|id| id.name)
1414 }
1415
1416 pub fn is_typescript_syntax(&self) -> bool {
1418 self.r#type.is_typescript_syntax() || self.body.is_none() || self.declare
1419 }
1420
1421 pub fn is_expression(&self) -> bool {
1423 self.r#type == FunctionType::FunctionExpression
1424 }
1425
1426 pub fn is_function_declaration(&self) -> bool {
1428 matches!(self.r#type, FunctionType::FunctionDeclaration)
1429 }
1430
1431 pub fn is_ts_declare_function(&self) -> bool {
1433 matches!(self.r#type, FunctionType::TSDeclareFunction)
1434 }
1435
1436 pub fn is_declaration(&self) -> bool {
1438 matches!(self.r#type, FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction)
1439 }
1440
1441 pub fn has_use_strict_directive(&self) -> bool {
1443 self.body.as_ref().is_some_and(|body| body.has_use_strict_directive())
1444 }
1445}
1446
1447impl FunctionType {
1448 pub fn is_typescript_syntax(self) -> bool {
1450 matches!(self, Self::TSDeclareFunction | Self::TSEmptyBodyFunctionExpression)
1451 }
1452}
1453
1454impl<'a> FormalParameters<'a> {
1455 pub fn parameters_count(&self) -> usize {
1457 self.items.len() + self.rest.as_ref().map_or(0, |_| 1)
1458 }
1459
1460 pub fn iter_bindings(&self) -> impl Iterator<Item = &BindingPattern<'a>> + '_ {
1462 self.items
1463 .iter()
1464 .map(|param| ¶m.pattern)
1465 .chain(self.rest.iter().map(|rest| &rest.argument))
1466 }
1467}
1468
1469impl FormalParameter<'_> {
1470 pub fn is_public(&self) -> bool {
1484 matches!(self.accessibility, Some(TSAccessibility::Public))
1485 }
1486
1487 #[inline]
1501 pub fn has_modifier(&self) -> bool {
1502 self.accessibility.is_some() || self.readonly || self.r#override
1503 }
1504}
1505
1506impl FormalParameterKind {
1507 pub fn is_signature(self) -> bool {
1509 self == Self::Signature
1510 }
1511}
1512
1513impl FormalParameters<'_> {
1514 pub fn is_empty(&self) -> bool {
1516 self.items.is_empty()
1517 }
1518
1519 pub fn has_parameter(&self) -> bool {
1521 !self.is_empty() || self.rest.is_some()
1522 }
1523}
1524
1525impl FunctionBody<'_> {
1526 pub fn is_empty(&self) -> bool {
1528 self.directives.is_empty() && self.statements.is_empty()
1529 }
1530
1531 pub fn has_use_strict_directive(&self) -> bool {
1533 self.directives.iter().any(Directive::is_use_strict)
1534 }
1535}
1536
1537impl<'a> ArrowFunctionExpression<'a> {
1538 pub fn get_expression(&self) -> Option<&Expression<'a>> {
1540 if self.expression
1541 && let Statement::ExpressionStatement(expr_stmt) = &self.body.statements[0]
1542 {
1543 return Some(&expr_stmt.expression);
1544 }
1545 None
1546 }
1547
1548 pub fn get_expression_mut(&mut self) -> Option<&mut Expression<'a>> {
1550 if self.expression
1551 && let Statement::ExpressionStatement(expr_stmt) = &mut self.body.statements[0]
1552 {
1553 return Some(&mut expr_stmt.expression);
1554 }
1555 None
1556 }
1557
1558 pub fn has_use_strict_directive(&self) -> bool {
1560 self.body.has_use_strict_directive()
1561 }
1562}
1563
1564impl<'a> Class<'a> {
1565 #[inline]
1567 pub fn name(&self) -> Option<Atom<'a>> {
1568 self.id.as_ref().map(|id| id.name)
1569 }
1570
1571 pub fn is_expression(&self) -> bool {
1578 self.r#type == ClassType::ClassExpression
1579 }
1580
1581 pub fn is_declaration(&self) -> bool {
1590 self.r#type == ClassType::ClassDeclaration
1591 }
1592
1593 pub fn is_typescript_syntax(&self) -> bool {
1595 self.declare || self.r#abstract
1596 }
1597}
1598
1599impl<'a> ClassElement<'a> {
1600 pub fn is_static_block(&self) -> bool {
1602 matches!(self, Self::StaticBlock(_))
1603 }
1604
1605 pub fn r#static(&self) -> bool {
1622 match self {
1623 Self::TSIndexSignature(_) | Self::StaticBlock(_) => false,
1624 Self::MethodDefinition(def) => def.r#static,
1625 Self::PropertyDefinition(def) => def.r#static,
1626 Self::AccessorProperty(def) => def.r#static,
1627 }
1628 }
1629
1630 pub fn computed(&self) -> bool {
1641 match self {
1642 Self::TSIndexSignature(_) | Self::StaticBlock(_) => false,
1643 Self::MethodDefinition(def) => def.computed,
1644 Self::PropertyDefinition(def) => def.computed,
1645 Self::AccessorProperty(def) => def.computed,
1646 }
1647 }
1648
1649 pub fn accessibility(&self) -> Option<TSAccessibility> {
1651 match self {
1652 Self::StaticBlock(_) | Self::TSIndexSignature(_) | Self::AccessorProperty(_) => None,
1653 Self::MethodDefinition(def) => def.accessibility,
1654 Self::PropertyDefinition(def) => def.accessibility,
1655 }
1656 }
1657
1658 pub fn method_definition_kind(&self) -> Option<MethodDefinitionKind> {
1661 match self {
1662 Self::TSIndexSignature(_)
1663 | Self::StaticBlock(_)
1664 | Self::PropertyDefinition(_)
1665 | Self::AccessorProperty(_) => None,
1666 Self::MethodDefinition(def) => Some(def.kind),
1667 }
1668 }
1669
1670 pub fn property_key(&self) -> Option<&PropertyKey<'a>> {
1674 match self {
1675 Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
1676 Self::MethodDefinition(def) => Some(&def.key),
1677 Self::PropertyDefinition(def) => Some(&def.key),
1678 Self::AccessorProperty(def) => Some(&def.key),
1679 }
1680 }
1681
1682 pub fn static_name(&self) -> Option<Cow<'a, str>> {
1685 match self {
1686 Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
1687 Self::MethodDefinition(def) => def.key.static_name(),
1688 Self::PropertyDefinition(def) => def.key.static_name(),
1689 Self::AccessorProperty(def) => def.key.static_name(),
1690 }
1691 }
1692
1693 pub fn is_property(&self) -> bool {
1695 matches!(self, Self::PropertyDefinition(_) | Self::AccessorProperty(_))
1696 }
1697
1698 pub fn is_ts_empty_body_function(&self) -> bool {
1701 match self {
1702 Self::PropertyDefinition(_)
1703 | Self::StaticBlock(_)
1704 | Self::AccessorProperty(_)
1705 | Self::TSIndexSignature(_) => false,
1706 Self::MethodDefinition(method) => method.value.body.is_none(),
1707 }
1708 }
1709
1710 pub fn is_typescript_syntax(&self) -> bool {
1713 match self {
1714 Self::TSIndexSignature(_) => true,
1715 Self::MethodDefinition(method) => method.value.is_typescript_syntax(),
1716 Self::PropertyDefinition(property) => {
1717 property.r#type == PropertyDefinitionType::TSAbstractPropertyDefinition
1718 }
1719 Self::AccessorProperty(property) => property.r#type.is_abstract(),
1720 Self::StaticBlock(_) => false,
1721 }
1722 }
1723
1724 pub fn has_decorator(&self) -> bool {
1726 match self {
1727 Self::MethodDefinition(method) => !method.decorators.is_empty(),
1728 Self::PropertyDefinition(property) => !property.decorators.is_empty(),
1729 Self::AccessorProperty(property) => !property.decorators.is_empty(),
1730 Self::StaticBlock(_) | Self::TSIndexSignature(_) => false,
1731 }
1732 }
1733
1734 pub fn is_abstract(&self) -> bool {
1743 match self {
1744 Self::MethodDefinition(method) => method.r#type.is_abstract(),
1745 Self::AccessorProperty(accessor) => accessor.r#type.is_abstract(),
1746 Self::PropertyDefinition(property) => property.r#type.is_abstract(),
1747 Self::StaticBlock(_) | Self::TSIndexSignature(_) => false,
1748 }
1749 }
1750}
1751
1752impl PropertyDefinitionType {
1753 pub fn is_abstract(self) -> bool {
1755 self == Self::TSAbstractPropertyDefinition
1756 }
1757}
1758
1759impl MethodDefinitionKind {
1760 pub fn is_constructor(self) -> bool {
1762 self == Self::Constructor
1763 }
1764
1765 pub fn is_method(self) -> bool {
1767 self == Self::Method
1768 }
1769
1770 pub fn is_set(self) -> bool {
1772 self == Self::Set
1773 }
1774
1775 pub fn is_get(self) -> bool {
1777 self == Self::Get
1778 }
1779
1780 pub fn is_accessor(self) -> bool {
1784 matches!(self, Self::Get | Self::Set)
1785 }
1786
1787 pub fn scope_flags(self) -> ScopeFlags {
1789 match self {
1790 Self::Constructor => ScopeFlags::Constructor | ScopeFlags::Function,
1791 Self::Method => ScopeFlags::Function,
1792 Self::Get => ScopeFlags::GetAccessor | ScopeFlags::Function,
1793 Self::Set => ScopeFlags::SetAccessor | ScopeFlags::Function,
1794 }
1795 }
1796}
1797
1798impl MethodDefinitionType {
1799 pub fn is_abstract(self) -> bool {
1803 self == Self::TSAbstractMethodDefinition
1804 }
1805}
1806
1807impl<'a> ModuleDeclaration<'a> {
1808 pub fn is_typescript_syntax(&self) -> bool {
1810 match self {
1811 ModuleDeclaration::ImportDeclaration(_) => false,
1812 ModuleDeclaration::ExportDefaultDeclaration(decl) => decl.is_typescript_syntax(),
1813 ModuleDeclaration::ExportNamedDeclaration(decl) => decl.is_typescript_syntax(),
1814 ModuleDeclaration::ExportAllDeclaration(decl) => decl.is_typescript_syntax(),
1815 ModuleDeclaration::TSNamespaceExportDeclaration(_)
1816 | ModuleDeclaration::TSExportAssignment(_) => true,
1817 }
1818 }
1819
1820 pub fn is_import(&self) -> bool {
1822 matches!(self, Self::ImportDeclaration(_))
1823 }
1824
1825 pub fn is_export(&self) -> bool {
1827 matches!(
1828 self,
1829 Self::ExportAllDeclaration(_)
1830 | Self::ExportDefaultDeclaration(_)
1831 | Self::ExportNamedDeclaration(_)
1832 | Self::TSExportAssignment(_)
1833 | Self::TSNamespaceExportDeclaration(_)
1834 )
1835 }
1836
1837 pub fn is_default_export(&self) -> bool {
1839 matches!(self, Self::ExportDefaultDeclaration(_))
1840 }
1841
1842 pub fn source(&self) -> Option<&StringLiteral<'a>> {
1850 match self {
1851 Self::ImportDeclaration(decl) => Some(&decl.source),
1852 Self::ExportAllDeclaration(decl) => Some(&decl.source),
1853 Self::ExportNamedDeclaration(decl) => decl.source.as_ref(),
1854 Self::ExportDefaultDeclaration(_)
1855 | Self::TSExportAssignment(_)
1856 | Self::TSNamespaceExportDeclaration(_) => None,
1857 }
1858 }
1859
1860 pub fn with_clause(&self) -> Option<&WithClause<'a>> {
1868 match self {
1869 Self::ImportDeclaration(decl) => decl.with_clause.as_deref(),
1870 Self::ExportAllDeclaration(decl) => decl.with_clause.as_deref(),
1871 Self::ExportNamedDeclaration(decl) => decl.with_clause.as_deref(),
1872 Self::ExportDefaultDeclaration(_)
1873 | Self::TSExportAssignment(_)
1874 | Self::TSNamespaceExportDeclaration(_) => None,
1875 }
1876 }
1877}
1878
1879impl AccessorPropertyType {
1880 pub fn is_abstract(self) -> bool {
1884 self == Self::TSAbstractAccessorProperty
1885 }
1886}
1887
1888impl<'a> ImportDeclarationSpecifier<'a> {
1889 pub fn local(&self) -> &BindingIdentifier<'a> {
1891 match self {
1892 ImportDeclarationSpecifier::ImportSpecifier(specifier) => &specifier.local,
1893 ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => &specifier.local,
1894 ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => &specifier.local,
1895 }
1896 }
1897
1898 pub fn name(&self) -> Cow<'a, str> {
1906 Cow::Borrowed(self.local().name.as_str())
1907 }
1908}
1909
1910impl<'a> ImportAttributeKey<'a> {
1911 pub fn as_atom(&self) -> Atom<'a> {
1913 match self {
1914 Self::Identifier(identifier) => identifier.name,
1915 Self::StringLiteral(literal) => literal.value,
1916 }
1917 }
1918}
1919
1920impl ExportNamedDeclaration<'_> {
1921 pub fn is_typescript_syntax(&self) -> bool {
1923 self.export_kind == ImportOrExportKind::Type
1924 || self.declaration.as_ref().is_some_and(Declaration::is_typescript_syntax)
1925 }
1926}
1927
1928impl ExportDefaultDeclaration<'_> {
1929 pub fn is_typescript_syntax(&self) -> bool {
1931 self.declaration.is_typescript_syntax()
1932 }
1933}
1934
1935impl ExportAllDeclaration<'_> {
1936 pub fn is_typescript_syntax(&self) -> bool {
1938 self.export_kind.is_type()
1939 }
1940}
1941
1942impl ExportDefaultDeclarationKind<'_> {
1943 #[inline]
1945 pub fn is_typescript_syntax(&self) -> bool {
1946 match self {
1947 Self::FunctionDeclaration(func) => func.is_typescript_syntax(),
1948 Self::ClassDeclaration(class) => class.is_typescript_syntax(),
1949 Self::TSInterfaceDeclaration(_) => true,
1950 _ => false,
1951 }
1952 }
1953}
1954
1955impl Display for ModuleExportName<'_> {
1956 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1957 match self {
1958 Self::IdentifierName(identifier) => identifier.name.fmt(f),
1959 Self::IdentifierReference(identifier) => identifier.name.fmt(f),
1960 Self::StringLiteral(literal) => write!(f, r#""{}""#, literal.value),
1961 }
1962 }
1963}
1964
1965impl<'a> ModuleExportName<'a> {
1966 pub fn name(&self) -> Atom<'a> {
1974 match self {
1975 Self::IdentifierName(identifier) => identifier.name,
1976 Self::IdentifierReference(identifier) => identifier.name,
1977 Self::StringLiteral(literal) => literal.value,
1978 }
1979 }
1980
1981 pub fn identifier_name(&self) -> Option<Atom<'a>> {
1989 match self {
1990 Self::IdentifierName(identifier) => Some(identifier.name),
1991 Self::IdentifierReference(identifier) => Some(identifier.name),
1992 Self::StringLiteral(_) => None,
1993 }
1994 }
1995
1996 pub fn is_identifier(&self) -> bool {
2003 matches!(self, Self::IdentifierName(_) | Self::IdentifierReference(_))
2004 }
2005}
2006
2007impl ImportPhase {
2008 pub fn as_str(self) -> &'static str {
2015 match self {
2016 Self::Source => "source",
2017 Self::Defer => "defer",
2018 }
2019 }
2020}