🔎 Search Terms
experimentalDecorators, parameter decorator, comment, JSDoc, emit, legacy decorators, visitParameterDeclaration
🕗 Version & Regression Information
- This is the behavior in every version I tried: the playground's current nightly and tsgo built from
main at df1a31e6d5.
- tsc 6.0.3 does not emit the comment.
⏯ Playground Link
https://tsgo.sxzz.dev/#eNplUMFKAzEQ/ZUhp7YsWykiuF4Ee1EQwetuD2l2tkayScgktVL67042VKo9JTPv5b2XdxSDaNpWjFLbOpKoRI/KyIAwJKuidhZ4MavrWoYdNSDtd7uZT+dDZzuLB+9CBH5CBE9w7CyAcpZiSCq6MMszwHKxgMcefUAlI/aQCMHFDwywWBYGo4qdfAM2jVsMczieOnsSm6oVkVhx0Lv6k5zlhJNJJ5QbvTYY3nyOSZ1oin3GIqfFmFedQOKUfK/O4Oj6ZLCAHIkw7Hn6B78jOZOyciFuk+3Z7ILHf9Rq8uDP4u8a6XUSeLYRg/NXuEtxrVkni/aaLoOV6uXZ9M8zzunMHl+4gqJ/bXzwGPSINkqzRuVYyIWplkzLrNLophJKNIKL3POxulnd1ff16pbnL9EM0hCefgDD4a0/
💻 Code
declare function dec(...args: any[]): any;
export class C {
constructor(
/** @deprecated use other */
@dec dep: number) {}
}
with "experimentalDecorators": true.
🙁 Actual behavior
The constructor is emitted with the parameter's comment:
constructor(
/** @deprecated use other */
dep) { }
🙂 Expected behavior
Same as tsc 6.0.3, which drops the comment:
(The class wrapper also differs between the two compilers, export class C vs let C = class C with C = __decorate(...); that's not what this issue is about.)
Additional information about the issue
This matters for tools that read JSDoc from the emitted JS: a JSDoc block that ends up on a bare parameter name gets parsed in a position it wasn't written for.
The transformer is not where the two compilers differ: Strada's visitParameterDeclaration in legacyDecorators.ts also calls setCommentRange(updated, node) with the original range, the same as tsgo. So the actual difference must be further downstream, presumably in how the printer emits comments for that range. We haven't found it.
As a local workaround, we set the comment range to the range already moved past the decorators, which gives the same output as tsc:
if updated != node.AsNode() {
- // While we emit the source map for the node after skipping decorators and modifiers,
- // we need to emit the comments for the original range.
- tx.EmitContext().SetCommentRange(updated, node.Loc)
newLoc := transformers.MoveRangePastModifiers(node.AsNode())
updated.Loc = newLoc
+ tx.EmitContext().SetCommentRange(updated, newLoc)
tx.EmitContext().SetSourceMapRange(updated, newLoc)
tx.EmitContext().SetEmitFlags(updated.Name(), printer.EFNoTrailingSourceMap)
}
That's a deviation from Strada's transformer, so it may not be the right upstream fix.
🔎 Search Terms
experimentalDecorators, parameter decorator, comment, JSDoc, emit, legacy decorators, visitParameterDeclaration
🕗 Version & Regression Information
mainatdf1a31e6d5.⏯ Playground Link
https://tsgo.sxzz.dev/#eNplUMFKAzEQ/ZUhp7YsWykiuF4Ee1EQwetuD2l2tkayScgktVL67042VKo9JTPv5b2XdxSDaNpWjFLbOpKoRI/KyIAwJKuidhZ4MavrWoYdNSDtd7uZT+dDZzuLB+9CBH5CBE9w7CyAcpZiSCq6MMszwHKxgMcefUAlI/aQCMHFDwywWBYGo4qdfAM2jVsMczieOnsSm6oVkVhx0Lv6k5zlhJNJJ5QbvTYY3nyOSZ1oin3GIqfFmFedQOKUfK/O4Oj6ZLCAHIkw7Hn6B78jOZOyciFuk+3Z7ILHf9Rq8uDP4u8a6XUSeLYRg/NXuEtxrVkni/aaLoOV6uXZ9M8zzunMHl+4gqJ/bXzwGPSINkqzRuVYyIWplkzLrNLophJKNIKL3POxulnd1ff16pbnL9EM0hCefgDD4a0/
💻 Code
with
"experimentalDecorators": true.🙁 Actual behavior
The constructor is emitted with the parameter's comment:
🙂 Expected behavior
Same as tsc 6.0.3, which drops the comment:
(The class wrapper also differs between the two compilers,
export class Cvslet C = class CwithC = __decorate(...); that's not what this issue is about.)Additional information about the issue
This matters for tools that read JSDoc from the emitted JS: a JSDoc block that ends up on a bare parameter name gets parsed in a position it wasn't written for.
The transformer is not where the two compilers differ: Strada's
visitParameterDeclarationinlegacyDecorators.tsalso callssetCommentRange(updated, node)with the original range, the same as tsgo. So the actual difference must be further downstream, presumably in how the printer emits comments for that range. We haven't found it.As a local workaround, we set the comment range to the range already moved past the decorators, which gives the same output as tsc:
if updated != node.AsNode() { - // While we emit the source map for the node after skipping decorators and modifiers, - // we need to emit the comments for the original range. - tx.EmitContext().SetCommentRange(updated, node.Loc) newLoc := transformers.MoveRangePastModifiers(node.AsNode()) updated.Loc = newLoc + tx.EmitContext().SetCommentRange(updated, newLoc) tx.EmitContext().SetSourceMapRange(updated, newLoc) tx.EmitContext().SetEmitFlags(updated.Name(), printer.EFNoTrailingSourceMap) }That's a deviation from Strada's transformer, so it may not be the right upstream fix.