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 _ => 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>> {
1119 match self {
1120 Declaration::FunctionDeclaration(decl) => decl.id.as_ref(),
1121 Declaration::ClassDeclaration(decl) => decl.id.as_ref(),
1122 Declaration::TSTypeAliasDeclaration(decl) => Some(&decl.id),
1123 Declaration::TSInterfaceDeclaration(decl) => Some(&decl.id),
1124 Declaration::TSEnumDeclaration(decl) => Some(&decl.id),
1125 Declaration::TSImportEqualsDeclaration(decl) => Some(&decl.id),
1126 Declaration::TSModuleDeclaration(decl) => {
1127 if let TSModuleDeclarationName::Identifier(ident) = &decl.id {
1128 Some(ident)
1129 } else {
1130 None
1131 }
1132 }
1133 Declaration::TSGlobalDeclaration(_) | Declaration::VariableDeclaration(_) => None,
1134 }
1135 }
1136
1137 pub fn declare(&self) -> bool {
1139 match self {
1140 Declaration::VariableDeclaration(decl) => decl.declare,
1141 Declaration::FunctionDeclaration(decl) => decl.declare,
1142 Declaration::ClassDeclaration(decl) => decl.declare,
1143 Declaration::TSEnumDeclaration(decl) => decl.declare,
1144 Declaration::TSTypeAliasDeclaration(decl) => decl.declare,
1145 Declaration::TSModuleDeclaration(decl) => decl.declare,
1146 Declaration::TSGlobalDeclaration(decl) => decl.declare,
1147 Declaration::TSInterfaceDeclaration(decl) => decl.declare,
1148 Declaration::TSImportEqualsDeclaration(_) => false,
1149 }
1150 }
1151
1152 pub fn is_type(&self) -> bool {
1154 matches!(self, Self::TSTypeAliasDeclaration(_) | Self::TSInterfaceDeclaration(_))
1155 }
1156}
1157
1158impl VariableDeclaration<'_> {
1159 pub fn is_typescript_syntax(&self) -> bool {
1161 self.declare
1162 }
1163
1164 pub fn has_init(&self) -> bool {
1166 self.declarations.iter().any(|decl| decl.init.is_some())
1167 }
1168}
1169
1170impl VariableDeclarationKind {
1171 pub fn is_var(self) -> bool {
1173 self == Self::Var
1174 }
1175
1176 pub fn is_const(self) -> bool {
1178 self == Self::Const
1179 }
1180
1181 pub fn is_lexical(self) -> bool {
1183 matches!(self, Self::Const | Self::Let | Self::Using | Self::AwaitUsing)
1184 }
1185
1186 pub fn is_using(self) -> bool {
1188 self == Self::Using || self == Self::AwaitUsing
1189 }
1190
1191 pub fn is_await(self) -> bool {
1193 self == Self::AwaitUsing
1194 }
1195
1196 pub fn as_str(self) -> &'static str {
1201 match self {
1202 Self::Var => "var",
1203 Self::Const => "const",
1204 Self::Let => "let",
1205 Self::Using => "using",
1206 Self::AwaitUsing => "await using",
1207 }
1208 }
1209}
1210
1211impl Display for VariableDeclarationKind {
1212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1213 self.as_str().fmt(f)
1214 }
1215}
1216
1217impl ForStatementInit<'_> {
1218 pub fn is_var_declaration(&self) -> bool {
1220 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_var())
1221 }
1222
1223 pub fn is_lexical_declaration(&self) -> bool {
1228 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_lexical())
1229 }
1230}
1231
1232impl ForStatementLeft<'_> {
1233 pub fn is_lexical_declaration(&self) -> bool {
1238 matches!(self, Self::VariableDeclaration(decl) if decl.kind.is_lexical())
1239 }
1240}
1241
1242impl SwitchCase<'_> {
1243 pub fn is_default_case(&self) -> bool {
1245 self.test.is_none()
1246 }
1247}
1248
1249impl<'a> BindingPattern<'a> {
1250 pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
1258 self.kind.get_identifier_name()
1259 }
1260
1261 pub fn get_binding_identifier(&self) -> Option<&BindingIdentifier<'a>> {
1271 self.kind.get_binding_identifier()
1272 }
1273
1274 pub fn get_binding_identifiers(&self) -> std::vec::Vec<&BindingIdentifier<'a>> {
1282 self.kind.get_binding_identifiers()
1283 }
1284}
1285
1286impl<'a> BindingPatternKind<'a> {
1287 pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
1295 match self {
1296 Self::BindingIdentifier(ident) => Some(ident.name),
1297 Self::AssignmentPattern(assign) => assign.left.get_identifier_name(),
1298 _ => None,
1299 }
1300 }
1301
1302 pub fn get_binding_identifier(&self) -> Option<&BindingIdentifier<'a>> {
1312 match self {
1313 Self::BindingIdentifier(ident) => Some(ident),
1314 Self::AssignmentPattern(assign) => assign.left.get_binding_identifier(),
1315 _ => None,
1316 }
1317 }
1318
1319 fn append_binding_identifiers<'b>(
1320 &'b self,
1321 idents: &mut std::vec::Vec<&'b BindingIdentifier<'a>>,
1322 ) {
1323 match self {
1324 Self::BindingIdentifier(ident) => idents.push(ident),
1325 Self::AssignmentPattern(assign) => assign.left.kind.append_binding_identifiers(idents),
1326 Self::ArrayPattern(pattern) => {
1327 pattern
1328 .elements
1329 .iter()
1330 .filter_map(|item| item.as_ref())
1331 .for_each(|item| item.kind.append_binding_identifiers(idents));
1332 if let Some(rest) = &pattern.rest {
1333 rest.argument.kind.append_binding_identifiers(idents);
1334 }
1335 }
1336 Self::ObjectPattern(pattern) => {
1337 pattern.properties.iter().for_each(|item| {
1338 item.value.kind.append_binding_identifiers(idents);
1339 });
1340 if let Some(rest) = &pattern.rest {
1341 rest.argument.kind.append_binding_identifiers(idents);
1342 }
1343 }
1344 }
1345 }
1346
1347 pub fn get_binding_identifiers(&self) -> std::vec::Vec<&BindingIdentifier<'a>> {
1355 let mut idents = vec![];
1356 self.append_binding_identifiers(&mut idents);
1357 idents
1358 }
1359
1360 pub fn is_destructuring_pattern(&self) -> bool {
1369 match self {
1370 Self::ObjectPattern(_) | Self::ArrayPattern(_) => true,
1371 Self::AssignmentPattern(pattern) => pattern.left.kind.is_destructuring_pattern(),
1372 Self::BindingIdentifier(_) => false,
1373 }
1374 }
1375
1376 pub fn is_binding_identifier(&self) -> bool {
1378 matches!(self, Self::BindingIdentifier(_))
1379 }
1380
1381 pub fn is_object_pattern(&self) -> bool {
1383 matches!(self, Self::ObjectPattern(_))
1384 }
1385
1386 pub fn is_array_pattern(&self) -> bool {
1388 matches!(self, Self::ArrayPattern(_))
1389 }
1390
1391 pub fn is_assignment_pattern(&self) -> bool {
1393 matches!(self, Self::AssignmentPattern(_))
1394 }
1395}
1396
1397impl ObjectPattern<'_> {
1398 pub fn is_empty(&self) -> bool {
1400 self.properties.is_empty() && self.rest.is_none()
1401 }
1402
1403 pub fn len(&self) -> usize {
1405 self.properties.len() + usize::from(self.rest.is_some())
1406 }
1407}
1408
1409impl ArrayPattern<'_> {
1410 pub fn is_empty(&self) -> bool {
1412 self.elements.is_empty() && self.rest.is_none()
1413 }
1414
1415 pub fn len(&self) -> usize {
1417 self.elements.len() + usize::from(self.rest.is_some())
1418 }
1419}
1420
1421impl<'a> Function<'a> {
1422 #[inline]
1424 pub fn name(&self) -> Option<Atom<'a>> {
1425 self.id.as_ref().map(|id| id.name)
1426 }
1427
1428 pub fn is_typescript_syntax(&self) -> bool {
1430 self.r#type.is_typescript_syntax() || self.body.is_none() || self.declare
1431 }
1432
1433 pub fn is_expression(&self) -> bool {
1435 self.r#type == FunctionType::FunctionExpression
1436 || self.r#type == FunctionType::TSEmptyBodyFunctionExpression
1437 }
1438
1439 pub fn is_function_declaration(&self) -> bool {
1441 matches!(self.r#type, FunctionType::FunctionDeclaration)
1442 }
1443
1444 pub fn is_ts_declare_function(&self) -> bool {
1446 matches!(self.r#type, FunctionType::TSDeclareFunction)
1447 }
1448
1449 pub fn is_declaration(&self) -> bool {
1451 matches!(self.r#type, FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction)
1452 }
1453
1454 pub fn has_use_strict_directive(&self) -> bool {
1456 self.body.as_ref().is_some_and(|body| body.has_use_strict_directive())
1457 }
1458}
1459
1460impl FunctionType {
1461 pub fn is_typescript_syntax(self) -> bool {
1463 matches!(self, Self::TSDeclareFunction | Self::TSEmptyBodyFunctionExpression)
1464 }
1465}
1466
1467impl<'a> FormalParameters<'a> {
1468 pub fn parameters_count(&self) -> usize {
1470 self.items.len() + self.rest.as_ref().map_or(0, |_| 1)
1471 }
1472
1473 pub fn iter_bindings(&self) -> impl Iterator<Item = &BindingPattern<'a>> + '_ {
1475 self.items
1476 .iter()
1477 .map(|param| ¶m.pattern)
1478 .chain(self.rest.iter().map(|rest| &rest.argument))
1479 }
1480}
1481
1482impl FormalParameter<'_> {
1483 pub fn is_public(&self) -> bool {
1497 matches!(self.accessibility, Some(TSAccessibility::Public))
1498 }
1499
1500 #[inline]
1514 pub fn has_modifier(&self) -> bool {
1515 self.accessibility.is_some() || self.readonly || self.r#override
1516 }
1517}
1518
1519impl FormalParameterKind {
1520 pub fn is_signature(self) -> bool {
1522 self == Self::Signature
1523 }
1524}
1525
1526impl FormalParameters<'_> {
1527 pub fn is_empty(&self) -> bool {
1529 self.items.is_empty()
1530 }
1531
1532 pub fn has_parameter(&self) -> bool {
1534 !self.is_empty() || self.rest.is_some()
1535 }
1536}
1537
1538impl FunctionBody<'_> {
1539 pub fn is_empty(&self) -> bool {
1541 self.directives.is_empty() && self.statements.is_empty()
1542 }
1543
1544 pub fn has_use_strict_directive(&self) -> bool {
1546 self.directives.iter().any(Directive::is_use_strict)
1547 }
1548}
1549
1550impl<'a> ArrowFunctionExpression<'a> {
1551 pub fn get_expression(&self) -> Option<&Expression<'a>> {
1553 if self.expression
1554 && let Statement::ExpressionStatement(expr_stmt) = &self.body.statements[0]
1555 {
1556 return Some(&expr_stmt.expression);
1557 }
1558 None
1559 }
1560
1561 pub fn get_expression_mut(&mut self) -> Option<&mut Expression<'a>> {
1563 if self.expression
1564 && let Statement::ExpressionStatement(expr_stmt) = &mut self.body.statements[0]
1565 {
1566 return Some(&mut expr_stmt.expression);
1567 }
1568 None
1569 }
1570
1571 pub fn has_use_strict_directive(&self) -> bool {
1573 self.body.has_use_strict_directive()
1574 }
1575}
1576
1577impl<'a> Class<'a> {
1578 #[inline]
1580 pub fn name(&self) -> Option<Atom<'a>> {
1581 self.id.as_ref().map(|id| id.name)
1582 }
1583
1584 pub fn is_expression(&self) -> bool {
1591 self.r#type == ClassType::ClassExpression
1592 }
1593
1594 pub fn is_declaration(&self) -> bool {
1603 self.r#type == ClassType::ClassDeclaration
1604 }
1605
1606 pub fn is_typescript_syntax(&self) -> bool {
1608 self.declare || self.r#abstract
1609 }
1610}
1611
1612impl<'a> ClassElement<'a> {
1613 pub fn is_static_block(&self) -> bool {
1615 matches!(self, Self::StaticBlock(_))
1616 }
1617
1618 pub fn r#static(&self) -> bool {
1635 match self {
1636 Self::TSIndexSignature(_) | Self::StaticBlock(_) => false,
1637 Self::MethodDefinition(def) => def.r#static,
1638 Self::PropertyDefinition(def) => def.r#static,
1639 Self::AccessorProperty(def) => def.r#static,
1640 }
1641 }
1642
1643 pub fn computed(&self) -> bool {
1654 match self {
1655 Self::TSIndexSignature(_) | Self::StaticBlock(_) => false,
1656 Self::MethodDefinition(def) => def.computed,
1657 Self::PropertyDefinition(def) => def.computed,
1658 Self::AccessorProperty(def) => def.computed,
1659 }
1660 }
1661
1662 pub fn accessibility(&self) -> Option<TSAccessibility> {
1664 match self {
1665 Self::StaticBlock(_) | Self::TSIndexSignature(_) | Self::AccessorProperty(_) => None,
1666 Self::MethodDefinition(def) => def.accessibility,
1667 Self::PropertyDefinition(def) => def.accessibility,
1668 }
1669 }
1670
1671 pub fn method_definition_kind(&self) -> Option<MethodDefinitionKind> {
1674 match self {
1675 Self::TSIndexSignature(_)
1676 | Self::StaticBlock(_)
1677 | Self::PropertyDefinition(_)
1678 | Self::AccessorProperty(_) => None,
1679 Self::MethodDefinition(def) => Some(def.kind),
1680 }
1681 }
1682
1683 pub fn property_key(&self) -> Option<&PropertyKey<'a>> {
1687 match self {
1688 Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
1689 Self::MethodDefinition(def) => Some(&def.key),
1690 Self::PropertyDefinition(def) => Some(&def.key),
1691 Self::AccessorProperty(def) => Some(&def.key),
1692 }
1693 }
1694
1695 pub fn static_name(&self) -> Option<Cow<'a, str>> {
1698 match self {
1699 Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
1700 Self::MethodDefinition(def) => def.key.static_name(),
1701 Self::PropertyDefinition(def) => def.key.static_name(),
1702 Self::AccessorProperty(def) => def.key.static_name(),
1703 }
1704 }
1705
1706 pub fn is_property(&self) -> bool {
1708 matches!(self, Self::PropertyDefinition(_) | Self::AccessorProperty(_))
1709 }
1710
1711 pub fn is_ts_empty_body_function(&self) -> bool {
1714 match self {
1715 Self::PropertyDefinition(_)
1716 | Self::StaticBlock(_)
1717 | Self::AccessorProperty(_)
1718 | Self::TSIndexSignature(_) => false,
1719 Self::MethodDefinition(method) => method.value.body.is_none(),
1720 }
1721 }
1722
1723 pub fn is_typescript_syntax(&self) -> bool {
1726 match self {
1727 Self::TSIndexSignature(_) => true,
1728 Self::MethodDefinition(method) => method.value.is_typescript_syntax(),
1729 Self::PropertyDefinition(property) => {
1730 property.r#type == PropertyDefinitionType::TSAbstractPropertyDefinition
1731 }
1732 Self::AccessorProperty(property) => property.r#type.is_abstract(),
1733 Self::StaticBlock(_) => false,
1734 }
1735 }
1736
1737 pub fn has_decorator(&self) -> bool {
1739 match self {
1740 Self::MethodDefinition(method) => !method.decorators.is_empty(),
1741 Self::PropertyDefinition(property) => !property.decorators.is_empty(),
1742 Self::AccessorProperty(property) => !property.decorators.is_empty(),
1743 Self::StaticBlock(_) | Self::TSIndexSignature(_) => false,
1744 }
1745 }
1746
1747 pub fn is_abstract(&self) -> bool {
1756 match self {
1757 Self::MethodDefinition(method) => method.r#type.is_abstract(),
1758 Self::AccessorProperty(accessor) => accessor.r#type.is_abstract(),
1759 Self::PropertyDefinition(property) => property.r#type.is_abstract(),
1760 Self::StaticBlock(_) | Self::TSIndexSignature(_) => false,
1761 }
1762 }
1763}
1764
1765impl PropertyDefinitionType {
1766 pub fn is_abstract(self) -> bool {
1768 self == Self::TSAbstractPropertyDefinition
1769 }
1770}
1771
1772impl MethodDefinitionKind {
1773 pub fn is_constructor(self) -> bool {
1775 self == Self::Constructor
1776 }
1777
1778 pub fn is_method(self) -> bool {
1780 self == Self::Method
1781 }
1782
1783 pub fn is_set(self) -> bool {
1785 self == Self::Set
1786 }
1787
1788 pub fn is_get(self) -> bool {
1790 self == Self::Get
1791 }
1792
1793 pub fn is_accessor(self) -> bool {
1797 matches!(self, Self::Get | Self::Set)
1798 }
1799
1800 pub fn scope_flags(self) -> ScopeFlags {
1802 match self {
1803 Self::Constructor => ScopeFlags::Constructor | ScopeFlags::Function,
1804 Self::Method => ScopeFlags::Function,
1805 Self::Get => ScopeFlags::GetAccessor | ScopeFlags::Function,
1806 Self::Set => ScopeFlags::SetAccessor | ScopeFlags::Function,
1807 }
1808 }
1809}
1810
1811impl MethodDefinitionType {
1812 pub fn is_abstract(self) -> bool {
1816 self == Self::TSAbstractMethodDefinition
1817 }
1818}
1819
1820impl<'a> ModuleDeclaration<'a> {
1821 pub fn is_typescript_syntax(&self) -> bool {
1823 match self {
1824 ModuleDeclaration::ImportDeclaration(_) => false,
1825 ModuleDeclaration::ExportDefaultDeclaration(decl) => decl.is_typescript_syntax(),
1826 ModuleDeclaration::ExportNamedDeclaration(decl) => decl.is_typescript_syntax(),
1827 ModuleDeclaration::ExportAllDeclaration(decl) => decl.is_typescript_syntax(),
1828 ModuleDeclaration::TSNamespaceExportDeclaration(_)
1829 | ModuleDeclaration::TSExportAssignment(_) => true,
1830 }
1831 }
1832
1833 pub fn is_import(&self) -> bool {
1835 matches!(self, Self::ImportDeclaration(_))
1836 }
1837
1838 pub fn is_export(&self) -> bool {
1840 matches!(
1841 self,
1842 Self::ExportAllDeclaration(_)
1843 | Self::ExportDefaultDeclaration(_)
1844 | Self::ExportNamedDeclaration(_)
1845 | Self::TSExportAssignment(_)
1846 | Self::TSNamespaceExportDeclaration(_)
1847 )
1848 }
1849
1850 pub fn is_default_export(&self) -> bool {
1852 matches!(self, Self::ExportDefaultDeclaration(_))
1853 }
1854
1855 pub fn source(&self) -> Option<&StringLiteral<'a>> {
1863 match self {
1864 Self::ImportDeclaration(decl) => Some(&decl.source),
1865 Self::ExportAllDeclaration(decl) => Some(&decl.source),
1866 Self::ExportNamedDeclaration(decl) => decl.source.as_ref(),
1867 Self::ExportDefaultDeclaration(_)
1868 | Self::TSExportAssignment(_)
1869 | Self::TSNamespaceExportDeclaration(_) => None,
1870 }
1871 }
1872
1873 pub fn with_clause(&self) -> Option<&WithClause<'a>> {
1881 match self {
1882 Self::ImportDeclaration(decl) => decl.with_clause.as_deref(),
1883 Self::ExportAllDeclaration(decl) => decl.with_clause.as_deref(),
1884 Self::ExportNamedDeclaration(decl) => decl.with_clause.as_deref(),
1885 Self::ExportDefaultDeclaration(_)
1886 | Self::TSExportAssignment(_)
1887 | Self::TSNamespaceExportDeclaration(_) => None,
1888 }
1889 }
1890}
1891
1892impl AccessorPropertyType {
1893 pub fn is_abstract(self) -> bool {
1897 self == Self::TSAbstractAccessorProperty
1898 }
1899}
1900
1901impl<'a> ImportDeclarationSpecifier<'a> {
1902 pub fn local(&self) -> &BindingIdentifier<'a> {
1904 match self {
1905 ImportDeclarationSpecifier::ImportSpecifier(specifier) => &specifier.local,
1906 ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => &specifier.local,
1907 ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => &specifier.local,
1908 }
1909 }
1910
1911 pub fn name(&self) -> Cow<'a, str> {
1919 Cow::Borrowed(self.local().name.as_str())
1920 }
1921}
1922
1923impl<'a> ImportAttributeKey<'a> {
1924 pub fn as_atom(&self) -> Atom<'a> {
1926 match self {
1927 Self::Identifier(identifier) => identifier.name,
1928 Self::StringLiteral(literal) => literal.value,
1929 }
1930 }
1931}
1932
1933impl ExportNamedDeclaration<'_> {
1934 pub fn is_typescript_syntax(&self) -> bool {
1936 self.export_kind == ImportOrExportKind::Type
1937 || self.declaration.as_ref().is_some_and(Declaration::is_typescript_syntax)
1938 }
1939}
1940
1941impl ExportDefaultDeclaration<'_> {
1942 pub fn is_typescript_syntax(&self) -> bool {
1944 self.declaration.is_typescript_syntax()
1945 }
1946}
1947
1948impl ExportAllDeclaration<'_> {
1949 pub fn is_typescript_syntax(&self) -> bool {
1951 self.export_kind.is_type()
1952 }
1953}
1954
1955impl ExportDefaultDeclarationKind<'_> {
1956 #[inline]
1958 pub fn is_typescript_syntax(&self) -> bool {
1959 match self {
1960 Self::FunctionDeclaration(func) => func.is_typescript_syntax(),
1961 Self::ClassDeclaration(class) => class.is_typescript_syntax(),
1962 Self::TSInterfaceDeclaration(_) => true,
1963 _ => false,
1964 }
1965 }
1966}
1967
1968impl Display for ModuleExportName<'_> {
1969 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1970 match self {
1971 Self::IdentifierName(identifier) => identifier.name.fmt(f),
1972 Self::IdentifierReference(identifier) => identifier.name.fmt(f),
1973 Self::StringLiteral(literal) => write!(f, r#""{}""#, literal.value),
1974 }
1975 }
1976}
1977
1978impl<'a> ModuleExportName<'a> {
1979 pub fn name(&self) -> Atom<'a> {
1987 match self {
1988 Self::IdentifierName(identifier) => identifier.name,
1989 Self::IdentifierReference(identifier) => identifier.name,
1990 Self::StringLiteral(literal) => literal.value,
1991 }
1992 }
1993
1994 pub fn identifier_name(&self) -> Option<Atom<'a>> {
2002 match self {
2003 Self::IdentifierName(identifier) => Some(identifier.name),
2004 Self::IdentifierReference(identifier) => Some(identifier.name),
2005 Self::StringLiteral(_) => None,
2006 }
2007 }
2008
2009 pub fn is_identifier(&self) -> bool {
2016 matches!(self, Self::IdentifierName(_) | Self::IdentifierReference(_))
2017 }
2018}
2019
2020impl ImportPhase {
2021 pub fn as_str(self) -> &'static str {
2028 match self {
2029 Self::Source => "source",
2030 Self::Defer => "defer",
2031 }
2032 }
2033}