Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ast/estree): fix TSImportType #9670

Closed
wants to merge 4 commits into from
Closed
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
11 changes: 11 additions & 0 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,9 +1289,12 @@ pub struct TSImportType<'a> {
#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
#[estree(ts_alias = "ObjectExpression")]
pub struct TSImportAttributes<'a> {
pub span: Span,
#[estree(skip)]
pub attributes_keyword: IdentifierName<'a>, // `with` or `assert`
#[estree(rename = "properties", via = TSImportAttributesProperties)]
pub elements: Vec<'a, TSImportAttribute<'a>>,
}

Expand All @@ -1300,15 +1303,23 @@ pub struct TSImportAttributes<'a> {
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
// Pluralize as `TSImportAttributeList` to avoid naming clash with `TSImportAttributes`.
#[plural(TSImportAttributeList)]
#[estree(
no_ts_def,
rename = "Property",
add_fields(method = False, shorthand = True, computed = False, kind = Init),
field_order(span, method, shorthand, computed, name, value, kind),
)]
pub struct TSImportAttribute<'a> {
pub span: Span,
#[estree(rename = "key")]
pub name: TSImportAttributeName<'a>,
pub value: Expression<'a>,
}

#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
#[estree(no_ts_def)]
pub enum TSImportAttributeName<'a> {
Identifier(IdentifierName<'a>) = 0,
StringLiteral(StringLiteral<'a>) = 1,
Expand Down
11 changes: 7 additions & 4 deletions crates/oxc_ast/src/generated/derive_estree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3106,20 +3106,23 @@ impl ESTree for TSImportAttributes<'_> {
state.serialize_field("type", &JsonSafeString("TSImportAttributes"));
state.serialize_field("start", &self.span.start);
state.serialize_field("end", &self.span.end);
state.serialize_field("attributesKeyword", &self.attributes_keyword);
state.serialize_field("elements", &self.elements);
state.serialize_field("properties", &crate::serialize::TSImportAttributesProperties(self));
state.end();
}
}

impl ESTree for TSImportAttribute<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut state = serializer.serialize_struct();
state.serialize_field("type", &JsonSafeString("TSImportAttribute"));
state.serialize_field("type", &JsonSafeString("Property"));
state.serialize_field("start", &self.span.start);
state.serialize_field("end", &self.span.end);
state.serialize_field("name", &self.name);
state.serialize_field("method", &crate::serialize::False(self));
state.serialize_field("shorthand", &crate::serialize::True(self));
state.serialize_field("computed", &crate::serialize::False(self));
state.serialize_field("key", &self.name);
state.serialize_field("value", &self.value);
state.serialize_field("kind", &crate::serialize::Init(self));
state.end();
}
}
Expand Down
69 changes: 69 additions & 0 deletions crates/oxc_ast/src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,75 @@ impl ESTree for ExportAllDeclarationWithClause<'_, '_> {
}
}

#[ast_meta]
#[estree(raw_deser = "
const start = DESER[u32](POS_OFFSET.span.start);
const end = DESER[u32](POS_OFFSET.span.end);
const attributesKeyword = DESER[IdentifierName](POS_OFFSET.attributes_keyword);
const properties = DESER[Vec<TSImportAttribute>](POS_OFFSET.elements);
const result = [
{
type: 'Property',
start,
end,
method: false,
shorthand: false,
computed: false,
key: attributesKeyword,
value: {
type: 'ObjectExpression',
start,
end,
properties,
},
kind: 'init',
},
];
result
")]
pub struct TSImportAttributesProperties<'a, 'b>(pub &'b TSImportAttributes<'a>);

impl ESTree for TSImportAttributesProperties<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut state = serializer.serialize_sequence();
state.serialize_element(&TSImportAttributesPropertiesWithProperty(self.0));
state.end();
}
}

pub struct TSImportAttributesPropertiesWithProperty<'a, 'b>(pub &'b TSImportAttributes<'a>);

impl ESTree for TSImportAttributesPropertiesWithProperty<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut state = serializer.serialize_struct();
state.serialize_field("type", &JsonSafeString("Property"));
// TODO: span
state.serialize_field("start", &self.0.span.end);
state.serialize_field("end", &self.0.span.end);
state.serialize_field("method", &false);
state.serialize_field("shorthand", &false);
state.serialize_field("computed", &false);
state.serialize_field("key", &self.0.attributes_keyword);
state.serialize_field("value", &TSImportAttributesPropertiesWithPropertyValue(self.0));
state.serialize_field("kind", &"init");
state.end();
}
}

struct TSImportAttributesPropertiesWithPropertyValue<'a, 'b>(&'b TSImportAttributes<'a>);

