oxc_parser/parser_parse/
slot_parameters.rs1use std::any::Any;
4
5use oxc_ast::ast::FormalParameters;
6use oxc_diagnostics::Diagnostics;
7
8use crate::{
9 Parser, ParserConfig, ParserDiagnostic, ParserImpl, UniquePromise,
10 config::{NoTokensParserConfig, RuntimeParserConfig, TokensParserConfig},
11 diagnostics,
12 lexer::Kind,
13};
14
15impl<'a, C: ParserConfig> Parser<'a, C> {
16 pub fn parse_slot_parameters(self) -> Result<FormalParameters<'a>, Diagnostics> {
20 self.parse_template_parameters(false)
21 }
22
23 pub fn parse_v_for_parameters(self) -> Result<FormalParameters<'a>, Diagnostics> {
29 self.parse_template_parameters(true)
30 }
31
32 fn parse_template_parameters(
33 self,
34 allow_elisions: bool,
35 ) -> Result<FormalParameters<'a>, Diagnostics> {
36 let config: &dyn Any = &self.config;
37 if config.is::<NoTokensParserConfig>() {
38 parse_no_tokens(
39 self.allocator,
40 self.source_text,
41 self.source_type,
42 self.options,
43 allow_elisions,
44 )
45 } else if config.is::<TokensParserConfig>() {
46 parse_tokens(
47 self.allocator,
48 self.source_text,
49 self.source_type,
50 self.options,
51 allow_elisions,
52 )
53 } else if let Some(&config) = config.downcast_ref::<RuntimeParserConfig>() {
54 parse_runtime(
55 self.allocator,
56 self.source_text,
57 self.source_type,
58 self.options,
59 config,
60 allow_elisions,
61 )
62 } else {
63 ParserImpl::<C>::new(
64 self.allocator,
65 self.source_text,
66 self.source_type,
67 self.options,
68 self.config,
69 UniquePromise::new(),
70 )
71 .parse_template_parameters(allow_elisions)
72 }
73 }
74}
75
76macro_rules! stock_goal {
78 ($name:ident, $config:ident) => {
79 #[inline(never)]
80 fn $name<'a>(
81 allocator: &'a oxc_allocator::Allocator,
82 source: &'a str,
83 source_type: oxc_span::SourceType,
84 options: crate::ParseOptions,
85 allow_elisions: bool,
86 ) -> Result<FormalParameters<'a>, Diagnostics> {
87 ParserImpl::<$config>::new(
88 allocator,
89 source,
90 source_type,
91 options,
92 $config,
93 UniquePromise::new(),
94 )
95 .parse_template_parameters(allow_elisions)
96 }
97 };
98}
99stock_goal!(parse_no_tokens, NoTokensParserConfig);
100stock_goal!(parse_tokens, TokensParserConfig);
101
102#[inline(never)]
103fn parse_runtime<'a>(
104 allocator: &'a oxc_allocator::Allocator,
105 source: &'a str,
106 source_type: oxc_span::SourceType,
107 options: crate::ParseOptions,
108 config: RuntimeParserConfig,
109 allow_elisions: bool,
110) -> Result<FormalParameters<'a>, Diagnostics> {
111 ParserImpl::<RuntimeParserConfig>::new(
112 allocator,
113 source,
114 source_type,
115 options,
116 config,
117 UniquePromise::new(),
118 )
119 .parse_template_parameters(allow_elisions)
120}
121
122impl<'a, C: ParserConfig> ParserImpl<'a, C> {
123 fn parse_template_parameters(
124 mut self,
125 allow_elisions: bool,
126 ) -> Result<FormalParameters<'a>, Diagnostics> {
127 self.bump_any();
128 let parameters = self.parse_template_parameter_items(allow_elisions);
129 if self.fatal_error.is_none() && !self.at(Kind::Eof) {
130 self.error(diagnostics::unexpected_token(self.cur_token().span()));
131 }
132 if let Some(fatal) = self.fatal_error.take() {
133 return Err(fatal.error.into_diagnostic().into());
134 }
135 self.check_unfinished_errors();
136 let errors = self
137 .lexer
138 .errors
139 .into_iter()
140 .chain(self.errors)
141 .map(ParserDiagnostic::into_diagnostic)
142 .collect::<Diagnostics>();
143 if errors.is_empty() { Ok(parameters) } else { Err(errors) }
144 }
145}
146
147#[cfg(test)]
148mod tests;