From bc098779c4e457b1454895973196cffb3b1cdedf Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 24 Feb 2023 09:20:34 +0800 Subject: [PATCH] Add missing parentheses for decorator (#14393) --- changelog_unreleased/javascript/14393.md | 22 +++ src/language-js/needs-parens.js | 4 + tests/config/format-test.js | 2 + .../__snapshots__/jsfmt.spec.js.snap | 138 ++++++++++++++++++ .../format/js/decorators/member-expression.js | 50 +++++++ 5 files changed, 216 insertions(+) create mode 100644 changelog_unreleased/javascript/14393.md create mode 100644 tests/format/js/decorators/member-expression.js diff --git a/changelog_unreleased/javascript/14393.md b/changelog_unreleased/javascript/14393.md new file mode 100644 index 000000000000..00cb3e4cd7c1 --- /dev/null +++ b/changelog_unreleased/javascript/14393.md @@ -0,0 +1,22 @@ +#### Add missing parentheses for decorator (#14393 by @fisker) + + +```jsx +// Input +class Person { + @(myDecoratorArray[0]) + greet() {} +} + +// Prettier stable +class Person { + @myDecoratorArray[0] + greet() {} +} + +// Prettier main +class Person { + @(myDecoratorArray[0]) + greet() {} +} +``` diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 6155f0a7999d..d5dc05a0b293 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -187,6 +187,10 @@ function needsParens(path, options) { } case "Decorator": { if (name === "expression") { + if (isMemberExpression(node) && node.computed) { + return true; + } + let hasCallExpression = false; let hasMemberExpression = false; let current = node; diff --git a/tests/config/format-test.js b/tests/config/format-test.js index 3a084702fb25..e5270a6480be 100644 --- a/tests/config/format-test.js +++ b/tests/config/format-test.js @@ -82,6 +82,8 @@ const meriyahDisabledTests = new Set([ __dirname, "../format/js/babel-plugins/decorator-auto-accessors.js" ), + // Parsing to different ASTs + path.join(__dirname, "../format/js/decorators/member-expression.js"), ]); const isUnstable = (filename, options) => { diff --git a/tests/format/js/decorators/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/decorators/__snapshots__/jsfmt.spec.js.snap index 913adbb6d37d..ce9aaf5a5ebc 100644 --- a/tests/format/js/decorators/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/decorators/__snapshots__/jsfmt.spec.js.snap @@ -162,6 +162,144 @@ export class Bar {} ================================================================================ `; +exports[`member-expression.js [acorn] format 1`] = ` +"Unexpected character '@' (3:5) + 1 | [ + 2 | class { +> 3 | @(decorators[0]) + | ^ + 4 | method() {} + 5 | }, + 6 | class {" +`; + +exports[`member-expression.js [espree] format 1`] = ` +"Unexpected character '@' (3:5) + 1 | [ + 2 | class { +> 3 | @(decorators[0]) + | ^ + 4 | method() {} + 5 | }, + 6 | class {" +`; + +exports[`member-expression.js format 1`] = ` +====================================options===================================== +parsers: ["babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +[ + class { + @(decorators[0]) + method() {} + }, + class { + @decorators[0] + method() {} + }, + class { + @(decorators?.[0]) + method() {} + }, + class { + @(decorators.at(0)) + method() {} + }, + class { + @(decorators?.at(0)) + method() {} + }, + class { + @(decorators.first) + method() {} + }, + class { + @(decorators?.first) + method() {} + }, + class { + @(decorators[first]) + method() {} + }, + class { + @decorators[first] + method() {} + }, + class { + @(decorators["first"]) + method() {} + }, + @(decorators[first]) + class { + method() {} + }, + @(decorators[0]) + class { + method() {} + }, +] + +=====================================output===================================== +[ + class { + @(decorators[0]) + method() {} + }, + class { + @decorators [0]; + method() {} + }, + class { + @(decorators?.[0]) + method() {} + }, + class { + @decorators.at(0) + method() {} + }, + class { + @(decorators?.at(0)) + method() {} + }, + class { + @decorators.first + method() {} + }, + class { + @(decorators?.first) + method() {} + }, + class { + @(decorators[first]) + method() {} + }, + class { + @decorators [first]; + method() {} + }, + class { + @(decorators["first"]) + method() {} + }, + ( + @(decorators[first]) + class { + method() {} + } + ), + ( + @(decorators[0]) + class { + method() {} + } + ), +]; + +================================================================================ +`; + exports[`methods.js [acorn] format 1`] = ` "Unexpected character '@' (3:3) 1 | diff --git a/tests/format/js/decorators/member-expression.js b/tests/format/js/decorators/member-expression.js new file mode 100644 index 000000000000..05baf20bc8d2 --- /dev/null +++ b/tests/format/js/decorators/member-expression.js @@ -0,0 +1,50 @@ +[ + class { + @(decorators[0]) + method() {} + }, + class { + @decorators[0] + method() {} + }, + class { + @(decorators?.[0]) + method() {} + }, + class { + @(decorators.at(0)) + method() {} + }, + class { + @(decorators?.at(0)) + method() {} + }, + class { + @(decorators.first) + method() {} + }, + class { + @(decorators?.first) + method() {} + }, + class { + @(decorators[first]) + method() {} + }, + class { + @decorators[first] + method() {} + }, + class { + @(decorators["first"]) + method() {} + }, + @(decorators[first]) + class { + method() {} + }, + @(decorators[0]) + class { + method() {} + }, +]