Skip to content

Commit 496dd62

Browse files
authored
refactor(parser): introduce context_add and context_remove functions (#14567)
This makes code easier to understand that only either adds or removes context flags.
1 parent 92e1748 commit 496dd62

File tree

9 files changed

+61
-63
lines changed

9 files changed

+61
-63
lines changed

crates/oxc_parser/src/cursor.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,32 @@ impl<'a> ParserImpl<'a> {
325325
answer
326326
}
327327

328+
#[expect(clippy::inline_always)]
329+
#[inline(always)] // inline because this is always on a hot path
330+
pub(crate) fn context_add<F, T>(&mut self, add_flags: Context, cb: F) -> T
331+
where
332+
F: FnOnce(&mut Self) -> T,
333+
{
334+
let ctx = self.ctx;
335+
self.ctx = ctx.union(add_flags);
336+
let result = cb(self);
337+
self.ctx = ctx;
338+
result
339+
}
340+
341+
#[expect(clippy::inline_always)]
342+
#[inline(always)] // inline because this is always on a hot path
343+
pub(crate) fn context_remove<F, T>(&mut self, remove_flags: Context, cb: F) -> T
344+
where
345+
F: FnOnce(&mut Self) -> T,
346+
{
347+
let ctx = self.ctx;
348+
self.ctx = ctx.difference(remove_flags);
349+
let result = cb(self);
350+
self.ctx = ctx;
351+
result
352+
}
353+
328354
#[expect(clippy::inline_always)]
329355
#[inline(always)] // inline because this is always on a hot path
330356
pub(crate) fn context<F, T>(&mut self, add_flags: Context, remove_flags: Context, cb: F) -> T

crates/oxc_parser/src/js/binding.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ impl<'a> ParserImpl<'a> {
1010
pub(super) fn parse_binding_pattern_with_initializer(&mut self) -> BindingPattern<'a> {
1111
let span = self.start_span();
1212
let pattern = self.parse_binding_pattern(true);
13-
self.context(Context::In, Context::empty(), |p| p.parse_initializer(span, pattern))
13+
self.context_add(Context::In, |p| p.parse_initializer(span, pattern))
1414
}
1515

1616
pub(super) fn parse_binding_pattern(&mut self, allow_question: bool) -> BindingPattern<'a> {
@@ -114,8 +114,7 @@ impl<'a> ParserImpl<'a> {
114114
// Rest element does not allow `= initializer`
115115
// function foo([...x = []]) { }
116116
// ^^^^ A rest element cannot have an initializer
117-
let argument = self
118-
.context(Context::In, Context::empty(), |p| p.parse_initializer(init_span, pattern));
117+
let argument = self.context_add(Context::In, |p| p.parse_initializer(init_span, pattern));
119118
if let BindingPatternKind::AssignmentPattern(pat) = &argument.kind {
120119
self.error(diagnostics::a_rest_element_cannot_have_an_initializer(pat.span));
121120
}
@@ -142,7 +141,7 @@ impl<'a> ParserImpl<'a> {
142141
let identifier =
143142
self.ast.binding_pattern_kind_binding_identifier(ident.span, ident.name);
144143
let left = self.ast.binding_pattern(identifier, NONE, false);
145-
self.context(Context::In, Context::empty(), |p| p.parse_initializer(span, left))
144+
self.context_add(Context::In, |p| p.parse_initializer(span, left))
146145
} else {
147146
return self.unexpected();
148147
}

crates/oxc_parser/src/js/class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl<'a> ParserImpl<'a> {
303303
if kind.is_identifier_or_keyword() || kind == Kind::Star || kind == Kind::LBrack {
304304
let is_ambient = modifiers.contains(ModifierKind::Declare);
305305
return if is_ambient {
306-
self.context(Context::Ambient, Context::empty(), |p| {
306+
self.context_add(Context::Ambient, |p| {
307307
p.parse_property_or_method_declaration(span, r#type, &modifiers, decorators)
308308
})
309309
} else {

crates/oxc_parser/src/js/expression.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ impl<'a> ParserImpl<'a> {
437437
pub(crate) fn parse_array_expression(&mut self) -> Expression<'a> {
438438
let span = self.start_span();
439439
self.expect(Kind::LBrack);
440-
let (elements, comma_span) = self.context(Context::In, Context::empty(), |p| {
440+
let (elements, comma_span) = self.context_add(Context::In, |p| {
441441
p.parse_delimited_list(Kind::RBrack, Kind::Comma, Self::parse_array_expression_element)
442442
});
443443
if let Some(comma_span) = comma_span {
@@ -480,7 +480,7 @@ impl<'a> ParserImpl<'a> {
480480

481481
quasis.push(self.parse_template_element(tagged));
482482
// TemplateHead Expression[+In, ?Yield, ?Await]
483-
let expr = self.context(Context::In, Context::empty(), Self::parse_expr);
483+
let expr = self.context_add(Context::In, Self::parse_expr);
484484
expressions.push(expr);
485485
self.re_lex_template_substitution_tail();
486486
while self.fatal_error.is_none() {
@@ -492,8 +492,7 @@ impl<'a> ParserImpl<'a> {
492492
Kind::TemplateMiddle => {
493493
quasis.push(self.parse_template_element(tagged));
494494
// TemplateMiddle Expression[+In, ?Yield, ?Await]
495-
let expr =
496-
self.context(Context::In, Context::empty(), Self::parse_expr);
495+
let expr = self.context_add(Context::In, Self::parse_expr);
497496
expressions.push(expr);
498497
self.re_lex_template_substitution_tail();
499498
}
@@ -840,7 +839,7 @@ impl<'a> ParserImpl<'a> {
840839
optional: bool,
841840
) -> Expression<'a> {
842841
self.bump_any(); // advance `[`
843-
let property = self.context(Context::In, Context::empty(), Self::parse_expr);
842+
let property = self.context_add(Context::In, Self::parse_expr);
844843
self.expect(Kind::RBrack);
845844
self.ast.member_expression_computed(self.end_span(lhs_span), lhs, property, optional).into()
846845
}
@@ -889,7 +888,7 @@ impl<'a> ParserImpl<'a> {
889888
let arguments = if self.eat(Kind::LParen) {
890889
// ArgumentList[Yield, Await] :
891890
// AssignmentExpression[+In, ?Yield, ?Await]
892-
let (call_arguments, _) = self.context(Context::In, Context::empty(), |p| {
891+
let (call_arguments, _) = self.context_add(Context::In, |p| {
893892
p.parse_delimited_list(Kind::RParen, Kind::Comma, Self::parse_call_argument)
894893
});
895894
self.expect(Kind::RParen);
@@ -1213,7 +1212,7 @@ impl<'a> ParserImpl<'a> {
12131212
if !self.eat(Kind::Question) {
12141213
return lhs;
12151214
}
1216-
let consequent = self.context(Context::In, Context::empty(), |p| {
1215+
let consequent = self.context_add(Context::In, |p| {
12171216
p.parse_assignment_expression_or_higher_impl(
12181217
/* allow_return_type_in_arrow_function */ false,
12191218
)
@@ -1399,9 +1398,8 @@ impl<'a> ParserImpl<'a> {
13991398
self.error(diagnostics::await_expression(self.cur_token().span()));
14001399
}
14011400
self.bump_any();
1402-
let argument = self.context(Context::Await, Context::empty(), |p| {
1403-
p.parse_simple_unary_expression(lhs_span)
1404-
});
1401+
let argument =
1402+
self.context_add(Context::Await, |p| p.parse_simple_unary_expression(lhs_span));
14051403
self.ast.expression_await(self.end_span(span), argument)
14061404
}
14071405

@@ -1435,11 +1433,7 @@ impl<'a> ParserImpl<'a> {
14351433
pub(crate) fn parse_decorator(&mut self) -> Decorator<'a> {
14361434
let span = self.start_span();
14371435
self.bump_any(); // bump @
1438-
let expr = self.context(
1439-
Context::Decorator,
1440-
Context::empty(),
1441-
Self::parse_lhs_expression_or_higher,
1442-
);
1436+
let expr = self.context_add(Context::Decorator, Self::parse_lhs_expression_or_higher);
14431437
self.ast.decorator(self.end_span(span), expr)
14441438
}
14451439

crates/oxc_parser/src/js/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'a> ParserImpl<'a> {
3232
let span = self.start_span();
3333
self.expect(Kind::LCurly);
3434

35-
let (directives, statements) = self.context(Context::Return, Context::empty(), |p| {
35+
let (directives, statements) = self.context_add(Context::Return, |p| {
3636
p.parse_directives_and_statements(/* is_top_level */ false)
3737
});
3838

crates/oxc_parser/src/js/module.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
55

66
use super::FunctionKind;
77
use crate::{
8-
Context, ParserImpl, StatementContext, diagnostics,
8+
ParserImpl, StatementContext, diagnostics,
99
lexer::Kind,
1010
modifiers::{Modifier, ModifierFlags, ModifierKind, Modifiers},
1111
};
@@ -281,7 +281,7 @@ impl<'a> ParserImpl<'a> {
281281
import_kind: ImportOrExportKind,
282282
) -> Vec<'a, ImportDeclarationSpecifier<'a>> {
283283
self.expect(Kind::LCurly);
284-
let (list, _) = self.context(Context::empty(), self.ctx, |p| {
284+
let (list, _) = self.context_remove(self.ctx, |p| {
285285
p.parse_delimited_list(Kind::RCurly, Kind::Comma, |parser| {
286286
parser.parse_import_specifier(import_kind)
287287
})
@@ -302,7 +302,7 @@ impl<'a> ParserImpl<'a> {
302302

303303
let span = self.start_span();
304304
self.expect(Kind::LCurly);
305-
let (with_entries, _) = self.context(Context::empty(), self.ctx, |p| {
305+
let (with_entries, _) = self.context_remove(self.ctx, |p| {
306306
p.parse_delimited_list(Kind::RCurly, Kind::Comma, Self::parse_import_attribute)
307307
});
308308
self.expect(Kind::RCurly);
@@ -478,7 +478,7 @@ impl<'a> ParserImpl<'a> {
478478
) -> Box<'a, ExportNamedDeclaration<'a>> {
479479
let export_kind = self.parse_import_or_export_kind();
480480
self.expect(Kind::LCurly);
481-
let (mut specifiers, _) = self.context(Context::empty(), self.ctx, |p| {
481+
let (mut specifiers, _) = self.context_remove(self.ctx, |p| {
482482
p.parse_delimited_list(Kind::RCurly, Kind::Comma, |parser| {
483483
parser.parse_export_specifier(export_kind)
484484
})

crates/oxc_parser/src/js/object.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<'a> ParserImpl<'a> {
1919
pub(crate) fn parse_object_expression(&mut self) -> Box<'a, ObjectExpression<'a>> {
2020
let span = self.start_span();
2121
self.expect(Kind::LCurly);
22-
let (object_expression_properties, _) = self.context(Context::In, Context::empty(), |p| {
22+
let (object_expression_properties, _) = self.context_add(Context::In, |p| {
2323
p.parse_delimited_list(
2424
Kind::RCurly,
2525
Kind::Comma,
@@ -180,11 +180,7 @@ impl<'a> ParserImpl<'a> {
180180
pub(crate) fn parse_computed_property_name(&mut self) -> Expression<'a> {
181181
self.bump_any(); // advance `[`
182182

183-
let expression = self.context(
184-
Context::In,
185-
Context::empty(),
186-
Self::parse_assignment_expression_or_higher,
187-
);
183+
let expression = self.context_add(Context::In, Self::parse_assignment_expression_or_higher);
188184

189185
self.expect(Kind::RBrack);
190186
expression

crates/oxc_parser/src/js/statement.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl<'a> ParserImpl<'a> {
384384
let is_async = self.at(Kind::Async) && !self.cur_token().escaped();
385385
let expr_span = self.start_span();
386386

387-
let init_expression = self.context(Context::empty(), Context::In, ParserImpl::parse_expr);
387+
let init_expression = self.context_remove(Context::In, ParserImpl::parse_expr);
388388

389389
match self.cur_kind() {
390390
Kind::In => {
@@ -418,7 +418,7 @@ impl<'a> ParserImpl<'a> {
418418
decl_kind: VariableDeclarationKind,
419419
r#await: bool,
420420
) -> Statement<'a> {
421-
let init_declaration = self.context(Context::empty(), Context::In, |p| {
421+
let init_declaration = self.context_remove(Context::In, |p| {
422422
p.parse_variable_declaration(
423423
start_span,
424424
decl_kind,
@@ -495,13 +495,13 @@ impl<'a> ParserImpl<'a> {
495495
let test = if matches!(self.cur_kind(), Kind::Semicolon | Kind::RParen) {
496496
None
497497
} else {
498-
Some(self.context(Context::In, Context::empty(), ParserImpl::parse_expr))
498+
Some(self.context_add(Context::In, ParserImpl::parse_expr))
499499
};
500500
self.expect(Kind::Semicolon);
501501
let update = if self.at(Kind::RParen) {
502502
None
503503
} else {
504-
Some(self.context(Context::In, Context::empty(), ParserImpl::parse_expr))
504+
Some(self.context_add(Context::In, ParserImpl::parse_expr))
505505
};
506506
self.expect(Kind::RParen);
507507
if r#await {
@@ -575,7 +575,7 @@ impl<'a> ParserImpl<'a> {
575575
let argument = if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
576576
None
577577
} else {
578-
let expr = self.context(Context::In, Context::empty(), ParserImpl::parse_expr);
578+
let expr = self.context_add(Context::In, ParserImpl::parse_expr);
579579
self.asi();
580580
Some(expr)
581581
};

crates/oxc_parser/src/ts/types.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,14 @@ impl<'a> ParserImpl<'a> {
2222
&& !self.cur_token().is_on_new_line()
2323
&& self.eat(Kind::Extends)
2424
{
25-
let extends_type = self.context(
26-
Context::DisallowConditionalTypes,
27-
Context::empty(),
28-
Self::parse_ts_type,
29-
);
25+
let extends_type =
26+
self.context_add(Context::DisallowConditionalTypes, Self::parse_ts_type);
3027
self.expect(Kind::Question);
31-
let true_type = self.context(
32-
Context::empty(),
33-
Context::DisallowConditionalTypes,
34-
Self::parse_ts_type,
35-
);
28+
let true_type =
29+
self.context_remove(Context::DisallowConditionalTypes, Self::parse_ts_type);
3630
self.expect(Kind::Colon);
37-
let false_type = self.context(
38-
Context::empty(),
39-
Context::DisallowConditionalTypes,
40-
Self::parse_ts_type,
41-
);
31+
let false_type =
32+
self.context_remove(Context::DisallowConditionalTypes, Self::parse_ts_type);
4233
return self.ast.ts_type_conditional_type(
4334
self.end_span(span),
4435
ty,
@@ -258,8 +249,7 @@ impl<'a> ParserImpl<'a> {
258249
Kind::Unique => self.parse_type_operator(TSTypeOperatorOperator::Unique),
259250
Kind::Readonly => self.parse_type_operator(TSTypeOperatorOperator::Readonly),
260251
Kind::Infer => self.parse_infer_type(),
261-
_ => self.context(
262-
Context::empty(),
252+
_ => self.context_remove(
263253
Context::DisallowConditionalTypes,
264254
Self::parse_postfix_type_or_higher,
265255
),
@@ -1042,11 +1032,8 @@ impl<'a> ParserImpl<'a> {
10421032

10431033
fn try_parse_constraint_of_infer_type(&mut self) -> Option<TSType<'a>> {
10441034
if self.eat(Kind::Extends) {
1045-
let constraint = self.context(
1046-
Context::DisallowConditionalTypes,
1047-
Context::empty(),
1048-
Self::parse_ts_type,
1049-
);
1035+
let constraint =
1036+
self.context_add(Context::DisallowConditionalTypes, Self::parse_ts_type);
10501037
if self.ctx.has_disallow_conditional_types() || !self.at(Kind::Question) {
10511038
return Some(constraint);
10521039
}
@@ -1067,11 +1054,7 @@ impl<'a> ParserImpl<'a> {
10671054

10681055
fn parse_return_type(&mut self) -> TSType<'a> {
10691056
self.bump_any();
1070-
self.context(
1071-
Context::empty(),
1072-
Context::DisallowConditionalTypes,
1073-
Self::parse_type_or_type_predicate,
1074-
)
1057+
self.context_remove(Context::DisallowConditionalTypes, Self::parse_type_or_type_predicate)
10751058
}
10761059

10771060
fn parse_type_or_type_predicate(&mut self) -> TSType<'a> {

0 commit comments

Comments
 (0)