oxc_parser/embedding/
projection.rs1use oxc_ast::ast::{Expression, FormalParameters, FunctionBody, Statement};
4use oxc_diagnostics::Diagnostics;
5use oxc_span::{GetSpan, SourceType, Span};
6
7use super::{EmbeddingGoal, EmbeddingHole, EmbeddingObservation};
8use crate::ParseOptions;
9
10macro_rules! projection {
11 ($owner:ident, $proof:ident, $root:ty, $accessor:ident) => {
12 pub struct $owner<'a> {
14 observation: EmbeddingObservation<'a>,
15 root: Option<&'a $root>,
16 }
17 impl core::fmt::Debug for $owner<'_> {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 f.debug_tuple(stringify!($owner)).field(&self.observation).finish()
20 }
21 }
22 pub struct $proof<'p, 'a> {
24 owner: &'p $owner<'a>,
25 root: &'a $root,
26 }
27 impl<'a> $owner<'a> {
28 #[must_use]
29 pub fn admitted(&self) -> Option<$proof<'_, 'a>> {
30 self.root
31 .filter(|_| self.observation.hole.is_none())
32 .map(|root| $proof { owner: self, root })
33 }
34 #[must_use]
35 pub const fn hole(&self) -> Option<EmbeddingHole> {
36 self.observation.hole
37 }
38 #[must_use]
39 pub fn diagnostics(&self) -> &Diagnostics {
40 self.observation.diagnostics()
41 }
42 #[must_use]
43 pub fn comments(&self) -> &[oxc_ast::ast::Comment] {
44 self.observation.comments()
45 }
46 #[must_use]
47 pub const fn content(&self) -> &'a str {
48 self.observation.content
49 }
50 #[must_use]
51 pub const fn source_type(&self) -> SourceType {
52 self.observation.source_type
53 }
54 #[must_use]
55 pub const fn parser_content_span(&self) -> Span {
56 self.observation.content_span
57 }
58 }
59 impl<'p, 'a> $proof<'p, 'a> {
60 #[must_use]
61 pub const fn $accessor(&self) -> &'a $root {
62 self.root
63 }
64 #[must_use]
65 pub const fn content(&self) -> &'a str {
66 self.owner.observation.content
67 }
68 #[must_use]
69 pub const fn parser_content_span(&self) -> Span {
70 self.owner.observation.content_span
71 }
72 #[must_use]
73 pub fn parser_container_span(&self) -> Span {
74 self.root.span()
75 }
76 #[must_use]
77 pub const fn source_type(&self) -> SourceType {
78 self.owner.observation.source_type
79 }
80 #[must_use]
81 pub const fn options(&self) -> ParseOptions {
82 self.owner.observation.options
83 }
84 }
85 };
86}
87
88projection!(ExpressionObservation, AdmittedExpression, Expression<'a>, expression);
89projection!(HandlerBodyObservation, AdmittedHandlerBody, FunctionBody<'a>, body);
90projection!(ParametersObservation, AdmittedParameters, FormalParameters<'a>, parameters);
91
92impl AdmittedExpression<'_, '_> {
93 #[must_use]
98 pub const fn has_legacy_literals(&self) -> bool {
99 self.owner.observation.parsed.has_legacy_literals
100 }
101}
102
103impl<'a> EmbeddingObservation<'a> {
104 pub fn into_expression(mut self) -> Result<ExpressionObservation<'a>, Box<Self>> {
122 if self.goal != EmbeddingGoal::Expr {
123 return Err(Box::new(self));
124 }
125 let root = if self.hole.is_none()
126 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
127 && let Expression::ParenthesizedExpression(wrapper) = statement.unbox().expression
128 {
129 Some(&*self.allocator.alloc(wrapper.unbox().expression))
130 } else {
131 None
132 };
133 if self.hole.is_none() && root.is_none() {
134 self.hole = Some(EmbeddingHole::InvalidExpressionShape);
135 }
136 Ok(ExpressionObservation { observation: self, root })
137 }
138
139 pub fn into_handler_body(mut self) -> Result<HandlerBodyObservation<'a>, Box<Self>> {
157 if self.goal != EmbeddingGoal::HandlerBody {
158 return Err(Box::new(self));
159 }
160 let root = if self.hole.is_none()
161 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
162 && let Expression::ArrowFunctionExpression(arrow) = statement.unbox().expression
163 {
164 Some(&*self.allocator.alloc(arrow.unbox().body.unbox()))
165 } else {
166 None
167 };
168 if self.hole.is_none() && root.is_none() {
169 self.hole = Some(EmbeddingHole::InvalidWrappedShape);
170 }
171 Ok(HandlerBodyObservation { observation: self, root })
172 }
173
174 pub fn into_parameters(mut self) -> Result<ParametersObservation<'a>, Box<Self>> {
184 if self.goal != EmbeddingGoal::Parameters {
185 return Err(Box::new(self));
186 }
187 let root = if self.hole.is_none()
188 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
189 && let Expression::ArrowFunctionExpression(arrow) = statement.unbox().expression
190 {
191 Some(&*self.allocator.alloc(arrow.unbox().params.unbox()))
192 } else {
193 None
194 };
195 if self.hole.is_none() && root.is_none() {
196 self.hole = Some(EmbeddingHole::InvalidWrappedShape);
197 }
198 Ok(ParametersObservation { observation: self, root })
199 }
200}