1use std::{fmt::Write, mem};
2
3use either::Either;
4use swc_atoms::{atom, Atom, Wtf8Atom};
5use swc_common::{BytePos, Span, Spanned};
6use swc_ecma_ast::*;
7
8use crate::{
9 error::SyntaxError, input::Tokens, lexer::Token, parser::util::IsSimpleParameterList, Context,
10 PResult, Parser,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14enum ParsingContext {
15 EnumMembers,
16 HeritageClauseElement,
17 TupleElementTypes,
18 TypeMembers,
19 TypeParametersOrArguments,
20}
21
22#[derive(Clone, Copy, PartialEq, Eq)]
23enum UnionOrIntersection {
24 Union,
25 Intersection,
26}
27
28#[derive(Clone, Copy, PartialEq, Eq)]
29enum SignatureParsingMode {
30 TSCallSignatureDeclaration,
31 TSConstructSignatureDeclaration,
32}
33
34fn make_decl_declare(mut decl: Decl) -> Decl {
36 match decl {
37 Decl::Class(ref mut c) => c.declare = true,
38 Decl::Fn(ref mut f) => f.declare = true,
39 Decl::Var(ref mut v) => v.declare = true,
40 Decl::TsInterface(ref mut i) => i.declare = true,
41 Decl::TsTypeAlias(ref mut a) => a.declare = true,
42 Decl::TsEnum(ref mut e) => e.declare = true,
43 Decl::TsModule(ref mut m) => m.declare = true,
44 Decl::Using(..) => unreachable!("Using is not a valid declaration for `declare` keyword"),
45 #[cfg(swc_ast_unknown)]
46 _ => unreachable!(),
47 }
48
49 decl
50}
51
52impl<I: Tokens> Parser<I> {
53 fn parse_ts_list<T, F>(&mut self, kind: ParsingContext, mut parse_element: F) -> PResult<Vec<T>>
55 where
56 F: FnMut(&mut Self) -> PResult<T>,
57 {
58 debug_assert!(self.input().syntax().typescript());
59 let mut buf = Vec::with_capacity(8);
60 while !self.is_ts_list_terminator(kind) {
61 buf.push(parse_element(self)?);
64 }
65 Ok(buf)
66 }
67
68 pub(super) fn try_parse_ts_bool<F>(&mut self, op: F) -> PResult<bool>
70 where
71 F: FnOnce(&mut Self) -> PResult<Option<bool>>,
72 {
73 if !self.input().syntax().typescript() {
74 return Ok(false);
75 }
76
77 let prev_ignore_error = self.input().get_ctx().contains(Context::IgnoreError);
78 let checkpoint = self.checkpoint_save();
79 self.set_ctx(self.ctx() | Context::IgnoreError);
80 let res = op(self);
81 match res {
82 Ok(Some(res)) if res => {
83 let mut ctx = self.ctx();
84 ctx.set(Context::IgnoreError, prev_ignore_error);
85 self.input_mut().set_ctx(ctx);
86 Ok(res)
87 }
88 _ => {
89 self.checkpoint_load(checkpoint);
90 Ok(false)
91 }
92 }
93 }
94
95 fn parse_ts_delimited_list_inner<T, F>(
97 &mut self,
98 kind: ParsingContext,
99 mut parse_element: F,
100 ) -> PResult<Vec<T>>
101 where
102 F: FnMut(&mut Self) -> PResult<(BytePos, T)>,
103 {
104 debug_assert!(self.input().syntax().typescript());
105 let mut buf = Vec::new();
106 loop {
107 trace_cur!(self, parse_ts_delimited_list_inner__element);
108
109 if self.is_ts_list_terminator(kind) {
110 break;
111 }
112
113 let (_, element) = parse_element(self)?;
114 buf.push(element);
115
116 if self.input_mut().eat(Token::Comma) {
117 continue;
118 }
119
120 if self.is_ts_list_terminator(kind) {
121 break;
122 }
123
124 if kind == ParsingContext::EnumMembers {
125 let expect = Token::Comma;
126 let cur = self.input().cur();
127 let cur = cur.to_string(self.input().get_token_value());
128 self.emit_err(
129 self.input().cur_span(),
130 SyntaxError::Expected(format!("{expect:?}"), cur),
131 );
132 continue;
133 }
134 expect!(self, Token::Comma);
136 }
137
138 Ok(buf)
139 }
140
141 pub(crate) fn ts_in_no_context<T, F>(&mut self, op: F) -> PResult<T>
143 where
144 F: FnOnce(&mut Self) -> PResult<T>,
145 {
146 debug_assert!(self.input().syntax().typescript());
147 trace_cur!(self, ts_in_no_context__before);
148 let res = op(self);
149 trace_cur!(self, ts_in_no_context__after);
150 res
151 }
152
153 fn is_ts_list_terminator(&mut self, kind: ParsingContext) -> bool {
155 debug_assert!(self.input().syntax().typescript());
156 let cur = self.input().cur();
157 match kind {
158 ParsingContext::EnumMembers | ParsingContext::TypeMembers => cur == Token::RBrace,
159 ParsingContext::HeritageClauseElement => {
160 matches!(cur, Token::LBrace | Token::Implements | Token::Extends)
161 }
162 ParsingContext::TupleElementTypes => cur == Token::RBracket,
163 ParsingContext::TypeParametersOrArguments => cur == Token::Gt,
164 }
165 }
166
167 pub(super) fn ts_next_token_can_follow_modifier(&mut self) -> bool {
169 debug_assert!(self.input().syntax().typescript());
170 self.bump();
176
177 let cur = self.input().cur();
178 !self.input().had_line_break_before_cur()
179 && matches!(
180 cur,
181 Token::LBracket
182 | Token::LBrace
183 | Token::Asterisk
184 | Token::DotDotDot
185 | Token::Hash
186 | Token::Str
187 | Token::Num
188 | Token::BigInt
189 )
190 || cur.is_word()
191 }
192
193 pub(crate) fn try_parse_ts<T, F>(&mut self, op: F) -> Option<T>
195 where
196 F: FnOnce(&mut Self) -> PResult<Option<T>>,
197 {
198 if !self.input().syntax().typescript() {
199 return None;
200 }
201 debug_tracing!(self, "try_parse_ts");
202
203 trace_cur!(self, try_parse_ts);
204
205 let prev_ignore_error = self.input().get_ctx().contains(Context::IgnoreError);
206 let checkpoint = self.checkpoint_save();
207 self.set_ctx(self.ctx() | Context::IgnoreError);
208 let res = op(self);
209 match res {
210 Ok(Some(res)) => {
211 trace_cur!(self, try_parse_ts__success_value);
212 let mut ctx = self.ctx();
213 ctx.set(Context::IgnoreError, prev_ignore_error);
214 self.input_mut().set_ctx(ctx);
215 Some(res)
216 }
217 Ok(None) => {
218 trace_cur!(self, try_parse_ts__success_no_value);
219 self.checkpoint_load(checkpoint);
220 None
221 }
222 Err(..) => {
223 trace_cur!(self, try_parse_ts__fail);
224 self.checkpoint_load(checkpoint);
225 None
226 }
227 }
228 }
229
230 fn parse_ts_type_member_semicolon(&mut self) -> PResult<()> {
232 debug_assert!(self.input().syntax().typescript());
233
234 if !self.input_mut().eat(Token::Comma) {
235 self.expect_general_semi()
236 } else {
237 Ok(())
238 }
239 }
240
241 fn is_ts_start_of_construct_signature(&mut self) -> bool {
243 debug_assert!(self.input().syntax().typescript());
244
245 self.bump();
246 let cur = self.input().cur();
247 matches!(cur, Token::LParen | Token::Lt)
248 }
249
250 fn parse_ts_delimited_list<T, F>(
252 &mut self,
253 kind: ParsingContext,
254 mut parse_element: F,
255 ) -> PResult<Vec<T>>
256 where
257 F: FnMut(&mut Self) -> PResult<T>,
258 {
259 self.parse_ts_delimited_list_inner(kind, |p| {
260 let start = p.input().cur_pos();
261 Ok((start, parse_element(p)?))
262 })
263 }
264
265 fn parse_ts_union_or_intersection_type<F>(
267 &mut self,
268 kind: UnionOrIntersection,
269 mut parse_constituent_type: F,
270 operator: Token,
271 ) -> PResult<Box<TsType>>
272 where
273 F: FnMut(&mut Self) -> PResult<Box<TsType>>,
274 {
275 trace_cur!(self, parse_ts_union_or_intersection_type);
276
277 debug_assert!(self.input().syntax().typescript());
278
279 let start = self.input().cur_pos(); self.input_mut().eat(operator);
281 trace_cur!(self, parse_ts_union_or_intersection_type__first_type);
282
283 let ty = parse_constituent_type(self)?;
284 trace_cur!(self, parse_ts_union_or_intersection_type__after_first);
285
286 if self.input().is(operator) {
287 let mut types = vec![ty];
288
289 while self.input_mut().eat(operator) {
290 trace_cur!(self, parse_ts_union_or_intersection_type__constituent);
291
292 types.push(parse_constituent_type(self)?);
293 }
294
295 return Ok(Box::new(TsType::TsUnionOrIntersectionType(match kind {
296 UnionOrIntersection::Union => TsUnionOrIntersectionType::TsUnionType(TsUnionType {
297 span: self.span(start),
298 types,
299 }),
300 UnionOrIntersection::Intersection => {
301 TsUnionOrIntersectionType::TsIntersectionType(TsIntersectionType {
302 span: self.span(start),
303 types,
304 })
305 }
306 })));
307 }
308 Ok(ty)
309 }
310
311 pub(crate) fn eat_any_ts_modifier(&mut self) -> PResult<bool> {
312 if self.syntax().typescript()
313 && {
314 let cur = self.input().cur();
315 matches!(
316 cur,
317 Token::Public | Token::Protected | Token::Private | Token::Readonly
318 )
319 }
320 && peek!(self)
321 .is_some_and(|t| t.is_word() || matches!(t, Token::LBrace | Token::LBracket))
322 {
323 let _ = self.parse_ts_modifier(&["public", "protected", "private", "readonly"], false);
324 Ok(true)
325 } else {
326 Ok(false)
327 }
328 }
329
330 pub(crate) fn parse_ts_modifier(
334 &mut self,
335 allowed_modifiers: &[&'static str],
336 stop_on_start_of_class_static_blocks: bool,
337 ) -> PResult<Option<&'static str>> {
338 debug_assert!(self.input().syntax().typescript());
339 let pos = {
340 let cur = self.input().cur();
341 let modifier = if cur == Token::Ident {
342 cur.clone().take_unknown_ident_ref(self.input()).clone()
343 } else if cur.is_known_ident() {
344 cur.take_known_ident()
345 } else if cur == Token::In {
346 atom!("in")
347 } else if cur == Token::Const {
348 atom!("const")
349 } else if cur == Token::Error {
350 let err = self.input_mut().expect_error_token_and_bump();
351 return Err(err);
352 } else if cur == Token::Eof {
353 return Err(self.eof_error());
354 } else {
355 return Ok(None);
356 };
357 allowed_modifiers
359 .iter()
360 .position(|s| **s == *modifier.as_str())
361 };
362 if let Some(pos) = pos {
363 if stop_on_start_of_class_static_blocks
364 && self.input().is(Token::Static)
365 && peek!(self).is_some_and(|peek| peek == Token::LBrace)
366 {
367 return Ok(None);
368 }
369 if self.try_parse_ts_bool(|p| Ok(Some(p.ts_next_token_can_follow_modifier())))? {
370 return Ok(Some(allowed_modifiers[pos]));
371 }
372 }
373 Ok(None)
374 }
375
376 fn parse_ts_bracketed_list<T, F>(
377 &mut self,
378 kind: ParsingContext,
379 parse_element: F,
380 bracket: bool,
381 skip_first_token: bool,
382 ) -> PResult<Vec<T>>
383 where
384 F: FnMut(&mut Self) -> PResult<T>,
385 {
386 debug_assert!(self.input().syntax().typescript());
387 if !skip_first_token {
388 if bracket {
389 expect!(self, Token::LBracket);
390 } else {
391 expect!(self, Token::Lt);
392 }
393 }
394 let result = self.parse_ts_delimited_list(kind, parse_element)?;
395 if bracket {
396 expect!(self, Token::RBracket);
397 } else {
398 expect!(self, Token::Gt);
399 }
400 Ok(result)
401 }
402
403 fn parse_ts_this_type_node(&mut self) -> PResult<TsThisType> {
405 debug_assert!(self.input().syntax().typescript());
406 expect!(self, Token::This);
407 Ok(TsThisType {
408 span: self.input().prev_span(),
409 })
410 }
411
412 fn parse_ts_entity_name(&mut self, allow_reserved_words: bool) -> PResult<TsEntityName> {
414 debug_assert!(self.input().syntax().typescript());
415 trace_cur!(self, parse_ts_entity_name);
416 let start = self.input().cur_pos();
417 let init = self.parse_ident_name()?;
418 if &*init.sym == "void" {
419 let dot_start = self.input().cur_pos();
420 let dot_span = self.span(dot_start);
421 self.emit_err(dot_span, SyntaxError::TS1005)
422 }
423 let mut entity = TsEntityName::Ident(init.into());
424 while self.input_mut().eat(Token::Dot) {
425 let dot_start = self.input().cur_pos();
426 let cur = self.input().cur();
427 if cur != Token::Hash && !cur.is_word() {
428 self.emit_err(
429 Span::new_with_checked(dot_start, dot_start),
430 SyntaxError::TS1003,
431 );
432 return Ok(entity);
433 }
434 let left = entity;
435 let right = if allow_reserved_words {
436 self.parse_ident_name()?
437 } else {
438 self.parse_ident(false, false)?.into()
439 };
440 let span = self.span(start);
441 entity = TsEntityName::TsQualifiedName(Box::new(TsQualifiedName { span, left, right }));
442 }
443 Ok(entity)
444 }
445
446 pub(crate) fn ts_look_ahead<T, F>(&mut self, op: F) -> T
447 where
448 F: FnOnce(&mut Self) -> T,
449 {
450 debug_assert!(self.input().syntax().typescript());
451 let checkpoint = self.checkpoint_save();
452 self.set_ctx(self.ctx() | Context::IgnoreError);
453 let ret = op(self);
454 self.checkpoint_load(checkpoint);
455 ret
456 }
457
458 pub(crate) fn parse_ts_type_args(&mut self) -> PResult<Box<TsTypeParamInstantiation>> {
460 trace_cur!(self, parse_ts_type_args);
461 debug_assert!(self.input().syntax().typescript());
462
463 let start = self.input().cur_pos();
464 let params = self.in_type(|p| {
465 p.ts_in_no_context(|p| {
468 if p.input().is(Token::LShift) {
469 p.input_mut().cut_lshift();
470 } else {
471 expect!(p, Token::Lt);
472 }
473 p.parse_ts_delimited_list(ParsingContext::TypeParametersOrArguments, |p| {
474 trace_cur!(p, parse_ts_type_args__arg);
475
476 p.parse_ts_type()
477 })
478 })
479 })?;
480 self.input_mut().set_expr_allowed(false);
484 self.expect_without_advance(Token::Gt)?;
485 let span = Span::new_with_checked(start, self.input().cur_span().hi);
486
487 if params.is_empty() {
489 self.emit_err(span, SyntaxError::EmptyTypeArgumentList);
490 }
491
492 Ok(Box::new(TsTypeParamInstantiation { span, params }))
493 }
494
495 fn parse_ts_type_ref(&mut self) -> PResult<TsTypeRef> {
497 trace_cur!(self, parse_ts_type_ref);
498 debug_assert!(self.input().syntax().typescript());
499
500 let start = self.input().cur_pos();
501
502 let has_modifier = self.eat_any_ts_modifier()?;
503
504 let type_name = self.parse_ts_entity_name(true)?;
505 trace_cur!(self, parse_ts_type_ref__type_args);
506 let type_params = if !self.input().had_line_break_before_cur()
507 && (self.input().is(Token::Lt) || self.input().is(Token::LShift))
508 {
509 let ret = self.do_outside_of_context(
510 Context::ShouldNotLexLtOrGtAsType,
511 Self::parse_ts_type_args,
512 )?;
513 self.assert_and_bump(Token::Gt);
514 Some(ret)
515 } else {
516 None
517 };
518
519 if has_modifier {
520 self.emit_err(self.span(start), SyntaxError::TS2369);
521 }
522
523 Ok(TsTypeRef {
524 span: self.span(start),
525 type_name,
526 type_params,
527 })
528 }
529
530 #[cfg_attr(
531 feature = "tracing-spans",
532 tracing::instrument(level = "debug", skip_all)
533 )]
534 pub(crate) fn parse_ts_type_ann(
535 &mut self,
536 eat_colon: bool,
537 start: BytePos,
538 ) -> PResult<Box<TsTypeAnn>> {
539 trace_cur!(self, parse_ts_type_ann);
540
541 debug_assert!(self.input().syntax().typescript());
542
543 self.in_type(|p| {
544 if eat_colon {
545 p.assert_and_bump(Token::Colon);
546 }
547
548 trace_cur!(p, parse_ts_type_ann__after_colon);
549
550 let type_ann = p.parse_ts_type()?;
551
552 Ok(Box::new(TsTypeAnn {
553 span: p.span(start),
554 type_ann,
555 }))
556 })
557 }
558
559 fn parse_ts_this_type_predicate(
561 &mut self,
562 start: BytePos,
563 has_asserts_keyword: bool,
564 lhs: TsThisType,
565 ) -> PResult<TsTypePredicate> {
566 debug_assert!(self.input().syntax().typescript());
567
568 let param_name = TsThisTypeOrIdent::TsThisType(lhs);
569 let type_ann = if self.input_mut().eat(Token::Is) {
570 let cur_pos = self.input().cur_pos();
571 Some(self.parse_ts_type_ann(false, cur_pos)?)
572 } else {
573 None
574 };
575
576 Ok(TsTypePredicate {
577 span: self.span(start),
578 asserts: has_asserts_keyword,
579 param_name,
580 type_ann,
581 })
582 }
583
584 fn eat_then_parse_ts_type(&mut self, token_to_eat: Token) -> PResult<Option<Box<TsType>>> {
586 if !cfg!(feature = "typescript") {
587 return Ok(Default::default());
588 }
589
590 self.in_type(|p| {
591 if !p.input_mut().eat(token_to_eat) {
592 return Ok(None);
593 }
594
595 p.parse_ts_type().map(Some)
596 })
597 }
598
599 fn expect_then_parse_ts_type(
601 &mut self,
602 token: Token,
603 token_str: &'static str,
604 ) -> PResult<Box<TsType>> {
605 debug_assert!(self.input().syntax().typescript());
606
607 self.in_type(|p| {
608 if !p.input_mut().eat(token) {
609 let got = format!("{:?}", p.input().cur());
610 syntax_error!(
611 p,
612 p.input().cur_span(),
613 SyntaxError::Unexpected {
614 got,
615 expected: token_str
616 }
617 );
618 }
619
620 p.parse_ts_type()
621 })
622 }
623
624 fn parse_ts_mapped_type_param(&mut self) -> PResult<TsTypeParam> {
626 debug_assert!(self.input().syntax().typescript());
627
628 let start = self.input().cur_pos();
629 let name = self.parse_ident_name()?;
630 let constraint = Some(self.expect_then_parse_ts_type(Token::In, "in")?);
631
632 Ok(TsTypeParam {
633 span: self.span(start),
634 name: name.into(),
635 is_in: false,
636 is_out: false,
637 is_const: false,
638 constraint,
639 default: None,
640 })
641 }
642
643 fn parse_ts_type_param(
645 &mut self,
646 permit_in_out: bool,
647 permit_const: bool,
648 ) -> PResult<TsTypeParam> {
649 debug_assert!(self.input().syntax().typescript());
650
651 let mut is_in = false;
652 let mut is_out = false;
653 let mut is_const = false;
654
655 let start = self.input().cur_pos();
656
657 while let Some(modifer) = self.parse_ts_modifier(
658 &[
659 "public",
660 "private",
661 "protected",
662 "readonly",
663 "abstract",
664 "const",
665 "override",
666 "in",
667 "out",
668 ],
669 false,
670 )? {
671 match modifer {
672 "const" => {
673 is_const = true;
674 if !permit_const {
675 self.emit_err(
676 self.input().prev_span(),
677 SyntaxError::TS1277(atom!("const")),
678 );
679 }
680 }
681 "in" => {
682 if !permit_in_out {
683 self.emit_err(self.input().prev_span(), SyntaxError::TS1274(atom!("in")));
684 } else if is_in {
685 self.emit_err(self.input().prev_span(), SyntaxError::TS1030(atom!("in")));
686 } else if is_out {
687 self.emit_err(
688 self.input().prev_span(),
689 SyntaxError::TS1029(atom!("in"), atom!("out")),
690 );
691 }
692 is_in = true;
693 }
694 "out" => {
695 if !permit_in_out {
696 self.emit_err(self.input().prev_span(), SyntaxError::TS1274(atom!("out")));
697 } else if is_out {
698 self.emit_err(self.input().prev_span(), SyntaxError::TS1030(atom!("out")));
699 }
700 is_out = true;
701 }
702 other => self.emit_err(self.input().prev_span(), SyntaxError::TS1273(other.into())),
703 };
704 }
705
706 let name = self.in_type(Self::parse_ident_name)?.into();
707 let constraint = self.eat_then_parse_ts_type(Token::Extends)?;
708 let default = self.eat_then_parse_ts_type(Token::Eq)?;
709
710 Ok(TsTypeParam {
711 span: self.span(start),
712 name,
713 is_in,
714 is_out,
715 is_const,
716 constraint,
717 default,
718 })
719 }
720
721 pub(crate) fn parse_ts_type_params(
723 &mut self,
724 permit_in_out: bool,
725 permit_const: bool,
726 ) -> PResult<Box<TsTypeParamDecl>> {
727 self.in_type(|p| {
728 p.ts_in_no_context(|p| {
729 let start = p.input().cur_pos();
730 let cur = p.input().cur();
731 if cur != Token::Lt && cur != Token::JSXTagStart {
732 unexpected!(p, "< (jsx tag start)")
733 }
734 p.bump();
735
736 let params = p.parse_ts_bracketed_list(
737 ParsingContext::TypeParametersOrArguments,
738 |p| p.parse_ts_type_param(permit_in_out, permit_const), false,
740 true,
742 )?;
743
744 Ok(Box::new(TsTypeParamDecl {
745 span: p.span(start),
746 params,
747 }))
748 })
749 })
750 }
751
752 pub(crate) fn try_parse_ts_type_params(
754 &mut self,
755 permit_in_out: bool,
756 permit_const: bool,
757 ) -> PResult<Option<Box<TsTypeParamDecl>>> {
758 if !cfg!(feature = "typescript") {
759 return Ok(None);
760 }
761
762 if self.input().cur() == Token::Lt {
763 return self
764 .parse_ts_type_params(permit_in_out, permit_const)
765 .map(Some);
766 }
767
768 Ok(None)
769 }
770
771 pub(crate) fn parse_ts_type_or_type_predicate_ann(
773 &mut self,
774 return_token: Token,
775 ) -> PResult<Box<TsTypeAnn>> {
776 debug_assert!(self.input().syntax().typescript());
777
778 self.in_type(|p| {
779 let return_token_start = p.input().cur_pos();
780 if !p.input_mut().eat(return_token) {
781 let cur = format!("{:?}", p.input().cur());
782 let span = p.input().cur_span();
783 syntax_error!(
784 p,
785 span,
786 SyntaxError::Expected(format!("{return_token:?}"), cur)
787 )
788 }
789
790 let type_pred_start = p.input().cur_pos();
791 let has_type_pred_asserts = p.input().cur() == Token::Asserts && {
792 let ctx = p.ctx();
793 peek!(p).is_some_and(|peek| {
794 if peek.is_word() {
795 !peek.is_reserved(ctx)
796 } else {
797 false
798 }
799 })
800 };
801
802 if has_type_pred_asserts {
803 p.assert_and_bump(Token::Asserts);
804 }
805
806 let has_type_pred_is = p.is_ident_ref()
807 && peek!(p).is_some_and(|peek| peek == Token::Is)
808 && !p.input_mut().has_linebreak_between_cur_and_peeked();
809 let is_type_predicate = has_type_pred_asserts || has_type_pred_is;
810 if !is_type_predicate {
811 return p.parse_ts_type_ann(
812 false,
814 return_token_start,
815 );
816 }
817
818 let type_pred_var = p.parse_ident_name()?;
819 let type_ann = if has_type_pred_is {
820 p.assert_and_bump(Token::Is);
821 let pos = p.input().cur_pos();
822 Some(p.parse_ts_type_ann(false, pos)?)
823 } else {
824 None
825 };
826
827 let node = Box::new(TsType::TsTypePredicate(TsTypePredicate {
828 span: p.span(type_pred_start),
829 asserts: has_type_pred_asserts,
830 param_name: TsThisTypeOrIdent::Ident(type_pred_var.into()),
831 type_ann,
832 }));
833
834 Ok(Box::new(TsTypeAnn {
835 span: p.span(return_token_start),
836 type_ann: node,
837 }))
838 })
839 }
840
841 fn is_start_of_expr(&mut self) -> bool {
842 self.is_start_of_left_hand_side_expr() || {
843 let cur = self.input().cur();
844 matches!(
845 cur,
846 Token::Plus
847 | Token::Minus
848 | Token::Tilde
849 | Token::Bang
850 | Token::Delete
851 | Token::TypeOf
852 | Token::Void
853 | Token::PlusPlus
854 | Token::MinusMinus
855 | Token::Lt
856 | Token::Await
857 | Token::Yield
858 ) || (cur == Token::Hash && peek!(self).is_some_and(|peek| peek.is_word()))
859 }
860 }
861
862 #[cfg_attr(
863 feature = "tracing-spans",
864 tracing::instrument(level = "debug", skip_all)
865 )]
866 pub(super) fn try_parse_ts_type_args(&mut self) -> Option<Box<TsTypeParamInstantiation>> {
867 trace_cur!(self, try_parse_ts_type_args);
868 debug_assert!(self.input().syntax().typescript());
869
870 self.try_parse_ts(|p| {
871 let type_args = p.parse_ts_type_args()?;
872 p.assert_and_bump(Token::Gt);
873 let cur = p.input().cur();
874 if matches!(
875 cur,
876 Token::Lt
877 | Token::Gt
878 | Token::Eq
879 | Token::RShift
880 | Token::GtEq
881 | Token::Plus
882 | Token::Minus
883 | Token::LParen
884 | Token::NoSubstitutionTemplateLiteral
885 | Token::TemplateHead
886 | Token::BackQuote
887 )
888 {
894 Ok(None)
895 } else if p.input().had_line_break_before_cur()
896 || p.input().cur().is_bin_op()
897 || !p.is_start_of_expr()
898 {
899 Ok(Some(type_args))
900 } else {
901 Ok(None)
902 }
903 })
904 }
905
906 fn try_parse_ts_type(&mut self) -> PResult<Option<Box<TsType>>> {
908 if !cfg!(feature = "typescript") {
909 return Ok(None);
910 }
911
912 self.eat_then_parse_ts_type(Token::Colon)
913 }
914
915 #[cfg_attr(
917 feature = "tracing-spans",
918 tracing::instrument(level = "debug", skip_all)
919 )]
920 pub(crate) fn try_parse_ts_type_ann(&mut self) -> PResult<Option<Box<TsTypeAnn>>> {
921 if !cfg!(feature = "typescript") {
922 return Ok(None);
923 }
924
925 if self.input().is(Token::Colon) {
926 let pos = self.cur_pos();
927 return self.parse_ts_type_ann(true, pos).map(Some);
928 }
929
930 Ok(None)
931 }
932
933 pub(super) fn next_then_parse_ts_type(&mut self) -> PResult<Box<TsType>> {
935 debug_assert!(self.input().syntax().typescript());
936
937 let result = self.in_type(|p| {
938 p.bump();
939 p.parse_ts_type()
940 });
941
942 if !self.ctx().contains(Context::InType) && {
943 let cur = self.input().cur();
944 cur == Token::Lt || cur == Token::Gt
945 } {
946 self.input_mut().merge_lt_gt();
947 }
948
949 result
950 }
951
952 fn parse_ts_enum_member(&mut self) -> PResult<TsEnumMember> {
954 debug_assert!(self.input().syntax().typescript());
955
956 let start = self.cur_pos();
957 let cur = self.input().cur();
962 let id = if cur == Token::Str {
963 TsEnumMemberId::Str(self.parse_str_lit())
964 } else if cur == Token::Num {
965 let (value, raw) = self.input_mut().expect_number_token_and_bump();
966 let mut new_raw = String::new();
967
968 new_raw.push('"');
969 new_raw.push_str(raw.as_str());
970 new_raw.push('"');
971
972 let span = self.span(start);
973
974 self.emit_err(span, SyntaxError::TS2452);
976
977 TsEnumMemberId::Str(Str {
978 span,
979 value: value.to_string().into(),
980 raw: Some(new_raw.into()),
981 })
982 } else if cur == Token::LBracket {
983 self.assert_and_bump(Token::LBracket);
984 let expr = self.parse_expr()?;
985 self.assert_and_bump(Token::RBracket);
986 let bracket_span = self.span(start);
987
988 match *expr {
989 Expr::Lit(Lit::Str(str_lit)) => {
990 TsEnumMemberId::Str(str_lit)
992 }
993 Expr::Tpl(mut tpl) if tpl.exprs.is_empty() => {
994 let tpl = mem::take(tpl.quasis.first_mut().unwrap());
997
998 let span = tpl.span;
999 let value = tpl.cooked.unwrap();
1000
1001 TsEnumMemberId::Str(Str {
1002 span,
1003 value,
1004 raw: None,
1005 })
1006 }
1007 _ => {
1008 self.emit_err(bracket_span, SyntaxError::TS1164);
1010 TsEnumMemberId::Ident(Ident::new_no_ctxt(atom!(""), bracket_span))
1011 }
1012 }
1013 } else if cur == Token::Error {
1014 let err = self.input_mut().expect_error_token_and_bump();
1015 return Err(err);
1016 } else {
1017 self.parse_ident_name()
1018 .map(Ident::from)
1019 .map(TsEnumMemberId::from)?
1020 };
1021
1022 let init = if self.input_mut().eat(Token::Eq) {
1023 Some(self.parse_assignment_expr()?)
1024 } else if self.input().cur() == Token::Comma || self.input().cur() == Token::RBrace {
1025 None
1026 } else {
1027 let start = self.cur_pos();
1028 self.bump();
1029 self.input_mut().store(Token::Comma);
1030 self.emit_err(Span::new_with_checked(start, start), SyntaxError::TS1005);
1031 None
1032 };
1033
1034 Ok(TsEnumMember {
1035 span: self.span(start),
1036 id,
1037 init,
1038 })
1039 }
1040
1041 pub(crate) fn parse_ts_enum_decl(
1043 &mut self,
1044 start: BytePos,
1045 is_const: bool,
1046 ) -> PResult<Box<TsEnumDecl>> {
1047 debug_assert!(self.input().syntax().typescript());
1048
1049 let id = self.parse_ident_name()?;
1050 expect!(self, Token::LBrace);
1051 let members =
1052 self.parse_ts_delimited_list(ParsingContext::EnumMembers, Self::parse_ts_enum_member)?;
1053 expect!(self, Token::RBrace);
1054
1055 Ok(Box::new(TsEnumDecl {
1056 span: self.span(start),
1057 declare: false,
1058 is_const,
1059 id: id.into(),
1060 members,
1061 }))
1062 }
1063
1064 fn try_parse_ts_type_or_type_predicate_ann(&mut self) -> PResult<Option<Box<TsTypeAnn>>> {
1068 if !cfg!(feature = "typescript") {
1069 return Ok(None);
1070 }
1071
1072 if self.input().is(Token::Colon) {
1073 self.parse_ts_type_or_type_predicate_ann(Token::Colon)
1074 .map(Some)
1075 } else {
1076 Ok(None)
1077 }
1078 }
1079
1080 fn parse_ts_tpl_lit_type(&mut self) -> PResult<TsTplLitType> {
1082 debug_assert!(self.input().syntax().typescript());
1083
1084 let start = self.cur_pos();
1085
1086 self.assert_and_bump(Token::BackQuote);
1087
1088 let (types, quasis) = self.parse_ts_tpl_type_elements()?;
1089
1090 expect!(self, Token::BackQuote);
1091
1092 Ok(TsTplLitType {
1093 span: self.span(start),
1094 types,
1095 quasis,
1096 })
1097 }
1098
1099 fn parse_ts_tpl_type_elements(&mut self) -> PResult<(Vec<Box<TsType>>, Vec<TplElement>)> {
1100 if !cfg!(feature = "typescript") {
1101 return Ok(Default::default());
1102 }
1103
1104 trace_cur!(self, parse_tpl_elements);
1105
1106 let mut types = Vec::new();
1107
1108 let cur_elem = self.parse_tpl_element(false)?;
1109 let mut is_tail = cur_elem.tail;
1110 let mut quasis = vec![cur_elem];
1111
1112 while !is_tail {
1113 expect!(self, Token::DollarLBrace);
1114 types.push(self.parse_ts_type()?);
1115 expect!(self, Token::RBrace);
1116 let elem = self.parse_tpl_element(false)?;
1117 is_tail = elem.tail;
1118 quasis.push(elem);
1119 }
1120
1121 Ok((types, quasis))
1122 }
1123
1124 fn parse_ts_lit_type_node(&mut self) -> PResult<TsLitType> {
1126 debug_assert!(self.input().syntax().typescript());
1127
1128 let start = self.cur_pos();
1129
1130 let lit = if self.input().is(Token::BackQuote) {
1131 let tpl = self.parse_ts_tpl_lit_type()?;
1132 TsLit::Tpl(tpl)
1133 } else {
1134 match self.parse_lit()? {
1135 Lit::BigInt(n) => TsLit::BigInt(n),
1136 Lit::Bool(n) => TsLit::Bool(n),
1137 Lit::Num(n) => TsLit::Number(n),
1138 Lit::Str(n) => TsLit::Str(n),
1139 _ => unreachable!(),
1140 }
1141 };
1142
1143 Ok(TsLitType {
1144 span: self.span(start),
1145 lit,
1146 })
1147 }
1148
1149 pub(crate) fn parse_ts_heritage_clause(&mut self) -> PResult<Vec<TsExprWithTypeArgs>> {
1151 debug_assert!(self.input().syntax().typescript());
1152
1153 self.parse_ts_delimited_list(
1154 ParsingContext::HeritageClauseElement,
1155 Self::parse_ts_heritage_clause_element,
1156 )
1157 }
1158
1159 fn parse_ts_heritage_clause_element(&mut self) -> PResult<TsExprWithTypeArgs> {
1160 debug_assert!(self.input().syntax().typescript());
1161
1162 let start = self.cur_pos();
1163 let ident = self.parse_ident_name()?.into();
1167 let expr = self.parse_subscripts(Callee::Expr(ident), true, true)?;
1168 if !matches!(
1169 &*expr,
1170 Expr::Ident(..) | Expr::Member(..) | Expr::TsInstantiation(..)
1171 ) {
1172 self.emit_err(self.span(start), SyntaxError::TS2499);
1173 }
1174
1175 match *expr {
1176 Expr::TsInstantiation(v) => Ok(TsExprWithTypeArgs {
1177 span: v.span,
1178 expr: v.expr,
1179 type_args: Some(v.type_args),
1180 }),
1181 _ => {
1182 let type_args = if self.input().is(Token::Lt) {
1183 let ret = self.parse_ts_type_args()?;
1184 self.assert_and_bump(Token::Gt);
1185 Some(ret)
1186 } else {
1187 None
1188 };
1189
1190 Ok(TsExprWithTypeArgs {
1191 span: self.span(start),
1192 expr,
1193 type_args,
1194 })
1195 }
1196 }
1197 }
1198
1199 fn skip_ts_parameter_start(&mut self) -> PResult<bool> {
1201 debug_assert!(self.input().syntax().typescript());
1202
1203 let _ = self.eat_any_ts_modifier()?;
1204
1205 let cur = self.input().cur();
1206
1207 if cur == Token::Void {
1208 Ok(false)
1209 } else if cur.is_word() || cur == Token::This {
1210 self.bump();
1211 Ok(true)
1212 } else if (cur == Token::LBrace || cur == Token::LBracket)
1213 && self.parse_binding_pat_or_ident(false).is_ok()
1214 {
1215 Ok(true)
1216 } else {
1217 Ok(false)
1218 }
1219 }
1220
1221 fn is_ts_unambiguously_start_of_fn_type(&mut self) -> PResult<bool> {
1223 debug_assert!(self.input().syntax().typescript());
1224
1225 self.assert_and_bump(Token::LParen);
1226
1227 let cur = self.input().cur();
1228 if cur == Token::RParen || cur == Token::DotDotDot {
1229 return Ok(true);
1232 }
1233 if self.skip_ts_parameter_start()? {
1234 let cur = self.input().cur();
1235 if matches!(
1236 cur,
1237 Token::Colon | Token::Comma | Token::Eq | Token::QuestionMark
1238 ) {
1239 return Ok(true);
1244 }
1245 if self.input_mut().eat(Token::RParen) && self.input().cur() == Token::Arrow {
1246 return Ok(true);
1248 }
1249 }
1250 Ok(false)
1251 }
1252
1253 fn is_ts_start_of_fn_type(&mut self) -> bool {
1254 debug_assert!(self.input().syntax().typescript());
1255
1256 if self.input().cur() == Token::Lt {
1257 return true;
1258 }
1259
1260 self.input().cur() == Token::LParen
1261 && self
1262 .ts_look_ahead(Self::is_ts_unambiguously_start_of_fn_type)
1263 .unwrap_or_default()
1264 }
1265
1266 fn is_ts_unambiguously_index_signature(&mut self) -> bool {
1268 debug_assert!(self.input().syntax().typescript());
1269
1270 self.assert_and_bump(Token::LBracket); self.eat_ident_ref() && {
1275 let cur = self.input().cur();
1276 cur == Token::Comma || cur == Token::Colon
1277 }
1278 }
1279
1280 pub(crate) fn try_parse_ts_index_signature(
1282 &mut self,
1283 index_signature_start: BytePos,
1284 readonly: bool,
1285 is_static: bool,
1286 ) -> PResult<Option<TsIndexSignature>> {
1287 if !cfg!(feature = "typescript") {
1288 return Ok(Default::default());
1289 }
1290
1291 if !(self.input().cur() == Token::LBracket
1292 && self.ts_look_ahead(Self::is_ts_unambiguously_index_signature))
1293 {
1294 return Ok(None);
1295 }
1296
1297 expect!(self, Token::LBracket);
1298
1299 let ident_start = self.cur_pos();
1300 let mut id = self.parse_ident_name().map(BindingIdent::from)?;
1301 let type_ann_start = self.cur_pos();
1302
1303 if self.input_mut().eat(Token::Comma) {
1304 self.emit_err(id.span, SyntaxError::TS1096);
1305 } else {
1306 expect!(self, Token::Colon);
1307 }
1308
1309 let type_ann = self.parse_ts_type_ann(false, type_ann_start)?;
1310 id.span = self.span(ident_start);
1311 id.type_ann = Some(type_ann);
1312
1313 expect!(self, Token::RBracket);
1314
1315 let params = vec![TsFnParam::Ident(id)];
1316
1317 let ty = self.try_parse_ts_type_ann()?;
1318 let type_ann = ty;
1319
1320 self.parse_ts_type_member_semicolon()?;
1321
1322 Ok(Some(TsIndexSignature {
1323 span: self.span(index_signature_start),
1324 readonly,
1325 is_static,
1326 params,
1327 type_ann,
1328 }))
1329 }
1330
1331 fn is_ts_external_module_ref(&mut self) -> bool {
1333 debug_assert!(self.input().syntax().typescript());
1334 self.input().is(Token::Require) && peek!(self).is_some_and(|t| t == Token::LParen)
1335 }
1336
1337 fn parse_ts_module_ref(&mut self) -> PResult<TsModuleRef> {
1339 debug_assert!(self.input().syntax().typescript());
1340
1341 if self.is_ts_external_module_ref() {
1342 self.parse_ts_external_module_ref().map(From::from)
1343 } else {
1344 self.parse_ts_entity_name(false)
1345 .map(From::from)
1346 }
1347 }
1348
1349 fn parse_ts_external_module_ref(&mut self) -> PResult<TsExternalModuleRef> {
1351 debug_assert!(self.input().syntax().typescript());
1352
1353 let start = self.cur_pos();
1354 expect!(self, Token::Require);
1355 expect!(self, Token::LParen);
1356 let cur = self.input().cur();
1357 if cur == Token::Error {
1358 let err = self.input_mut().expect_error_token_and_bump();
1359 return Err(err);
1360 } else if cur != Token::Str {
1361 unexpected!(self, "a string literal")
1362 }
1363 let expr = self.parse_str_lit();
1364 expect!(self, Token::RParen);
1365 Ok(TsExternalModuleRef {
1366 span: self.span(start),
1367 expr,
1368 })
1369 }
1370
1371 pub(crate) fn parse_ts_import_equals_decl(
1373 &mut self,
1374 start: BytePos,
1375 id: Ident,
1376 is_export: bool,
1377 is_type_only: bool,
1378 ) -> PResult<Box<TsImportEqualsDecl>> {
1379 debug_assert!(self.input().syntax().typescript());
1380
1381 expect!(self, Token::Eq);
1382 let module_ref = self.parse_ts_module_ref()?;
1383 self.expect_general_semi()?;
1384
1385 Ok(Box::new(TsImportEqualsDecl {
1386 span: self.span(start),
1387 id,
1388 is_export,
1389 is_type_only,
1390 module_ref,
1391 }))
1392 }
1393
1394 fn parse_ts_binding_list_for_signature(&mut self) -> PResult<Vec<TsFnParam>> {
1398 if !cfg!(feature = "typescript") {
1399 return Ok(Default::default());
1400 }
1401
1402 debug_assert!(self.input().syntax().typescript());
1403
1404 let params = self.parse_formal_params()?;
1405 let mut list = Vec::with_capacity(4);
1406
1407 for param in params {
1408 let item = match param.pat {
1409 Pat::Ident(pat) => TsFnParam::Ident(pat),
1410 Pat::Array(pat) => TsFnParam::Array(pat),
1411 Pat::Object(pat) => TsFnParam::Object(pat),
1412 Pat::Rest(pat) => TsFnParam::Rest(pat),
1413 _ => unexpected!(
1414 self,
1415 "an identifier, [ for an array pattern, { for an object patter or ... for a \
1416 rest pattern"
1417 ),
1418 };
1419 list.push(item);
1420 }
1421 expect!(self, Token::RParen);
1422 Ok(list)
1423 }
1424
1425 fn is_ts_start_of_mapped_type(&mut self) -> bool {
1427 debug_assert!(self.input().syntax().typescript());
1428
1429 self.bump();
1430 if self.input_mut().eat(Token::Plus) || self.input_mut().eat(Token::Minus) {
1431 return self.input().is(Token::Readonly);
1432 }
1433
1434 self.input_mut().eat(Token::Readonly);
1435
1436 if !self.input().is(Token::LBracket) {
1437 return false;
1438 }
1439 self.bump();
1440 if !self.is_ident_ref() {
1441 return false;
1442 }
1443 self.bump();
1444
1445 self.input().is(Token::In)
1446 }
1447
1448 fn parse_ts_signature_member(
1450 &mut self,
1451 kind: SignatureParsingMode,
1452 ) -> PResult<Either<TsCallSignatureDecl, TsConstructSignatureDecl>> {
1453 debug_assert!(self.input().syntax().typescript());
1454
1455 let start = self.cur_pos();
1456
1457 if kind == SignatureParsingMode::TSConstructSignatureDeclaration {
1458 expect!(self, Token::New);
1459 }
1460
1461 let type_params = self.try_parse_ts_type_params(false, true)?;
1463 expect!(self, Token::LParen);
1464 let params = self.parse_ts_binding_list_for_signature()?;
1465 let type_ann = if self.input().is(Token::Colon) {
1466 Some(self.parse_ts_type_or_type_predicate_ann(Token::Colon)?)
1467 } else {
1468 None
1469 };
1470 self.parse_ts_type_member_semicolon()?;
1473
1474 match kind {
1475 SignatureParsingMode::TSCallSignatureDeclaration => {
1476 Ok(Either::Left(TsCallSignatureDecl {
1477 span: self.span(start),
1478 params,
1479 type_ann,
1480 type_params,
1481 }))
1482 }
1483 SignatureParsingMode::TSConstructSignatureDeclaration => {
1484 Ok(Either::Right(TsConstructSignatureDecl {
1485 span: self.span(start),
1486 params,
1487 type_ann,
1488 type_params,
1489 }))
1490 }
1491 }
1492 }
1493
1494 fn try_parse_ts_tuple_element_name(&mut self) -> Option<Pat> {
1495 if !cfg!(feature = "typescript") {
1496 return Default::default();
1497 }
1498
1499 self.try_parse_ts(|p| {
1500 let start = p.cur_pos();
1501
1502 let rest = if p.input_mut().eat(Token::DotDotDot) {
1503 Some(p.input().prev_span())
1504 } else {
1505 None
1506 };
1507
1508 let mut ident = p.parse_ident_name().map(Ident::from)?;
1509 if p.input_mut().eat(Token::QuestionMark) {
1510 ident.optional = true;
1511 ident.span = ident.span.with_hi(p.input().prev_span().hi);
1512 }
1513 expect!(p, Token::Colon);
1514
1515 Ok(Some(if let Some(dot3_token) = rest {
1516 RestPat {
1517 span: p.span(start),
1518 dot3_token,
1519 arg: ident.into(),
1520 type_ann: None,
1521 }
1522 .into()
1523 } else {
1524 ident.into()
1525 }))
1526 })
1527 }
1528
1529 fn parse_ts_tuple_element_type(&mut self) -> PResult<TsTupleElement> {
1531 debug_assert!(self.input().syntax().typescript());
1532
1533 let start = self.cur_pos();
1535
1536 let label = self.try_parse_ts_tuple_element_name();
1537
1538 if self.input_mut().eat(Token::DotDotDot) {
1539 let type_ann = self.parse_ts_type()?;
1540 return Ok(TsTupleElement {
1541 span: self.span(start),
1542 label,
1543 ty: Box::new(TsType::TsRestType(TsRestType {
1544 span: self.span(start),
1545 type_ann,
1546 })),
1547 });
1548 }
1549
1550 let ty = self.parse_ts_type()?;
1551 if self.input_mut().eat(Token::QuestionMark) {
1553 let type_ann = ty;
1554 return Ok(TsTupleElement {
1555 span: self.span(start),
1556 label,
1557 ty: Box::new(TsType::TsOptionalType(TsOptionalType {
1558 span: self.span(start),
1559 type_ann,
1560 })),
1561 });
1562 }
1563
1564 Ok(TsTupleElement {
1565 span: self.span(start),
1566 label,
1567 ty,
1568 })
1569 }
1570
1571 fn parse_ts_tuple_type(&mut self) -> PResult<TsTupleType> {
1573 debug_assert!(self.input().syntax().typescript());
1574
1575 let start = self.cur_pos();
1576 let elems = self.parse_ts_bracketed_list(
1577 ParsingContext::TupleElementTypes,
1578 Self::parse_ts_tuple_element_type,
1579 true,
1580 false,
1581 )?;
1582
1583 let mut seen_optional_element = false;
1588
1589 for elem in elems.iter() {
1590 match *elem.ty {
1591 TsType::TsRestType(..) => {}
1592 TsType::TsOptionalType(..) => {
1593 seen_optional_element = true;
1594 }
1595 _ if seen_optional_element => {
1596 syntax_error!(self, self.span(start), SyntaxError::TsRequiredAfterOptional)
1597 }
1598 _ => {}
1599 }
1600 }
1601
1602 Ok(TsTupleType {
1603 span: self.span(start),
1604 elem_types: elems,
1605 })
1606 }
1607
1608 fn parse_ts_mapped_type(&mut self) -> PResult<TsMappedType> {
1610 debug_assert!(self.input().syntax().typescript());
1611
1612 let start = self.cur_pos();
1613 expect!(self, Token::LBrace);
1614 let mut readonly = None;
1615 let cur = self.input().cur();
1616 if cur == Token::Plus || cur == Token::Minus {
1617 readonly = Some(if cur == Token::Plus {
1618 TruePlusMinus::Plus
1619 } else {
1620 TruePlusMinus::Minus
1621 });
1622 self.bump();
1623 expect!(self, Token::Readonly)
1624 } else if self.input_mut().eat(Token::Readonly) {
1625 readonly = Some(TruePlusMinus::True);
1626 }
1627
1628 expect!(self, Token::LBracket);
1629 let type_param = self.parse_ts_mapped_type_param()?;
1630 let name_type = if self.input_mut().eat(Token::As) {
1631 Some(self.parse_ts_type()?)
1632 } else {
1633 None
1634 };
1635 expect!(self, Token::RBracket);
1636
1637 let mut optional = None;
1638 let cur = self.input().cur();
1639 if cur == Token::Plus || cur == Token::Minus {
1640 optional = Some(if cur == Token::Plus {
1641 TruePlusMinus::Plus
1642 } else {
1643 TruePlusMinus::Minus
1644 });
1645 self.bump(); expect!(self, Token::QuestionMark);
1647 } else if self.input_mut().eat(Token::QuestionMark) {
1648 optional = Some(TruePlusMinus::True);
1649 }
1650
1651 let type_ann = self.try_parse_ts_type()?;
1652 self.expect_general_semi()?;
1653 expect!(self, Token::RBrace);
1654
1655 Ok(TsMappedType {
1656 span: self.span(start),
1657 readonly,
1658 optional,
1659 type_param,
1660 name_type,
1661 type_ann,
1662 })
1663 }
1664
1665 fn parse_ts_parenthesized_type(&mut self) -> PResult<TsParenthesizedType> {
1667 debug_assert!(self.input().syntax().typescript());
1668 trace_cur!(self, parse_ts_parenthesized_type);
1669
1670 let start = self.cur_pos();
1671 expect!(self, Token::LParen);
1672 let type_ann = self.parse_ts_type()?;
1673 expect!(self, Token::RParen);
1674 Ok(TsParenthesizedType {
1675 span: self.span(start),
1676 type_ann,
1677 })
1678 }
1679
1680 pub(crate) fn parse_ts_type_alias_decl(
1682 &mut self,
1683 start: BytePos,
1684 ) -> PResult<Box<TsTypeAliasDecl>> {
1685 debug_assert!(self.input().syntax().typescript());
1686
1687 let id = self.parse_ident_name()?;
1688 let type_params = self.try_parse_ts_type_params(true, false)?;
1689 let type_ann = self.expect_then_parse_ts_type(Token::Eq, "=")?;
1690 self.expect_general_semi()?;
1691 Ok(Box::new(TsTypeAliasDecl {
1692 declare: false,
1693 span: self.span(start),
1694 id: id.into(),
1695 type_params,
1696 type_ann,
1697 }))
1698 }
1699
1700 fn parse_ts_fn_or_constructor_type(
1702 &mut self,
1703 is_fn_type: bool,
1704 ) -> PResult<TsFnOrConstructorType> {
1705 trace_cur!(self, parse_ts_fn_or_constructor_type);
1706
1707 debug_assert!(self.input().syntax().typescript());
1708
1709 let start = self.cur_pos();
1710 let is_abstract = if !is_fn_type {
1711 self.input_mut().eat(Token::Abstract)
1712 } else {
1713 false
1714 };
1715 if !is_fn_type {
1716 expect!(self, Token::New);
1717 }
1718
1719 let type_params = self.try_parse_ts_type_params(false, true)?;
1721 expect!(self, Token::LParen);
1722 let params = self.parse_ts_binding_list_for_signature()?;
1723 let type_ann = self.parse_ts_type_or_type_predicate_ann(Token::Arrow)?;
1724 Ok(if is_fn_type {
1727 TsFnOrConstructorType::TsFnType(TsFnType {
1728 span: self.span(start),
1729 type_params,
1730 params,
1731 type_ann,
1732 })
1733 } else {
1734 TsFnOrConstructorType::TsConstructorType(TsConstructorType {
1735 span: self.span(start),
1736 type_params,
1737 params,
1738 type_ann,
1739 is_abstract,
1740 })
1741 })
1742 }
1743
1744 fn parse_ts_union_type_or_higher(&mut self) -> PResult<Box<TsType>> {
1746 trace_cur!(self, parse_ts_union_type_or_higher);
1747 debug_assert!(self.input().syntax().typescript());
1748
1749 self.parse_ts_union_or_intersection_type(
1750 UnionOrIntersection::Union,
1751 Self::parse_ts_intersection_type_or_higher,
1752 Token::Pipe,
1753 )
1754 }
1755
1756 fn parse_ts_intersection_type_or_higher(&mut self) -> PResult<Box<TsType>> {
1758 trace_cur!(self, parse_ts_intersection_type_or_higher);
1759
1760 debug_assert!(self.input().syntax().typescript());
1761
1762 self.parse_ts_union_or_intersection_type(
1763 UnionOrIntersection::Intersection,
1764 Self::parse_ts_type_operator_or_higher,
1765 Token::Ampersand,
1766 )
1767 }
1768
1769 fn parse_ts_type_operator_or_higher(&mut self) -> PResult<Box<TsType>> {
1771 trace_cur!(self, parse_ts_type_operator_or_higher);
1772 debug_assert!(self.input().syntax().typescript());
1773
1774 let operator = if self.input().is(Token::Keyof) {
1775 Some(TsTypeOperatorOp::KeyOf)
1776 } else if self.input().is(Token::Unique) {
1777 Some(TsTypeOperatorOp::Unique)
1778 } else if self.input().is(Token::Readonly) {
1779 Some(TsTypeOperatorOp::ReadOnly)
1780 } else {
1781 None
1782 };
1783
1784 match operator {
1785 Some(operator) => self
1786 .parse_ts_type_operator(operator)
1787 .map(TsType::from)
1788 .map(Box::new),
1789 None => {
1790 trace_cur!(self, parse_ts_type_operator_or_higher__not_operator);
1791
1792 if self.input().is(Token::Infer) {
1793 self.parse_ts_infer_type().map(TsType::from).map(Box::new)
1794 } else {
1795 let readonly = self.parse_ts_modifier(&["readonly"], false)?.is_some();
1796 self.parse_ts_array_type_or_higher(readonly)
1797 }
1798 }
1799 }
1800 }
1801
1802 fn parse_ts_type_operator(&mut self, op: TsTypeOperatorOp) -> PResult<TsTypeOperator> {
1804 debug_assert!(self.input().syntax().typescript());
1805
1806 let start = self.cur_pos();
1807 match op {
1808 TsTypeOperatorOp::Unique => expect!(self, Token::Unique),
1809 TsTypeOperatorOp::KeyOf => expect!(self, Token::Keyof),
1810 TsTypeOperatorOp::ReadOnly => expect!(self, Token::Readonly),
1811 #[cfg(swc_ast_unknown)]
1812 _ => unreachable!(),
1813 }
1814
1815 let type_ann = self.parse_ts_type_operator_or_higher()?;
1816 Ok(TsTypeOperator {
1817 span: self.span(start),
1818 op,
1819 type_ann,
1820 })
1821 }
1822
1823 fn parse_ts_infer_type(&mut self) -> PResult<TsInferType> {
1825 debug_assert!(self.input().syntax().typescript());
1826
1827 let start = self.cur_pos();
1828 expect!(self, Token::Infer);
1829 let type_param_name = self.parse_ident_name()?;
1830 let constraint = self.try_parse_ts(|p| {
1831 expect!(p, Token::Extends);
1832 let constraint = p.parse_ts_non_conditional_type();
1833 if p.ctx().contains(Context::DisallowConditionalTypes)
1834 || !p.input().is(Token::QuestionMark)
1835 {
1836 constraint.map(Some)
1837 } else {
1838 Ok(None)
1839 }
1840 });
1841 let type_param = TsTypeParam {
1842 span: type_param_name.span(),
1843 name: type_param_name.into(),
1844 is_in: false,
1845 is_out: false,
1846 is_const: false,
1847 constraint,
1848 default: None,
1849 };
1850 Ok(TsInferType {
1851 span: self.span(start),
1852 type_param,
1853 })
1854 }
1855
1856 fn parse_ts_non_conditional_type(&mut self) -> PResult<Box<TsType>> {
1858 trace_cur!(self, parse_ts_non_conditional_type);
1859
1860 debug_assert!(self.input().syntax().typescript());
1861
1862 if self.is_ts_start_of_fn_type() {
1863 return self
1864 .parse_ts_fn_or_constructor_type(true)
1865 .map(TsType::from)
1866 .map(Box::new);
1867 }
1868 if (self.input().is(Token::Abstract) && peek!(self).is_some_and(|cur| cur == Token::New))
1869 || self.input().is(Token::New)
1870 {
1871 return self
1873 .parse_ts_fn_or_constructor_type(false)
1874 .map(TsType::from)
1875 .map(Box::new);
1876 }
1877
1878 self.parse_ts_union_type_or_higher()
1879 }
1880
1881 fn parse_ts_array_type_or_higher(&mut self, readonly: bool) -> PResult<Box<TsType>> {
1883 trace_cur!(self, parse_ts_array_type_or_higher);
1884 debug_assert!(self.input().syntax().typescript());
1885
1886 let mut ty = self.parse_ts_non_array_type()?;
1887
1888 while !self.input().had_line_break_before_cur() && self.input_mut().eat(Token::LBracket) {
1889 if self.input_mut().eat(Token::RBracket) {
1890 ty = Box::new(TsType::TsArrayType(TsArrayType {
1891 span: self.span(ty.span_lo()),
1892 elem_type: ty,
1893 }));
1894 } else {
1895 let index_type = self.parse_ts_type()?;
1896 expect!(self, Token::RBracket);
1897 ty = Box::new(TsType::TsIndexedAccessType(TsIndexedAccessType {
1898 span: self.span(ty.span_lo()),
1899 readonly,
1900 obj_type: ty,
1901 index_type,
1902 }))
1903 }
1904 }
1905
1906 Ok(ty)
1907 }
1908
1909 pub(crate) fn parse_ts_type(&mut self) -> PResult<Box<TsType>> {
1913 trace_cur!(self, parse_ts_type);
1914
1915 debug_assert!(self.input().syntax().typescript());
1916
1917 debug_assert!(self.ctx().contains(Context::InType));
1919
1920 let start = self.cur_pos();
1921
1922 self.do_outside_of_context(Context::DisallowConditionalTypes, |p| {
1923 let ty = p.parse_ts_non_conditional_type()?;
1924 if p.input().had_line_break_before_cur() || !p.input_mut().eat(Token::Extends) {
1925 return Ok(ty);
1926 }
1927
1928 let check_type = ty;
1929 let extends_type = p.do_inside_of_context(
1930 Context::DisallowConditionalTypes,
1931 Self::parse_ts_non_conditional_type,
1932 )?;
1933
1934 expect!(p, Token::QuestionMark);
1935
1936 let true_type = p.parse_ts_type()?;
1937
1938 expect!(p, Token::Colon);
1939
1940 let false_type = p.parse_ts_type()?;
1941
1942 Ok(Box::new(TsType::TsConditionalType(TsConditionalType {
1943 span: p.span(start),
1944 check_type,
1945 extends_type,
1946 true_type,
1947 false_type,
1948 })))
1949 })
1950 }
1951
1952 fn parse_ts_property_name(&mut self) -> PResult<(bool, Box<Expr>)> {
1956 let (computed, key) = if self.input_mut().eat(Token::LBracket) {
1957 let key = self.parse_assignment_expr()?;
1958 expect!(self, Token::RBracket);
1959 (true, key)
1960 } else {
1961 self.do_inside_of_context(Context::InPropertyName, |p| {
1962 let cur = p.input().cur();
1964
1965 let key = if cur == Token::Num || cur == Token::Str {
1966 p.parse_new_expr()
1967 } else if cur == Token::Error {
1968 let err = p.input_mut().expect_error_token_and_bump();
1969 return Err(err);
1970 } else {
1971 p.parse_maybe_private_name().map(|e| match e {
1972 Either::Left(e) => {
1973 p.emit_err(e.span(), SyntaxError::PrivateNameInInterface);
1974
1975 e.into()
1976 }
1977 Either::Right(e) => e.into(),
1978 })
1979 };
1980 key.map(|key| (false, key))
1981 })?
1982 };
1983
1984 Ok((computed, key))
1985 }
1986
1987 fn parse_ts_property_or_method_signature(
1989 &mut self,
1990 start: BytePos,
1991 readonly: bool,
1992 ) -> PResult<Either<TsPropertySignature, TsMethodSignature>> {
1993 debug_assert!(self.input().syntax().typescript());
1994
1995 let (computed, key) = self.parse_ts_property_name()?;
1996
1997 let optional = self.input_mut().eat(Token::QuestionMark);
1998
1999 let cur = self.input().cur();
2000 if matches!(cur, Token::LParen | Token::Lt) {
2001 if readonly {
2002 syntax_error!(self, SyntaxError::ReadOnlyMethod);
2003 }
2004
2005 let type_params = self.try_parse_ts_type_params(false, true)?;
2006 expect!(self, Token::LParen);
2007 let params = self.parse_ts_binding_list_for_signature()?;
2008 let type_ann = if self.input().is(Token::Colon) {
2009 self.parse_ts_type_or_type_predicate_ann(Token::Colon)
2010 .map(Some)?
2011 } else {
2012 None
2013 };
2014 self.parse_ts_type_member_semicolon()?;
2017 Ok(Either::Right(TsMethodSignature {
2018 span: self.span(start),
2019 computed,
2020 key,
2021 optional,
2022 type_params,
2023 params,
2024 type_ann,
2025 }))
2026 } else {
2027 let type_ann = self.try_parse_ts_type_ann()?;
2028
2029 self.parse_ts_type_member_semicolon()?;
2030 Ok(Either::Left(TsPropertySignature {
2031 span: self.span(start),
2032 computed,
2033 readonly,
2034 key,
2035 optional,
2036 type_ann,
2037 }))
2038 }
2039 }
2040
2041 fn parse_ts_type_member(&mut self) -> PResult<TsTypeElement> {
2043 debug_assert!(self.input().syntax().typescript());
2044
2045 fn into_type_elem(
2046 e: Either<TsCallSignatureDecl, TsConstructSignatureDecl>,
2047 ) -> TsTypeElement {
2048 match e {
2049 Either::Left(e) => e.into(),
2050 Either::Right(e) => e.into(),
2051 }
2052 }
2053 let cur = self.input().cur();
2054 if cur == Token::LParen || cur == Token::Lt {
2055 return self
2056 .parse_ts_signature_member(SignatureParsingMode::TSCallSignatureDeclaration)
2057 .map(into_type_elem);
2058 }
2059 if self.input().is(Token::New)
2060 && self.ts_look_ahead(Self::is_ts_start_of_construct_signature)
2061 {
2062 return self
2063 .parse_ts_signature_member(SignatureParsingMode::TSConstructSignatureDeclaration)
2064 .map(into_type_elem);
2065 }
2066 let start = self.cur_pos();
2068 let readonly = self.parse_ts_modifier(&["readonly"], false)?.is_some();
2069
2070 let idx = self.try_parse_ts_index_signature(start, readonly, false)?;
2071 if let Some(idx) = idx {
2072 return Ok(idx.into());
2073 }
2074
2075 if let Some(v) = self.try_parse_ts(|p| {
2076 let start = p.input().cur_pos();
2077
2078 if readonly {
2079 syntax_error!(p, SyntaxError::GetterSetterCannotBeReadonly)
2080 }
2081
2082 let is_get = if p.input_mut().eat(Token::Get) {
2083 true
2084 } else {
2085 expect!(p, Token::Set);
2086 false
2087 };
2088
2089 let (computed, key) = p.parse_ts_property_name()?;
2090
2091 if is_get {
2092 expect!(p, Token::LParen);
2093 expect!(p, Token::RParen);
2094 let type_ann = p.try_parse_ts_type_ann()?;
2095
2096 p.parse_ts_type_member_semicolon()?;
2097
2098 Ok(Some(TsTypeElement::TsGetterSignature(TsGetterSignature {
2099 span: p.span(start),
2100 key,
2101 computed,
2102 type_ann,
2103 })))
2104 } else {
2105 expect!(p, Token::LParen);
2106 let params = p.parse_ts_binding_list_for_signature()?;
2107 if params.is_empty() {
2108 syntax_error!(p, SyntaxError::SetterParamRequired)
2109 }
2110 let param = params.into_iter().next().unwrap();
2111
2112 p.parse_ts_type_member_semicolon()?;
2113
2114 Ok(Some(TsTypeElement::TsSetterSignature(TsSetterSignature {
2115 span: p.span(start),
2116 key,
2117 computed,
2118 param,
2119 })))
2120 }
2121 }) {
2122 return Ok(v);
2123 }
2124
2125 self.parse_ts_property_or_method_signature(start, readonly)
2126 .map(|e| match e {
2127 Either::Left(e) => e.into(),
2128 Either::Right(e) => e.into(),
2129 })
2130 }
2131
2132 fn parse_ts_object_type_members(&mut self) -> PResult<Vec<TsTypeElement>> {
2134 debug_assert!(self.input().syntax().typescript());
2135
2136 expect!(self, Token::LBrace);
2137 let members =
2138 self.parse_ts_list(ParsingContext::TypeMembers, |p| p.parse_ts_type_member())?;
2139 expect!(self, Token::RBrace);
2140 Ok(members)
2141 }
2142
2143 fn parse_ts_type_lit(&mut self) -> PResult<TsTypeLit> {
2145 debug_assert!(self.input().syntax().typescript());
2146
2147 let start = self.cur_pos();
2148 let members = self.parse_ts_object_type_members()?;
2149 Ok(TsTypeLit {
2150 span: self.span(start),
2151 members,
2152 })
2153 }
2154
2155 pub(crate) fn parse_ts_interface_decl(
2157 &mut self,
2158 start: BytePos,
2159 ) -> PResult<Box<TsInterfaceDecl>> {
2160 debug_assert!(self.input().syntax().typescript());
2161
2162 let id = self.parse_ident_name()?;
2163 match &*id.sym {
2164 "string" | "null" | "number" | "object" | "any" | "unknown" | "boolean" | "bigint"
2165 | "symbol" | "void" | "never" | "intrinsic" => {
2166 self.emit_err(id.span, SyntaxError::TS2427);
2167 }
2168 _ => {}
2169 }
2170
2171 let type_params = self.try_parse_ts_type_params(true, false)?;
2172
2173 let extends = if self.input_mut().eat(Token::Extends) {
2174 self.parse_ts_heritage_clause()?
2175 } else {
2176 Vec::new()
2177 };
2178
2179 if self.input().is(Token::Extends) {
2183 self.emit_err(self.input().cur_span(), SyntaxError::TS1172);
2184
2185 while self.input().cur() != Token::Eof && !self.input().is(Token::LBrace) {
2186 self.bump();
2187 }
2188 }
2189
2190 let body_start = self.cur_pos();
2191 let body = self.in_type(Self::parse_ts_object_type_members)?;
2192 let body = TsInterfaceBody {
2193 span: self.span(body_start),
2194 body,
2195 };
2196 Ok(Box::new(TsInterfaceDecl {
2197 span: self.span(start),
2198 declare: false,
2199 id: id.into(),
2200 type_params,
2201 extends,
2202 body,
2203 }))
2204 }
2205
2206 pub(crate) fn parse_ts_type_assertion(&mut self, start: BytePos) -> PResult<TsTypeAssertion> {
2208 debug_assert!(self.input().syntax().typescript());
2209
2210 if self.input().syntax().disallow_ambiguous_jsx_like() {
2211 self.emit_err(self.span(start), SyntaxError::ReservedTypeAssertion);
2212 }
2213
2214 let type_ann = self.in_type(Self::parse_ts_type)?;
2218 expect!(self, Token::Gt);
2219 let expr = self.parse_unary_expr()?;
2220 Ok(TsTypeAssertion {
2221 span: self.span(start),
2222 type_ann,
2223 expr,
2224 })
2225 }
2226
2227 fn parse_ts_import_type(&mut self) -> PResult<TsImportType> {
2229 let start = self.cur_pos();
2230 self.assert_and_bump(Token::Import);
2231
2232 expect!(self, Token::LParen);
2233
2234 let cur = self.input().cur();
2235
2236 let arg = if cur == Token::Str {
2237 self.parse_str_lit()
2238 } else if cur == Token::Error {
2239 let err = self.input_mut().expect_error_token_and_bump();
2240 return Err(err);
2241 } else {
2242 let arg_span = self.input().cur_span();
2243 self.bump();
2244 self.emit_err(arg_span, SyntaxError::TS1141);
2245 Str {
2246 span: arg_span,
2247 value: Wtf8Atom::default(),
2248 raw: Some(atom!("\"\"")),
2249 }
2250 };
2251
2252 let attributes = if self.input_mut().eat(Token::Comma)
2255 && self.input().syntax().import_attributes()
2256 && self.input().is(Token::LBrace)
2257 {
2258 Some(self.parse_ts_call_options()?)
2259 } else {
2260 None
2261 };
2262
2263 expect!(self, Token::RParen);
2264
2265 let qualifier = if self.input_mut().eat(Token::Dot) {
2266 self.parse_ts_entity_name(false).map(Some)?
2267 } else {
2268 None
2269 };
2270
2271 let type_args = if self.input().is(Token::Lt) {
2272 let ret = self.do_outside_of_context(
2273 Context::ShouldNotLexLtOrGtAsType,
2274 Self::parse_ts_type_args,
2275 )?;
2276 self.assert_and_bump(Token::Gt);
2277 Some(ret)
2278 } else {
2279 None
2280 };
2281
2282 Ok(TsImportType {
2283 span: self.span(start),
2284 arg,
2285 qualifier,
2286 type_args,
2287 attributes,
2288 })
2289 }
2290
2291 fn parse_ts_call_options(&mut self) -> PResult<TsImportCallOptions> {
2292 debug_assert!(self.input().syntax().typescript());
2293 let start = self.cur_pos();
2294 self.assert_and_bump(Token::LBrace);
2295
2296 expect!(self, Token::With);
2297 expect!(self, Token::Colon);
2298
2299 let value = match self.parse_object_expr()? {
2300 Expr::Object(v) => v,
2301 _ => unreachable!(),
2302 };
2303 self.input_mut().eat(Token::Comma);
2304 expect!(self, Token::RBrace);
2305 Ok(TsImportCallOptions {
2306 span: self.span(start),
2307 with: Box::new(value),
2308 })
2309 }
2310
2311 fn parse_ts_type_query(&mut self) -> PResult<TsTypeQuery> {
2313 debug_assert!(self.input().syntax().typescript());
2314
2315 let start = self.cur_pos();
2316 expect!(self, Token::TypeOf);
2317 let expr_name = if self.input().is(Token::Import) {
2318 self.parse_ts_import_type().map(From::from)?
2319 } else {
2320 self.parse_ts_entity_name(true).map(From::from)?
2321 };
2322
2323 let type_args = if !self.input().had_line_break_before_cur() && self.input().is(Token::Lt) {
2324 let ret = self.do_outside_of_context(
2325 Context::ShouldNotLexLtOrGtAsType,
2326 Self::parse_ts_type_args,
2327 )?;
2328 self.assert_and_bump(Token::Gt);
2329 Some(ret)
2330 } else {
2331 None
2332 };
2333
2334 Ok(TsTypeQuery {
2335 span: self.span(start),
2336 expr_name,
2337 type_args,
2338 })
2339 }
2340
2341 fn parse_ts_module_block(&mut self) -> PResult<TsModuleBlock> {
2343 trace_cur!(self, parse_ts_module_block);
2344
2345 debug_assert!(self.input().syntax().typescript());
2346
2347 let start = self.cur_pos();
2348 expect!(self, Token::LBrace);
2349 let body = self.do_inside_of_context(Context::TsModuleBlock, |p| {
2350 p.do_outside_of_context(Context::TopLevel, |p| {
2351 p.parse_module_item_block_body(false, Some(Token::RBrace))
2352 })
2353 })?;
2354
2355 Ok(TsModuleBlock {
2356 span: self.span(start),
2357 body,
2358 })
2359 }
2360
2361 fn parse_ts_module_or_ns_decl(
2363 &mut self,
2364 start: BytePos,
2365 namespace: bool,
2366 ) -> PResult<Box<TsModuleDecl>> {
2367 debug_assert!(self.input().syntax().typescript());
2368
2369 let id = self.parse_ident_name()?;
2370 let body: TsNamespaceBody = if self.input_mut().eat(Token::Dot) {
2371 let inner_start = self.cur_pos();
2372 let inner = self.parse_ts_module_or_ns_decl(inner_start, namespace)?;
2373 let inner = TsNamespaceDecl {
2374 span: inner.span,
2375 id: match inner.id {
2376 TsModuleName::Ident(i) => i,
2377 _ => unreachable!(),
2378 },
2379 body: Box::new(inner.body.unwrap()),
2380 declare: inner.declare,
2381 global: inner.global,
2382 };
2383 inner.into()
2384 } else {
2385 self.parse_ts_module_block().map(From::from)?
2386 };
2387
2388 Ok(Box::new(TsModuleDecl {
2389 span: self.span(start),
2390 declare: false,
2391 id: TsModuleName::Ident(id.into()),
2392 body: Some(body),
2393 global: false,
2394 namespace,
2395 }))
2396 }
2397
2398 fn parse_ts_ambient_external_module_decl(
2400 &mut self,
2401 start: BytePos,
2402 ) -> PResult<Box<TsModuleDecl>> {
2403 debug_assert!(self.input().syntax().typescript());
2404
2405 let (global, id) = if self.input().is(Token::Global) {
2406 let id = self.parse_ident_name()?;
2407 (true, TsModuleName::Ident(id.into()))
2408 } else if self.input().cur() == Token::Str {
2409 let id = TsModuleName::Str(self.parse_str_lit());
2410 (false, id)
2411 } else {
2412 unexpected!(self, "global or a string literal");
2413 };
2414
2415 let body = if self.input().is(Token::LBrace) {
2416 Some(self.parse_ts_module_block().map(TsNamespaceBody::from)?)
2417 } else {
2418 self.expect_general_semi()?;
2419 None
2420 };
2421
2422 Ok(Box::new(TsModuleDecl {
2423 span: self.span(start),
2424 declare: false,
2425 id,
2426 global,
2427 body,
2428 namespace: false,
2429 }))
2430 }
2431
2432 fn parse_ts_non_array_type(&mut self) -> PResult<Box<TsType>> {
2434 if !cfg!(feature = "typescript") {
2435 unreachable!()
2436 }
2437 trace_cur!(self, parse_ts_non_array_type);
2438 debug_assert!(self.input().syntax().typescript());
2439
2440 let start = self.cur_pos();
2441
2442 let cur = self.input().cur();
2443 if cur.is_known_ident()
2444 || matches!(
2445 cur,
2446 Token::Ident
2447 | Token::Void
2448 | Token::Yield
2449 | Token::Null
2450 | Token::Await
2451 | Token::Break
2452 )
2453 {
2454 if self.input().is(Token::Asserts)
2455 && peek!(self).is_some_and(|peek| peek == Token::This)
2456 {
2457 self.bump();
2458 let this_keyword = self.parse_ts_this_type_node()?;
2459 return self
2460 .parse_ts_this_type_predicate(start, true, this_keyword)
2461 .map(TsType::from)
2462 .map(Box::new);
2463 }
2464 let kind = if self.input().is(Token::Void) {
2465 Some(TsKeywordTypeKind::TsVoidKeyword)
2466 } else if self.input().is(Token::Null) {
2467 Some(TsKeywordTypeKind::TsNullKeyword)
2468 } else if self.input().is(Token::Any) {
2469 Some(TsKeywordTypeKind::TsAnyKeyword)
2470 } else if self.input().is(Token::Boolean) {
2471 Some(TsKeywordTypeKind::TsBooleanKeyword)
2472 } else if self.input().is(Token::Bigint) {
2473 Some(TsKeywordTypeKind::TsBigIntKeyword)
2474 } else if self.input().is(Token::Never) {
2475 Some(TsKeywordTypeKind::TsNeverKeyword)
2476 } else if self.input().is(Token::Number) {
2477 Some(TsKeywordTypeKind::TsNumberKeyword)
2478 } else if self.input().is(Token::Object) {
2479 Some(TsKeywordTypeKind::TsObjectKeyword)
2480 } else if self.input().is(Token::String) {
2481 Some(TsKeywordTypeKind::TsStringKeyword)
2482 } else if self.input().is(Token::Symbol) {
2483 Some(TsKeywordTypeKind::TsSymbolKeyword)
2484 } else if self.input().is(Token::Unknown) {
2485 Some(TsKeywordTypeKind::TsUnknownKeyword)
2486 } else if self.input().is(Token::Undefined) {
2487 Some(TsKeywordTypeKind::TsUndefinedKeyword)
2488 } else if self.input().is(Token::Intrinsic) {
2489 Some(TsKeywordTypeKind::TsIntrinsicKeyword)
2490 } else {
2491 None
2492 };
2493
2494 let peeked_is_dot = peek!(self).is_some_and(|cur| cur == Token::Dot);
2495
2496 match kind {
2497 Some(kind) if !peeked_is_dot => {
2498 self.bump();
2499 return Ok(Box::new(TsType::TsKeywordType(TsKeywordType {
2500 span: self.span(start),
2501 kind,
2502 })));
2503 }
2504 _ => {
2505 return self.parse_ts_type_ref().map(TsType::from).map(Box::new);
2506 }
2507 }
2508 } else if matches!(
2509 cur,
2510 Token::BigInt | Token::Str | Token::Num | Token::True | Token::False | Token::BackQuote
2511 ) {
2512 return self
2513 .parse_ts_lit_type_node()
2514 .map(TsType::from)
2515 .map(Box::new);
2516 } else if cur == Token::NoSubstitutionTemplateLiteral || cur == Token::TemplateHead {
2517 return self.parse_tagged_tpl_ty().map(TsType::from).map(Box::new);
2518 } else if cur == Token::Minus {
2519 let start = self.cur_pos();
2520
2521 self.bump();
2522
2523 let cur = self.input().cur();
2524 if !(cur == Token::Num || cur == Token::BigInt) {
2525 unexpected!(self, "numeric literal or bigint literal")
2526 }
2527
2528 let lit = self.parse_lit()?;
2529 let lit = match lit {
2530 Lit::Num(Number { span, value, raw }) => {
2531 let mut new_raw = String::from("-");
2532
2533 match raw {
2534 Some(raw) => {
2535 new_raw.push_str(&raw);
2536 }
2537 _ => {
2538 write!(new_raw, "{value}").unwrap();
2539 }
2540 };
2541
2542 TsLit::Number(Number {
2543 span,
2544 value: -value,
2545 raw: Some(new_raw.into()),
2546 })
2547 }
2548 Lit::BigInt(BigInt { span, value, raw }) => {
2549 let mut new_raw = String::from("-");
2550
2551 match raw {
2552 Some(raw) => {
2553 new_raw.push_str(&raw);
2554 }
2555 _ => {
2556 write!(new_raw, "{value}").unwrap();
2557 }
2558 };
2559
2560 TsLit::BigInt(BigInt {
2561 span,
2562 value: Box::new(-*value),
2563 raw: Some(new_raw.into()),
2564 })
2565 }
2566 _ => unreachable!(),
2567 };
2568
2569 return Ok(Box::new(TsType::TsLitType(TsLitType {
2570 span: self.span(start),
2571 lit,
2572 })));
2573 } else if cur == Token::Import {
2574 return self.parse_ts_import_type().map(TsType::from).map(Box::new);
2575 } else if cur == Token::This {
2576 let start = self.cur_pos();
2577 let this_keyword = self.parse_ts_this_type_node()?;
2578 return if !self.input().had_line_break_before_cur() && self.input().is(Token::Is) {
2579 self.parse_ts_this_type_predicate(start, false, this_keyword)
2580 .map(TsType::from)
2581 .map(Box::new)
2582 } else {
2583 Ok(Box::new(TsType::TsThisType(this_keyword)))
2584 };
2585 } else if cur == Token::TypeOf {
2586 return self.parse_ts_type_query().map(TsType::from).map(Box::new);
2587 } else if cur == Token::LBrace {
2588 return if self.ts_look_ahead(Self::is_ts_start_of_mapped_type) {
2589 self.parse_ts_mapped_type().map(TsType::from).map(Box::new)
2590 } else {
2591 self.parse_ts_type_lit().map(TsType::from).map(Box::new)
2592 };
2593 } else if cur == Token::LBracket {
2594 return self.parse_ts_tuple_type().map(TsType::from).map(Box::new);
2595 } else if cur == Token::LParen {
2596 return self
2597 .parse_ts_parenthesized_type()
2598 .map(TsType::from)
2599 .map(Box::new);
2600 }
2601
2602 unexpected!(
2606 self,
2607 "an identifier, void, yield, null, await, break, a string literal, a numeric literal, \
2608 true, false, `, -, import, this, typeof, {, [, ("
2609 )
2610 }
2611
2612 pub(crate) fn parse_ts_expr_stmt(
2614 &mut self,
2615 decorators: Vec<Decorator>,
2616 expr: Ident,
2617 ) -> PResult<Option<Decl>> {
2618 if !cfg!(feature = "typescript") {
2619 return Ok(Default::default());
2620 }
2621
2622 let start = expr.span_lo();
2623
2624 match &*expr.sym {
2625 "declare" => {
2626 let decl = self.try_parse_ts_declare(start, decorators)?;
2627 if let Some(decl) = decl {
2628 Ok(Some(make_decl_declare(decl)))
2629 } else {
2630 Ok(None)
2631 }
2632 }
2633 "global" => {
2634 if self.input().is(Token::LBrace) {
2639 let global = true;
2640 let id = TsModuleName::Ident(expr);
2641 let body = self
2642 .parse_ts_module_block()
2643 .map(TsNamespaceBody::from)
2644 .map(Some)?;
2645 Ok(Some(
2646 TsModuleDecl {
2647 span: self.span(start),
2648 global,
2649 declare: false,
2650 namespace: false,
2651 id,
2652 body,
2653 }
2654 .into(),
2655 ))
2656 } else {
2657 Ok(None)
2658 }
2659 }
2660 _ => self.parse_ts_decl(start, decorators, expr.sym, false),
2661 }
2662 }
2663
2664 pub(crate) fn try_parse_ts_declare(
2666 &mut self,
2667 start: BytePos,
2668 decorators: Vec<Decorator>,
2669 ) -> PResult<Option<Decl>> {
2670 if !self.syntax().typescript() {
2671 return Ok(None);
2672 }
2673
2674 if self
2675 .ctx()
2676 .contains(Context::InDeclare | Context::TsModuleBlock)
2677 {
2678 let span_of_declare = self.span(start);
2679 self.emit_err(span_of_declare, SyntaxError::TS1038);
2680 }
2681
2682 let declare_start = start;
2683 self.do_inside_of_context(Context::InDeclare, |p| {
2684 if p.input().is(Token::Function) {
2685 return p
2686 .parse_fn_decl(decorators)
2687 .map(|decl| match decl {
2688 Decl::Fn(f) => FnDecl {
2689 declare: true,
2690 function: Box::new(Function {
2691 span: Span {
2692 lo: declare_start,
2693 ..f.function.span
2694 },
2695 ..*f.function
2696 }),
2697 ..f
2698 }
2699 .into(),
2700 _ => decl,
2701 })
2702 .map(Some);
2703 }
2704
2705 if p.input().is(Token::Class) {
2706 return p
2707 .parse_class_decl(start, start, decorators, false)
2708 .map(|decl| match decl {
2709 Decl::Class(c) => ClassDecl {
2710 declare: true,
2711 class: Box::new(Class {
2712 span: Span {
2713 lo: declare_start,
2714 ..c.class.span
2715 },
2716 ..*c.class
2717 }),
2718 ..c
2719 }
2720 .into(),
2721 _ => decl,
2722 })
2723 .map(Some);
2724 }
2725
2726 if p.input().is(Token::Const) && peek!(p).is_some_and(|peek| peek == Token::Enum) {
2727 p.assert_and_bump(Token::Const);
2728 p.assert_and_bump(Token::Enum);
2729
2730 return p
2731 .parse_ts_enum_decl(start, true)
2732 .map(|decl| TsEnumDecl {
2733 declare: true,
2734 span: Span {
2735 lo: declare_start,
2736 ..decl.span
2737 },
2738 ..*decl
2739 })
2740 .map(Box::new)
2741 .map(From::from)
2742 .map(Some);
2743 }
2744
2745 let cur = p.input().cur();
2746 if matches!(cur, Token::Const | Token::Var | Token::Let) {
2747 return p
2748 .parse_var_stmt(false)
2749 .map(|decl| VarDecl {
2750 declare: true,
2751 span: Span {
2752 lo: declare_start,
2753 ..decl.span
2754 },
2755 ..*decl
2756 })
2757 .map(Box::new)
2758 .map(From::from)
2759 .map(Some);
2760 }
2761
2762 if p.input().is(Token::Global) {
2763 return p
2764 .parse_ts_ambient_external_module_decl(start)
2765 .map(Decl::from)
2766 .map(make_decl_declare)
2767 .map(Some);
2768 } else if p.input().cur().is_word() {
2769 let value = p.input_mut().cur().take_word(p.input_mut()).unwrap();
2770 return p
2771 .parse_ts_decl(start, decorators, value, true)
2772 .map(|v| v.map(make_decl_declare));
2773 }
2774
2775 Ok(None)
2776 })
2777 }
2778
2779 pub(crate) fn try_parse_ts_export_decl(
2784 &mut self,
2785 decorators: Vec<Decorator>,
2786 value: Atom,
2787 ) -> Option<Decl> {
2788 if !cfg!(feature = "typescript") {
2789 return None;
2790 }
2791
2792 self.try_parse_ts(|p| {
2793 let start = p.cur_pos();
2794 let opt = p.parse_ts_decl(start, decorators, value, true)?;
2795 Ok(opt)
2796 })
2797 }
2798
2799 fn parse_ts_decl(
2804 &mut self,
2805 start: BytePos,
2806 decorators: Vec<Decorator>,
2807 value: Atom,
2808 next: bool,
2809 ) -> PResult<Option<Decl>> {
2810 if !cfg!(feature = "typescript") {
2811 return Ok(Default::default());
2812 }
2813
2814 match &*value {
2815 "abstract" => {
2816 if next
2817 || (self.input().is(Token::Class) && !self.input().had_line_break_before_cur())
2818 {
2819 if next {
2820 self.bump();
2821 }
2822 return Ok(Some(self.parse_class_decl(start, start, decorators, true)?));
2823 }
2824 }
2825
2826 "enum" => {
2827 if next || self.is_ident_ref() {
2828 if next {
2829 self.bump();
2830 }
2831 return self
2832 .parse_ts_enum_decl(start, false)
2833 .map(From::from)
2834 .map(Some);
2835 }
2836 }
2837
2838 "interface" => {
2839 if next || (self.is_ident_ref()) {
2840 if next {
2841 self.bump();
2842 }
2843
2844 return self
2845 .parse_ts_interface_decl(start)
2846 .map(From::from)
2847 .map(Some);
2848 }
2849 }
2850
2851 "module" if !self.input().had_line_break_before_cur() => {
2852 if next {
2853 self.bump();
2854 }
2855
2856 let cur = self.input().cur();
2857 if cur == Token::Str {
2858 return self
2859 .parse_ts_ambient_external_module_decl(start)
2860 .map(From::from)
2861 .map(Some);
2862 } else if cur == Token::Error {
2863 let err = self.input_mut().expect_error_token_and_bump();
2864 return Err(err);
2865 } else if cur == Token::Eof {
2866 return Err(self.eof_error());
2867 } else if next || self.is_ident_ref() {
2868 return self
2869 .parse_ts_module_or_ns_decl(start, false)
2870 .map(From::from)
2871 .map(Some);
2872 }
2873 }
2874
2875 "namespace" => {
2876 if next || self.is_ident_ref() {
2877 if next {
2878 self.bump();
2879 }
2880 return self
2881 .parse_ts_module_or_ns_decl(start, true)
2882 .map(From::from)
2883 .map(Some);
2884 }
2885 }
2886
2887 "type" => {
2888 if next || (!self.input().had_line_break_before_cur() && self.is_ident_ref()) {
2889 if next {
2890 self.bump();
2891 }
2892 return self
2893 .parse_ts_type_alias_decl(start)
2894 .map(From::from)
2895 .map(Some);
2896 }
2897 }
2898
2899 _ => {}
2900 }
2901
2902 Ok(None)
2903 }
2904
2905 pub(crate) fn try_parse_ts_generic_async_arrow_fn(
2907 &mut self,
2908 start: BytePos,
2909 ) -> PResult<Option<ArrowExpr>> {
2910 if !cfg!(feature = "typescript") {
2911 return Ok(Default::default());
2912 }
2913
2914 let cur = self.input().cur();
2915 let res = if cur == Token::Lt || cur == Token::JSXTagStart {
2916 self.try_parse_ts(|p| {
2917 let type_params = p.parse_ts_type_params(false, false)?;
2918 expect!(p, Token::LParen);
2920 let params: Vec<Pat> = p
2921 .parse_formal_params()?
2922 .into_iter()
2923 .map(|p| p.pat)
2924 .collect();
2925 expect!(p, Token::RParen);
2926 let return_type = p.try_parse_ts_type_or_type_predicate_ann()?;
2927 expect!(p, Token::Arrow);
2928
2929 Ok(Some((type_params, params, return_type)))
2930 })
2931 } else {
2932 None
2933 };
2934
2935 let (type_params, params, return_type) = match res {
2936 Some(v) => v,
2937 None => return Ok(None),
2938 };
2939
2940 self.do_inside_of_context(Context::InAsync, |p| {
2941 p.do_outside_of_context(Context::InGenerator, |p| {
2942 let is_generator = false;
2943 let is_async = true;
2944 let body = p.parse_fn_block_or_expr_body(
2945 true,
2946 false,
2947 true,
2948 params.is_simple_parameter_list(),
2949 )?;
2950 Ok(Some(ArrowExpr {
2951 span: p.span(start),
2952 body,
2953 is_async,
2954 is_generator,
2955 type_params: Some(type_params),
2956 params,
2957 return_type,
2958 ..Default::default()
2959 }))
2960 })
2961 })
2962 }
2963}
2964
2965#[cfg(test)]
2966mod tests {
2967 use swc_atoms::atom;
2968 use swc_common::DUMMY_SP;
2969 use swc_ecma_ast::*;
2970 use swc_ecma_visit::assert_eq_ignore_span;
2971
2972 use crate::{test_parser, Syntax};
2973
2974 #[test]
2975 fn issue_708_1() {
2976 let actual = test_parser(
2977 "type test = -1;",
2978 Syntax::Typescript(Default::default()),
2979 |p| p.parse_module(),
2980 );
2981
2982 let expected = Module {
2983 span: DUMMY_SP,
2984 shebang: None,
2985 body: {
2986 let first = TsTypeAliasDecl {
2987 span: DUMMY_SP,
2988 declare: false,
2989 id: Ident::new_no_ctxt(atom!("test"), DUMMY_SP),
2990 type_params: None,
2991 type_ann: Box::new(TsType::TsLitType(TsLitType {
2992 span: DUMMY_SP,
2993 lit: TsLit::Number(Number {
2994 span: DUMMY_SP,
2995 value: -1.0,
2996 raw: Some(atom!("-1")),
2997 }),
2998 })),
2999 }
3000 .into();
3001 vec![first]
3002 },
3003 };
3004
3005 assert_eq_ignore_span!(actual, expected);
3006 }
3007
3008 #[test]
3009 fn issue_708_2() {
3010 let actual = test_parser(
3011 "const t = -1;",
3012 Syntax::Typescript(Default::default()),
3013 |p| p.parse_module(),
3014 );
3015
3016 let expected = Module {
3017 span: DUMMY_SP,
3018 shebang: None,
3019 body: {
3020 let second = VarDecl {
3021 span: DUMMY_SP,
3022 kind: VarDeclKind::Const,
3023 declare: false,
3024 decls: vec![VarDeclarator {
3025 span: DUMMY_SP,
3026 name: Pat::Ident(Ident::new_no_ctxt(atom!("t"), DUMMY_SP).into()),
3027 init: Some(Box::new(Expr::Unary(UnaryExpr {
3028 span: DUMMY_SP,
3029 op: op!(unary, "-"),
3030 arg: Box::new(Expr::Lit(Lit::Num(Number {
3031 span: DUMMY_SP,
3032 value: 1.0,
3033 raw: Some(atom!("1")),
3034 }))),
3035 }))),
3036 definite: false,
3037 }],
3038 ..Default::default()
3039 }
3040 .into();
3041 vec![second]
3042 },
3043 };
3044
3045 assert_eq_ignore_span!(actual, expected);
3046 }
3047}