mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(parser): parse assert keyword in TSImportAttributes (#4610)
closes #4601
This commit is contained in:
parent
6ff200d072
commit
a40a217de4
12 changed files with 122 additions and 79 deletions
|
|
@ -1062,6 +1062,7 @@ pub struct TSImportType<'a> {
|
|||
pub struct TSImportAttributes<'a> {
|
||||
#[serde(flatten)]
|
||||
pub span: Span,
|
||||
pub attributes_keyword: IdentifierName<'a>, // `with` or `assert`
|
||||
pub elements: Vec<'a, TSImportAttribute<'a>>,
|
||||
}
|
||||
|
||||
|
|
@ -1251,7 +1252,7 @@ pub struct TSNonNullExpression<'a> {
|
|||
/// @LogParam x: number // parameter decorator
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
|||
|
|
@ -930,18 +930,19 @@ const _: () = {
|
|||
assert!(offset_of!(TSTypeQuery, type_parameters) == 24usize);
|
||||
assert!(size_of::<TSTypeQueryExprName>() == 16usize);
|
||||
assert!(align_of::<TSTypeQueryExprName>() == 8usize);
|
||||
assert!(size_of::<TSImportType>() == 96usize);
|
||||
assert!(size_of::<TSImportType>() == 120usize);
|
||||
assert!(align_of::<TSImportType>() == 8usize);
|
||||
assert!(offset_of!(TSImportType, span) == 0usize);
|
||||
assert!(offset_of!(TSImportType, is_type_of) == 8usize);
|
||||
assert!(offset_of!(TSImportType, parameter) == 16usize);
|
||||
assert!(offset_of!(TSImportType, qualifier) == 32usize);
|
||||
assert!(offset_of!(TSImportType, attributes) == 48usize);
|
||||
assert!(offset_of!(TSImportType, type_parameters) == 88usize);
|
||||
assert!(size_of::<TSImportAttributes>() == 40usize);
|
||||
assert!(offset_of!(TSImportType, type_parameters) == 112usize);
|
||||
assert!(size_of::<TSImportAttributes>() == 64usize);
|
||||
assert!(align_of::<TSImportAttributes>() == 8usize);
|
||||
assert!(offset_of!(TSImportAttributes, span) == 0usize);
|
||||
assert!(offset_of!(TSImportAttributes, elements) == 8usize);
|
||||
assert!(offset_of!(TSImportAttributes, attributes_keyword) == 8usize);
|
||||
assert!(offset_of!(TSImportAttributes, elements) == 32usize);
|
||||
assert!(size_of::<TSImportAttribute>() == 56usize);
|
||||
assert!(align_of::<TSImportAttribute>() == 8usize);
|
||||
assert!(offset_of!(TSImportAttribute, span) == 0usize);
|
||||
|
|
@ -2050,18 +2051,19 @@ const _: () = {
|
|||
assert!(offset_of!(TSTypeQuery, type_parameters) == 16usize);
|
||||
assert!(size_of::<TSTypeQueryExprName>() == 8usize);
|
||||
assert!(align_of::<TSTypeQueryExprName>() == 4usize);
|
||||
assert!(size_of::<TSImportType>() == 56usize);
|
||||
assert!(size_of::<TSImportType>() == 72usize);
|
||||
assert!(align_of::<TSImportType>() == 4usize);
|
||||
assert!(offset_of!(TSImportType, span) == 0usize);
|
||||
assert!(offset_of!(TSImportType, is_type_of) == 8usize);
|
||||
assert!(offset_of!(TSImportType, parameter) == 12usize);
|
||||
assert!(offset_of!(TSImportType, qualifier) == 20usize);
|
||||
assert!(offset_of!(TSImportType, attributes) == 28usize);
|
||||
assert!(offset_of!(TSImportType, type_parameters) == 52usize);
|
||||
assert!(size_of::<TSImportAttributes>() == 24usize);
|
||||
assert!(offset_of!(TSImportType, type_parameters) == 68usize);
|
||||
assert!(size_of::<TSImportAttributes>() == 40usize);
|
||||
assert!(align_of::<TSImportAttributes>() == 4usize);
|
||||
assert!(offset_of!(TSImportAttributes, span) == 0usize);
|
||||
assert!(offset_of!(TSImportAttributes, elements) == 8usize);
|
||||
assert!(offset_of!(TSImportAttributes, attributes_keyword) == 8usize);
|
||||
assert!(offset_of!(TSImportAttributes, elements) == 24usize);
|
||||
assert!(size_of::<TSImportAttribute>() == 36usize);
|
||||
assert!(align_of::<TSImportAttribute>() == 4usize);
|
||||
assert!(offset_of!(TSImportAttribute, span) == 0usize);
|
||||
|
|
|
|||
|
|
@ -11832,14 +11832,16 @@ impl<'a> AstBuilder<'a> {
|
|||
///
|
||||
/// ## Parameters
|
||||
/// - span: The [`Span`] covering this node
|
||||
/// - attributes_keyword
|
||||
/// - elements
|
||||
#[inline]
|
||||
pub fn ts_import_attributes(
|
||||
self,
|
||||
span: Span,
|
||||
attributes_keyword: IdentifierName<'a>,
|
||||
elements: Vec<'a, TSImportAttribute<'a>>,
|
||||
) -> TSImportAttributes<'a> {
|
||||
TSImportAttributes { span, elements }
|
||||
TSImportAttributes { span, attributes_keyword, elements }
|
||||
}
|
||||
|
||||
/// Builds a [`TSImportAttributes`] and stores it in the memory arena.
|
||||
|
|
@ -11848,14 +11850,16 @@ impl<'a> AstBuilder<'a> {
|
|||
///
|
||||
/// ## Parameters
|
||||
/// - span: The [`Span`] covering this node
|
||||
/// - attributes_keyword
|
||||
/// - elements
|
||||
#[inline]
|
||||
pub fn alloc_ts_import_attributes(
|
||||
self,
|
||||
span: Span,
|
||||
attributes_keyword: IdentifierName<'a>,
|
||||
elements: Vec<'a, TSImportAttribute<'a>>,
|
||||
) -> Box<'a, TSImportAttributes<'a>> {
|
||||
Box::new_in(self.ts_import_attributes(span, elements), self.allocator)
|
||||
Box::new_in(self.ts_import_attributes(span, attributes_keyword, elements), self.allocator)
|
||||
}
|
||||
|
||||
/// Builds a [`TSImportAttribute`]
|
||||
|
|
|
|||
|
|
@ -2157,6 +2157,7 @@ pub mod walk {
|
|||
it: &TSImportAttributes<'a>,
|
||||
) {
|
||||
// NOTE: AstKind doesn't exists!
|
||||
visitor.visit_identifier_name(&it.attributes_keyword);
|
||||
visitor.visit_ts_import_attribute_list(&it.elements);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2230,6 +2230,7 @@ pub mod walk_mut {
|
|||
it: &mut TSImportAttributes<'a>,
|
||||
) {
|
||||
// NOTE: AstType doesn't exists!
|
||||
visitor.visit_identifier_name(&mut it.attributes_keyword);
|
||||
visitor.visit_ts_import_attribute_list(&mut it.elements);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@ proc-macro = true
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["full"] }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["full"] }
|
||||
proc-macro2 = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -3286,10 +3286,18 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportType<'a> {
|
|||
|
||||
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportAttributes<'a> {
|
||||
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
|
||||
// { with: { ... } }
|
||||
p.print_str("{ with: { ");
|
||||
p.print_char(b'{');
|
||||
p.print_soft_space();
|
||||
self.attributes_keyword.gen(p, ctx);
|
||||
p.print_str(":");
|
||||
p.print_soft_space();
|
||||
p.print_char(b'{');
|
||||
p.print_soft_space();
|
||||
p.print_list(&self.elements, ctx);
|
||||
p.print_str(" }}");
|
||||
p.print_soft_space();
|
||||
p.print_char(b'}');
|
||||
p.print_soft_space();
|
||||
p.print_char(b'}');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1001,9 +1001,14 @@ impl<'a> ParserImpl<'a> {
|
|||
|
||||
fn parse_ts_import_attributes(&mut self) -> Result<TSImportAttributes<'a>> {
|
||||
let span = self.start_span();
|
||||
// { with:
|
||||
self.expect(Kind::LCurly)?;
|
||||
self.expect(Kind::With)?;
|
||||
let attributes_keyword = match self.cur_kind() {
|
||||
Kind::Assert if !self.cur_token().is_on_new_line => self.parse_identifier_name()?,
|
||||
Kind::With => self.parse_identifier_name()?,
|
||||
_ => {
|
||||
return Err(self.unexpected());
|
||||
}
|
||||
};
|
||||
self.expect(Kind::Colon)?;
|
||||
self.expect(Kind::LCurly)?;
|
||||
let elements = self.parse_delimited_list(
|
||||
|
|
@ -1014,7 +1019,7 @@ impl<'a> ParserImpl<'a> {
|
|||
)?;
|
||||
self.expect(Kind::RCurly)?;
|
||||
self.expect(Kind::RCurly)?;
|
||||
Ok(self.ast.ts_import_attributes(span, elements))
|
||||
Ok(self.ast.ts_import_attributes(self.end_span(span), attributes_keyword, elements))
|
||||
}
|
||||
|
||||
fn parse_ts_import_attribute(&mut self) -> Result<TSImportAttribute<'a>> {
|
||||
|
|
|
|||
|
|
@ -292,38 +292,39 @@ pub(crate) enum AncestorType {
|
|||
TSImportTypeQualifier = 260,
|
||||
TSImportTypeAttributes = 261,
|
||||
TSImportTypeTypeParameters = 262,
|
||||
TSImportAttributesElements = 263,
|
||||
TSImportAttributeName = 264,
|
||||
TSImportAttributeValue = 265,
|
||||
TSFunctionTypeThisParam = 266,
|
||||
TSFunctionTypeParams = 267,
|
||||
TSFunctionTypeReturnType = 268,
|
||||
TSFunctionTypeTypeParameters = 269,
|
||||
TSConstructorTypeParams = 270,
|
||||
TSConstructorTypeReturnType = 271,
|
||||
TSConstructorTypeTypeParameters = 272,
|
||||
TSMappedTypeTypeParameter = 273,
|
||||
TSMappedTypeNameType = 274,
|
||||
TSMappedTypeTypeAnnotation = 275,
|
||||
TSTemplateLiteralTypeQuasis = 276,
|
||||
TSTemplateLiteralTypeTypes = 277,
|
||||
TSAsExpressionExpression = 278,
|
||||
TSAsExpressionTypeAnnotation = 279,
|
||||
TSSatisfiesExpressionExpression = 280,
|
||||
TSSatisfiesExpressionTypeAnnotation = 281,
|
||||
TSTypeAssertionExpression = 282,
|
||||
TSTypeAssertionTypeAnnotation = 283,
|
||||
TSImportEqualsDeclarationId = 284,
|
||||
TSImportEqualsDeclarationModuleReference = 285,
|
||||
TSExternalModuleReferenceExpression = 286,
|
||||
TSNonNullExpressionExpression = 287,
|
||||
DecoratorExpression = 288,
|
||||
TSExportAssignmentExpression = 289,
|
||||
TSNamespaceExportDeclarationId = 290,
|
||||
TSInstantiationExpressionExpression = 291,
|
||||
TSInstantiationExpressionTypeParameters = 292,
|
||||
JSDocNullableTypeTypeAnnotation = 293,
|
||||
JSDocNonNullableTypeTypeAnnotation = 294,
|
||||
TSImportAttributesAttributesKeyword = 263,
|
||||
TSImportAttributesElements = 264,
|
||||
TSImportAttributeName = 265,
|
||||
TSImportAttributeValue = 266,
|
||||
TSFunctionTypeThisParam = 267,
|
||||
TSFunctionTypeParams = 268,
|
||||
TSFunctionTypeReturnType = 269,
|
||||
TSFunctionTypeTypeParameters = 270,
|
||||
TSConstructorTypeParams = 271,
|
||||
TSConstructorTypeReturnType = 272,
|
||||
TSConstructorTypeTypeParameters = 273,
|
||||
TSMappedTypeTypeParameter = 274,
|
||||
TSMappedTypeNameType = 275,
|
||||
TSMappedTypeTypeAnnotation = 276,
|
||||
TSTemplateLiteralTypeQuasis = 277,
|
||||
TSTemplateLiteralTypeTypes = 278,
|
||||
TSAsExpressionExpression = 279,
|
||||
TSAsExpressionTypeAnnotation = 280,
|
||||
TSSatisfiesExpressionExpression = 281,
|
||||
TSSatisfiesExpressionTypeAnnotation = 282,
|
||||
TSTypeAssertionExpression = 283,
|
||||
TSTypeAssertionTypeAnnotation = 284,
|
||||
TSImportEqualsDeclarationId = 285,
|
||||
TSImportEqualsDeclarationModuleReference = 286,
|
||||
TSExternalModuleReferenceExpression = 287,
|
||||
TSNonNullExpressionExpression = 288,
|
||||
DecoratorExpression = 289,
|
||||
TSExportAssignmentExpression = 290,
|
||||
TSNamespaceExportDeclarationId = 291,
|
||||
TSInstantiationExpressionExpression = 292,
|
||||
TSInstantiationExpressionTypeParameters = 293,
|
||||
JSDocNullableTypeTypeAnnotation = 294,
|
||||
JSDocNonNullableTypeTypeAnnotation = 295,
|
||||
}
|
||||
|
||||
/// Ancestor type used in AST traversal.
|
||||
|
|
@ -804,6 +805,8 @@ pub enum Ancestor<'a> {
|
|||
AncestorType::TSImportTypeAttributes as u16,
|
||||
TSImportTypeTypeParameters(TSImportTypeWithoutTypeParameters<'a>) =
|
||||
AncestorType::TSImportTypeTypeParameters as u16,
|
||||
TSImportAttributesAttributesKeyword(TSImportAttributesWithoutAttributesKeyword<'a>) =
|
||||
AncestorType::TSImportAttributesAttributesKeyword as u16,
|
||||
TSImportAttributesElements(TSImportAttributesWithoutElements<'a>) =
|
||||
AncestorType::TSImportAttributesElements as u16,
|
||||
TSImportAttributeName(TSImportAttributeWithoutName<'a>) =
|
||||
|
|
@ -1726,7 +1729,10 @@ impl<'a> Ancestor<'a> {
|
|||
|
||||
#[inline]
|
||||
pub fn is_ts_import_attributes(&self) -> bool {
|
||||
matches!(self, Self::TSImportAttributesElements(_))
|
||||
matches!(
|
||||
self,
|
||||
Self::TSImportAttributesAttributesKeyword(_) | Self::TSImportAttributesElements(_)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -11231,9 +11237,30 @@ impl<'a> TSImportTypeWithoutTypeParameters<'a> {
|
|||
}
|
||||
|
||||
pub(crate) const OFFSET_TS_IMPORT_ATTRIBUTES_SPAN: usize = offset_of!(TSImportAttributes, span);
|
||||
pub(crate) const OFFSET_TS_IMPORT_ATTRIBUTES_ATTRIBUTES_KEYWORD: usize =
|
||||
offset_of!(TSImportAttributes, attributes_keyword);
|
||||
pub(crate) const OFFSET_TS_IMPORT_ATTRIBUTES_ELEMENTS: usize =
|
||||
offset_of!(TSImportAttributes, elements);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct TSImportAttributesWithoutAttributesKeyword<'a>(pub(crate) *const TSImportAttributes<'a>);
|
||||
|
||||
impl<'a> TSImportAttributesWithoutAttributesKeyword<'a> {
|
||||
#[inline]
|
||||
pub fn span(&self) -> &Span {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_TS_IMPORT_ATTRIBUTES_SPAN) as *const Span) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn elements(&self) -> &Vec<'a, TSImportAttribute<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_TS_IMPORT_ATTRIBUTES_ELEMENTS)
|
||||
as *const Vec<'a, TSImportAttribute<'a>>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct TSImportAttributesWithoutElements<'a>(pub(crate) *const TSImportAttributes<'a>);
|
||||
|
|
@ -11243,6 +11270,14 @@ impl<'a> TSImportAttributesWithoutElements<'a> {
|
|||
pub fn span(&self) -> &Span {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_TS_IMPORT_ATTRIBUTES_SPAN) as *const Span) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn attributes_keyword(&self) -> &IdentifierName<'a> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_TS_IMPORT_ATTRIBUTES_ATTRIBUTES_KEYWORD)
|
||||
as *const IdentifierName<'a>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const OFFSET_TS_IMPORT_ATTRIBUTE_SPAN: usize = offset_of!(TSImportAttribute, span);
|
||||
|
|
|
|||
|
|
@ -5125,9 +5125,16 @@ pub(crate) unsafe fn walk_ts_import_attributes<'a, Tr: Traverse<'a>>(
|
|||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
traverser.enter_ts_import_attributes(&mut *node, ctx);
|
||||
ctx.push_stack(Ancestor::TSImportAttributesElements(
|
||||
ancestor::TSImportAttributesWithoutElements(node),
|
||||
ctx.push_stack(Ancestor::TSImportAttributesAttributesKeyword(
|
||||
ancestor::TSImportAttributesWithoutAttributesKeyword(node),
|
||||
));
|
||||
walk_identifier_name(
|
||||
traverser,
|
||||
(node as *mut u8).add(ancestor::OFFSET_TS_IMPORT_ATTRIBUTES_ATTRIBUTES_KEYWORD)
|
||||
as *mut IdentifierName,
|
||||
ctx,
|
||||
);
|
||||
ctx.retag_stack(AncestorType::TSImportAttributesElements);
|
||||
for item in (*((node as *mut u8).add(ancestor::OFFSET_TS_IMPORT_ATTRIBUTES_ELEMENTS)
|
||||
as *mut Vec<TSImportAttribute>))
|
||||
.iter_mut()
|
||||
|
|
|
|||
|
|
@ -90,12 +90,11 @@ Negative Passed: 14/14 (100.00%)
|
|||
· ─────────
|
||||
╰────
|
||||
|
||||
× Expected `with` but found `string`
|
||||
× Unexpected token
|
||||
╭─[fail/oxc-2394.ts:20:22]
|
||||
19 │ export type LocalInterface =
|
||||
20 │ & import("pkg", {"resolution-mode": "require"}).RequireInterface
|
||||
· ────────┬────────
|
||||
· ╰── `with` expected
|
||||
· ─────────────────
|
||||
21 │ & import("pkg", {"resolution-mode": "import"}).ImportInterface;
|
||||
╰────
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
commit: d8086f14
|
||||
|
||||
parser_typescript Summary:
|
||||
AST Parsed : 6444/6456 (99.81%)
|
||||
Positive Passed: 6421/6456 (99.46%)
|
||||
AST Parsed : 6446/6456 (99.85%)
|
||||
Positive Passed: 6423/6456 (99.49%)
|
||||
Negative Passed: 1167/5653 (20.64%)
|
||||
Expect Syntax Error: "compiler/ClassDeclaration10.ts"
|
||||
Expect Syntax Error: "compiler/ClassDeclaration11.ts"
|
||||
|
|
@ -4817,16 +4817,6 @@ Expect to Parse: "conformance/jsdoc/overloadTag3.ts"
|
|||
· ──────
|
||||
5 │ /**
|
||||
╰────
|
||||
Expect to Parse: "conformance/moduleResolution/resolutionModeImportType1.ts"
|
||||
|
||||
× Expected `with` but found `assert`
|
||||
╭─[conformance/moduleResolution/resolutionModeImportType1.ts:2:38]
|
||||
1 │ type Default = typeof import("foo").x;
|
||||
2 │ type Import = typeof import("foo", { assert: { "resolution-mode": "import" } }).x;
|
||||
· ───┬──
|
||||
· ╰── `with` expected
|
||||
3 │ type Require = typeof import("foo", { assert: { "resolution-mode": "require" } }).x;
|
||||
╰────
|
||||
Expect to Parse: "conformance/moduleResolution/untypedModuleImport.ts"
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
|
|
@ -4845,16 +4835,6 @@ Expect to Parse: "conformance/moduleResolution/untypedModuleImport_vsAmbient.ts"
|
|||
· ▲
|
||||
╰────
|
||||
help: Try insert a semicolon here
|
||||
Expect to Parse: "conformance/node/nodeModulesImportTypeModeDeclarationEmit1.ts"
|
||||
|
||||
× Expected `with` but found `assert`
|
||||
╭─[conformance/node/nodeModulesImportTypeModeDeclarationEmit1.ts:2:23]
|
||||
1 │ export type LocalInterface =
|
||||
2 │ & import("pkg", { assert: {"resolution-mode": "require"} }).RequireInterface
|
||||
· ───┬──
|
||||
· ╰── `with` expected
|
||||
3 │ & import("pkg", { assert: {"resolution-mode": "import"} }).ImportInterface;
|
||||
╰────
|
||||
Expect to Parse: "conformance/salsa/annotatedThisPropertyInitializerDoesntNarrow.ts"
|
||||
|
||||
× Cannot use export statement outside a module
|
||||
|
|
|
|||
Loading…
Reference in a new issue