Skip to main content

react_compiler_ast/
patterns.rs

1use serde::Serialize;
2
3use crate::common::BaseNode;
4use crate::common::RawNode;
5use crate::expressions::{Expression, Identifier};
6
7/// Covers assignment targets and patterns.
8/// In Babel, LVal includes Identifier, MemberExpression, ObjectPattern, ArrayPattern,
9/// RestElement, AssignmentPattern.
10#[derive(Debug, Clone, Serialize)]
11#[serde(tag = "type")]
12pub enum PatternLike {
13    Identifier(Identifier),
14    ObjectPattern(ObjectPattern),
15    ArrayPattern(ArrayPattern),
16    AssignmentPattern(AssignmentPattern),
17    RestElement(RestElement),
18    // Expressions can appear in pattern positions (e.g., MemberExpression as LVal)
19    MemberExpression(crate::expressions::MemberExpression),
20    TSAsExpression(crate::expressions::TSAsExpression),
21    TSSatisfiesExpression(crate::expressions::TSSatisfiesExpression),
22    TSNonNullExpression(crate::expressions::TSNonNullExpression),
23    TSTypeAssertion(crate::expressions::TSTypeAssertion),
24    // Flow's analogue of the TS cast wrappers: `(expr: SomeType)`.
25    TypeCastExpression(crate::expressions::TypeCastExpression),
26}
27
28impl PatternLike {
29    /// Convert to the matching [`Expression`] variant when this pattern shares
30    /// a node `type` with `Expression` (i.e. it can appear in expression
31    /// position), otherwise `None`.
32    ///
33    /// Reproduces exactly the set that `serde_json::from_value::<Expression>`
34    /// of the same node would accept: the eight variants below wrap the same
35    /// inner types as their `Expression` counterparts (`AssignmentPattern`
36    /// included — `Expression` carries it for error-recovery positions), while
37    /// the pattern-only variants (`ObjectPattern`, `ArrayPattern`,
38    /// `RestElement`) are not expressions and yield `None`.
39    pub fn as_expression(&self) -> Option<Expression> {
40        match self {
41            PatternLike::Identifier(x) => Some(Expression::Identifier(x.clone())),
42            PatternLike::MemberExpression(x) => Some(Expression::MemberExpression(x.clone())),
43            PatternLike::AssignmentPattern(x) => Some(Expression::AssignmentPattern(x.clone())),
44            PatternLike::TSAsExpression(x) => Some(Expression::TSAsExpression(x.clone())),
45            PatternLike::TSSatisfiesExpression(x) => {
46                Some(Expression::TSSatisfiesExpression(x.clone()))
47            }
48            PatternLike::TSNonNullExpression(x) => Some(Expression::TSNonNullExpression(x.clone())),
49            PatternLike::TSTypeAssertion(x) => Some(Expression::TSTypeAssertion(x.clone())),
50            PatternLike::TypeCastExpression(x) => Some(Expression::TypeCastExpression(x.clone())),
51            PatternLike::ObjectPattern(_)
52            | PatternLike::ArrayPattern(_)
53            | PatternLike::RestElement(_) => None,
54        }
55    }
56}
57
58#[derive(Debug, Clone, Serialize)]
59pub struct ObjectPattern {
60    #[serde(flatten)]
61    pub base: BaseNode,
62    pub properties: Vec<ObjectPatternProperty>,
63    #[serde(
64        default,
65        skip_serializing_if = "Option::is_none",
66        rename = "typeAnnotation"
67    )]
68    pub type_annotation: Option<RawNode>,
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub decorators: Option<Vec<RawNode>>,
71}
72
73#[derive(Debug, Clone, Serialize)]
74#[serde(tag = "type")]
75pub enum ObjectPatternProperty {
76    ObjectProperty(ObjectPatternProp),
77    RestElement(RestElement),
78}
79
80#[derive(Debug, Clone, Serialize)]
81pub struct ObjectPatternProp {
82    #[serde(flatten)]
83    pub base: BaseNode,
84    pub key: Box<Expression>,
85    pub value: Box<PatternLike>,
86    pub computed: bool,
87    pub shorthand: bool,
88    #[serde(default, skip_serializing_if = "Option::is_none")]
89    pub decorators: Option<Vec<RawNode>>,
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub method: Option<bool>,
92}
93
94#[derive(Debug, Clone, Serialize)]
95pub struct ArrayPattern {
96    #[serde(flatten)]
97    pub base: BaseNode,
98    pub elements: Vec<Option<PatternLike>>,
99    #[serde(
100        default,
101        skip_serializing_if = "Option::is_none",
102        rename = "typeAnnotation"
103    )]
104    pub type_annotation: Option<RawNode>,
105    #[serde(default, skip_serializing_if = "Option::is_none")]
106    pub decorators: Option<Vec<RawNode>>,
107}
108
109#[derive(Debug, Clone, Serialize)]
110pub struct AssignmentPattern {
111    #[serde(flatten)]
112    pub base: BaseNode,
113    pub left: Box<PatternLike>,
114    pub right: Box<Expression>,
115    #[serde(
116        default,
117        skip_serializing_if = "Option::is_none",
118        rename = "typeAnnotation"
119    )]
120    pub type_annotation: Option<RawNode>,
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub decorators: Option<Vec<RawNode>>,
123}
124
125#[derive(Debug, Clone, Serialize)]
126pub struct RestElement {
127    #[serde(flatten)]
128    pub base: BaseNode,
129    pub argument: Box<PatternLike>,
130    #[serde(
131        default,
132        skip_serializing_if = "Option::is_none",
133        rename = "typeAnnotation"
134    )]
135    pub type_annotation: Option<RawNode>,
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub decorators: Option<Vec<RawNode>>,
138}