diff --git a/changelog_unreleased/typescript/16578.md b/changelog_unreleased/typescript/16578.md new file mode 100644 index 000000000..2250a06e3 --- /dev/null +++ b/changelog_unreleased/typescript/16578.md @@ -0,0 +1,31 @@ +#### Preserve a comment between modifier and the decorated property name (#16578 by @sosukesuzuki) + +There was a bug where block comments between the modifier and the name of a decorated property were being treated as trailing comments of the decorator. This behavior was not only unexpected but also lacked idempotency. + +With this change, the position of the block comment between the modifier and the property name is preserved. + + +```tsx +// Input +class Foo { + @decorator + readonly /* comment */ propertyName; +} + +// Prettier stable +class Foo { + @decorator /* comment */ + readonly propertyName; +} + +// Prettier stable (second output) +class Foo { + @decorator /* comment */ readonly propertyName; +} + +// Prettier main +class Foo { + @decorator + readonly /* comment */ propertyName; +} +``` diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index dbe120c97..d4781440f 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -528,7 +528,8 @@ function handleMethodNameComments({ // on the decorator node instead of the method node if ( precedingNode?.type === "Decorator" && - propertyLikeNodeTypes.has(enclosingNode?.type) + propertyLikeNodeTypes.has(enclosingNode?.type) && + isLineComment(comment) ) { addTrailingComment(precedingNode, comment); return true; diff --git a/tests/format/typescript/comments/16065-2.ts b/tests/format/typescript/comments/16065-2.ts new file mode 100644 index 000000000..f63e84107 --- /dev/null +++ b/tests/format/typescript/comments/16065-2.ts @@ -0,0 +1,27 @@ +class Foo { + // PropertyDefinition + @decorator + readonly /* comment */ propertyDefinition; + + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + + // MethodDefinition + @decorator + private /* comment */ methodDefinition() {} + + // AccessorProperty + @decorator + accessor /* comment */ accessorProperty = 3; + + constructor( + // TSParameterProperty + @decorator + readonly /* comment */ parameterProperty, + ) {} +} diff --git a/tests/format/typescript/comments/__snapshots__/format.test.js.snap b/tests/format/typescript/comments/__snapshots__/format.test.js.snap index 254b0e7f8..032a0e5d5 100644 --- a/tests/format/typescript/comments/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/comments/__snapshots__/format.test.js.snap @@ -156,6 +156,72 @@ class Foo { ================================================================================ `; +exports[`16065-2.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +class Foo { + // PropertyDefinition + @decorator + readonly /* comment */ propertyDefinition; + + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + + // MethodDefinition + @decorator + private /* comment */ methodDefinition() {} + + // AccessorProperty + @decorator + accessor /* comment */ accessorProperty = 3; + + constructor( + // TSParameterProperty + @decorator + readonly /* comment */ parameterProperty, + ) {} +} + +=====================================output===================================== +class Foo { + // PropertyDefinition + @decorator + readonly /* comment */ propertyDefinition; + + // TSAbstractPropertyDefinition + @decorator + abstract /* comment */ abstractPropertyDefinition; + + // TSAbstractMethodDefinition + @decorator + abstract /* comment */ abstractMethodDefinition; + + // MethodDefinition + @decorator + private /* comment */ methodDefinition() {} + + // AccessorProperty + @decorator + accessor /* comment */ accessorProperty = 3; + + constructor( + // TSParameterProperty + @decorator + readonly /* comment */ parameterProperty, + ) {} +} + +================================================================================ +`; + exports[`abstract_class.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"]