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
79 changes: 54 additions & 25 deletions crates/oxc_transformer/src/decorator/legacy/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,25 @@ enum EnumType {
Object,
}

/// Metadata for decorated methods
pub(super) struct MethodMetadata<'a> {
/// The `design:type` metadata expression
pub r#type: Expression<'a>,
/// The `design:paramtypes` metadata expression
pub param_types: Expression<'a>,
/// The `design:returntype` metadata expression (optional, omitted for getters/setters)
pub return_type: Option<Expression<'a>>,
}

pub struct LegacyDecoratorMetadata<'a, 'ctx> {
ctx: &'ctx TransformCtx<'a>,
/// Stack of method metadata arrays, each array contains 3 expressions:
/// `[design:type, design:paramtypes, design:returntype]`
/// Stack of method metadata.
///
/// Only the method that needs to be pushed onto a stack is the method metadata,
/// which should be inserted after all real decorators. However, method parameters
/// will be processed before the metadata generation, so we need to temporarily store
/// them in a stack and pop them when in exit_method_definition.
method_metadata_stack: SparseStack<[Expression<'a>; 3]>,
method_metadata_stack: SparseStack<MethodMetadata<'a>>,
/// Stack of constructor metadata expressions, each expression
/// is the `design:paramtypes`.
///
Expand Down Expand Up @@ -182,7 +191,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for LegacyDecoratorMetadata<'a, '_> {
&& constructor.value.params.items.iter().all(|param| param.decorators.is_empty()))
{
let serialized_type =
self.serialize_parameter_types_of_node(&constructor.value.params, ctx);
self.serialize_parameters_types_of_node(&constructor.value.params, ctx);

Some(self.create_metadata("design:paramtypes", serialized_type, ctx))
} else {
Expand All @@ -208,18 +217,32 @@ impl<'a> Traverse<'a, TransformState<'a>> for LegacyDecoratorMetadata<'a, '_> {
|| method.value.params.items.iter().any(|param| !param.decorators.is_empty()));

let metadata = is_decorated.then(|| {
[
self.create_metadata("design:type", Self::global_function(ctx), ctx),
{
let serialized_type =
self.serialize_parameter_types_of_node(&method.value.params, ctx);
self.create_metadata("design:paramtypes", serialized_type, ctx)
},
{
let serialized_type = self.serialize_return_type_of_node(&method.value, ctx);
self.create_metadata("design:returntype", serialized_type, ctx)
},
]
// TypeScript only emits `design:returntype` for regular methods,
// not for getters or setters.

let (design_type, return_type) = if method.kind.is_get() {
// For getters, the design type is the type of the property
(self.serialize_return_type_of_node(&method.value, ctx), None)
} else if method.kind.is_set()
&& let Some(param) = method.value.params.items.first()
{
// For setters, the design type is the type of the first parameter
(self.serialize_parameter_types_of_node(param, ctx), None)
} else {
// For methods, the design type is always `Function`
(
Self::global_function(ctx),
Some(self.serialize_return_type_of_node(&method.value, ctx)),
)
};

let param_types = self.serialize_parameters_types_of_node(&method.value.params, ctx);

MethodMetadata {
r#type: self.create_metadata("design:type", design_type, ctx),
param_types: self.create_metadata("design:paramtypes", param_types, ctx),
return_type: return_type.map(|t| self.create_metadata("design:returntype", t, ctx)),
}
});

self.method_metadata_stack.push(metadata);
Expand Down Expand Up @@ -302,7 +325,7 @@ impl<'a> LegacyDecoratorMetadata<'a, '_> {
enum_type
}

pub fn pop_method_metadata(&mut self) -> Option<[Expression<'a>; 3]> {
pub fn pop_method_metadata(&mut self) -> Option<MethodMetadata<'a>> {
self.method_metadata_stack.pop()
}

Expand Down Expand Up @@ -407,21 +430,15 @@ impl<'a> LegacyDecoratorMetadata<'a, '_> {
}

