mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Avoid printing comments on static fields twice. (#47363)
* Avoid printing comments on static fields twice.
In TS4.4, when a transformer adds a static field with a synthetic
comment to a decorated class, TS prints the synthetic comment twice:
@Decorator
class MyClass {
/* comment */ staticField = 'x'; // field and comment added by transformer
}
Becomes:
var MyClass = class MyClass {}
/*comment*/
/*comment*/
MyClass.newField = "x";
__decorate(MyClass, Decorator, ...)
This is because the classFields transformer calls `setOriginalNode(n,
propertyDeclaration)` on both the expression statement , and the
assignment expression contained in it, leading to the synthetic comment
appearing twice.
This change avoids the problem by explicitly deleting any synthetic
comments from the assignment expression created for static fields when
creating the expression statement containing the assignment. This allows
us to retain the information of the original node without printing the
synthetic comment twice.
* Update src/testRunner/unittests/transform.ts
Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
parent
0f1496f354
commit
faee7b3621
@ -1335,6 +1335,11 @@ namespace ts {
|
||||
setSourceMapRange(statement, moveRangePastModifiers(property));
|
||||
setCommentRange(statement, property);
|
||||
setOriginalNode(statement, property);
|
||||
// `setOriginalNode` *copies* the `emitNode` from `property`, so now both
|
||||
// `statement` and `expression` have a copy of the synthesized comments.
|
||||
// Drop the comments from expression to avoid printing them twice.
|
||||
setSyntheticLeadingComments(expression, undefined);
|
||||
setSyntheticTrailingComments(expression, undefined);
|
||||
statements.push(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,6 +599,63 @@ module MyModule {
|
||||
}, exports => {
|
||||
assert.equal(exports.stringLength, 5);
|
||||
});
|
||||
|
||||
function addStaticFieldWithComment(context: TransformationContext) {
|
||||
return (sourceFile: SourceFile): SourceFile => {
|
||||
return visitNode(sourceFile, rootTransform, isSourceFile);
|
||||
};
|
||||
function rootTransform<T extends Node>(node: T): Node {
|
||||
if (isClassLike(node)) {
|
||||
const newMembers = [factory.createPropertyDeclaration(/* decorators */ undefined, [factory.createModifier(SyntaxKind.StaticKeyword)], "newField", /* questionOrExclamationToken */ undefined, /* type */ undefined, factory.createStringLiteral("x"))];
|
||||
setSyntheticLeadingComments(newMembers[0], [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]);
|
||||
return isClassDeclaration(node) ?
|
||||
factory.updateClassDeclaration(
|
||||
node, node.decorators,
|
||||
/* modifierFlags */ undefined, node.name,
|
||||
node.typeParameters, node.heritageClauses,
|
||||
newMembers) :
|
||||
factory.updateClassExpression(
|
||||
node, node.decorators,
|
||||
/* modifierFlags */ undefined, node.name,
|
||||
node.typeParameters, node.heritageClauses,
|
||||
newMembers);
|
||||
}
|
||||
return visitEachChild(node, rootTransform, context);
|
||||
}
|
||||
}
|
||||
|
||||
testBaseline("transformSyntheticCommentOnStaticFieldInClassDeclaration", () => {
|
||||
return transpileModule(`
|
||||
declare const Decorator: any;
|
||||
@Decorator
|
||||
class MyClass {
|
||||
}
|
||||
`, {
|
||||
transformers: {
|
||||
before: [addStaticFieldWithComment],
|
||||
},
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES2015,
|
||||
newLine: NewLineKind.CarriageReturnLineFeed,
|
||||
}
|
||||
}).outputText;
|
||||
});
|
||||
|
||||
testBaseline("transformSyntheticCommentOnStaticFieldInClassExpression", () => {
|
||||
return transpileModule(`
|
||||
const MyClass = class {
|
||||
};
|
||||
`, {
|
||||
transformers: {
|
||||
before: [addStaticFieldWithComment],
|
||||
},
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES2015,
|
||||
newLine: NewLineKind.CarriageReturnLineFeed,
|
||||
}
|
||||
}).outputText;
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
let MyClass = class MyClass {
|
||||
};
|
||||
/*comment*/
|
||||
MyClass.newField = "x";
|
||||
MyClass = __decorate([
|
||||
Decorator
|
||||
], MyClass);
|
||||
@ -0,0 +1,6 @@
|
||||
var _a;
|
||||
const MyClass = (_a = class {
|
||||
},
|
||||
/*comment*/
|
||||
_a.newField = "x",
|
||||
_a);
|
||||
Loading…
x
Reference in New Issue
Block a user