[rust] swc->estree for optional chaining

Handles conversion of optional chains from swc -> estree.
This commit is contained in:
Joe Savona
2023-07-25 16:56:29 -07:00
parent 8bc6184728
commit d4a1356eca
3 changed files with 301 additions and 27 deletions
@@ -2008,6 +2008,63 @@ impl Serialize for ChainExpression {
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct OptionalMemberExpression {
pub object: Expression,
pub property: Identifier,
#[serde(rename = "computed")]
pub is_computed: bool,
#[serde(rename = "optional")]
#[serde(default)]
pub is_optional: bool,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for OptionalMemberExpression {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "OptionalMemberExpression")?;
state.serialize_entry("object", &self.object)?;
state.serialize_entry("property", &self.property)?;
state.serialize_entry("computed", &self.is_computed)?;
state.serialize_entry("optional", &self.is_optional)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct OptionalCallExpression {
pub callee: ExpressionOrSuper,
pub arguments: Vec<ExpressionOrSpread>,
#[serde(rename = "optional")]
#[serde(default)]
pub is_optional: bool,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for OptionalCallExpression {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "OptionalCallExpression")?;
state.serialize_entry("callee", &self.callee)?;
state.serialize_entry("arguments", &self.arguments)?;
state.serialize_entry("optional", &self.is_optional)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct ImportExpression {
pub source: Expression,
#[serde(default)]
@@ -2282,6 +2339,8 @@ pub enum Expression {
MetaProperty(Box<MetaProperty>),
NewExpression(Box<NewExpression>),
ObjectExpression(Box<ObjectExpression>),
OptionalCallExpression(Box<OptionalCallExpression>),
OptionalMemberExpression(Box<OptionalMemberExpression>),
SequenceExpression(Box<SequenceExpression>),
TaggedTemplateExpression(Box<TaggedTemplateExpression>),
TemplateLiteral(Box<TemplateLiteral>),
@@ -2311,6 +2370,8 @@ enum __ExpressionTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -2483,6 +2544,22 @@ impl<'de> serde::Deserialize<'de> for Expression {
)?;
Ok(Expression::ObjectExpression(node))
}
__ExpressionTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::OptionalCallExpression(node))
}
__ExpressionTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::OptionalMemberExpression(node))
}
__ExpressionTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -3000,6 +3077,8 @@ enum __ExpressionOrSuperTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -3181,6 +3260,30 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSuper {
)?;
Ok(ExpressionOrSuper::Expression(Expression::ObjectExpression(node)))
}
__ExpressionOrSuperTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
ExpressionOrSuper::Expression(
Expression::OptionalCallExpression(node),
),
)
}
__ExpressionOrSuperTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
ExpressionOrSuper::Expression(
Expression::OptionalMemberExpression(node),
),
)
}
__ExpressionOrSuperTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -3279,6 +3382,8 @@ enum __ExpressionOrSpreadTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -3464,6 +3569,30 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSpread {
)?;
Ok(ExpressionOrSpread::Expression(Expression::ObjectExpression(node)))
}
__ExpressionOrSpreadTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
ExpressionOrSpread::Expression(
Expression::OptionalCallExpression(node),
),
)
}
__ExpressionOrSpreadTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
ExpressionOrSpread::Expression(
Expression::OptionalMemberExpression(node),
),
)
}
__ExpressionOrSpreadTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -3563,6 +3692,8 @@ enum __FunctionBodyTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -3743,6 +3874,22 @@ impl<'de> serde::Deserialize<'de> for FunctionBody {
)?;
Ok(FunctionBody::Expression(Expression::ObjectExpression(node)))
}
__FunctionBodyTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::OptionalCallExpression(node)))
}
__FunctionBodyTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::OptionalMemberExpression(node)))
}
__FunctionBodyTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -3901,6 +4048,8 @@ enum __ForInitTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -4074,6 +4223,22 @@ impl<'de> serde::Deserialize<'de> for ForInit {
)?;
Ok(ForInit::Expression(Expression::ObjectExpression(node)))
}
__ForInitTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::OptionalCallExpression(node)))
}
__ForInitTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::OptionalMemberExpression(node)))
}
__ForInitTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -4372,6 +4537,8 @@ enum __AssignmentTargetTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -4552,6 +4719,30 @@ impl<'de> serde::Deserialize<'de> for AssignmentTarget {
)?;
Ok(AssignmentTarget::Expression(Expression::ObjectExpression(node)))
}
__AssignmentTargetTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
AssignmentTarget::Expression(
Expression::OptionalCallExpression(node),
),
)
}
__AssignmentTargetTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
AssignmentTarget::Expression(
Expression::OptionalMemberExpression(node),
),
)
}
__AssignmentTargetTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -4758,6 +4949,8 @@ enum __JSXExpressionOrEmptyTag {
MetaProperty,
NewExpression,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
TaggedTemplateExpression,
TemplateLiteral,
@@ -4947,6 +5140,30 @@ impl<'de> serde::Deserialize<'de> for JSXExpressionOrEmpty {
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::ObjectExpression(node)))
}
__JSXExpressionOrEmptyTag::OptionalCallExpression => {
let node: Box<OptionalCallExpression> = <Box<
OptionalCallExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
JSXExpressionOrEmpty::Expression(
Expression::OptionalCallExpression(node),
),
)
}
__JSXExpressionOrEmptyTag::OptionalMemberExpression => {
let node: Box<OptionalMemberExpression> = <Box<
OptionalMemberExpression,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(
JSXExpressionOrEmpty::Expression(
Expression::OptionalMemberExpression(node),
),
)
}
__JSXExpressionOrEmptyTag::SequenceExpression => {
let node: Box<SequenceExpression> = <Box<
SequenceExpression,
@@ -903,6 +903,40 @@
}
}
},
"OptionalMemberExpression": {
"fields": {
"object": {
"type": "Expression"
},
"property": {
"type": "Identifier"
},
"is_computed": {
"type": "bool",
"rename": "computed"
},
"is_optional": {
"type": "bool",
"optional": true,
"rename": "optional"
}
}
},
"OptionalCallExpression": {
"fields": {
"callee": {
"type": "ExpressionOrSuper"
},
"arguments": {
"type": "Vec<ExpressionOrSpread>"
},
"is_optional": {
"type": "bool",
"optional": true,
"rename": "optional"
}
}
},
"ImportExpression": {
"fields": {
"source": {
@@ -955,6 +989,8 @@
"MetaProperty",
"NewExpression",
"ObjectExpression",
"OptionalCallExpression",
"OptionalMemberExpression",
"SequenceExpression",
"TaggedTemplateExpression",
"TemplateLiteral",
@@ -8,9 +8,9 @@ use swc_core::common::errors::Handler;
use swc_core::common::source_map::Pos;
use swc_core::common::{FileName, FilePathMapping, Mark, SourceMap, Span, SyntaxContext, GLOBALS};
use swc_core::ecma::ast::{
AssignOp, BinaryOp, BlockStmt, BlockStmtOrExpr, Callee, Decl, EsVersion, Expr, ExprOrSpread,
Function, Ident, Lit, MemberExpr, MemberProp, ModuleItem, Pat, PatOrExpr, Program, Stmt,
UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
AssignOp, BinaryOp, BlockStmt, BlockStmtOrExpr, CallExpr, Callee, Decl, EsVersion, Expr,
ExprOrSpread, Function, Ident, Lit, MemberExpr, MemberProp, ModuleItem, OptChainBase, Pat,
PatOrExpr, Program, Stmt, UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
};
use swc_core::ecma::parser::Syntax;
use swc_core::ecma::transforms::base::resolver;
@@ -334,27 +334,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> forget_estree::Expression {
}
_ => todo!(),
},
arguments: expr
.args
.iter()
.map(|arg| match arg {
ExprOrSpread {
spread: Some(spread),
expr,
} => forget_estree::ExpressionOrSpread::SpreadElement(Box::new(
forget_estree::SpreadElement {
argument: convert_expression(cx, expr),
loc: None,
range: convert_span(&spread),
},
)),
ExprOrSpread { spread: None, expr } => {
forget_estree::ExpressionOrSpread::Expression(convert_expression(
cx, expr,
))
}
})
.collect(),
arguments: convert_arguments(cx, &expr.args),
is_optional: false,
loc: None,
range: convert_span(&expr.span),
@@ -471,10 +451,53 @@ fn convert_expression(cx: &Context, expr: &Expr) -> forget_estree::Expression {
range: convert_span(&expr.span),
},
)),
Expr::OptChain(expr) => match expr.base.as_ref() {
OptChainBase::Call(base) => forget_estree::Expression::OptionalCallExpression(
Box::new(forget_estree::OptionalCallExpression {
callee: forget_estree::ExpressionOrSuper::Expression(convert_expression(
cx,
&base.callee,
)),
arguments: convert_arguments(cx, &base.args),
is_optional: expr.optional,
loc: None,
range: convert_span(&expr.span),
}),
),
OptChainBase::Member(base) => {
let mut member = convert_member_expression(cx, base);
member.is_optional = expr.optional;
forget_estree::Expression::MemberExpression(Box::new(member))
}
},
_ => todo!("translate expression {:#?}", expr),
}
}
fn convert_arguments(
cx: &Context,
arguments: &[ExprOrSpread],
) -> Vec<forget_estree::ExpressionOrSpread> {
arguments
.iter()
.map(|arg| match arg {
ExprOrSpread {
spread: Some(spread),
expr,
} => forget_estree::ExpressionOrSpread::SpreadElement(Box::new(
forget_estree::SpreadElement {
argument: convert_expression(cx, expr),
loc: None,
range: convert_span(&spread),
},
)),
ExprOrSpread { spread: None, expr } => {
forget_estree::ExpressionOrSpread::Expression(convert_expression(cx, expr))
}
})
.collect()
}
fn convert_assignment_target(cx: &Context, target: &PatOrExpr) -> forget_estree::AssignmentTarget {
match target {
PatOrExpr::Pat(target) => {
@@ -554,7 +577,7 @@ fn convert_binary_operator(op: BinaryOp) -> Operator {
BinaryOp::Div => Operator::Binary(forget_estree::BinaryOperator::Divide),
BinaryOp::EqEq => Operator::Binary(forget_estree::BinaryOperator::Equals),
BinaryOp::EqEqEq => Operator::Binary(forget_estree::BinaryOperator::StrictEquals),
// BinaryOp::Exp => Operator::Binary(forget_estree::BinaryOperator::AsteriskAsterisk),
BinaryOp::Exp => Operator::Binary(forget_estree::BinaryOperator::Exponent),
BinaryOp::Gt => Operator::Binary(forget_estree::BinaryOperator::GreaterThan),
BinaryOp::GtEq => Operator::Binary(forget_estree::BinaryOperator::GreaterThanOrEqual),
BinaryOp::In => Operator::Binary(forget_estree::BinaryOperator::In),
@@ -577,8 +600,6 @@ fn convert_binary_operator(op: BinaryOp) -> Operator {
BinaryOp::NullishCoalescing => {
Operator::Logical(forget_estree::LogicalOperator::NullCoalescing)
}
_ => panic!("Unsupported binary operator `{}`", op),
}
}