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<'a> EmbeddingObservation<'a> {
93 pub fn into_expression(mut self) -> Result<ExpressionObservation<'a>, Box<Self>> {
111 if self.goal != EmbeddingGoal::Expr {
112 return Err(Box::new(self));
113 }
114 let root = if self.hole.is_none()
115 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
116 && let Expression::ParenthesizedExpression(wrapper) = statement.unbox().expression
117 {
118 Some(&*self.allocator.alloc(wrapper.unbox().expression))
119 } else {
120 None
121 };
122 if self.hole.is_none() && root.is_none() {
123 self.hole = Some(EmbeddingHole::InvalidExpressionShape);
124 }
125 Ok(ExpressionObservation { observation: self, root })
126 }
127
128 pub fn into_handler_body(mut self) -> Result<HandlerBodyObservation<'a>, Box<Self>> {
146 if self.goal != EmbeddingGoal::HandlerBody {
147 return Err(Box::new(self));
148 }
149 let root = if self.hole.is_none()
150 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
151 && let Expression::ArrowFunctionExpression(arrow) = statement.unbox().expression
152 {
153 Some(&*self.allocator.alloc(arrow.unbox().body.unbox()))
154 } else {
155 None
156 };
157 if self.hole.is_none() && root.is_none() {
158 self.hole = Some(EmbeddingHole::InvalidWrappedShape);
159 }
160 Ok(HandlerBodyObservation { observation: self, root })
161 }
162
163 pub fn into_parameters(mut self) -> Result<ParametersObservation<'a>, Box<Self>> {
173 if self.goal != EmbeddingGoal::Parameters {
174 return Err(Box::new(self));
175 }
176 let root = if self.hole.is_none()
177 && let Some(Statement::ExpressionStatement(statement)) = self.parsed.program.body.pop()
178 && let Expression::ArrowFunctionExpression(arrow) = statement.unbox().expression
179 {
180 Some(&*self.allocator.alloc(arrow.unbox().params.unbox()))
181 } else {
182 None
183 };
184 if self.hole.is_none() && root.is_none() {
185 self.hole = Some(EmbeddingHole::InvalidWrappedShape);
186 }
187 Ok(ParametersObservation { observation: self, root })
188 }
189}