1use std::fmt::Write;
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();
952 let id = if cur.is_str() {
953 TsEnumMemberId::Str(parse_str_lit(p))
954 } else if cur.is_num() {
955 let (value, raw) = p.input_mut().expect_number_token_and_bump();
956 let mut new_raw = String::new();
957
958 new_raw.push('"');
959 new_raw.push_str(raw.as_str());
960 new_raw.push('"');
961
962 let span = p.span(start);
963
964 p.emit_err(span, SyntaxError::TS2452);
966
967 TsEnumMemberId::Str(Str {
968 span,
969 value: value.to_string().into(),
970 raw: Some(new_raw.into()),
971 })
972 } else if cur.is_lbracket() {
973 p.assert_and_bump(&P::Token::LBRACKET);
974 let _ = p.parse_expr()?;
975 p.emit_err(p.span(start), SyntaxError::TS1164);
976 p.assert_and_bump(&P::Token::RBRACKET);
977 TsEnumMemberId::Ident(Ident::new_no_ctxt(atom!(""), p.span(start)))
978 } else if cur.is_error() {
979 let err = p.input_mut().expect_error_token_and_bump();
980 return Err(err);
981 } else {
982 parse_ident_name(p)
983 .map(Ident::from)
984 .map(TsEnumMemberId::from)?
985 };
986
987 let init = if p.input_mut().eat(&P::Token::EQUAL) {
988 Some(parse_assignment_expr(p)?)
989 } else if p.input().cur().is_comma() || p.input().cur().is_rbrace() {
990 None
991 } else {
992 let start = p.cur_pos();
993 p.bump();
994 p.input_mut().store(P::Token::COMMA);
995 p.emit_err(Span::new_with_checked(start, start), SyntaxError::TS1005);
996 None
997 };
998
999 Ok(TsEnumMember {
1000 span: p.span(start),
1001 id,
1002 init,
1003 })
1004}
1005
1006pub fn parse_ts_enum_decl<'a, P: Parser<'a>>(
1008 p: &mut P,
1009 start: BytePos,
1010 is_const: bool,
1011) -> PResult<Box<TsEnumDecl>> {
1012 debug_assert!(p.input().syntax().typescript());
1013
1014 let id = parse_ident_name(p)?;
1015 expect!(p, &P::Token::LBRACE);
1016 let members = parse_ts_delimited_list(p, ParsingContext::EnumMembers, parse_ts_enum_member)?;
1017 expect!(p, &P::Token::RBRACE);
1018
1019 Ok(Box::new(TsEnumDecl {
1020 span: p.span(start),
1021 declare: false,
1022 is_const,
1023 id: id.into(),
1024 members,
1025 }))
1026}
1027
1028pub fn try_parse_ts_type_or_type_predicate_ann<'a, P: Parser<'a>>(
1032 p: &mut P,
1033) -> PResult<Option<Box<TsTypeAnn>>> {
1034 if !cfg!(feature = "typescript") {
1035 return Ok(None);
1036 }
1037
1038 if p.input().is(&P::Token::COLON) {
1039 parse_ts_type_or_type_predicate_ann(p, &P::Token::COLON).map(Some)
1040 } else {
1041 Ok(None)
1042 }
1043}
1044
1045fn parse_ts_tpl_lit_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTplLitType> {
1047 debug_assert!(p.input().syntax().typescript());
1048
1049 let start = p.cur_pos();
1050
1051 p.assert_and_bump(&P::Token::BACKQUOTE);
1052
1053 let (types, quasis) = parse_ts_tpl_type_elements(p)?;
1054
1055 expect!(p, &P::Token::BACKQUOTE);
1056
1057 Ok(TsTplLitType {
1058 span: p.span(start),
1059 types,
1060 quasis,
1061 })
1062}
1063
1064fn parse_ts_tpl_type_elements<'a, P: Parser<'a>>(
1065 p: &mut P,
1066) -> PResult<(Vec<Box<TsType>>, Vec<TplElement>)> {
1067 if !cfg!(feature = "typescript") {
1068 return Ok(Default::default());
1069 }
1070
1071 trace_cur!(p, parse_tpl_elements);
1072
1073 let mut types = Vec::new();
1074
1075 let cur_elem = p.parse_tpl_element(false)?;
1076 let mut is_tail = cur_elem.tail;
1077 let mut quasis = vec![cur_elem];
1078
1079 while !is_tail {
1080 expect!(p, &P::Token::DOLLAR_LBRACE);
1081 types.push(parse_ts_type(p)?);
1082 expect!(p, &P::Token::RBRACE);
1083 let elem = p.parse_tpl_element(false)?;
1084 is_tail = elem.tail;
1085 quasis.push(elem);
1086 }
1087
1088 Ok((types, quasis))
1089}
1090
1091fn parse_ts_lit_type_node<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsLitType> {
1093 debug_assert!(p.input().syntax().typescript());
1094
1095 let start = p.cur_pos();
1096
1097 let lit = if p.input().is(&P::Token::BACKQUOTE) {
1098 let tpl = parse_ts_tpl_lit_type(p)?;
1099 TsLit::Tpl(tpl)
1100 } else {
1101 match parse_lit(p)? {
1102 Lit::BigInt(n) => TsLit::BigInt(n),
1103 Lit::Bool(n) => TsLit::Bool(n),
1104 Lit::Num(n) => TsLit::Number(n),
1105 Lit::Str(n) => TsLit::Str(n),
1106 _ => unreachable!(),
1107 }
1108 };
1109
1110 Ok(TsLitType {
1111 span: p.span(start),
1112 lit,
1113 })
1114}
1115
1116pub fn parse_ts_heritage_clause<'a>(p: &mut impl Parser<'a>) -> PResult<Vec<TsExprWithTypeArgs>> {
1118 debug_assert!(p.input().syntax().typescript());
1119
1120 parse_ts_delimited_list(
1121 p,
1122 ParsingContext::HeritageClauseElement,
1123 parse_ts_heritage_clause_element,
1124 )
1125}
1126
1127fn parse_ts_heritage_clause_element<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsExprWithTypeArgs> {
1128 debug_assert!(p.input().syntax().typescript());
1129
1130 let start = p.cur_pos();
1131 let ident = parse_ident_name(p)?.into();
1135 let expr = parse_subscripts(p, Callee::Expr(ident), true, true)?;
1136 if !matches!(
1137 &*expr,
1138 Expr::Ident(..) | Expr::Member(..) | Expr::TsInstantiation(..)
1139 ) {
1140 p.emit_err(p.span(start), SyntaxError::TS2499);
1141 }
1142
1143 match *expr {
1144 Expr::TsInstantiation(v) => Ok(TsExprWithTypeArgs {
1145 span: v.span,
1146 expr: v.expr,
1147 type_args: Some(v.type_args),
1148 }),
1149 _ => {
1150 let type_args = if p.input().is(&P::Token::LESS) {
1151 let ret = parse_ts_type_args(p)?;
1152 p.assert_and_bump(&P::Token::GREATER);
1153 Some(ret)
1154 } else {
1155 None
1156 };
1157
1158 Ok(TsExprWithTypeArgs {
1159 span: p.span(start),
1160 expr,
1161 type_args,
1162 })
1163 }
1164 }
1165}
1166
1167fn skip_ts_parameter_start<'a, P: Parser<'a>>(p: &mut P) -> PResult<bool> {
1169 debug_assert!(p.input().syntax().typescript());
1170
1171 let _ = eat_any_ts_modifier(p)?;
1172
1173 let cur = p.input().cur();
1174 if cur.is_word() || cur.is_this() {
1175 p.bump();
1176 Ok(true)
1177 } else if (cur.is_lbrace() || cur.is_lbracket()) && parse_binding_pat_or_ident(p, false).is_ok()
1178 {
1179 Ok(true)
1180 } else {
1181 Ok(false)
1182 }
1183}
1184
1185fn is_ts_unambiguously_start_of_fn_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<bool> {
1187 debug_assert!(p.input().syntax().typescript());
1188
1189 p.assert_and_bump(&P::Token::LPAREN);
1190
1191 let cur = p.input().cur();
1192 if cur.is_rparen() || cur.is_dotdotdot() {
1193 return Ok(true);
1196 }
1197 if skip_ts_parameter_start(p)? {
1198 let cur = p.input().cur();
1199 if cur.is_colon() || cur.is_comma() || cur.is_equal() || cur.is_question() {
1200 return Ok(true);
1205 }
1206 if p.input_mut().eat(&P::Token::RPAREN) && p.input().cur().is_arrow() {
1207 return Ok(true);
1209 }
1210 }
1211 Ok(false)
1212}
1213
1214fn is_ts_start_of_fn_type<'a, P: Parser<'a>>(p: &mut P) -> bool {
1215 debug_assert!(p.input().syntax().typescript());
1216
1217 if p.input().cur().is_less() {
1218 return true;
1219 }
1220
1221 p.input().cur().is_lparen()
1222 && ts_look_ahead(p, is_ts_unambiguously_start_of_fn_type).unwrap_or_default()
1223}
1224
1225fn is_ts_unambiguously_index_signature<'a, P: Parser<'a>>(p: &mut P) -> bool {
1227 debug_assert!(p.input().syntax().typescript());
1228
1229 p.assert_and_bump(&P::Token::LBRACKET); p.eat_ident_ref() && {
1234 let cur = p.input().cur();
1235 cur.is_comma() || cur.is_colon()
1236 }
1237}
1238
1239pub fn try_parse_ts_index_signature<'a, P: Parser<'a>>(
1241 p: &mut P,
1242 index_signature_start: BytePos,
1243 readonly: bool,
1244 is_static: bool,
1245) -> PResult<Option<TsIndexSignature>> {
1246 if !cfg!(feature = "typescript") {
1247 return Ok(Default::default());
1248 }
1249
1250 if !(p.input().cur().is_lbracket() && ts_look_ahead(p, is_ts_unambiguously_index_signature)) {
1251 return Ok(None);
1252 }
1253
1254 expect!(p, &P::Token::LBRACKET);
1255
1256 let ident_start = p.cur_pos();
1257 let mut id = parse_ident_name(p).map(BindingIdent::from)?;
1258 let type_ann_start = p.cur_pos();
1259
1260 if p.input_mut().eat(&P::Token::COMMA) {
1261 p.emit_err(id.span, SyntaxError::TS1096);
1262 } else {
1263 expect!(p, &P::Token::COLON);
1264 }
1265
1266 let type_ann = parse_ts_type_ann(p, false, type_ann_start)?;
1267 id.span = p.span(ident_start);
1268 id.type_ann = Some(type_ann);
1269
1270 expect!(p, &P::Token::RBRACKET);
1271
1272 let params = vec![TsFnParam::Ident(id)];
1273
1274 let ty = try_parse_ts_type_ann(p)?;
1275 let type_ann = ty;
1276
1277 parse_ts_type_member_semicolon(p)?;
1278
1279 Ok(Some(TsIndexSignature {
1280 span: p.span(index_signature_start),
1281 readonly,
1282 is_static,
1283 params,
1284 type_ann,
1285 }))
1286}
1287
1288fn is_ts_external_module_ref<'a, P: Parser<'a>>(p: &mut P) -> bool {
1290 debug_assert!(p.input().syntax().typescript());
1291 p.input().is(&P::Token::REQUIRE) && peek!(p).is_some_and(|t| t.is_lparen())
1292}
1293
1294fn parse_ts_module_ref<'a>(p: &mut impl Parser<'a>) -> PResult<TsModuleRef> {
1296 debug_assert!(p.input().syntax().typescript());
1297
1298 if is_ts_external_module_ref(p) {
1299 parse_ts_external_module_ref(p).map(From::from)
1300 } else {
1301 parse_ts_entity_name(p, false).map(From::from)
1302 }
1303}
1304
1305fn parse_ts_external_module_ref<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsExternalModuleRef> {
1307 debug_assert!(p.input().syntax().typescript());
1308
1309 let start = p.cur_pos();
1310 expect!(p, &P::Token::REQUIRE);
1311 expect!(p, &P::Token::LPAREN);
1312 let cur = p.input().cur();
1313 if cur.is_error() {
1314 let err = p.input_mut().expect_error_token_and_bump();
1315 return Err(err);
1316 } else if !cur.is_str() {
1317 unexpected!(p, "a string literal")
1318 }
1319 let expr = parse_str_lit(p);
1320 expect!(p, &P::Token::RPAREN);
1321 Ok(TsExternalModuleRef {
1322 span: p.span(start),
1323 expr,
1324 })
1325}
1326
1327pub fn parse_ts_import_equals_decl<'a, P: Parser<'a>>(
1329 p: &mut P,
1330 start: BytePos,
1331 id: Ident,
1332 is_export: bool,
1333 is_type_only: bool,
1334) -> PResult<Box<TsImportEqualsDecl>> {
1335 debug_assert!(p.input().syntax().typescript());
1336
1337 expect!(p, &P::Token::EQUAL);
1338 let module_ref = parse_ts_module_ref(p)?;
1339 p.expect_general_semi()?;
1340
1341 Ok(Box::new(TsImportEqualsDecl {
1342 span: p.span(start),
1343 id,
1344 is_export,
1345 is_type_only,
1346 module_ref,
1347 }))
1348}
1349
1350fn parse_ts_binding_list_for_signature<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<TsFnParam>> {
1354 if !cfg!(feature = "typescript") {
1355 return Ok(Default::default());
1356 }
1357
1358 debug_assert!(p.input().syntax().typescript());
1359
1360 let params = parse_formal_params(p)?;
1361 let mut list = Vec::with_capacity(4);
1362
1363 for param in params {
1364 let item = match param.pat {
1365 Pat::Ident(pat) => TsFnParam::Ident(pat),
1366 Pat::Array(pat) => TsFnParam::Array(pat),
1367 Pat::Object(pat) => TsFnParam::Object(pat),
1368 Pat::Rest(pat) => TsFnParam::Rest(pat),
1369 _ => unexpected!(
1370 p,
1371 "an identifier, [ for an array pattern, { for an object patter or ... for a rest \
1372 pattern"
1373 ),
1374 };
1375 list.push(item);
1376 }
1377 expect!(p, &P::Token::RPAREN);
1378 Ok(list)
1379}
1380
1381pub fn is_ts_start_of_mapped_type<'a, P: Parser<'a>>(p: &mut P) -> bool {
1383 debug_assert!(p.input().syntax().typescript());
1384
1385 p.bump();
1386 if p.input_mut().eat(&P::Token::PLUS) || p.input_mut().eat(&P::Token::MINUS) {
1387 return p.input().is(&P::Token::READONLY);
1388 }
1389
1390 p.input_mut().eat(&P::Token::READONLY);
1391
1392 if !p.input().is(&P::Token::LBRACKET) {
1393 return false;
1394 }
1395 p.bump();
1396 if !p.is_ident_ref() {
1397 return false;
1398 }
1399 p.bump();
1400
1401 p.input().is(&P::Token::IN)
1402}
1403
1404fn parse_ts_signature_member<'a, P: Parser<'a>>(
1406 p: &mut P,
1407 kind: SignatureParsingMode,
1408) -> PResult<Either<TsCallSignatureDecl, TsConstructSignatureDecl>> {
1409 debug_assert!(p.input().syntax().typescript());
1410
1411 let start = p.cur_pos();
1412
1413 if kind == SignatureParsingMode::TSConstructSignatureDeclaration {
1414 expect!(p, &P::Token::NEW);
1415 }
1416
1417 let type_params = try_parse_ts_type_params(p, false, true)?;
1419 expect!(p, &P::Token::LPAREN);
1420 let params = parse_ts_binding_list_for_signature(p)?;
1421 let type_ann = if p.input().is(&P::Token::COLON) {
1422 Some(parse_ts_type_or_type_predicate_ann(p, &P::Token::COLON)?)
1423 } else {
1424 None
1425 };
1426 parse_ts_type_member_semicolon(p)?;
1429
1430 match kind {
1431 SignatureParsingMode::TSCallSignatureDeclaration => Ok(Either::Left(TsCallSignatureDecl {
1432 span: p.span(start),
1433 params,
1434 type_ann,
1435 type_params,
1436 })),
1437 SignatureParsingMode::TSConstructSignatureDeclaration => {
1438 Ok(Either::Right(TsConstructSignatureDecl {
1439 span: p.span(start),
1440 params,
1441 type_ann,
1442 type_params,
1443 }))
1444 }
1445 }
1446}
1447
1448fn try_parse_ts_tuple_element_name<'a, P: Parser<'a>>(p: &mut P) -> Option<Pat> {
1449 if !cfg!(feature = "typescript") {
1450 return Default::default();
1451 }
1452
1453 try_parse_ts(p, |p| {
1454 let start = p.cur_pos();
1455
1456 let rest = if p.input_mut().eat(&P::Token::DOTDOTDOT) {
1457 Some(p.input().prev_span())
1458 } else {
1459 None
1460 };
1461
1462 let mut ident = parse_ident_name(p).map(Ident::from)?;
1463 if p.input_mut().eat(&P::Token::QUESTION) {
1464 ident.optional = true;
1465 ident.span = ident.span.with_hi(p.input().prev_span().hi);
1466 }
1467 expect!(p, &P::Token::COLON);
1468
1469 Ok(Some(if let Some(dot3_token) = rest {
1470 RestPat {
1471 span: p.span(start),
1472 dot3_token,
1473 arg: ident.into(),
1474 type_ann: None,
1475 }
1476 .into()
1477 } else {
1478 ident.into()
1479 }))
1480 })
1481}
1482
1483fn parse_ts_tuple_element_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTupleElement> {
1485 debug_assert!(p.input().syntax().typescript());
1486
1487 let start = p.cur_pos();
1489
1490 let label = try_parse_ts_tuple_element_name(p);
1491
1492 if p.input_mut().eat(&P::Token::DOTDOTDOT) {
1493 let type_ann = parse_ts_type(p)?;
1494 return Ok(TsTupleElement {
1495 span: p.span(start),
1496 label,
1497 ty: Box::new(TsType::TsRestType(TsRestType {
1498 span: p.span(start),
1499 type_ann,
1500 })),
1501 });
1502 }
1503
1504 let ty = parse_ts_type(p)?;
1505 if p.input_mut().eat(&P::Token::QUESTION) {
1507 let type_ann = ty;
1508 return Ok(TsTupleElement {
1509 span: p.span(start),
1510 label,
1511 ty: Box::new(TsType::TsOptionalType(TsOptionalType {
1512 span: p.span(start),
1513 type_ann,
1514 })),
1515 });
1516 }
1517
1518 Ok(TsTupleElement {
1519 span: p.span(start),
1520 label,
1521 ty,
1522 })
1523}
1524
1525pub fn parse_ts_tuple_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTupleType> {
1527 debug_assert!(p.input().syntax().typescript());
1528
1529 let start = p.cur_pos();
1530 let elems = parse_ts_bracketed_list(
1531 p,
1532 ParsingContext::TupleElementTypes,
1533 parse_ts_tuple_element_type,
1534 true,
1535 false,
1536 )?;
1537
1538 let mut seen_optional_element = false;
1543
1544 for elem in elems.iter() {
1545 match *elem.ty {
1546 TsType::TsRestType(..) => {}
1547 TsType::TsOptionalType(..) => {
1548 seen_optional_element = true;
1549 }
1550 _ if seen_optional_element => {
1551 syntax_error!(p, p.span(start), SyntaxError::TsRequiredAfterOptional)
1552 }
1553 _ => {}
1554 }
1555 }
1556
1557 Ok(TsTupleType {
1558 span: p.span(start),
1559 elem_types: elems,
1560 })
1561}
1562
1563pub fn parse_ts_mapped_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsMappedType> {
1565 debug_assert!(p.input().syntax().typescript());
1566
1567 let start = p.cur_pos();
1568 expect!(p, &P::Token::LBRACE);
1569 let mut readonly = None;
1570 let cur = p.input().cur();
1571 if cur.is_plus() || cur.is_minus() {
1572 readonly = Some(if cur.is_plus() {
1573 TruePlusMinus::Plus
1574 } else {
1575 TruePlusMinus::Minus
1576 });
1577 p.bump();
1578 expect!(p, &P::Token::READONLY)
1579 } else if p.input_mut().eat(&P::Token::READONLY) {
1580 readonly = Some(TruePlusMinus::True);
1581 }
1582
1583 expect!(p, &P::Token::LBRACKET);
1584 let type_param = parse_ts_mapped_type_param(p)?;
1585 let name_type = if p.input_mut().eat(&P::Token::AS) {
1586 Some(parse_ts_type(p)?)
1587 } else {
1588 None
1589 };
1590 expect!(p, &P::Token::RBRACKET);
1591
1592 let mut optional = None;
1593 let cur = p.input().cur();
1594 if cur.is_plus() || cur.is_minus() {
1595 optional = Some(if cur.is_plus() {
1596 TruePlusMinus::Plus
1597 } else {
1598 TruePlusMinus::Minus
1599 });
1600 p.bump(); expect!(p, &P::Token::QUESTION);
1602 } else if p.input_mut().eat(&P::Token::QUESTION) {
1603 optional = Some(TruePlusMinus::True);
1604 }
1605
1606 let type_ann = try_parse_ts_type(p)?;
1607 p.expect_general_semi()?;
1608 expect!(p, &P::Token::RBRACE);
1609
1610 Ok(TsMappedType {
1611 span: p.span(start),
1612 readonly,
1613 optional,
1614 type_param,
1615 name_type,
1616 type_ann,
1617 })
1618}
1619
1620pub fn parse_ts_parenthesized_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsParenthesizedType> {
1622 debug_assert!(p.input().syntax().typescript());
1623 trace_cur!(p, parse_ts_parenthesized_type);
1624
1625 let start = p.cur_pos();
1626 expect!(p, &P::Token::LPAREN);
1627 let type_ann = parse_ts_type(p)?;
1628 expect!(p, &P::Token::RPAREN);
1629 Ok(TsParenthesizedType {
1630 span: p.span(start),
1631 type_ann,
1632 })
1633}
1634
1635pub fn parse_ts_type_alias_decl<'a, P: Parser<'a>>(
1637 p: &mut P,
1638 start: BytePos,
1639) -> PResult<Box<TsTypeAliasDecl>> {
1640 debug_assert!(p.input().syntax().typescript());
1641
1642 let id = parse_ident_name(p)?;
1643 let type_params = try_parse_ts_type_params(p, true, false)?;
1644 let type_ann = expect_then_parse_ts_type(p, &P::Token::EQUAL, "=")?;
1645 p.expect_general_semi()?;
1646 Ok(Box::new(TsTypeAliasDecl {
1647 declare: false,
1648 span: p.span(start),
1649 id: id.into(),
1650 type_params,
1651 type_ann,
1652 }))
1653}
1654
1655fn parse_ts_fn_or_constructor_type<'a, P: Parser<'a>>(
1657 p: &mut P,
1658 is_fn_type: bool,
1659) -> PResult<TsFnOrConstructorType> {
1660 trace_cur!(p, parse_ts_fn_or_constructor_type);
1661
1662 debug_assert!(p.input().syntax().typescript());
1663
1664 let start = p.cur_pos();
1665 let is_abstract = if !is_fn_type {
1666 p.input_mut().eat(&P::Token::ABSTRACT)
1667 } else {
1668 false
1669 };
1670 if !is_fn_type {
1671 expect!(p, &P::Token::NEW);
1672 }
1673
1674 let type_params = try_parse_ts_type_params(p, false, true)?;
1676 expect!(p, &P::Token::LPAREN);
1677 let params = parse_ts_binding_list_for_signature(p)?;
1678 let type_ann = parse_ts_type_or_type_predicate_ann(p, &P::Token::ARROW)?;
1679 Ok(if is_fn_type {
1682 TsFnOrConstructorType::TsFnType(TsFnType {
1683 span: p.span(start),
1684 type_params,
1685 params,
1686 type_ann,
1687 })
1688 } else {
1689 TsFnOrConstructorType::TsConstructorType(TsConstructorType {
1690 span: p.span(start),
1691 type_params,
1692 params,
1693 type_ann,
1694 is_abstract,
1695 })
1696 })
1697}
1698
1699fn parse_ts_union_type_or_higher<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
1701 trace_cur!(p, parse_ts_union_type_or_higher);
1702 debug_assert!(p.input().syntax().typescript());
1703
1704 parse_ts_union_or_intersection_type(
1705 p,
1706 UnionOrIntersection::Union,
1707 parse_ts_intersection_type_or_higher,
1708 &P::Token::BIT_OR,
1709 )
1710}
1711
1712fn parse_ts_intersection_type_or_higher<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
1714 trace_cur!(p, parse_ts_intersection_type_or_higher);
1715
1716 debug_assert!(p.input().syntax().typescript());
1717
1718 parse_ts_union_or_intersection_type(
1719 p,
1720 UnionOrIntersection::Intersection,
1721 parse_ts_type_operator_or_higher,
1722 &P::Token::BIT_AND,
1723 )
1724}
1725
1726fn parse_ts_type_operator_or_higher<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
1728 trace_cur!(p, parse_ts_type_operator_or_higher);
1729 debug_assert!(p.input().syntax().typescript());
1730
1731 let operator = if p.input().is(&P::Token::KEYOF) {
1732 Some(TsTypeOperatorOp::KeyOf)
1733 } else if p.input().is(&P::Token::UNIQUE) {
1734 Some(TsTypeOperatorOp::Unique)
1735 } else if p.input().is(&P::Token::READONLY) {
1736 Some(TsTypeOperatorOp::ReadOnly)
1737 } else {
1738 None
1739 };
1740
1741 match operator {
1742 Some(operator) => parse_ts_type_operator(p, operator)
1743 .map(TsType::from)
1744 .map(Box::new),
1745 None => {
1746 trace_cur!(p, parse_ts_type_operator_or_higher__not_operator);
1747
1748 if p.input().is(&P::Token::INFER) {
1749 parse_ts_infer_type(p).map(TsType::from).map(Box::new)
1750 } else {
1751 let readonly = parse_ts_modifier(p, &["readonly"], false)?.is_some();
1752 parse_ts_array_type_or_higher(p, readonly)
1753 }
1754 }
1755 }
1756}
1757
1758fn parse_ts_type_operator<'a, P: Parser<'a>>(
1760 p: &mut P,
1761 op: TsTypeOperatorOp,
1762) -> PResult<TsTypeOperator> {
1763 debug_assert!(p.input().syntax().typescript());
1764
1765 let start = p.cur_pos();
1766 match op {
1767 TsTypeOperatorOp::Unique => expect!(p, &P::Token::UNIQUE),
1768 TsTypeOperatorOp::KeyOf => expect!(p, &P::Token::KEYOF),
1769 TsTypeOperatorOp::ReadOnly => expect!(p, &P::Token::READONLY),
1770 }
1771
1772 let type_ann = parse_ts_type_operator_or_higher(p)?;
1773 Ok(TsTypeOperator {
1774 span: p.span(start),
1775 op,
1776 type_ann,
1777 })
1778}
1779
1780fn parse_ts_infer_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsInferType> {
1782 debug_assert!(p.input().syntax().typescript());
1783
1784 let start = p.cur_pos();
1785 expect!(p, &P::Token::INFER);
1786 let type_param_name = parse_ident_name(p)?;
1787 let constraint = try_parse_ts(p, |p| {
1788 expect!(p, &P::Token::EXTENDS);
1789 let constraint = parse_ts_non_conditional_type(p);
1790 if p.ctx().contains(Context::DisallowConditionalTypes) || !p.input().is(&P::Token::QUESTION)
1791 {
1792 constraint.map(Some)
1793 } else {
1794 Ok(None)
1795 }
1796 });
1797 let type_param = TsTypeParam {
1798 span: type_param_name.span(),
1799 name: type_param_name.into(),
1800 is_in: false,
1801 is_out: false,
1802 is_const: false,
1803 constraint,
1804 default: None,
1805 };
1806 Ok(TsInferType {
1807 span: p.span(start),
1808 type_param,
1809 })
1810}
1811
1812fn parse_ts_non_conditional_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
1814 trace_cur!(p, parse_ts_non_conditional_type);
1815
1816 debug_assert!(p.input().syntax().typescript());
1817
1818 if is_ts_start_of_fn_type(p) {
1819 return parse_ts_fn_or_constructor_type(p, true)
1820 .map(TsType::from)
1821 .map(Box::new);
1822 }
1823 if (p.input().is(&P::Token::ABSTRACT) && peek!(p).is_some_and(|cur| cur.is_new()))
1824 || p.input().is(&P::Token::NEW)
1825 {
1826 return parse_ts_fn_or_constructor_type(p, false)
1828 .map(TsType::from)
1829 .map(Box::new);
1830 }
1831
1832 parse_ts_union_type_or_higher(p)
1833}
1834
1835fn parse_ts_array_type_or_higher<'a, P: Parser<'a>>(
1837 p: &mut P,
1838 readonly: bool,
1839) -> PResult<Box<TsType>> {
1840 trace_cur!(p, parse_ts_array_type_or_higher);
1841 debug_assert!(p.input().syntax().typescript());
1842
1843 let mut ty = parse_ts_non_array_type(p)?;
1844
1845 while !p.input().had_line_break_before_cur() && p.input_mut().eat(&P::Token::LBRACKET) {
1846 if p.input_mut().eat(&P::Token::RBRACKET) {
1847 ty = Box::new(TsType::TsArrayType(TsArrayType {
1848 span: p.span(ty.span_lo()),
1849 elem_type: ty,
1850 }));
1851 } else {
1852 let index_type = parse_ts_type(p)?;
1853 expect!(p, &P::Token::RBRACKET);
1854 ty = Box::new(TsType::TsIndexedAccessType(TsIndexedAccessType {
1855 span: p.span(ty.span_lo()),
1856 readonly,
1857 obj_type: ty,
1858 index_type,
1859 }))
1860 }
1861 }
1862
1863 Ok(ty)
1864}
1865
1866pub fn parse_ts_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
1870 trace_cur!(p, parse_ts_type);
1871
1872 debug_assert!(p.input().syntax().typescript());
1873
1874 debug_assert!(p.ctx().contains(Context::InType));
1876
1877 let start = p.cur_pos();
1878
1879 p.do_outside_of_context(Context::DisallowConditionalTypes, |p| {
1880 let ty = parse_ts_non_conditional_type(p)?;
1881 if p.input().had_line_break_before_cur() || !p.input_mut().eat(&P::Token::EXTENDS) {
1882 return Ok(ty);
1883 }
1884
1885 let check_type = ty;
1886 let extends_type = p.do_inside_of_context(
1887 Context::DisallowConditionalTypes,
1888 parse_ts_non_conditional_type,
1889 )?;
1890
1891 expect!(p, &P::Token::QUESTION);
1892
1893 let true_type = parse_ts_type(p)?;
1894
1895 expect!(p, &P::Token::COLON);
1896
1897 let false_type = parse_ts_type(p)?;
1898
1899 Ok(Box::new(TsType::TsConditionalType(TsConditionalType {
1900 span: p.span(start),
1901 check_type,
1902 extends_type,
1903 true_type,
1904 false_type,
1905 })))
1906 })
1907}
1908
1909fn parse_ts_property_name<'a, P: Parser<'a>>(p: &mut P) -> PResult<(bool, Box<Expr>)> {
1913 let (computed, key) = if p.input_mut().eat(&P::Token::LBRACKET) {
1914 let key = parse_assignment_expr(p)?;
1915 expect!(p, &P::Token::RBRACKET);
1916 (true, key)
1917 } else {
1918 p.do_inside_of_context(Context::InPropertyName, |p| {
1919 let cur = p.input().cur();
1921
1922 let key = if cur.is_num() || cur.is_str() {
1923 parse_new_expr(p)
1924 } else if cur.is_error() {
1925 let err = p.input_mut().expect_error_token_and_bump();
1926 return Err(err);
1927 } else {
1928 parse_maybe_private_name(p).map(|e| match e {
1929 Either::Left(e) => {
1930 p.emit_err(e.span(), SyntaxError::PrivateNameInInterface);
1931
1932 e.into()
1933 }
1934 Either::Right(e) => e.into(),
1935 })
1936 };
1937 key.map(|key| (false, key))
1938 })?
1939 };
1940
1941 Ok((computed, key))
1942}
1943
1944fn parse_ts_property_or_method_signature<'a, P: Parser<'a>>(
1946 p: &mut P,
1947 start: BytePos,
1948 readonly: bool,
1949) -> PResult<Either<TsPropertySignature, TsMethodSignature>> {
1950 debug_assert!(p.input().syntax().typescript());
1951
1952 let (computed, key) = parse_ts_property_name(p)?;
1953
1954 let optional = p.input_mut().eat(&P::Token::QUESTION);
1955
1956 let cur = p.input().cur();
1957 if cur.is_lparen() || cur.is_less() {
1958 if readonly {
1959 syntax_error!(p, SyntaxError::ReadOnlyMethod)
1960 }
1961
1962 let type_params = try_parse_ts_type_params(p, false, true)?;
1963 expect!(p, &P::Token::LPAREN);
1964 let params = parse_ts_binding_list_for_signature(p)?;
1965 let type_ann = if p.input().is(&P::Token::COLON) {
1966 parse_ts_type_or_type_predicate_ann(p, &P::Token::COLON).map(Some)?
1967 } else {
1968 None
1969 };
1970 parse_ts_type_member_semicolon(p)?;
1973 Ok(Either::Right(TsMethodSignature {
1974 span: p.span(start),
1975 computed,
1976 key,
1977 optional,
1978 type_params,
1979 params,
1980 type_ann,
1981 }))
1982 } else {
1983 let type_ann = try_parse_ts_type_ann(p)?;
1984
1985 parse_ts_type_member_semicolon(p)?;
1986 Ok(Either::Left(TsPropertySignature {
1987 span: p.span(start),
1988 computed,
1989 readonly,
1990 key,
1991 optional,
1992 type_ann,
1993 }))
1994 }
1995}
1996
1997fn parse_ts_type_member<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTypeElement> {
1999 debug_assert!(p.input().syntax().typescript());
2000
2001 fn into_type_elem(e: Either<TsCallSignatureDecl, TsConstructSignatureDecl>) -> TsTypeElement {
2002 match e {
2003 Either::Left(e) => e.into(),
2004 Either::Right(e) => e.into(),
2005 }
2006 }
2007 let cur = p.input().cur();
2008 if cur.is_lparen() || cur.is_less() {
2009 return parse_ts_signature_member(p, SignatureParsingMode::TSCallSignatureDeclaration)
2010 .map(into_type_elem);
2011 }
2012 if p.input().is(&P::Token::NEW) && ts_look_ahead(p, is_ts_start_of_construct_signature) {
2013 return parse_ts_signature_member(p, SignatureParsingMode::TSConstructSignatureDeclaration)
2014 .map(into_type_elem);
2015 }
2016 let start = p.cur_pos();
2018 let readonly = parse_ts_modifier(p, &["readonly"], false)?.is_some();
2019
2020 let idx = try_parse_ts_index_signature(p, start, readonly, false)?;
2021 if let Some(idx) = idx {
2022 return Ok(idx.into());
2023 }
2024
2025 if let Some(v) = try_parse_ts(p, |p| {
2026 let start = p.input().cur_pos();
2027
2028 if readonly {
2029 syntax_error!(p, SyntaxError::GetterSetterCannotBeReadonly)
2030 }
2031
2032 let is_get = if p.input_mut().eat(&P::Token::GET) {
2033 true
2034 } else {
2035 expect!(p, &P::Token::SET);
2036 false
2037 };
2038
2039 let (computed, key) = parse_ts_property_name(p)?;
2040
2041 if is_get {
2042 expect!(p, &P::Token::LPAREN);
2043 expect!(p, &P::Token::RPAREN);
2044 let type_ann = try_parse_ts_type_ann(p)?;
2045
2046 parse_ts_type_member_semicolon(p)?;
2047
2048 Ok(Some(TsTypeElement::TsGetterSignature(TsGetterSignature {
2049 span: p.span(start),
2050 key,
2051 computed,
2052 type_ann,
2053 })))
2054 } else {
2055 expect!(p, &P::Token::LPAREN);
2056 let params = parse_ts_binding_list_for_signature(p)?;
2057 if params.is_empty() {
2058 syntax_error!(p, SyntaxError::SetterParamRequired)
2059 }
2060 let param = params.into_iter().next().unwrap();
2061
2062 parse_ts_type_member_semicolon(p)?;
2063
2064 Ok(Some(TsTypeElement::TsSetterSignature(TsSetterSignature {
2065 span: p.span(start),
2066 key,
2067 computed,
2068 param,
2069 })))
2070 }
2071 }) {
2072 return Ok(v);
2073 }
2074
2075 parse_ts_property_or_method_signature(p, start, readonly).map(|e| match e {
2076 Either::Left(e) => e.into(),
2077 Either::Right(e) => e.into(),
2078 })
2079}
2080
2081fn parse_ts_object_type_members<'a, P: Parser<'a>>(p: &mut P) -> PResult<Vec<TsTypeElement>> {
2083 debug_assert!(p.input().syntax().typescript());
2084
2085 expect!(p, &P::Token::LBRACE);
2086 let members = parse_ts_list(p, ParsingContext::TypeMembers, |p| parse_ts_type_member(p))?;
2087 expect!(p, &P::Token::RBRACE);
2088 Ok(members)
2089}
2090
2091pub fn parse_ts_type_lit<'a>(p: &mut impl Parser<'a>) -> PResult<TsTypeLit> {
2093 debug_assert!(p.input().syntax().typescript());
2094
2095 let start = p.cur_pos();
2096 let members = parse_ts_object_type_members(p)?;
2097 Ok(TsTypeLit {
2098 span: p.span(start),
2099 members,
2100 })
2101}
2102
2103pub fn parse_ts_interface_decl<'a, P: Parser<'a>>(
2105 p: &mut P,
2106 start: BytePos,
2107) -> PResult<Box<TsInterfaceDecl>> {
2108 debug_assert!(p.input().syntax().typescript());
2109
2110 let id = parse_ident_name(p)?;
2111 match &*id.sym {
2112 "string" | "null" | "number" | "object" | "any" | "unknown" | "boolean" | "bigint"
2113 | "symbol" | "void" | "never" | "intrinsic" => {
2114 p.emit_err(id.span, SyntaxError::TS2427);
2115 }
2116 _ => {}
2117 }
2118
2119 let type_params = try_parse_ts_type_params(p, true, false)?;
2120
2121 let extends = if p.input_mut().eat(&P::Token::EXTENDS) {
2122 parse_ts_heritage_clause(p)?
2123 } else {
2124 Vec::new()
2125 };
2126
2127 if p.input().is(&P::Token::EXTENDS) {
2131 p.emit_err(p.input().cur_span(), SyntaxError::TS1172);
2132
2133 while !p.input().cur().is_eof() && !p.input().is(&P::Token::LBRACE) {
2134 p.bump();
2135 }
2136 }
2137
2138 let body_start = p.cur_pos();
2139 let body = p.in_type(parse_ts_object_type_members)?;
2140 let body = TsInterfaceBody {
2141 span: p.span(body_start),
2142 body,
2143 };
2144 Ok(Box::new(TsInterfaceDecl {
2145 span: p.span(start),
2146 declare: false,
2147 id: id.into(),
2148 type_params,
2149 extends,
2150 body,
2151 }))
2152}
2153
2154pub fn parse_ts_type_assertion<'a, P: Parser<'a>>(
2156 p: &mut P,
2157 start: BytePos,
2158) -> PResult<TsTypeAssertion> {
2159 debug_assert!(p.input().syntax().typescript());
2160
2161 if p.input().syntax().disallow_ambiguous_jsx_like() {
2162 p.emit_err(p.span(start), SyntaxError::ReservedTypeAssertion);
2163 }
2164
2165 let type_ann = p.in_type(parse_ts_type)?;
2169 expect!(p, &P::Token::GREATER);
2170 let expr = p.parse_unary_expr()?;
2171 Ok(TsTypeAssertion {
2172 span: p.span(start),
2173 type_ann,
2174 expr,
2175 })
2176}
2177
2178fn parse_ts_import_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsImportType> {
2180 let start = p.cur_pos();
2181 p.assert_and_bump(&P::Token::IMPORT);
2182
2183 expect!(p, &P::Token::LPAREN);
2184
2185 let cur = p.input().cur();
2186
2187 let arg = if cur.is_str() {
2188 parse_str_lit(p)
2189 } else if cur.is_error() {
2190 let err = p.input_mut().expect_error_token_and_bump();
2191 return Err(err);
2192 } else {
2193 let arg_span = p.input().cur_span();
2194 p.bump();
2195 p.emit_err(arg_span, SyntaxError::TS1141);
2196 Str {
2197 span: arg_span,
2198 value: atom!(""),
2199 raw: Some(atom!("\"\"")),
2200 }
2201 };
2202
2203 let attributes = if p.input_mut().eat(&P::Token::COMMA)
2206 && p.input().syntax().import_attributes()
2207 && p.input().is(&P::Token::LBRACE)
2208 {
2209 Some(parse_ts_call_options(p)?)
2210 } else {
2211 None
2212 };
2213
2214 expect!(p, &P::Token::RPAREN);
2215
2216 let qualifier = if p.input_mut().eat(&P::Token::DOT) {
2217 parse_ts_entity_name(p, false).map(Some)?
2218 } else {
2219 None
2220 };
2221
2222 let type_args = if p.input().is(&P::Token::LESS) {
2223 let ret = p.do_outside_of_context(Context::ShouldNotLexLtOrGtAsType, parse_ts_type_args)?;
2224 p.assert_and_bump(&P::Token::GREATER);
2225 Some(ret)
2226 } else {
2227 None
2228 };
2229
2230 Ok(TsImportType {
2231 span: p.span(start),
2232 arg,
2233 qualifier,
2234 type_args,
2235 attributes,
2236 })
2237}
2238
2239fn parse_ts_call_options<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsImportCallOptions> {
2240 debug_assert!(p.input().syntax().typescript());
2241 let start = p.cur_pos();
2242 p.assert_and_bump(&P::Token::LBRACE);
2243
2244 expect!(p, &P::Token::WITH);
2245 expect!(p, &P::Token::COLON);
2246
2247 let value = match parse_object_expr(p)? {
2248 Expr::Object(v) => v,
2249 _ => unreachable!(),
2250 };
2251 p.input_mut().eat(&P::Token::COMMA);
2252 expect!(p, &P::Token::RBRACE);
2253 Ok(TsImportCallOptions {
2254 span: p.span(start),
2255 with: Box::new(value),
2256 })
2257}
2258
2259fn parse_ts_type_query<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTypeQuery> {
2261 debug_assert!(p.input().syntax().typescript());
2262
2263 let start = p.cur_pos();
2264 expect!(p, &P::Token::TYPEOF);
2265 let expr_name = if p.input().is(&P::Token::IMPORT) {
2266 parse_ts_import_type(p).map(From::from)?
2267 } else {
2268 parse_ts_entity_name(
2269 p, true,
2271 )
2272 .map(From::from)?
2273 };
2274
2275 let type_args = if !p.input().had_line_break_before_cur() && p.input().is(&P::Token::LESS) {
2276 let ret = p.do_outside_of_context(Context::ShouldNotLexLtOrGtAsType, parse_ts_type_args)?;
2277 p.assert_and_bump(&P::Token::GREATER);
2278 Some(ret)
2279 } else {
2280 None
2281 };
2282
2283 Ok(TsTypeQuery {
2284 span: p.span(start),
2285 expr_name,
2286 type_args,
2287 })
2288}
2289
2290fn parse_ts_module_block<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsModuleBlock> {
2292 trace_cur!(p, parse_ts_module_block);
2293
2294 debug_assert!(p.input().syntax().typescript());
2295
2296 let start = p.cur_pos();
2297 expect!(p, &P::Token::LBRACE);
2298 let body = p.do_inside_of_context(Context::TsModuleBlock, |p| {
2299 p.do_outside_of_context(Context::TopLevel, |p| {
2300 parse_module_item_block_body(p, false, Some(&P::Token::RBRACE))
2301 })
2302 })?;
2303
2304 Ok(TsModuleBlock {
2305 span: p.span(start),
2306 body,
2307 })
2308}
2309
2310fn parse_ts_module_or_ns_decl<'a, P: Parser<'a>>(
2312 p: &mut P,
2313 start: BytePos,
2314 namespace: bool,
2315) -> PResult<Box<TsModuleDecl>> {
2316 debug_assert!(p.input().syntax().typescript());
2317
2318 let id = parse_ident_name(p)?;
2319 let body: TsNamespaceBody = if p.input_mut().eat(&P::Token::DOT) {
2320 let inner_start = p.cur_pos();
2321 let inner = parse_ts_module_or_ns_decl(p, inner_start, namespace)?;
2322 let inner = TsNamespaceDecl {
2323 span: inner.span,
2324 id: match inner.id {
2325 TsModuleName::Ident(i) => i,
2326 _ => unreachable!(),
2327 },
2328 body: Box::new(inner.body.unwrap()),
2329 declare: inner.declare,
2330 global: inner.global,
2331 };
2332 inner.into()
2333 } else {
2334 parse_ts_module_block(p).map(From::from)?
2335 };
2336
2337 Ok(Box::new(TsModuleDecl {
2338 span: p.span(start),
2339 declare: false,
2340 id: TsModuleName::Ident(id.into()),
2341 body: Some(body),
2342 global: false,
2343 namespace,
2344 }))
2345}
2346
2347fn parse_ts_ambient_external_module_decl<'a, P: Parser<'a>>(
2349 p: &mut P,
2350 start: BytePos,
2351) -> PResult<Box<TsModuleDecl>> {
2352 debug_assert!(p.input().syntax().typescript());
2353
2354 let (global, id) = if p.input().is(&P::Token::GLOBAL) {
2355 let id = parse_ident_name(p)?;
2356 (true, TsModuleName::Ident(id.into()))
2357 } else if p.input().cur().is_str() {
2358 let id = TsModuleName::Str(parse_str_lit(p));
2359 (false, id)
2360 } else {
2361 unexpected!(p, "global or a string literal");
2362 };
2363
2364 let body = if p.input().is(&P::Token::LBRACE) {
2365 Some(parse_ts_module_block(p).map(TsNamespaceBody::from)?)
2366 } else {
2367 p.expect_general_semi()?;
2368 None
2369 };
2370
2371 Ok(Box::new(TsModuleDecl {
2372 span: p.span(start),
2373 declare: false,
2374 id,
2375 global,
2376 body,
2377 namespace: false,
2378 }))
2379}
2380
2381fn parse_ts_non_array_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<Box<TsType>> {
2383 if !cfg!(feature = "typescript") {
2384 unreachable!()
2385 }
2386 trace_cur!(p, parse_ts_non_array_type);
2387 debug_assert!(p.input().syntax().typescript());
2388
2389 let start = p.cur_pos();
2390
2391 let cur = p.input().cur();
2392 if cur.is_known_ident()
2393 || cur.is_unknown_ident()
2394 || cur.is_void()
2395 || cur.is_yield()
2396 || cur.is_null()
2397 || cur.is_await()
2398 || cur.is_break()
2399 {
2400 if p.input().is(&P::Token::ASSERTS) && peek!(p).is_some_and(|peek| peek.is_this()) {
2401 p.bump();
2402 let this_keyword = parse_ts_this_type_node(p)?;
2403 return parse_ts_this_type_predicate(p, start, true, this_keyword)
2404 .map(TsType::from)
2405 .map(Box::new);
2406 }
2407 let kind = if p.input().is(&P::Token::VOID) {
2408 Some(TsKeywordTypeKind::TsVoidKeyword)
2409 } else if p.input().is(&P::Token::NULL) {
2410 Some(TsKeywordTypeKind::TsNullKeyword)
2411 } else if p.input().is(&P::Token::ANY) {
2412 Some(TsKeywordTypeKind::TsAnyKeyword)
2413 } else if p.input().is(&P::Token::BOOLEAN) {
2414 Some(TsKeywordTypeKind::TsBooleanKeyword)
2415 } else if p.input().is(&P::Token::BIGINT) {
2416 Some(TsKeywordTypeKind::TsBigIntKeyword)
2417 } else if p.input().is(&P::Token::NEVER) {
2418 Some(TsKeywordTypeKind::TsNeverKeyword)
2419 } else if p.input().is(&P::Token::NUMBER) {
2420 Some(TsKeywordTypeKind::TsNumberKeyword)
2421 } else if p.input().is(&P::Token::OBJECT) {
2422 Some(TsKeywordTypeKind::TsObjectKeyword)
2423 } else if p.input().is(&P::Token::STRING) {
2424 Some(TsKeywordTypeKind::TsStringKeyword)
2425 } else if p.input().is(&P::Token::SYMBOL) {
2426 Some(TsKeywordTypeKind::TsSymbolKeyword)
2427 } else if p.input().is(&P::Token::UNKNOWN) {
2428 Some(TsKeywordTypeKind::TsUnknownKeyword)
2429 } else if p.input().is(&P::Token::UNDEFINED) {
2430 Some(TsKeywordTypeKind::TsUndefinedKeyword)
2431 } else if p.input().is(&P::Token::INTRINSIC) {
2432 Some(TsKeywordTypeKind::TsIntrinsicKeyword)
2433 } else {
2434 None
2435 };
2436
2437 let peeked_is_dot = peek!(p).is_some_and(|cur| cur.is_dot());
2438
2439 match kind {
2440 Some(kind) if !peeked_is_dot => {
2441 p.bump();
2442 return Ok(Box::new(TsType::TsKeywordType(TsKeywordType {
2443 span: p.span(start),
2444 kind,
2445 })));
2446 }
2447 _ => {
2448 return parse_ts_type_ref(p).map(TsType::from).map(Box::new);
2449 }
2450 }
2451 } else if cur.is_bigint()
2452 || cur.is_str()
2453 || cur.is_num()
2454 || cur.is_true()
2455 || cur.is_false()
2456 || cur.is_backquote()
2457 {
2458 return parse_ts_lit_type_node(p).map(TsType::from).map(Box::new);
2459 } else if cur.is_no_substitution_template_literal() || cur.is_template_head() {
2460 return p.parse_tagged_tpl_ty().map(TsType::from).map(Box::new);
2461 } else if cur.is_minus() {
2462 let start = p.cur_pos();
2463
2464 p.bump();
2465
2466 let cur = p.input().cur();
2467 if !(cur.is_num() || cur.is_bigint()) {
2468 unexpected!(p, "numeric literal or bigint literal")
2469 }
2470
2471 let lit = parse_lit(p)?;
2472 let lit = match lit {
2473 Lit::Num(Number { span, value, raw }) => {
2474 let mut new_raw = String::from("-");
2475
2476 match raw {
2477 Some(raw) => {
2478 new_raw.push_str(&raw);
2479 }
2480 _ => {
2481 write!(new_raw, "{value}").unwrap();
2482 }
2483 };
2484
2485 TsLit::Number(Number {
2486 span,
2487 value: -value,
2488 raw: Some(new_raw.into()),
2489 })
2490 }
2491 Lit::BigInt(BigInt { span, value, raw }) => {
2492 let mut new_raw = String::from("-");
2493
2494 match raw {
2495 Some(raw) => {
2496 new_raw.push_str(&raw);
2497 }
2498 _ => {
2499 write!(new_raw, "{value}").unwrap();
2500 }
2501 };
2502
2503 TsLit::BigInt(BigInt {
2504 span,
2505 value: Box::new(-*value),
2506 raw: Some(new_raw.into()),
2507 })
2508 }
2509 _ => unreachable!(),
2510 };
2511
2512 return Ok(Box::new(TsType::TsLitType(TsLitType {
2513 span: p.span(start),
2514 lit,
2515 })));
2516 } else if cur.is_import() {
2517 return parse_ts_import_type(p).map(TsType::from).map(Box::new);
2518 } else if cur.is_this() {
2519 let start = p.cur_pos();
2520 let this_keyword = parse_ts_this_type_node(p)?;
2521 return if !p.input().had_line_break_before_cur() && p.input().is(&P::Token::IS) {
2522 parse_ts_this_type_predicate(p, start, false, this_keyword)
2523 .map(TsType::from)
2524 .map(Box::new)
2525 } else {
2526 Ok(Box::new(TsType::TsThisType(this_keyword)))
2527 };
2528 } else if cur.is_typeof() {
2529 return parse_ts_type_query(p).map(TsType::from).map(Box::new);
2530 } else if cur.is_lbrace() {
2531 return if ts_look_ahead(p, is_ts_start_of_mapped_type) {
2532 parse_ts_mapped_type(p).map(TsType::from).map(Box::new)
2533 } else {
2534 parse_ts_type_lit(p).map(TsType::from).map(Box::new)
2535 };
2536 } else if cur.is_lbracket() {
2537 return parse_ts_tuple_type(p).map(TsType::from).map(Box::new);
2538 } else if cur.is_lparen() {
2539 return parse_ts_parenthesized_type(p)
2540 .map(TsType::from)
2541 .map(Box::new);
2542 }
2543
2544 unexpected!(
2548 p,
2549 "an identifier, void, yield, null, await, break, a string literal, a numeric literal, \
2550 true, false, `, -, import, this, typeof, {, [, ("
2551 )
2552}
2553
2554pub fn parse_ts_expr_stmt<'a, P: Parser<'a>>(
2556 p: &mut P,
2557 decorators: Vec<Decorator>,
2558 expr: Ident,
2559) -> PResult<Option<Decl>> {
2560 if !cfg!(feature = "typescript") {
2561 return Ok(Default::default());
2562 }
2563
2564 let start = expr.span_lo();
2565
2566 match &*expr.sym {
2567 "declare" => {
2568 let decl = try_parse_ts_declare(p, start, decorators)?;
2569 if let Some(decl) = decl {
2570 Ok(Some(make_decl_declare(decl)))
2571 } else {
2572 Ok(None)
2573 }
2574 }
2575 "global" => {
2576 if p.input().is(&P::Token::LBRACE) {
2581 let global = true;
2582 let id = TsModuleName::Ident(expr);
2583 let body = parse_ts_module_block(p)
2584 .map(TsNamespaceBody::from)
2585 .map(Some)?;
2586 Ok(Some(
2587 TsModuleDecl {
2588 span: p.span(start),
2589 global,
2590 declare: false,
2591 namespace: false,
2592 id,
2593 body,
2594 }
2595 .into(),
2596 ))
2597 } else {
2598 Ok(None)
2599 }
2600 }
2601 _ => parse_ts_decl(p, start, decorators, expr.sym, false),
2602 }
2603}
2604
2605pub fn try_parse_ts_declare<'a, P: Parser<'a>>(
2607 p: &mut P,
2608 start: BytePos,
2609 decorators: Vec<Decorator>,
2610) -> PResult<Option<Decl>> {
2611 if !p.syntax().typescript() {
2612 return Ok(None);
2613 }
2614
2615 if p.ctx()
2616 .contains(Context::InDeclare | Context::TsModuleBlock)
2617 {
2618 let span_of_declare = p.span(start);
2619 p.emit_err(span_of_declare, SyntaxError::TS1038);
2620 }
2621
2622 let declare_start = start;
2623 p.do_inside_of_context(Context::InDeclare, |p| {
2624 if p.input().is(&P::Token::FUNCTION) {
2625 return parse_fn_decl(p, decorators)
2626 .map(|decl| match decl {
2627 Decl::Fn(f) => FnDecl {
2628 declare: true,
2629 function: Box::new(Function {
2630 span: Span {
2631 lo: declare_start,
2632 ..f.function.span
2633 },
2634 ..*f.function
2635 }),
2636 ..f
2637 }
2638 .into(),
2639 _ => decl,
2640 })
2641 .map(Some);
2642 }
2643
2644 if p.input().is(&P::Token::CLASS) {
2645 return parse_class_decl(p, start, start, decorators, false)
2646 .map(|decl| match decl {
2647 Decl::Class(c) => ClassDecl {
2648 declare: true,
2649 class: Box::new(Class {
2650 span: Span {
2651 lo: declare_start,
2652 ..c.class.span
2653 },
2654 ..*c.class
2655 }),
2656 ..c
2657 }
2658 .into(),
2659 _ => decl,
2660 })
2661 .map(Some);
2662 }
2663
2664 if p.input().is(&P::Token::CONST) && peek!(p).is_some_and(|peek| peek.is_enum()) {
2665 p.assert_and_bump(&P::Token::CONST);
2666 p.assert_and_bump(&P::Token::ENUM);
2667
2668 return parse_ts_enum_decl(p, start, true)
2669 .map(|decl| TsEnumDecl {
2670 declare: true,
2671 span: Span {
2672 lo: declare_start,
2673 ..decl.span
2674 },
2675 ..*decl
2676 })
2677 .map(Box::new)
2678 .map(From::from)
2679 .map(Some);
2680 }
2681
2682 let cur = p.input().cur();
2683 if cur.is_const() || cur.is_var() || cur.is_let() {
2684 return parse_var_stmt(p, false)
2685 .map(|decl| VarDecl {
2686 declare: true,
2687 span: Span {
2688 lo: declare_start,
2689 ..decl.span
2690 },
2691 ..*decl
2692 })
2693 .map(Box::new)
2694 .map(From::from)
2695 .map(Some);
2696 }
2697
2698 if p.input().is(&P::Token::GLOBAL) {
2699 return parse_ts_ambient_external_module_decl(p, start)
2700 .map(Decl::from)
2701 .map(make_decl_declare)
2702 .map(Some);
2703 } else if p.input().cur().is_word() {
2704 let value = p
2705 .input_mut()
2706 .cur()
2707 .clone()
2708 .take_word(p.input_mut())
2709 .unwrap();
2710 return parse_ts_decl(p, start, decorators, value, true)
2711 .map(|v| v.map(make_decl_declare));
2712 }
2713
2714 Ok(None)
2715 })
2716}
2717
2718pub fn try_parse_ts_export_decl<'a, P: Parser<'a>>(
2723 p: &mut P,
2724 decorators: Vec<Decorator>,
2725 value: Atom,
2726) -> Option<Decl> {
2727 if !cfg!(feature = "typescript") {
2728 return None;
2729 }
2730
2731 try_parse_ts(p, |p| {
2732 let start = p.cur_pos();
2733 let opt = parse_ts_decl(p, start, decorators, value, true)?;
2734 Ok(opt)
2735 })
2736}
2737
2738fn parse_ts_decl<'a, P: Parser<'a>>(
2743 p: &mut P,
2744 start: BytePos,
2745 decorators: Vec<Decorator>,
2746 value: Atom,
2747 next: bool,
2748) -> PResult<Option<Decl>> {
2749 if !cfg!(feature = "typescript") {
2750 return Ok(Default::default());
2751 }
2752
2753 match &*value {
2754 "abstract" => {
2755 if next || (p.input().is(&P::Token::CLASS) && !p.input().had_line_break_before_cur()) {
2756 if next {
2757 p.bump();
2758 }
2759 return Ok(Some(parse_class_decl(p, start, start, decorators, true)?));
2760 }
2761 }
2762
2763 "enum" => {
2764 if next || p.is_ident_ref() {
2765 if next {
2766 p.bump();
2767 }
2768 return parse_ts_enum_decl(p, start, false)
2769 .map(From::from)
2770 .map(Some);
2771 }
2772 }
2773
2774 "interface" => {
2775 if next || (p.is_ident_ref()) {
2776 if next {
2777 p.bump();
2778 }
2779
2780 return parse_ts_interface_decl(p, start).map(From::from).map(Some);
2781 }
2782 }
2783
2784 "module" if !p.input().had_line_break_before_cur() => {
2785 if next {
2786 p.bump();
2787 }
2788
2789 let cur = p.input().cur();
2790 if cur.is_str() {
2791 return parse_ts_ambient_external_module_decl(p, start)
2792 .map(From::from)
2793 .map(Some);
2794 } else if cur.is_error() {
2795 let err = p.input_mut().expect_error_token_and_bump();
2796 return Err(err);
2797 } else if cur.is_eof() {
2798 return Err(eof_error(p));
2799 } else if next || p.is_ident_ref() {
2800 return parse_ts_module_or_ns_decl(p, start, false)
2801 .map(From::from)
2802 .map(Some);
2803 }
2804 }
2805
2806 "namespace" => {
2807 if next || p.is_ident_ref() {
2808 if next {
2809 p.bump();
2810 }
2811 return parse_ts_module_or_ns_decl(p, start, true)
2812 .map(From::from)
2813 .map(Some);
2814 }
2815 }
2816
2817 "type" => {
2818 if next || (!p.input().had_line_break_before_cur() && p.is_ident_ref()) {
2819 if next {
2820 p.bump();
2821 }
2822 return parse_ts_type_alias_decl(p, start).map(From::from).map(Some);
2823 }
2824 }
2825
2826 _ => {}
2827 }
2828
2829 Ok(None)
2830}
2831
2832pub fn try_parse_ts_generic_async_arrow_fn<'a, P: Parser<'a>>(
2834 p: &mut P,
2835 start: BytePos,
2836) -> PResult<Option<ArrowExpr>> {
2837 if !cfg!(feature = "typescript") {
2838 return Ok(Default::default());
2839 }
2840
2841 let cur = p.input().cur();
2842 let res = if cur.is_less() || cur.is_jsx_tag_start() {
2843 try_parse_ts(p, |p| {
2844 let type_params = parse_ts_type_params(p, false, false)?;
2845 expect!(p, &P::Token::LPAREN);
2847 let params: Vec<Pat> = parse_formal_params(p)?.into_iter().map(|p| p.pat).collect();
2848 expect!(p, &P::Token::RPAREN);
2849 let return_type = try_parse_ts_type_or_type_predicate_ann(p)?;
2850 expect!(p, &P::Token::ARROW);
2851
2852 Ok(Some((type_params, params, return_type)))
2853 })
2854 } else {
2855 None
2856 };
2857
2858 let (type_params, params, return_type) = match res {
2859 Some(v) => v,
2860 None => return Ok(None),
2861 };
2862
2863 p.do_inside_of_context(Context::InAsync, |p| {
2864 p.do_outside_of_context(Context::InGenerator, |p| {
2865 let is_generator = false;
2866 let is_async = true;
2867 let body = parse_fn_block_or_expr_body(
2868 p,
2869 true,
2870 false,
2871 true,
2872 params.is_simple_parameter_list(),
2873 )?;
2874 Ok(Some(ArrowExpr {
2875 span: p.span(start),
2876 body,
2877 is_async,
2878 is_generator,
2879 type_params: Some(type_params),
2880 params,
2881 return_type,
2882 ..Default::default()
2883 }))
2884 })
2885 })
2886}