use ktrs_syntax::SyntaxKind::*;
use super::TOP_LEVEL_DECLARATION_FIRST;
use crate::builder::Marker;
use crate::parsing::Parser;
use crate::token_set::TokenSet;
impl Parser {
pub(crate) fn parse_type_ref(&mut self) {
self.parse_type_ref_1(TokenSet::EMPTY);
}
pub(crate) fn parse_type_ref_without_intersections(&mut self) {
self.parse_type_ref_2(TokenSet::EMPTY, false);
}
pub(crate) fn parse_type_ref_1(&mut self, extra_recovery_set: TokenSet) {
self.parse_type_ref_2(extra_recovery_set, true);
}
fn parse_type_ref_2(&mut self, extra_recovery_set: TokenSet, allow_simple_intersection_types: bool) {
let type_ref_marker = self.parse_type_ref_contents(extra_recovery_set, allow_simple_intersection_types);
type_ref_marker.done(self, TYPE_REFERENCE);
}
fn parse_type_ref_contents(&mut self, extra_recovery_set: TokenSet, allow_simple_intersection_types: bool) -> Marker {
let type_ref_marker = self.mark();
self.parse_type_modifier_list();
let lookahead = self.lookahead(1);
let lookahead2 = self.lookahead(2);
let mut type_before_dot = true;
let with_context_receiver = self.at(CONTEXT_KEYWORD) && lookahead == Some(LPAR);
let mut was_function_type_parsed = false;
let context_receivers_start = self.mark();
if with_context_receiver {
self.parse_context_parameter_or_receiver_list(true);
}
let mut type_element_marker = self.mark();
if self.at(IDENTIFIER)
&& !(lookahead == Some(DOT) && lookahead2 == Some(IDENTIFIER))
&& lookahead != Some(LT)
&& self.at(DYNAMIC_KEYWORD)
{
let dynamic_type = self.mark();
self.advance(); dynamic_type.done(self, DYNAMIC_TYPE);
} else if self.at(IDENTIFIER) || self.at(PACKAGE_KEYWORD) || self.at_parenthesized_mutable_for_platform_types(0) {
self.parse_user_type();
} else if self.at(LPAR) {
let function_or_parenthesized_type = self.mark();
self.advance(); let contents = self.parse_type_ref_contents(TokenSet::EMPTY, true);
contents.drop(self);
if self.at(RPAR) && self.lookahead(1) != Some(ARROW) {
self.advance();
function_or_parenthesized_type.drop(self);
} else {
function_or_parenthesized_type.rollback_to(self);
let function_type = context_receivers_start.precede(self);
self.parse_function_type(function_type);
was_function_type_parsed = true;
}
} else {
self.error_with_recovery(
"Type expected",
Some(TokenSet::or_set(&[
TOP_LEVEL_DECLARATION_FIRST,
TokenSet::create(&[EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON]),
extra_recovery_set,
])),
);
type_before_dot = false;
}
self.my_builder.disable_joining_complex_tokens();
type_element_marker = self.parse_nullable_type_suffix(type_element_marker);
self.my_builder.restore_joining_complex_tokens_state();
let mut was_intersection = false;
if allow_simple_intersection_types && self.at(AND) {
let left_type_ref = type_element_marker;
type_element_marker = type_element_marker.precede(self);
let intersection_type = left_type_ref.precede(self);
left_type_ref.done(self, TYPE_REFERENCE);
self.advance(); self.parse_type_ref_2(extra_recovery_set, true);
intersection_type.done(self, INTERSECTION_TYPE);
was_intersection = true;
}
if type_before_dot && self.at(DOT) && !was_intersection && !was_function_type_parsed {
let function_type = context_receivers_start.precede(self);
let receiver_type_ref = type_element_marker.precede(self);
let receiver_type = receiver_type_ref.precede(self);
receiver_type_ref.done(self, TYPE_REFERENCE);
receiver_type.done(self, FUNCTION_TYPE_RECEIVER);
self.advance();
if self.at(LPAR) {
self.parse_function_type(function_type);
} else {
function_type.drop(self);
self.error("Expecting function type");
}
was_function_type_parsed = true;
}
if with_context_receiver && !was_function_type_parsed {
self.error_with_recovery(
"Function type expected expected",
Some(TokenSet::or_set(&[
TOP_LEVEL_DECLARATION_FIRST,
TokenSet::create(&[EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON]),
extra_recovery_set,
])),
);
}
type_element_marker.drop(self);
context_receivers_start.drop(self);
type_ref_marker
}
fn parse_nullable_type_suffix(&mut self, type_element_marker: Marker) -> Marker {
let mut type_element_marker = type_element_marker;
while self.at(QUEST) && self.my_builder.raw_lookup(1) != Some(COLON) {
let precede = type_element_marker.precede(self);
self.advance(); type_element_marker.done(self, NULLABLE_TYPE);
type_element_marker = precede;
}
type_element_marker
}
}