Change new() parser to make use of matching-) functionality

This commit is contained in:
dkanus 2026-04-30 17:27:27 +07:00
parent b1f0714483
commit c58bcd4aac

View File

@ -223,7 +223,7 @@ impl<'src, 'arena> Parser<'src, 'arena> {
state: &mut NewArgumentListParseState<'src, 'arena>,
) -> Option<NewClassSpecifierParseAction> {
let has_parsed_all_allowed_arguments =
state.call_argument_list_parse_state.parsed_slot_count > 2;
state.call_argument_list_parse_state.parsed_slot_count >= 3;
let likely_missing_comma = !self.next_token_definitely_cannot_start_expression()
&& !has_parsed_all_allowed_arguments;
if likely_missing_comma {
@ -282,29 +282,42 @@ impl<'src, 'arena> Parser<'src, 'arena> {
}
}
/// Reports a missing closing `)` in a `new(...)` argument list and
/// determines whether the class specifier should be parsed or skipped.
/// Recovers from a missing closing `)` in a `new(...)` argument list.
///
/// Returns whether class-specifier parsing should continue after recovery.
#[must_use]
fn recover_from_missing_new_closing_parenthesis(
&mut self,
state: &NewArgumentListParseState<'src, 'arena>,
) -> NewClassSpecifierParseAction {
let mut error = self
.make_error_at_last_consumed(ParseErrorKind::NewMissingClosingParenthesis)
self.make_error_at_last_consumed(ParseErrorKind::NewMissingClosingParenthesis)
.widen_error_span_from(state.left_parenthesis_position)
.blame_token(self.peek_position_or_eof())
.related_token("new_keyword", state.new_keyword_position)
.related_token("left_parenthesis", state.left_parenthesis_position);
let class_specifier_parse_action = if self.next_token_definitely_cannot_start_expression() {
error = error.sync_error_at_matching_delimiter(self, state.left_parenthesis_position);
// Skipping the class specifier avoids cascading errors when
// the next token cannot start an expression anyway.
.related_token("left_parenthesis", state.left_parenthesis_position)
.report(self);
// Missing-delimiter recovery normally syncs to the matching `)`.
// `new(...) ClassName` is an exception: after a missing `)`, the next
// expression may already be the class specifier, not another argument.
let matching_right_parenthesis_ahead = self
.file
.matching_delimiter(state.left_parenthesis_position)
.is_some_and(|right_parenthesis_position| {
self.peek_position_or_eof() <= right_parenthesis_position
});
if matching_right_parenthesis_ahead {
self.recover_at_matching_delimiter_or_sync(state.left_parenthesis_position);
// After syncing through the matched `)`, the argument-list error is
// contained, so class-specifier parsing can proceed normally.
return NewClassSpecifierParseAction::Parse;
}
if self.next_token_definitely_cannot_start_expression() {
// There is no plausible class specifier to parse, so skip it to
// avoid error cascade.
NewClassSpecifierParseAction::Skip
} else {
NewClassSpecifierParseAction::Parse
};
error.report_error(self);
class_specifier_parse_action
}
}
/// Parses the class specifier of a `new` expression after argument-list