Skip to main content

oxc_parser/parser_parse/
slot_parameters.rs

1//! Direct, original-source slot parameter grammar. No wrapper or retry.
2
3use 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    /// Parse the entire original source as an arrow-function parameter list,
17    /// retaining original spans, binding defaults, rest and TS annotations.
18    /// This goal has an EOF delimiter; it adds no synthetic source or AST.
19    pub fn parse_slot_parameters(self) -> Result<FormalParameters<'a>, Diagnostics> {
20        let config: &dyn Any = &self.config;
21        if config.is::<NoTokensParserConfig>() {
22            parse_no_tokens(self.allocator, self.source_text, self.source_type, self.options)
23        } else if config.is::<TokensParserConfig>() {
24            parse_tokens(self.allocator, self.source_text, self.source_type, self.options)
25        } else if let Some(&config) = config.downcast_ref::<RuntimeParserConfig>() {
26            parse_runtime(self.allocator, self.source_text, self.source_type, self.options, config)
27        } else {
28            ParserImpl::<C>::new(
29                self.allocator,
30                self.source_text,
31                self.source_type,
32                self.options,
33                self.config,
34                UniquePromise::new(),
35            )
36            .parse_slot_parameters()
37        }
38    }
39}
40
41// Stock goals remain provider-instantiated, as the ordinary expression entry.
42macro_rules! stock_goal {
43    ($name:ident, $config:ident) => {
44        #[inline(never)]
45        fn $name<'a>(
46            allocator: &'a oxc_allocator::Allocator,
47            source: &'a str,
48            source_type: oxc_span::SourceType,
49            options: crate::ParseOptions,
50        ) -> Result<FormalParameters<'a>, Diagnostics> {
51            ParserImpl::<$config>::new(
52                allocator,
53                source,
54                source_type,
55                options,
56                $config,
57                UniquePromise::new(),
58            )
59            .parse_slot_parameters()
60        }
61    };
62}
63stock_goal!(parse_no_tokens, NoTokensParserConfig);
64stock_goal!(parse_tokens, TokensParserConfig);
65
66#[inline(never)]
67fn parse_runtime<'a>(
68    allocator: &'a oxc_allocator::Allocator,
69    source: &'a str,
70    source_type: oxc_span::SourceType,
71    options: crate::ParseOptions,
72    config: RuntimeParserConfig,
73) -> Result<FormalParameters<'a>, Diagnostics> {
74    ParserImpl::<RuntimeParserConfig>::new(
75        allocator,
76        source,
77        source_type,
78        options,
79        config,
80        UniquePromise::new(),
81    )
82    .parse_slot_parameters()
83}
84
85impl<'a, C: ParserConfig> ParserImpl<'a, C> {
86    fn parse_slot_parameters(mut self) -> Result<FormalParameters<'a>, Diagnostics> {
87        self.bump_any();
88        let parameters = self.parse_slot_parameter_items();
89        if self.fatal_error.is_none() && !self.at(Kind::Eof) {
90            self.error(diagnostics::unexpected_token(self.cur_token().span()));
91        }
92        if let Some(fatal) = self.fatal_error.take() {
93            return Err(fatal.error.into_diagnostic().into());
94        }
95        self.check_unfinished_errors();
96        let errors = self
97            .lexer
98            .errors
99            .into_iter()
100            .chain(self.errors)
101            .map(ParserDiagnostic::into_diagnostic)
102            .collect::<Diagnostics>();
103        if errors.is_empty() { Ok(parameters) } else { Err(errors) }
104    }
105}
106
107#[cfg(test)]
108mod tests;