/// Serializes the type of a node for use with decorator type metadata.
fn serialize_parameter_types_of_node(
fn serialize_parameters_types_of_node(
&mut self,
params: &FormalParameters<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let mut elements =
ctx.ast.vec_with_capacity(params.items.len() + usize::from(params.rest.is_some()));
elements.extend(params.items.iter().map(|param| {
let type_annotation = match &param.pattern.kind {
BindingPatternKind::AssignmentPattern(pattern) => {
pattern.left.type_annotation.as_ref()
}
_ => param.pattern.type_annotation.as_ref(),
};
ArrayExpressionElement::from(self.serialize_type_annotation(type_annotation, ctx))
ArrayExpressionElement::from(self.serialize_parameter_types_of_node(param, ctx))
}));

if let Some(rest) = &params.rest {
Expand All @@ -432,6 +449,18 @@ impl<'a> LegacyDecoratorMetadata<'a, '_> {
ctx.ast.expression_array(SPAN, elements)
}

fn serialize_parameter_types_of_node(
&mut self,
param: &FormalParameter<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let type_annotation = match &param.pattern.kind {
BindingPatternKind::AssignmentPattern(pattern) => pattern.left.type_annotation.as_ref(),
_ => param.pattern.type_annotation.as_ref(),
};
self.serialize_type_annotation(type_annotation, ctx)
}

/// Serializes the return type of a node for use with decorator type metadata.
fn serialize_return_type_of_node(
&mut self,
Expand Down
6 changes: 5 additions & 1 deletion crates/oxc_transformer/src/decorator/legacy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,11 @@ impl<'a> LegacyDecorator<'a, '_> {
decorations.push(ArrayExpressionElement::from(metadata));
}
} else if let Some(metadata) = self.metadata.pop_method_metadata() {
decorations.extend(metadata.map(ArrayExpressionElement::from));
decorations.push(ArrayExpressionElement::from(metadata.r#type));
decorations.push(ArrayExpressionElement::from(metadata.param_types));
if let Some(return_type) = metadata.return_type {
decorations.push(ArrayExpressionElement::from(return_type));
}
}
}

Expand Down
70 changes: 35 additions & 35 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8672,7 +8672,7 @@ rebuilt : [ReferenceId(13)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImport.ts
Symbol reference IDs mismatch for "Observable":
after transform: SymbolId(0): [ReferenceId(2), ReferenceId(8), ReferenceId(9)]
after transform: SymbolId(0): [ReferenceId(2), ReferenceId(4), ReferenceId(5)]
rebuilt : SymbolId(0): [ReferenceId(12), ReferenceId(13)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImportOnDeclare.ts
Expand Down Expand Up @@ -8727,22 +8727,22 @@ Reference symbol mismatch for "decorator":
after transform: SymbolId(0) "decorator"
rebuilt : <None>
Reference flags mismatch for "Promise":
after transform: ReferenceId(26): ReferenceFlags(Read | Type)
after transform: ReferenceId(30): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(28): ReferenceFlags(Read)
Reference flags mismatch for "Promise":
after transform: ReferenceId(27): ReferenceFlags(Read | Type)
after transform: ReferenceId(31): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(29): ReferenceFlags(Read)
Reference flags mismatch for "Promise":
after transform: ReferenceId(32): ReferenceFlags(Read | Type)
after transform: ReferenceId(25): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(34): ReferenceFlags(Read)
Reference flags mismatch for "Promise":
after transform: ReferenceId(33): ReferenceFlags(Read | Type)
after transform: ReferenceId(26): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(35): ReferenceFlags(Read)
Unresolved references mismatch:
after transform: ["Function", "MethodDecorator", "Object", "Promise", "require"]
rebuilt : ["Function", "Object", "Promise", "decorator", "require"]
Unresolved reference IDs mismatch for "Promise":
after transform: [ReferenceId(3), ReferenceId(5), ReferenceId(6), ReferenceId(11), ReferenceId(19), ReferenceId(26), ReferenceId(27), ReferenceId(32), ReferenceId(33)]
after transform: [ReferenceId(3), ReferenceId(5), ReferenceId(6), ReferenceId(9), ReferenceId(17), ReferenceId(25), ReferenceId(26), ReferenceId(30), ReferenceId(31)]
rebuilt : [ReferenceId(12), ReferenceId(20), ReferenceId(28), ReferenceId(29), ReferenceId(34), ReferenceId(35)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataRestParameterWithImportedType.ts
Expand Down Expand Up @@ -8864,7 +8864,7 @@ rebuilt : ["Object", "database"]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts
Symbol reference IDs mismatch for "Yoha":
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(5), ReferenceId(6)]
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(4), ReferenceId(5)]
rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferences.ts
Expand Down Expand Up @@ -35962,8 +35962,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "TypedPropertyDescriptor", "require"]
rebuilt : ["Function", "dec", "require"]
after transform: ["TypedPropertyDescriptor", "require"]
rebuilt : ["dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/class/accessor/decoratorOnClassAccessor2.ts
Bindings mismatch:
Expand All @@ -35976,8 +35976,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "TypedPropertyDescriptor", "require"]
rebuilt : ["Function", "dec", "require"]
after transform: ["TypedPropertyDescriptor", "require"]
rebuilt : ["dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/class/accessor/decoratorOnClassAccessor4.ts
Bindings mismatch:
Expand All @@ -35990,8 +35990,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Function", "Number", "dec", "require"]
after transform: ["Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Number", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/class/accessor/decoratorOnClassAccessor5.ts
Bindings mismatch:
Expand All @@ -36004,8 +36004,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Function", "Number", "dec", "require"]
after transform: ["Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Number", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/class/accessor/decoratorOnClassAccessor8.ts
Bindings mismatch:
Expand Down Expand Up @@ -36033,8 +36033,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Function", "Number", "dec", "require"]
after transform: ["Number", "TypedPropertyDescriptor", "require"]
rebuilt : ["Number", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/class/constructor/decoratorOnClassConstructor3.ts
Unresolved references mismatch:
Expand Down Expand Up @@ -38551,8 +38551,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "TypedPropertyDescriptor"]
rebuilt : ["Function", "dec"]
after transform: ["TypedPropertyDescriptor"]
rebuilt : ["dec"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/es6/decorators/class/decoratorOnClass1.es6.ts
Bindings mismatch:
Expand Down Expand Up @@ -39372,10 +39372,10 @@ Bindings mismatch:
after transform: ScopeId(0): ["C", "_decorate", "_decorateMetadata", "_method", "_method2", "dec", "method3"]
rebuilt : ScopeId(0): ["C", "_decorate", "_decorateMetadata", "_method", "_method2", "method3"]
Reference flags mismatch for "_method":
after transform: ReferenceId(39): ReferenceFlags(Read | Write)
after transform: ReferenceId(31): ReferenceFlags(Read | Write)
rebuilt : ReferenceId(2): ReferenceFlags(Write)
Reference flags mismatch for "_method2":
after transform: ReferenceId(48): ReferenceFlags(Read | Write)
after transform: ReferenceId(39): ReferenceFlags(Read | Write)
rebuilt : ReferenceId(4): ReferenceFlags(Write)
Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
Expand All @@ -39396,8 +39396,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Object", "require"]
rebuilt : ["Function", "Object", "dec", "require"]
after transform: ["Object", "require"]
rebuilt : ["Object", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/esDecorators/classDeclaration/accessors/esDecorators-classDeclaration-accessors-nonStaticPrivate.ts
Bindings mismatch:
Expand All @@ -39410,18 +39410,18 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Object", "WeakSet", "require"]
rebuilt : ["Function", "Object", "WeakSet", "dec", "require"]
after transform: ["Object", "WeakSet", "require"]
rebuilt : ["Object", "WeakSet", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/esDecorators/classDeclaration/accessors/esDecorators-classDeclaration-accessors-static.ts
Bindings mismatch:
after transform: ScopeId(0): ["C", "_decorate", "_decorateMetadata", "_method", "_method2", "dec", "method3"]
rebuilt : ScopeId(0): ["C", "_decorate", "_decorateMetadata", "_method", "_method2", "method3"]
Reference flags mismatch for "_method":
after transform: ReferenceId(39): ReferenceFlags(Read | Write)
after transform: ReferenceId(31): ReferenceFlags(Read | Write)
rebuilt : ReferenceId(2): ReferenceFlags(Write)
Reference flags mismatch for "_method2":
after transform: ReferenceId(48): ReferenceFlags(Read | Write)
after transform: ReferenceId(39): ReferenceFlags(Read | Write)
rebuilt : ReferenceId(4): ReferenceFlags(Write)
Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
Expand All @@ -39442,8 +39442,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Object", "require"]
rebuilt : ["Function", "Object", "dec", "require"]
after transform: ["Object", "require"]
rebuilt : ["Object", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/esDecorators/classDeclaration/accessors/esDecorators-classDeclaration-accessors-staticPrivate.ts
Bindings mismatch:
Expand All @@ -39453,13 +39453,13 @@ Symbol span mismatch for "D":
after transform: SymbolId(3): Span { start: 137, end: 138 }
rebuilt : SymbolId(9): Span { start: 0, end: 0 }
Symbol reference IDs mismatch for "D":
after transform: SymbolId(3): [ReferenceId(23), ReferenceId(25)]
rebuilt : SymbolId(9): [ReferenceId(20), ReferenceId(30), ReferenceId(33)]
after transform: SymbolId(3): [ReferenceId(20), ReferenceId(22)]
rebuilt : SymbolId(9): [ReferenceId(17), ReferenceId(27), ReferenceId(30)]
Symbol span mismatch for "D":
after transform: SymbolId(14): Span { start: 0, end: 0 }
rebuilt : SymbolId(10): Span { start: 137, end: 138 }
Symbol reference IDs mismatch for "D":
after transform: SymbolId(14): [ReferenceId(28)]
after transform: SymbolId(14): [ReferenceId(25)]
rebuilt : SymbolId(10): []
Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
Expand All @@ -39474,8 +39474,8 @@ Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Function", "Object", "require"]
rebuilt : ["Function", "Object", "dec", "require"]
after transform: ["Object", "require"]
rebuilt : ["Object", "dec", "require"]

semantic Error: tasks/coverage/typescript/tests/cases/conformance/esDecorators/classDeclaration/classSuper/esDecorators-classDeclaration-classSuper.1.ts
Bindings mismatch:
Expand Down Expand Up @@ -40482,7 +40482,7 @@ Bindings mismatch:
after transform: ScopeId(0): ["_C", "_decorateMetadata", "_defineProperty", "_get_x", "_method", "_set_x", "_y", "dec"]
rebuilt : ScopeId(0): ["_C", "_decorateMetadata", "_defineProperty", "_get_x", "_method", "_set_x", "_y"]
Symbol reference IDs mismatch for "_decorateMetadata":
after transform: SymbolId(10): [ReferenceId(24), ReferenceId(25), ReferenceId(26), ReferenceId(28), ReferenceId(29), ReferenceId(30), ReferenceId(32), ReferenceId(34), ReferenceId(35), ReferenceId(37), ReferenceId(39), ReferenceId(41), ReferenceId(42), ReferenceId(43), ReferenceId(45), ReferenceId(46), ReferenceId(47), ReferenceId(49), ReferenceId(51), ReferenceId(52), ReferenceId(54), ReferenceId(56)]
after transform: SymbolId(10): [ReferenceId(24), ReferenceId(25), ReferenceId(26), ReferenceId(27), ReferenceId(28), ReferenceId(31), ReferenceId(32), ReferenceId(34), ReferenceId(36), ReferenceId(38), ReferenceId(39), ReferenceId(40), ReferenceId(41), ReferenceId(42), ReferenceId(45), ReferenceId(46), ReferenceId(48), ReferenceId(50)]
rebuilt : SymbolId(1): []
Reference symbol mismatch for "dec":
after transform: SymbolId(0) "dec"
Expand Down
Loading
Loading