1use std::ops::Neg;
2
3use crate::ast::VariableOrPropertyAccess;
4use crate::{
5 derive_ASTNode, parse_bracketed, throw_unexpected_token_with_token, to_string_bracketed,
6 ListItem, ParseErrors, Quoted,
7};
8use crate::{
9 errors::parse_lexing_error, extensions::decorators::Decorated, Decorator, Marker, ParseResult,
10 VariableField, WithComment,
11};
12use derive_partial_eq_extras::PartialEqExtras;
13use iterator_endiate::EndiateIteratorExt;
14use tokenizer_lib::sized_tokens::{SizedToken, TokenEnd, TokenReaderWithTokenEnds, TokenStart};
15
16use super::{
17 interface::{parse_interface_members, InterfaceMember},
18 type_declarations::TypeParameter,
19};
20
21use crate::{
22 number::NumberRepresentation, tokens::token_as_identifier, ASTNode, ParseError, ParseOptions,
23 Span, TSXKeyword, TSXToken, Token, TokenReader,
24};
25
26#[apply(derive_ASTNode)]
28#[derive(Debug, Clone, PartialEqExtras, get_field_by_type::GetFieldByType)]
29#[get_field_by_type_target(Span)]
30#[partial_eq_ignore_types(Span)]
31pub enum TypeAnnotation {
32 CommonName(CommonTypes, Span),
34 Name(TypeName, Span),
36 NameWithGenericArguments(TypeName, Vec<TypeAnnotation>, Span),
38 Union(Vec<TypeAnnotation>, Span),
40 Intersection(Vec<TypeAnnotation>, Span),
42 StringLiteral(String, Quoted, Span),
44 NumberLiteral(NumberRepresentation, Span),
46 BooleanLiteral(bool, Span),
48 ArrayLiteral(Box<TypeAnnotation>, Span),
51 FunctionLiteral {
53 type_parameters: Option<Vec<TypeParameter>>,
54 parameters: TypeAnnotationFunctionParameters,
55 return_type: Box<TypeAnnotation>,
56 position: Span,
57 },
58 ConstructorLiteral {
60 type_parameters: Option<Vec<TypeParameter>>,
61 parameters: TypeAnnotationFunctionParameters,
62 return_type: Box<TypeAnnotation>,
63 position: Span,
64 },
65 ObjectLiteral(Vec<WithComment<Decorated<InterfaceMember>>>, Span),
67 TupleLiteral(Vec<TupleLiteralElement>, Span),
69 TemplateLiteral {
71 parts: Vec<(String, AnnotationWithBinder)>,
72 last: String,
73 position: Span,
74 },
75 Readonly(Box<TypeAnnotation>, Span),
77 Abstract(Box<TypeAnnotation>, Span),
79 Index(Box<TypeAnnotation>, Box<TypeAnnotation>, Span),
81 KeyOf(Box<TypeAnnotation>, Span),
83 TypeOf(Box<VariableOrPropertyAccess>, Span),
84 Infer {
85 name: String,
86 extends: Option<Box<TypeAnnotation>>,
87 position: Span,
88 },
89 Asserts(Box<TypeAnnotation>, Span),
91 Extends {
92 item: Box<TypeAnnotation>,
93 extends: Box<TypeAnnotation>,
94 position: Span,
95 },
96 Is {
97 reference: IsItem,
98 is: Box<TypeAnnotation>,
99 position: Span,
100 },
101 Conditional {
102 condition: Box<TypeAnnotation>,
103 resolve_true: Box<TypeAnnotation>,
104 resolve_false: Box<TypeAnnotation>,
105 position: Span,
106 },
107 Symbol {
108 unique: bool,
110 #[cfg(feature = "extras")]
111 name: Option<String>,
112 position: Span,
113 },
114 ParenthesizedReference(Box<TypeAnnotation>, Span),
116 Decorated(
118 Decorator,
119 #[cfg_attr(target_family = "wasm", tsify(type = "TypeAnnotation"))] Box<Self>,
120 Span,
121 ),
122 This(Span),
124 #[cfg_attr(feature = "self-rust-tokenize", self_tokenize_field(0))]
125 Marker(Marker<TypeAnnotation>, Span),
126}
127
128impl ListItem for TypeAnnotation {
129 type LAST = ();
130}
131
132#[derive(Debug, Clone, PartialEq)]
133#[apply(derive_ASTNode)]
134pub enum AnnotationWithBinder {
135 Annotated { name: String, ty: TypeAnnotation, position: Span },
136 NoAnnotation(TypeAnnotation),
137}
138
139impl ASTNode for AnnotationWithBinder {
140 fn get_position(&self) -> Span {
141 match self {
142 AnnotationWithBinder::Annotated { position, .. } => *position,
143 AnnotationWithBinder::NoAnnotation(ty) => ty.get_position(),
144 }
145 }
146
147 fn from_reader(
148 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
149 state: &mut crate::ParsingState,
150 options: &ParseOptions,
151 ) -> ParseResult<Self> {
152 if let Some(Token(TSXToken::Colon, _)) = reader.peek_n(1) {
153 let (name, pos) =
154 token_as_identifier(reader.next().unwrap(), "tuple literal named item")?;
155 reader.next();
156 let ty = TypeAnnotation::from_reader(reader, state, options)?;
157 Ok(AnnotationWithBinder::Annotated { position: pos.union(ty.get_position()), name, ty })
158 } else {
159 TypeAnnotation::from_reader(reader, state, options).map(Self::NoAnnotation)
160 }
161 }
162
163 fn to_string_from_buffer<T: source_map::ToString>(
164 &self,
165 buf: &mut T,
166 options: &crate::ToStringOptions,
167 local: crate::LocalToStringInformation,
168 ) {
169 if let AnnotationWithBinder::Annotated { name, .. } = self {
170 buf.push_str(name);
171 buf.push_str(": ");
172 }
173 self.get_inner_ref().to_string_from_buffer(buf, options, local);
174 }
175}
176
177impl AnnotationWithBinder {
178 #[must_use]
179 pub fn get_inner_ref(&self) -> &TypeAnnotation {
180 match self {
181 AnnotationWithBinder::Annotated { ty, .. } | AnnotationWithBinder::NoAnnotation(ty) => {
182 ty
183 }
184 }
185 }
186}
187
188#[derive(Debug, Clone, PartialEq)]
189#[apply(derive_ASTNode)]
190pub enum TupleElementKind {
191 Standard,
192 Spread,
193 Optional,
194}
195
196#[derive(Debug, Clone, PartialEq)]
198#[apply(derive_ASTNode)]
199pub enum CommonTypes {
200 String,
201 Number,
202 Boolean,
203 Any,
204 Null,
205 Undefined,
206 Unknown,
207 Never,
208}
209
210impl CommonTypes {
211 fn name(&self) -> &'static str {
212 match self {
213 CommonTypes::String => "string",
214 CommonTypes::Number => "number",
215 CommonTypes::Boolean => "boolean",
216 CommonTypes::Any => "any",
217 CommonTypes::Null => "null",
218 CommonTypes::Undefined => "undefined",
219 CommonTypes::Never => "never",
220 CommonTypes::Unknown => "unknown",
221 }
222 }
223}
224
225#[apply(derive_ASTNode)]
226#[derive(Debug, Clone, PartialEq)]
227pub enum TypeName {
228 Name(String),
229 FromNamespace(Vec<String>),
231}
232
233#[apply(derive_ASTNode)]
234#[derive(Debug, Clone, PartialEq)]
235pub enum IsItem {
236 Reference(String),
237 This,
238}
239
240impl ASTNode for TypeAnnotation {
241 fn from_reader(
242 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
243 state: &mut crate::ParsingState,
244 options: &ParseOptions,
245 ) -> ParseResult<Self> {
246 Self::from_reader_with_config(reader, state, options, None, None)
247 }
248
249 fn to_string_from_buffer<T: source_map::ToString>(
250 &self,
251 buf: &mut T,
252 options: &crate::ToStringOptions,
253 local: crate::LocalToStringInformation,
254 ) {
255 match self {
256 Self::Marker(..) => {
257 assert!(options.expect_markers,);
258 }
259 Self::CommonName(name, _) => buf.push_str(name.name()),
260 Self::Decorated(decorator, on_type_annotation, _) => {
261 decorator.to_string_from_buffer(buf, options, local);
262 buf.push(' ');
263 on_type_annotation.to_string_from_buffer(buf, options, local);
264 }
265 Self::Name(name, _) => match name {
266 TypeName::Name(name) => {
267 buf.push_str(name);
268 }
269 TypeName::FromNamespace(namespace) => {
270 for (not_at_end, item) in namespace.iter().nendiate() {
271 buf.push_str(item);
272 if not_at_end {
273 buf.push('.');
274 }
275 }
276 }
277 },
278 Self::NameWithGenericArguments(name, arguments, _) => {
279 match name {
280 TypeName::Name(name) => {
281 buf.push_str(name);
282 }
283 TypeName::FromNamespace(namespace) => {
284 for (not_at_end, item) in namespace.iter().nendiate() {
285 buf.push_str(item);
286 if not_at_end {
287 buf.push('.');
288 }
289 }
290 }
291 }
292 to_string_bracketed(arguments, ('<', '>'), buf, options, local);
293 }
294 Self::FunctionLiteral { type_parameters, parameters, return_type, .. } => {
295 if let Some(type_parameters) = type_parameters {
296 to_string_bracketed(type_parameters, ('<', '>'), buf, options, local);
297 }
298 parameters.to_string_from_buffer(buf, options, local);
299 buf.push_str(" => ");
300 return_type.to_string_from_buffer(buf, options, local);
301 }
302 Self::BooleanLiteral(true, _) => buf.push_str("true"),
303 Self::BooleanLiteral(false, _) => buf.push_str("false"),
304 Self::This(..) => buf.push_str("this"),
305 Self::NumberLiteral(value, _) => {
306 buf.push_str(&value.to_string());
307 }
308 Self::StringLiteral(expression, quoted, _) => {
309 buf.push(quoted.as_char());
310 buf.push_str(expression.as_str());
311 buf.push(quoted.as_char());
312 }
313 Self::Union(union_members, _) => {
314 for (at_end, member) in union_members.iter().endiate() {
315 member.to_string_from_buffer(buf, options, local);
316 if !at_end {
317 buf.push_str(" | ");
318 }
319 }
320 }
321 Self::Intersection(intersection_members, _) => {
322 for (at_end, member) in intersection_members.iter().endiate() {
323 member.to_string_from_buffer(buf, options, local);
324 if !at_end {
325 buf.push_str(" & ");
326 }
327 }
328 }
329 Self::TypeOf(on, _pos) => {
330 buf.push_str("typeof ");
331 on.to_string_from_buffer(buf, options, local);
332 }
333 Self::Infer { name, extends, position: _ } => {
334 buf.push_str("infer ");
335 buf.push_str(name.as_str());
336 if let Some(ref extends) = extends {
337 buf.push_str(" extends ");
338 extends.to_string_from_buffer(buf, options, local);
339 }
340 }
341 Self::ObjectLiteral(members, _) => {
342 to_string_bracketed(members, ('{', '}'), buf, options, local);
343 }
344 Self::TupleLiteral(members, _) => {
345 to_string_bracketed(members, ('[', ']'), buf, options, local);
346 }
347 Self::Index(on, with, _) => {
348 on.to_string_from_buffer(buf, options, local);
349 buf.push('[');
350 with.to_string_from_buffer(buf, options, local);
351 buf.push(']');
352 }
353 Self::Abstract(item, _) => {
354 buf.push_str("abstract ");
355 item.to_string_from_buffer(buf, options, local);
356 }
357 Self::KeyOf(item, _) => {
358 buf.push_str("keyof ");
359 item.to_string_from_buffer(buf, options, local);
360 }
361 Self::Conditional { condition, resolve_true, resolve_false, .. } => {
362 let split_lines = crate::are_nodes_over_length(
364 [condition, resolve_true, resolve_false].iter().map(AsRef::as_ref),
365 options,
366 local,
367 Some(
368 u32::from(options.max_line_length)
369 .saturating_sub(buf.characters_on_current_line()),
370 ),
371 true,
372 );
373 condition.to_string_from_buffer(buf, options, local);
374 if split_lines {
375 buf.push_new_line();
376 options.add_indent(local.depth + 1, buf);
377 buf.push_str("? ");
378 } else {
379 buf.push_str(if options.pretty { " ? " } else { "?" });
380 }
381 resolve_true.to_string_from_buffer(buf, options, local);
382 if split_lines {
383 buf.push_new_line();
384 options.add_indent(local.depth + 1, buf);
385 buf.push_str(": ");
386 } else {
387 buf.push_str(if options.pretty { " : " } else { ":" });
388 }
389 resolve_false.to_string_from_buffer(buf, options, local);
390 }
391 Self::ArrayLiteral(item, _) => {
392 item.to_string_from_buffer(buf, options, local);
393 buf.push_str("[]");
394 }
395 Self::ConstructorLiteral { parameters, type_parameters, return_type, .. } => {
396 buf.push_str("new ");
397 if let Some(type_parameters) = type_parameters {
398 to_string_bracketed(type_parameters, ('<', '>'), buf, options, local);
399 }
400 parameters.to_string_from_buffer(buf, options, local);
401 buf.push_str(" => ");
402 return_type.to_string_from_buffer(buf, options, local);
403 }
404 Self::Readonly(readonly_type, _) => {
405 buf.push_str("readonly ");
406 readonly_type.to_string_from_buffer(buf, options, local);
407 }
408 Self::ParenthesizedReference(reference, _) => {
409 buf.push('(');
410 reference.to_string_from_buffer(buf, options, local);
411 buf.push(')');
412 }
413 Self::TemplateLiteral { parts, last, .. } => {
414 buf.push('`');
415 for (static_part, dynamic_part) in parts {
416 buf.push_str_contains_new_line(static_part.as_str());
417
418 buf.push_str("${");
419 dynamic_part.to_string_from_buffer(buf, options, local);
420 buf.push('}');
421 }
422 buf.push_str_contains_new_line(last.as_str());
423 buf.push('`');
424 }
425 Self::Symbol { unique, .. } => {
426 if *unique {
427 buf.push_str("unique ");
428 }
429 buf.push_str("symbol");
430 }
431 Self::Extends { item, extends, .. } => {
432 item.to_string_from_buffer(buf, options, local);
433 buf.push_str(" extends ");
434 extends.to_string_from_buffer(buf, options, local);
435 }
436 Self::Is { reference, is, .. } => {
437 buf.push_str(match reference {
438 IsItem::Reference(reference) => reference,
439 IsItem::This => "this",
440 });
441 buf.push_str(" is ");
442 is.to_string_from_buffer(buf, options, local);
443 }
444 Self::Asserts(predicate, _pos) => {
445 buf.push_str("asserts ");
446 predicate.to_string_from_buffer(buf, options, local);
447 }
448 }
449 }
450
451 fn get_position(&self) -> Span {
452 *get_field_by_type::GetFieldByType::get(self)
453 }
454}
455
456#[derive(Clone, Copy)]
458pub(crate) enum TypeOperatorKind {
459 Union,
460 Intersection,
461 Function,
463 Query,
464}
465
466impl TypeAnnotation {
467 pub(crate) fn from_reader_with_config(
470 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
471 state: &mut crate::ParsingState,
472 options: &ParseOptions,
473 parent_kind: Option<TypeOperatorKind>,
474 start: Option<TokenStart>,
475 ) -> ParseResult<Self> {
476 if let (true, Some(Token(peek, at))) = (options.partial_syntax, reader.peek()) {
477 let next_is_not_type_annotation_like = matches!(
478 peek,
479 TSXToken::CloseParentheses
480 | TSXToken::CloseBracket
481 | TSXToken::CloseBrace
482 | TSXToken::Comma
483 | TSXToken::OpenChevron
484 ) || peek.is_assignment()
485 || (start.map_or(false, |start| {
486 peek.is_statement_or_declaration_start()
487 && state
488 .line_starts
489 .byte_indexes_on_different_lines(start.0 as usize, at.0 as usize)
490 }));
491
492 if next_is_not_type_annotation_like {
493 let point = start.unwrap_or(*at);
494 let position = point.union(source_map::End(at.0));
496 return Ok(TypeAnnotation::Marker(state.new_partial_point_marker(point), position));
497 }
498 }
499
500 while let Some(Token(TSXToken::Comment(_) | TSXToken::MultiLineComment(_), _)) =
501 reader.peek()
502 {
503 reader.next();
504 }
505
506 if let (None, Some(Token(TSXToken::BitwiseOr, _))) = (parent_kind, reader.peek()) {
507 reader.next();
508 }
509 if let (None, Some(Token(TSXToken::BitwiseAnd, _))) = (parent_kind, reader.peek()) {
510 reader.next();
511 }
512
513 let mut reference = match reader.next().ok_or_else(parse_lexing_error)? {
514 t @ Token(TSXToken::Keyword(TSXKeyword::True), _) => {
516 Self::BooleanLiteral(true, t.get_span())
517 }
518 t @ Token(TSXToken::Keyword(TSXKeyword::False), _) => {
519 Self::BooleanLiteral(false, t.get_span())
520 }
521 t @ Token(TSXToken::Keyword(TSXKeyword::This), _) => Self::This(t.get_span()),
522 Token(TSXToken::Keyword(TSXKeyword::Infer), start) => {
523 let token = reader.next().ok_or_else(parse_lexing_error)?;
524 let (name, position) = token_as_identifier(token, "infer name")?;
525 let (position, extends) = if reader
526 .conditional_next(|t| matches!(t, TSXToken::Keyword(TSXKeyword::Extends)))
527 .is_some()
528 {
529 let extends = TypeAnnotation::from_reader_with_config(
530 reader,
531 state,
532 options,
533 Some(TypeOperatorKind::Query),
534 None,
535 )?;
536 (start.union(extends.get_position()), Some(Box::new(extends)))
537 } else {
538 (start.union(position), None)
539 };
540 Self::Infer { name, extends, position }
541 }
542 Token(TSXToken::Keyword(TSXKeyword::Asserts), start) => {
543 let predicate = TypeAnnotation::from_reader_with_config(
544 reader,
545 state,
546 options,
547 parent_kind,
548 Some(start),
549 )?;
550 let position = start.union(predicate.get_position());
551 Self::Asserts(Box::new(predicate), position)
552 }
553 Token(TSXToken::Keyword(TSXKeyword::TypeOf), start) => {
554 let reference = VariableOrPropertyAccess::from_reader(reader, state, options)?;
555 let position = start.union(reference.get_position());
556 Self::TypeOf(Box::new(reference), position)
557 }
558 t @ Token(TSXToken::Keyword(TSXKeyword::Symbol), _) => {
559 let position = t.get_span();
560 #[cfg(feature = "extras")]
561 let name =
562 reader.conditional_next(|t| matches!(t, TSXToken::StringLiteral(..))).map(
563 |t| {
564 if let Token(TSXToken::StringLiteral(content, _), _) = t {
565 content
566 } else {
567 unreachable!()
568 }
569 },
570 );
571 Self::Symbol {
572 unique: false,
573 position,
574 #[cfg(feature = "extras")]
575 name,
576 }
577 }
578 t @ Token(TSXToken::Keyword(TSXKeyword::Unique), _) => {
579 let kw_pos = reader.expect_next(TSXToken::Keyword(TSXKeyword::Symbol))?;
580 let position = t.get_span().union(kw_pos.with_length("symbol".len()));
581 #[cfg(feature = "extras")]
582 let name =
583 reader.conditional_next(|t| matches!(t, TSXToken::StringLiteral(..))).map(
584 |t| {
585 if let Token(TSXToken::StringLiteral(content, _), _) = t {
586 content
587 } else {
588 unreachable!()
589 }
590 },
591 );
592 Self::Symbol {
593 unique: true,
594 position,
595 #[cfg(feature = "extras")]
596 name,
597 }
598 }
599 Token(TSXToken::NumberLiteral(value), start) => {
600 let position = start.with_length(value.len());
601 match value.parse::<NumberRepresentation>() {
602 Ok(number) => Self::NumberLiteral(number, position),
603 Err(_) => {
604 return Err(crate::ParseError::new(
606 crate::ParseErrors::InvalidNumberLiteral,
607 position,
608 ));
609 }
610 }
611 }
612 Token(TSXToken::Subtract, start) => {
613 let Token(token, pos) = reader.next().ok_or_else(parse_lexing_error)?;
614 if let TSXToken::NumberLiteral(value) = token {
615 let position = pos.union(start.with_length(value.len()));
616 match value.parse::<NumberRepresentation>() {
617 Ok(number) => Self::NumberLiteral(number.neg(), position),
618 Err(_) => {
619 return Err(crate::ParseError::new(
621 crate::ParseErrors::InvalidNumberLiteral,
622 position,
623 ));
624 }
625 }
626 } else {
627 return Err(ParseError::new(
628 ParseErrors::ExpectedNumberLiteral,
629 start.with_length(token.length() as usize + 1),
630 ));
631 }
632 }
633 Token(TSXToken::StringLiteral(content, quoted), start) => {
634 let pos = start.with_length(content.len() + 2);
635 Self::StringLiteral(content, quoted, pos)
636 }
637 Token(TSXToken::At, pos) => {
638 let decorator = Decorator::from_reader_sub_at_symbol(reader, state, options, pos)?;
639 let this_declaration = Self::from_reader_with_config(
641 reader,
642 state,
643 options,
644 Some(TypeOperatorKind::Query),
645 start,
646 )?;
647 let position = pos.union(this_declaration.get_position());
648 Self::Decorated(decorator, Box::new(this_declaration), position)
649 }
650 Token(TSXToken::OpenParentheses, start) => {
652 let mut bracket_count = 1;
654 let next = reader.scan(|t, _| {
655 match t {
656 TSXToken::OpenParentheses => {
657 bracket_count += 1;
658 }
659 TSXToken::CloseParentheses => {
660 bracket_count -= 1;
661 }
662 _ => {}
663 }
664 bracket_count == 0
665 });
666 if let Some(Token(TSXToken::Arrow, _)) = next {
668 let parameters =
669 TypeAnnotationFunctionParameters::from_reader_sub_open_parenthesis(
670 reader, state, options, start,
671 )?;
672 reader.expect_next(TSXToken::Arrow)?;
673 let return_type = Self::from_reader(reader, state, options)?;
674 Self::FunctionLiteral {
675 position: start.union(return_type.get_position()),
676 type_parameters: None,
677 parameters,
678 return_type: Box::new(return_type),
679 }
680 } else {
681 let type_annotation = Self::from_reader(reader, state, options)?;
682 let position =
683 start.union(reader.expect_next_get_end(TSXToken::CloseParentheses)?);
684 Self::ParenthesizedReference(type_annotation.into(), position)
685 }
686 }
687 Token(TSXToken::OpenChevron, start) => {
688 let (type_parameters, _, _) =
689 parse_bracketed(reader, state, options, None, TSXToken::CloseChevron)?;
690 let parameters =
691 TypeAnnotationFunctionParameters::from_reader(reader, state, options)?;
692 reader.expect_next(TSXToken::Arrow)?;
693 let return_type = Self::from_reader(reader, state, options)?;
694 Self::FunctionLiteral {
695 position: start.union(return_type.get_position()),
696 type_parameters: Some(type_parameters),
697 parameters,
698 return_type: Box::new(return_type),
699 }
700 }
701 Token(TSXToken::OpenBrace, start) => {
703 let members = parse_interface_members(reader, state, options)?;
704 let position = start.union(reader.expect_next_get_end(TSXToken::CloseBrace)?);
705 Self::ObjectLiteral(members, position)
706 }
707 Token(TSXToken::OpenBracket, start) => {
709 let (members, _, end) =
710 parse_bracketed(reader, state, options, None, TSXToken::CloseBracket)?;
711 let position = start.union(end);
712 Self::TupleLiteral(members, position)
713 }
714 Token(TSXToken::TemplateLiteralStart, start) => {
715 let mut parts = Vec::new();
716 let mut last = String::new();
717 let mut end: Option<TokenEnd> = None;
718 while end.is_none() {
719 match reader.next().ok_or_else(parse_lexing_error)? {
720 Token(TSXToken::TemplateLiteralChunk(chunk), _) => {
721 last = chunk;
722 }
723 Token(TSXToken::TemplateLiteralExpressionStart, _) => {
724 let expression =
725 AnnotationWithBinder::from_reader(reader, state, options)?;
726 parts.push((std::mem::take(&mut last), expression));
727 let next = reader.next();
728 debug_assert!(matches!(
729 next,
730 Some(Token(TSXToken::TemplateLiteralExpressionEnd, _))
731 ));
732 }
733 Token(TSXToken::TemplateLiteralEnd, end_position) => {
734 end = Some(TokenEnd::new(end_position.0));
735 }
736 Token(TSXToken::EOS, _) => return Err(parse_lexing_error()),
737 t => unreachable!("Token {:?}", t),
738 }
739 }
740 Self::TemplateLiteral { parts, last, position: start.union(end.unwrap()) }
741 }
742 Token(TSXToken::Keyword(TSXKeyword::Readonly), start) => {
743 let readonly_type = TypeAnnotation::from_reader_with_config(
744 reader,
745 state,
746 options,
747 Some(TypeOperatorKind::Query),
748 Some(start),
749 )?;
750 let position = start.union(readonly_type.get_position());
751 TypeAnnotation::Readonly(Box::new(readonly_type), position)
752 }
753 Token(TSXToken::Keyword(TSXKeyword::KeyOf), start) => {
754 let key_of_type = TypeAnnotation::from_reader_with_config(
755 reader,
756 state,
757 options,
758 Some(TypeOperatorKind::Query),
759 Some(start),
760 )?;
761 let position = start.union(key_of_type.get_position());
762 TypeAnnotation::KeyOf(Box::new(key_of_type), position)
763 }
764 Token(TSXToken::Keyword(TSXKeyword::Abstract), start) => {
766 let inner_type = TypeAnnotation::from_reader_with_config(
767 reader,
768 state,
769 options,
770 Some(TypeOperatorKind::Query),
771 Some(start),
772 )?;
773 let position = start.union(inner_type.get_position());
774 TypeAnnotation::Abstract(Box::new(inner_type), position)
775 }
776 Token(TSXToken::Keyword(TSXKeyword::New), start) => {
777 let type_parameters = reader
778 .conditional_next(|token| *token == TSXToken::OpenChevron)
779 .is_some()
780 .then(|| {
781 parse_bracketed(reader, state, options, None, TSXToken::CloseChevron)
782 .map(|(params, _, _)| params)
783 })
784 .transpose()?;
785 let parameters =
786 TypeAnnotationFunctionParameters::from_reader(reader, state, options)?;
787
788 reader.expect_next(TSXToken::Arrow)?;
789 let return_type = Self::from_reader(reader, state, options)?;
790 Self::ConstructorLiteral {
791 position: start.union(return_type.get_position()),
792 parameters,
793 type_parameters,
794 return_type: Box::new(return_type),
795 }
796 }
797 token => {
798 let (name, pos) = token_as_identifier(token, "type reference")?;
799 match name.as_str() {
800 "string" => Self::CommonName(CommonTypes::String, pos),
801 "number" => Self::CommonName(CommonTypes::Number, pos),
802 "boolean" => Self::CommonName(CommonTypes::Boolean, pos),
803 "any" => Self::CommonName(CommonTypes::Any, pos),
804 "null" => Self::CommonName(CommonTypes::Null, pos),
805 "undefined" => Self::CommonName(CommonTypes::Undefined, pos),
806 "unknown" => Self::CommonName(CommonTypes::Unknown, pos),
807 "never" => Self::CommonName(CommonTypes::Never, pos),
808 _ => Self::Name(TypeName::Name(name), pos),
809 }
810 }
811 };
812 if let Some(Token(TSXToken::Dot, _)) = reader.peek() {
814 let Self::Name(TypeName::Name(name), mut position) = reference else {
815 return Ok(reference);
816 };
817 let mut namespace = vec![name];
818 while reader.conditional_next(|tok| *tok == TSXToken::Dot).is_some() {
819 let (part, end) = token_as_identifier(reader.next().unwrap(), "namespace name")?;
820 namespace.push(part);
821 position = position.union(end);
822 }
823 reference = Self::Name(TypeName::FromNamespace(namespace), position);
824 }
825
826 if let Some(Token(TSXToken::OpenChevron, _position)) = reader.peek() {
828 let Self::Name(name, start_span) = reference else {
830 let position = reader.next().unwrap().get_span();
831 return Err(ParseError::new(
832 crate::ParseErrors::TypeArgumentsNotValidOnReference,
833 position,
834 ));
835 };
836 reader.next();
837 let (generic_arguments, end) =
838 generic_arguments_from_reader_sub_open_angle(reader, state, options, parent_kind)?;
839 reference =
840 Self::NameWithGenericArguments(name, generic_arguments, start_span.union(end));
841 };
842
843 while reader.conditional_next(|tok| *tok == TSXToken::OpenBracket).is_some() {
846 let start = reference.get_position();
847 if let Some(Token(TSXToken::CloseBracket, _)) = reader.peek() {
848 let position = reference
849 .get_position()
850 .union(reader.next().ok_or_else(parse_lexing_error)?.get_end());
851 reference = Self::ArrayLiteral(Box::new(reference), position);
852 } else {
853 let indexer = TypeAnnotation::from_reader(reader, state, options)?;
855 let position = start.union(reader.expect_next_get_end(TSXToken::CloseBracket)?);
856 reference = Self::Index(Box::new(reference), Box::new(indexer), position);
857 }
858 }
859
860 if let Some(Token(TSXToken::Keyword(TSXKeyword::Is), _)) = reader.peek() {
861 fn type_annotation_as_name(
862 reference: TypeAnnotation,
863 ) -> Result<(IsItem, Span), TypeAnnotation> {
864 match reference {
865 TypeAnnotation::CommonName(name, span) => {
866 Ok((IsItem::Reference(name.name().to_owned()), span))
867 }
868 TypeAnnotation::Name(TypeName::Name(name), span) => {
869 Ok((IsItem::Reference(name), span))
870 }
871 TypeAnnotation::This(span) => Ok((IsItem::This, span)),
872 _ => Err(reference),
873 }
874 }
875
876 match type_annotation_as_name(reference) {
877 Ok((item, span)) => {
878 reader.next();
879 let is_type = TypeAnnotation::from_reader_with_config(
880 reader,
881 state,
882 options,
883 Some(TypeOperatorKind::Query),
884 Some(span.get_start()),
885 )?;
886 let position = span.union(is_type.get_position());
888
889 reference =
890 TypeAnnotation::Is { reference: item, is: Box::new(is_type), position };
891 }
892 Err(reference) => {
893 return Err(ParseError::new(
894 crate::ParseErrors::InvalidLHSOfIs,
895 reference.get_position(),
896 ));
897 }
898 }
899 }
900
901 if let Some(Token(TSXToken::Keyword(TSXKeyword::Extends), _)) = reader.peek() {
902 if parent_kind.is_some() {
903 return Ok(reference);
904 }
905 reader.next();
906 let extends_type = TypeAnnotation::from_reader_with_config(
907 reader,
908 state,
909 options,
910 Some(TypeOperatorKind::Query),
911 start,
912 )?;
913 let position = reference.get_position().union(extends_type.get_position());
915 reference = TypeAnnotation::Extends {
916 item: Box::new(reference),
917 extends: Box::new(extends_type),
918 position,
919 };
920 }
921
922 match reader.peek() {
924 Some(Token(TSXToken::BitwiseOr, _)) => {
925 if let Some(TypeOperatorKind::Query | TypeOperatorKind::Function) = parent_kind {
926 return Ok(reference);
927 }
928 let mut union_members = vec![reference];
929 while let Some(Token(TSXToken::BitwiseOr, _)) = reader.peek() {
930 reader.next();
931 union_members.push(Self::from_reader_with_config(
932 reader,
933 state,
934 options,
935 Some(parent_kind.unwrap_or(TypeOperatorKind::Union)),
936 start,
937 )?);
938 }
939 let position = union_members
940 .first()
941 .unwrap()
942 .get_position()
943 .union(union_members.last().unwrap().get_position());
944 Ok(Self::Union(union_members, position))
945 }
946 Some(Token(TSXToken::BitwiseAnd, _)) => {
947 if let Some(
948 TypeOperatorKind::Union | TypeOperatorKind::Query | TypeOperatorKind::Function,
949 ) = parent_kind
950 {
951 return Ok(reference);
952 }
953 let mut intersection_members = vec![reference];
954 while let Some(Token(TSXToken::BitwiseAnd, _)) = reader.peek() {
955 reader.next();
956 intersection_members.push(Self::from_reader_with_config(
957 reader,
958 state,
959 options,
960 Some(parent_kind.unwrap_or(TypeOperatorKind::Intersection)),
961 start,
962 )?);
963 }
964 let position = intersection_members
965 .first()
966 .unwrap()
967 .get_position()
968 .union(intersection_members.last().unwrap().get_position());
969
970 Ok(Self::Intersection(intersection_members, position))
971 }
972 Some(Token(TSXToken::Arrow, _)) => {
973 if let Some(TypeOperatorKind::Query | TypeOperatorKind::Function) = parent_kind {
974 return Ok(reference);
975 }
976 reader.next();
977 let return_type = Self::from_reader_with_config(
978 reader,
979 state,
980 options,
981 Some(TypeOperatorKind::Function),
982 start,
983 )?;
984 let parameters_position = reference.get_position();
985 let position = parameters_position.union(return_type.get_position());
986 Ok(Self::FunctionLiteral {
987 position,
988 type_parameters: None,
989 parameters: TypeAnnotationFunctionParameters {
990 parameters: vec![TypeAnnotationFunctionParameter {
991 position,
992 name: None,
993 type_annotation: reference,
994 is_optional: false,
995 decorators: Default::default(),
996 }],
997 rest_parameter: None,
998 position: parameters_position,
999 },
1000 return_type: Box::new(return_type),
1001 })
1002 }
1003 Some(Token(TSXToken::QuestionMark, _)) => {
1004 if let Some(TypeOperatorKind::Query) = parent_kind {
1005 return Ok(reference);
1006 }
1007 reader.next();
1008 let lhs = TypeAnnotation::from_reader(reader, state, options)?;
1009 reader.expect_next(TSXToken::Colon)?;
1010 let rhs = TypeAnnotation::from_reader(reader, state, options)?;
1011 let position = reference.get_position().union(rhs.get_position());
1012 Ok(TypeAnnotation::Conditional {
1014 condition: Box::new(reference),
1015 resolve_true: Box::new(lhs),
1016 resolve_false: Box::new(rhs),
1017 position,
1018 })
1019 }
1020 _ => Ok(reference),
1021 }
1022 }
1023}
1024
1025pub(crate) fn generic_arguments_from_reader_sub_open_angle(
1029 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
1030 state: &mut crate::ParsingState,
1031 options: &ParseOptions,
1032 kind: Option<TypeOperatorKind>,
1033) -> ParseResult<(Vec<TypeAnnotation>, TokenEnd)> {
1034 let mut generic_arguments = Vec::new();
1035
1036 loop {
1037 let argument = TypeAnnotation::from_reader_with_config(reader, state, options, kind, None)?;
1038
1039 generic_arguments.push(argument);
1040
1041 let peek_mut = reader.peek_mut();
1046
1047 if let Some(Token(t @ TSXToken::BitwiseShiftRight, start)) = peek_mut {
1048 let end = TokenEnd::new(start.0 + 1);
1049 start.0 += 1;
1050 *t = TSXToken::CloseChevron;
1051 return Ok((generic_arguments, end));
1052 }
1053
1054 if let Some(Token(t @ TSXToken::BitwiseShiftRightUnsigned, start)) = peek_mut {
1055 let end = TokenEnd::new(start.0 + 2);
1056 start.0 += 2;
1057 *t = TSXToken::CloseChevron;
1058 return Ok((generic_arguments, end));
1059 }
1060
1061 match reader.next().ok_or_else(parse_lexing_error)? {
1062 Token(TSXToken::Comma, _) => {}
1063 t @ Token(TSXToken::CloseChevron, _) => return Ok((generic_arguments, t.get_end())),
1064 token => {
1065 return throw_unexpected_token_with_token(
1066 token,
1067 &[TSXToken::CloseChevron, TSXToken::Comma],
1068 )
1069 }
1070 };
1071 }
1072}
1073
1074#[derive(Debug, Clone, PartialEq)]
1076#[apply(derive_ASTNode)]
1077pub struct TypeAnnotationFunctionParameters {
1078 pub parameters: Vec<TypeAnnotationFunctionParameter>,
1079 pub rest_parameter: Option<Box<TypeAnnotationSpreadFunctionParameter>>,
1080 pub position: Span,
1081}
1082
1083impl ASTNode for TypeAnnotationFunctionParameters {
1084 fn get_position(&self) -> Span {
1085 self.position
1086 }
1087
1088 fn from_reader(
1089 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
1090 state: &mut crate::ParsingState,
1091 options: &ParseOptions,
1092 ) -> ParseResult<Self> {
1093 let start = reader.expect_next(TSXToken::OpenParentheses)?;
1094 Self::from_reader_sub_open_parenthesis(reader, state, options, start)
1095 }
1096
1097 fn to_string_from_buffer<T: source_map::ToString>(
1098 &self,
1099 buf: &mut T,
1100 options: &crate::ToStringOptions,
1101 local: crate::LocalToStringInformation,
1102 ) {
1103 buf.push('(');
1104 for parameter in &self.parameters {
1105 if let Some(ref name) = parameter.name {
1106 name.to_string_from_buffer(buf, options, local);
1107 }
1108 if parameter.is_optional {
1109 buf.push_str("?: ");
1110 } else {
1111 buf.push_str(": ");
1112 }
1113 parameter.type_annotation.to_string_from_buffer(buf, options, local);
1114 }
1115 if let Some(ref rest_parameter) = self.rest_parameter {
1116 buf.push_str("...");
1117 buf.push_str(&rest_parameter.name);
1118 rest_parameter.type_annotation.to_string_from_buffer(buf, options, local);
1119 }
1120 buf.push(')');
1121 }
1122}
1123
1124impl TypeAnnotationFunctionParameters {
1125 pub(crate) fn from_reader_sub_open_parenthesis(
1126 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
1127 state: &mut crate::ParsingState,
1128 options: &ParseOptions,
1129 start: TokenStart,
1130 ) -> ParseResult<Self> {
1131 let mut parameters = Vec::new();
1132 let mut rest_parameter = None;
1133 while !matches!(reader.peek(), Some(Token(TSXToken::CloseParentheses, _))) {
1134 while reader.peek().map_or(false, |Token(ty, _)| ty.is_comment()) {
1135 reader.next();
1136 }
1137 let mut decorators = Vec::<Decorator>::new();
1138 while let Some(Token(TSXToken::At, _)) = reader.peek() {
1139 decorators.push(Decorator::from_reader(reader, state, options)?);
1140 }
1141
1142 if let Some(Token(TSXToken::Spread, _)) = reader.peek() {
1143 let token = reader.next().unwrap();
1144 let (name, _) = token_as_identifier(
1145 reader.next().ok_or_else(parse_lexing_error)?,
1146 "spread function parameter",
1147 )?;
1148 reader.expect_next(TSXToken::Colon)?;
1149 let type_annotation = TypeAnnotation::from_reader(reader, state, options)?;
1150 rest_parameter = Some(Box::new(TypeAnnotationSpreadFunctionParameter {
1151 position: token.get_span().union(type_annotation.get_position()),
1152 name,
1153 type_annotation,
1154 decorators,
1155 }));
1156 break;
1157 }
1158
1159 let mut local = 0;
1160 let after_variable_field = reader.scan(|token, _| match token {
1161 TSXToken::OpenBracket | TSXToken::OpenBrace | TSXToken::OpenParentheses => {
1162 local += 1;
1163 false
1164 }
1165 TSXToken::CloseBracket | TSXToken::CloseBrace | TSXToken::CloseParentheses => {
1166 local -= 1;
1167 local == 0
1168 }
1169 _ => local == 0,
1170 });
1171 let name: Option<WithComment<VariableField>> =
1172 if let Some(Token(TSXToken::Colon | TSXToken::OptionalMember, _)) =
1173 after_variable_field
1174 {
1175 Some(ASTNode::from_reader(reader, state, options)?)
1176 } else {
1177 None
1178 };
1179 let is_optional = match reader.next().ok_or_else(parse_lexing_error)? {
1180 Token(TSXToken::Colon, _) => false,
1181 Token(TSXToken::OptionalMember, _) => true,
1182 token => {
1183 return throw_unexpected_token_with_token(
1184 token,
1185 &[TSXToken::Colon, TSXToken::OptionalMember],
1186 )
1187 }
1188 };
1189 let type_annotation = TypeAnnotation::from_reader(reader, state, options)?;
1190 let position = name
1191 .as_ref()
1192 .map_or(type_annotation.get_position(), ASTNode::get_position)
1193 .union(type_annotation.get_position());
1194
1195 parameters.push(TypeAnnotationFunctionParameter {
1196 decorators,
1197 name,
1198 type_annotation,
1199 is_optional,
1200 position,
1201 });
1202
1203 if reader.conditional_next(|tok| matches!(tok, TSXToken::Comma)).is_none() {
1204 break;
1205 }
1206 }
1207 let end = reader.expect_next_get_end(TSXToken::CloseParentheses)?;
1208 Ok(TypeAnnotationFunctionParameters {
1209 position: start.union(end),
1210 parameters,
1211 rest_parameter,
1212 })
1213 }
1214}
1215
1216#[derive(Debug, Clone, PartialEq)]
1217#[apply(derive_ASTNode)]
1218pub struct TypeAnnotationFunctionParameter {
1219 pub decorators: Vec<Decorator>,
1220 pub name: Option<WithComment<VariableField>>,
1222 pub type_annotation: TypeAnnotation,
1223 pub is_optional: bool,
1224 pub position: Span,
1225}
1226
1227#[derive(Debug, Clone, PartialEq)]
1228#[apply(derive_ASTNode)]
1229pub struct TypeAnnotationSpreadFunctionParameter {
1230 pub decorators: Vec<Decorator>,
1231 pub name: String,
1232 pub type_annotation: TypeAnnotation,
1233 pub position: Span,
1234}
1235
1236#[derive(Debug, Clone, PartialEq)]
1237#[apply(derive_ASTNode)]
1238pub struct TupleLiteralElement(pub TupleElementKind, pub AnnotationWithBinder, pub Span);
1239
1240impl ASTNode for TupleLiteralElement {
1241 fn get_position(&self) -> Span {
1242 self.2
1243 }
1244
1245 fn from_reader(
1246 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
1247 state: &mut crate::ParsingState,
1248 options: &crate::ParseOptions,
1249 ) -> ParseResult<Self> {
1250 let is_spread = reader.conditional_next(|token| matches!(token, TSXToken::Spread));
1251
1252 let annotation_with_binder = AnnotationWithBinder::from_reader(reader, state, options)?;
1253
1254 let (kind, position) = if let Some(spread) = is_spread {
1255 (TupleElementKind::Spread, spread.1.union(annotation_with_binder.get_position()))
1256 } else if let Some(trailing_question) =
1257 reader.conditional_next(|token| matches!(token, TSXToken::QuestionMark))
1258 {
1259 (
1260 TupleElementKind::Optional,
1261 annotation_with_binder.get_position().union(trailing_question.get_end()),
1262 )
1263 } else {
1264 (TupleElementKind::Standard, annotation_with_binder.get_position())
1265 };
1266
1267 Ok(Self(kind, annotation_with_binder, position))
1268 }
1269
1270 fn to_string_from_buffer<T: source_map::ToString>(
1271 &self,
1272 buf: &mut T,
1273 options: &crate::ToStringOptions,
1274 local: crate::LocalToStringInformation,
1275 ) {
1276 if let TupleElementKind::Spread = self.0 {
1277 buf.push_str("...");
1278 }
1279 self.1.to_string_from_buffer(buf, options, local);
1280 if let TupleElementKind::Optional = self.0 {
1281 buf.push('?');
1282 }
1283 }
1284}
1285
1286impl ListItem for TupleLiteralElement {
1287 const EMPTY: Option<Self> = None;
1288
1289 type LAST = ();
1290}
1291
1292#[cfg(test)]
1293mod tests {
1294 use super::*;
1295 use crate::{assert_matches_ast, number::NumberRepresentation, span};
1296
1297 #[test]
1298 fn name() {
1299 assert_matches_ast!(
1300 "something",
1301 TypeAnnotation::Name(TypeName::Name(Deref @ "something"), span!(0, 9))
1302 );
1303 assert_matches_ast!("string", TypeAnnotation::CommonName(CommonTypes::String, span!(0, 6)));
1304 }
1305
1306 #[test]
1307 fn literals() {
1308 assert_matches_ast!(
1309 "\"my_string\"",
1310 TypeAnnotation::StringLiteral(Deref @ "my_string", Quoted::Double, span!(0, 11))
1311 );
1312 assert_matches_ast!(
1313 "45",
1314 TypeAnnotation::NumberLiteral(NumberRepresentation::Number { .. }, span!(0, 2))
1315 );
1316 assert_matches_ast!("true", TypeAnnotation::BooleanLiteral(true, span!(0, 4)));
1317 }
1318
1319 #[test]
1320 fn generics() {
1321 assert_matches_ast!(
1322 "Array<string>",
1323 TypeAnnotation::NameWithGenericArguments(
1324 TypeName::Name(Deref @ "Array"),
1325 Deref @ [TypeAnnotation::CommonName(CommonTypes::String, span!(6, 12))],
1326 span!(0, 13),
1327 )
1328 );
1329
1330 assert_matches_ast!(
1331 "Map<string, number>",
1332 TypeAnnotation::NameWithGenericArguments(
1333 TypeName::Name(Deref @ "Map"),
1334 Deref @
1335 [TypeAnnotation::CommonName(CommonTypes::String, span!(4, 10)), TypeAnnotation::CommonName(CommonTypes::Number, span!(12, 18))],
1336 span!(0, 19),
1337 )
1338 );
1339
1340 assert_matches_ast!(
1341 "Array<Array<string>>",
1342 TypeAnnotation::NameWithGenericArguments(
1343 TypeName::Name(Deref @ "Array"),
1344 Deref @ [TypeAnnotation::NameWithGenericArguments(
1345 TypeName::Name(Deref @ "Array"),
1346 Deref @ [TypeAnnotation::CommonName(CommonTypes::String, span!(12, 18))],
1347 span!(6, 19),
1348 )],
1349 span!(0, 20),
1350 )
1351 );
1352 }
1353
1354 #[test]
1355 fn union() {
1356 assert_matches_ast!(
1357 "string | number",
1358 TypeAnnotation::Union(
1359 Deref @
1360 [TypeAnnotation::CommonName(CommonTypes::String, span!(0, 6)), TypeAnnotation::CommonName(CommonTypes::Number, span!(9, 15))],
1361 _,
1362 )
1363 );
1364
1365 assert_matches_ast!(
1367 "| string | number",
1368 TypeAnnotation::Union(
1369 Deref @
1370 [TypeAnnotation::CommonName(CommonTypes::String, span!(2, 8)), TypeAnnotation::CommonName(CommonTypes::Number, span!(11, 17))],
1371 _,
1372 )
1373 );
1374 }
1375
1376 #[test]
1377 fn intersection() {
1378 assert_matches_ast!(
1379 "string & number",
1380 TypeAnnotation::Intersection(
1381 Deref @
1382 [TypeAnnotation::CommonName(CommonTypes::String, span!(0, 6)), TypeAnnotation::CommonName(CommonTypes::Number, span!(9, 15))],
1383 _,
1384 )
1385 );
1386 }
1387
1388 #[test]
1389 fn tuple_literal() {
1390 assert_matches_ast!(
1391 "[number, x: string]",
1392 TypeAnnotation::TupleLiteral(
1393 Deref @ [TupleLiteralElement(
1394 TupleElementKind::Standard,
1395 AnnotationWithBinder::NoAnnotation(TypeAnnotation::CommonName(
1396 CommonTypes::Number,
1397 span!(1, 7),
1398 )),
1399 _,
1400 ), TupleLiteralElement(
1401 TupleElementKind::Standard,
1402 AnnotationWithBinder::Annotated {
1403 name: Deref @ "x",
1404 ty: TypeAnnotation::CommonName(CommonTypes::String, span!(12, 18)),
1405 position: _,
1406 },
1407 _,
1408 )],
1409 span!(0, 19),
1410 )
1411 );
1412 }
1413
1414 #[test]
1415 fn functions() {
1416 assert_matches_ast!(
1417 "T => T",
1418 TypeAnnotation::FunctionLiteral {
1419 type_parameters: None,
1420 parameters: TypeAnnotationFunctionParameters {
1421 parameters: Deref @ [ TypeAnnotationFunctionParameter { .. } ],
1422 ..
1423 },
1424 return_type: Deref @ TypeAnnotation::Name(TypeName::Name(Deref @ "T"), span!(5, 6)),
1425 ..
1426 }
1427 );
1428 }
1430
1431 #[test]
1432 fn template_literal() {
1433 assert_matches_ast!(
1434 "`test-${X}`",
1435 TypeAnnotation::TemplateLiteral {
1436 parts: Deref @ [
1437 (
1438 Deref @ "test-",
1439 AnnotationWithBinder::NoAnnotation(TypeAnnotation::Name(TypeName::Name(Deref @ "X"), span!(8, 9)))
1440 )
1441 ],
1442 ..
1443 }
1444 );
1445 }
1446
1447 #[test]
1448 fn array_shorthand() {
1449 assert_matches_ast!(
1450 "string[]",
1451 TypeAnnotation::ArrayLiteral(
1452 Deref @ TypeAnnotation::CommonName(CommonTypes::String, span!(0, 6)),
1453 span!(0, 8),
1454 )
1455 );
1456 assert_matches_ast!(
1457 "(number | null)[]",
1458 TypeAnnotation::ArrayLiteral(
1459 Deref @ TypeAnnotation::ParenthesizedReference(
1460 Deref @ TypeAnnotation::Union(
1461 Deref @
1462 [TypeAnnotation::CommonName(CommonTypes::Number, span!(1, 7)), TypeAnnotation::CommonName(CommonTypes::Null, span!(10, 14))],
1463 _,
1464 ),
1465 span!(0, 15),
1466 ),
1467 span!(0, 17),
1468 )
1469 );
1470 assert_matches_ast!(
1471 "string[][]",
1472 TypeAnnotation::ArrayLiteral(
1473 Deref @ TypeAnnotation::ArrayLiteral(
1474 Deref @ TypeAnnotation::CommonName(CommonTypes::String, span!(0, 6)),
1475 span!(0, 8),
1476 ),
1477 span!(0, 10),
1478 )
1479 );
1480 }
1481}