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