use hermes_ast::node::{
Identifier, Node, TSTypeParameter, TSTypeParameterDeclaration,
TSTypeParameterInstantiation,
};
use hermes_ast::node_child::{NodeList, NodeMetadata};
use crate::js::JSParserImpl;
use crate::lexer::GrammarContext;
use crate::token_kinds::TokenKind;
impl<'gc, 'ast, 'ctx, 'a> JSParserImpl<'gc, 'ast, 'ctx, 'a> {
pub(in crate::js) fn parse_ts_type_parameters(
&mut self,
) -> Option<&'gc Node<'gc>> {
debug_assert!(self.check(TokenKind::less));
let start = self.advance(GrammarContext::Type).start;
let mut params: Vec<&'gc Node<'gc>> = Vec::new();
loop {
params.push(self.parse_ts_type_parameter()?);
if !self.check_and_eat(TokenKind::comma, GrammarContext::Type) {
break;
}
if self.check(TokenKind::greater) {
break;
}
}
let end = self.cur_range().end;
if !self.eat_at(
TokenKind::greater,
GrammarContext::Type,
" at end of type parameters",
Some("start of type parameters"),
start,
) {
return None;
}
let node =
Node::TSTypeParameterDeclaration(TSTypeParameterDeclaration::new(
NodeMetadata::new(self.dummy_range()),
NodeList::from_iter(self.gc, params),
));
Some(self.set_location(start, end, node))
}
fn parse_ts_type_parameter(&mut self) -> Option<&'gc Node<'gc>> {
let start = self.cur_start();
if !self.need(TokenKind::identifier, " in type parameter") {
return None;
}
let name_range = self.cur_range();
let name_node = Node::Identifier(Identifier::new(
NodeMetadata::new(self.dummy_range()),
self.lexer.token().get_identifier(),
None,
false,
));
let name = self.set_location(name_range.start, name_range.end, name_node);
self.advance(GrammarContext::Type);
let mut constraint: Option<&'gc Node<'gc>> = None;
if self.check_and_eat(TokenKind::rw_extends, GrammarContext::Type) {
constraint = Some(self.parse_type_annotation_ts(None)?);
}
let mut init: Option<&'gc Node<'gc>> = None;
if self.check_and_eat(TokenKind::equal, GrammarContext::Type) {
init = Some(self.parse_type_annotation_ts(None)?);
}
let node = Node::TSTypeParameter(TSTypeParameter::new(
NodeMetadata::new(self.dummy_range()),
name,
constraint,
init,
));
Some(self.set_location(start, self.lexer.prev_token_end(), node))
}
pub(in crate::js) fn parse_ts_type_arguments(
&mut self,
) -> Option<&'gc Node<'gc>> {
debug_assert!(self.check(TokenKind::less));
let start = self.advance(GrammarContext::Type).start;
let mut params: Vec<&'gc Node<'gc>> = Vec::new();
while !self.check(TokenKind::greater) {
params.push(self.parse_type_annotation_ts(None)?);
if !self.check_and_eat(TokenKind::comma, GrammarContext::Type) {
break;
}
}
let end = self.cur_range().end;
if !self.eat_at(
TokenKind::greater,
GrammarContext::Type,
" at end of type parameters",
Some("start of type parameters"),
start,
) {
return None;
}
let node = Node::TSTypeParameterInstantiation(
TSTypeParameterInstantiation::new(
NodeMetadata::new(self.dummy_range()),
NodeList::from_iter(self.gc, params),
),
);
Some(self.set_location(start, end, node))
}
}