impl ESTree for TSImportAttributesPropertiesWithPropertyValue<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut state = serializer.serialize_struct();
state.serialize_field("type", &JsonSafeString("ObjectExpression"));
// TODO: span
state.serialize_field("start", &self.0.span.start);
state.serialize_field("end", &self.0.span.end);
state.serialize_field("properties", &self.0.elements);
Comment on lines +568 to +572
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As commented in #9663 (comment), there's no span information for inner braces to serialize this as ObjectExpression.

type A = import("foo", {  with:  {  foo: "foo"  }  })
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- TSImportAttributes.span
                          ^^^^                       <-- TSImportAttributes.attributes_keyword.span
                                 ^^^^^^^^^^^^^^^^    <-- ???
                                    ^^^^^^^^^^       <-- TSImportAttribute.span

state.end();
}
}

// --------------------
// JSX
// --------------------
Expand Down
33 changes: 29 additions & 4 deletions napi/parser/deserialize-js.js
Original file line number Diff line number Diff line change
Expand Up @@ -1780,22 +1780,47 @@ function deserializeTSImportType(pos) {
}

function deserializeTSImportAttributes(pos) {
const start = deserializeU32(pos);
const end = deserializeU32(pos + 4);
const attributesKeyword = deserializeIdentifierName(pos + 8);
const properties = deserializeVecTSImportAttribute(pos + 32);
const result = [
{
type: 'Property',
start,
end,
method: false,
shorthand: false,
computed: false,
key: attributesKeyword,
value: {
type: 'ObjectExpression',
start,
end,
properties,
},
kind: 'init',
},
];
return {
type: 'TSImportAttributes',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
attributesKeyword: deserializeIdentifierName(pos + 8),
elements: deserializeVecTSImportAttribute(pos + 32),
properties: result,
};
}

function deserializeTSImportAttribute(pos) {
return {
type: 'TSImportAttribute',
type: 'Property',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
name: deserializeTSImportAttributeName(pos + 8),
method: false,
shorthand: true,
computed: false,
key: deserializeTSImportAttributeName(pos + 8),
value: deserializeExpression(pos + 56),
kind: 'init',
};
}

Expand Down
33 changes: 29 additions & 4 deletions napi/parser/deserialize-ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -1833,22 +1833,47 @@ function deserializeTSImportType(pos) {
}

function deserializeTSImportAttributes(pos) {
const start = deserializeU32(pos);
const end = deserializeU32(pos + 4);
const attributesKeyword = deserializeIdentifierName(pos + 8);
const properties = deserializeVecTSImportAttribute(pos + 32);
const result = [
{
type: 'Property',
start,
end,
method: false,
shorthand: false,
computed: false,
key: attributesKeyword,
value: {
type: 'ObjectExpression',
start,
end,
properties,
},
kind: 'init',
},
];
return {
type: 'TSImportAttributes',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
attributesKeyword: deserializeIdentifierName(pos + 8),
elements: deserializeVecTSImportAttribute(pos + 32),
properties: result,
};
}

function deserializeTSImportAttribute(pos) {
return {
type: 'TSImportAttribute',
type: 'Property',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
name: deserializeTSImportAttributeName(pos + 8),
method: false,
shorthand: true,
computed: false,
key: deserializeTSImportAttributeName(pos + 8),
value: deserializeExpression(pos + 56),
kind: 'init',
};
}

Expand Down
18 changes: 1 addition & 17 deletions npm/oxc-types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1282,26 +1282,12 @@ export type TSTypeQueryExprName = TSImportType | TSTypeName;
export interface TSImportType extends Span {
type: 'TSImportType';
argument: TSType;
options: TSImportAttributes | null;
options: ObjectExpression | null;
qualifier: TSTypeName | null;
typeArguments: TSTypeParameterInstantiation | null;
isTypeOf: boolean;
}

export interface TSImportAttributes extends Span {
type: 'TSImportAttributes';
attributesKeyword: IdentifierName;
elements: Array<TSImportAttribute>;
}

export interface TSImportAttribute extends Span {
type: 'TSImportAttribute';
name: TSImportAttributeName;
value: Expression;
}

export type TSImportAttributeName = IdentifierName | StringLiteral;

export interface TSFunctionType extends Span {
type: 'TSFunctionType';
typeParameters: TSTypeParameterDeclaration | null;
Expand Down Expand Up @@ -1789,8 +1775,6 @@ export type Node =
| TSInferType
| TSTypeQuery
| TSImportType
| TSImportAttributes
| TSImportAttribute
| TSFunctionType
| TSConstructorType
| TSMappedType
Expand Down
Loading