Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ pub struct ThisExpression {
pub struct ArrayExpression<'a> {
#[estree(flatten)]
pub span: Span,
#[tsify(type = "Array<SpreadElement | Expression | null>")]
#[estree(type = "Array<SpreadElement | Expression | null>")]
pub elements: Vec<'a, ArrayExpressionElement<'a>>,
/// Array trailing comma
/// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas#arrays>
Expand Down Expand Up @@ -832,7 +832,7 @@ pub use match_assignment_target_pattern;
pub struct ArrayAssignmentTarget<'a> {
#[estree(flatten)]
pub span: Span,
#[tsify(type = "Array<AssignmentTargetMaybeDefault | AssignmentTargetRest | null>")]
#[estree(type = "Array<AssignmentTargetMaybeDefault | AssignmentTargetRest | null>")]
pub elements: Vec<'a, Option<AssignmentTargetMaybeDefault<'a>>>,
#[estree(skip)]
pub rest: Option<AssignmentTargetRest<'a>>,
Expand All @@ -850,7 +850,7 @@ pub struct ArrayAssignmentTarget<'a> {
pub struct ObjectAssignmentTarget<'a> {
#[estree(flatten)]
pub span: Span,
#[tsify(type = "Array<AssignmentTargetProperty | AssignmentTargetRest>")]
#[estree(type = "Array<AssignmentTargetProperty | AssignmentTargetRest>")]
pub properties: Vec<'a, AssignmentTargetProperty<'a>>,
#[estree(skip)]
pub rest: Option<AssignmentTargetRest<'a>>,
Expand Down Expand Up @@ -1497,8 +1497,10 @@ pub struct DebuggerStatement {
#[estree(no_type)]
pub struct BindingPattern<'a> {
// serde(flatten) the attributes because estree has no `BindingPattern`
#[estree(flatten)]
#[tsify(type = "(BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern)")]
#[estree(
flatten,
type = "(BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern)"
)]
#[span]
pub kind: BindingPatternKind<'a>,
pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
Expand Down Expand Up @@ -1540,7 +1542,7 @@ pub struct AssignmentPattern<'a> {
pub struct ObjectPattern<'a> {
#[estree(flatten)]
pub span: Span,
#[tsify(type = "Array<BindingProperty | BindingRestElement>")]
#[estree(type = "Array<BindingProperty | BindingRestElement>")]
pub properties: Vec<'a, BindingProperty<'a>>,
#[estree(skip)]
pub rest: Option<Box<'a, BindingRestElement<'a>>>,
Expand All @@ -1566,7 +1568,7 @@ pub struct BindingProperty<'a> {
pub struct ArrayPattern<'a> {
#[estree(flatten)]
pub span: Span,
#[tsify(type = "Array<BindingPattern | BindingRestElement | null>")]
#[estree(type = "Array<BindingPattern | BindingRestElement | null>")]
pub elements: Vec<'a, Option<BindingPattern<'a>>>,
#[estree(skip)]
pub rest: Option<Box<'a, BindingRestElement<'a>>>,
Expand Down Expand Up @@ -1713,7 +1715,7 @@ pub struct FormalParameters<'a> {
#[estree(flatten)]
pub span: Span,
pub kind: FormalParameterKind,
#[tsify(type = "Array<FormalParameter | FormalParameterRest>")]
#[estree(type = "Array<FormalParameter | FormalParameterRest>")]
pub items: Vec<'a, FormalParameter<'a>>,
#[estree(skip)]
pub rest: Option<Box<'a, BindingRestElement<'a>>>,
Expand Down
2 changes: 1 addition & 1 deletion tasks/ast_tools/src/generators/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn typescript_struct(def: &StructDef) -> String {
if field.markers.derive_attributes.estree.skip {
continue;
}
let ty = match &field.markers.derive_attributes.tsify_type {
let ty = match &field.markers.derive_attributes.estree.typescript_type {
Some(ty) => ty.clone(),
None => type_to_string(field.typ.name()),
};
Expand Down
48 changes: 17 additions & 31 deletions tasks/ast_tools/src/markers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ pub struct ScopeMarkers {
pub struct DeriveAttributes {
pub clone_in: CloneInAttribute,
pub estree: ESTreeFieldAttribute,
pub tsify_type: Option<String>,
}

/// A enum representing the value passed in `#[clone_in(...)]` derive helper attribute.
Expand Down Expand Up @@ -169,16 +168,24 @@ pub struct ESTreeFieldAttribute {
pub flatten: bool,
pub skip: bool,
pub rename: Option<String>,
pub typescript_type: Option<String>,
}

impl Parse for ESTreeFieldAttribute {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
let mut flatten = false;
let mut skip = false;
let mut rename = None;
let mut typescript_type = None;

loop {
let ident = input.call(Ident::parse_any).unwrap().to_string();
let is_type = input.peek(Token![type]);
let ident = if is_type {
input.parse::<Token![type]>()?;
"type".to_string()
} else {
input.call(Ident::parse_any).unwrap().to_string()
};
match ident.as_str() {
"rename" => {
input.parse::<Token![=]>()?;
Expand All @@ -201,6 +208,13 @@ impl Parse for ESTreeFieldAttribute {
skip = true;
}
}
"type" => {
input.parse::<Token![=]>()?;
assert!(
typescript_type.replace(input.parse::<LitStr>()?.value()).is_none(),
"Duplicate estree(type)"
);
}
arg => panic!("Unsupported #[estree(...)] argument: {arg}"),
}
let comma = input.peek(Token![,]);
Expand All @@ -210,19 +224,7 @@ impl Parse for ESTreeFieldAttribute {
break;
}
}
Ok(Self { flatten, skip, rename })
}
}

/// A struct representing the `#[tsify(type = "...")]` attribute.
pub struct TsifyAttribute(String);

impl Parse for TsifyAttribute {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
input.parse::<Token![type]>()?;
input.parse::<Token![=]>()?;
let type_ = input.parse::<LitStr>()?;
Ok(Self(type_.value()))
Ok(Self { flatten, skip, rename, typescript_type })
}
}

Expand Down Expand Up @@ -364,35 +366,19 @@ where
Ok(None)
}
}
fn try_parse_tsify_type(attr: &Attribute) -> crate::Result<Option<String>> {
if attr.path().is_ident("tsify") {
let arg = attr.parse_args_with(TsifyAttribute::parse).normalize()?;
Ok(Some(arg.0))
} else {
Ok(None)
}
}
let mut clone_in = None;
let mut estree = None;
let mut tsify_type = None;
for attr in attrs {
if let Some(attr) = try_parse_clone_in(attr)? {
assert!(clone_in.replace(attr).is_none(), "Duplicate `#[clone_in(...)]` attribute.");
}
if let Some(attr) = try_parse_estree(attr)? {
assert!(estree.replace(attr).is_none(), "Duplicate `#[estree(...)]` attribute.");
}
if let Some(attr) = try_parse_tsify_type(attr)? {
assert!(
tsify_type.replace(attr).is_none(),
"Duplicate `#[tsify(type = \"...\")]` attribute."
);
}
}
Ok(DeriveAttributes {
clone_in: clone_in.unwrap_or_default(),
estree: estree.unwrap_or_default(),
tsify_type,
})
}

Expand Down