Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support decorator auto accessors syntax #12299

Merged
merged 9 commits into from Mar 2, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions changelog_unreleased/javascript/12299.md
@@ -0,0 +1,12 @@
#### Support decorator auto accessors syntax (#12299 by @sosukesuzuki)

Support auto accessors syntax that is introduced in [new decorators proposal](https://github.com/tc39/proposal-decorators).

<!-- prettier-ignore -->
```jsx
// Example
@defineElement("my-class")
class C extends HTMLElement {
@reactive accessor clicked = false;
}
```
1 change: 1 addition & 0 deletions src/language-js/parse/babel.js
Expand Up @@ -39,6 +39,7 @@ const parseOptions = {
"asyncDoExpressions",
"regexpUnicodeSets",
"destructuringPrivate",
"decoratorAutoAccessors",
],
tokens: true,
ranges: true,
Expand Down
3 changes: 3 additions & 0 deletions src/language-js/print/class.js
Expand Up @@ -217,6 +217,9 @@ function printClassProperty(path, options, print) {
if (node.variance) {
parts.push(print("variance"));
}
if (node.type === "ClassAccessorProperty") {
parts.push("accessor ");
}
parts.push(
printPropertyKey(path, options, print),
printOptionalToken(path),
Expand Down
3 changes: 2 additions & 1 deletion src/language-js/print/statement.js
Expand Up @@ -167,7 +167,8 @@ function printSwitchCaseConsequent(path, options, print) {
const isClassProperty = ({ type }) =>
type === "ClassProperty" ||
type === "PropertyDefinition" ||
type === "ClassPrivateProperty";
type === "ClassPrivateProperty" ||
type === "ClassAccessorProperty";
/**
* @returns {boolean}
*/
Expand Down
2 changes: 2 additions & 0 deletions src/language-js/printer-estree.js
Expand Up @@ -96,6 +96,7 @@ function genericPrint(path, options, print, args) {
type === "ClassMethod" ||
type === "ClassPrivateMethod" ||
type === "ClassProperty" ||
type === "ClassAccessorProperty" ||
type === "PropertyDefinition" ||
type === "TSAbstractPropertyDefinition" ||
type === "ClassPrivateProperty" ||
Expand Down Expand Up @@ -759,6 +760,7 @@ function printPathNoParens(path, options, print, args) {
case "ClassProperty":
case "PropertyDefinition":
case "ClassPrivateProperty":
case "ClassAccessorProperty":
return printClassProperty(path, options, print);
case "TemplateElement":
return replaceTextEndOfLine(node.value.raw);
Expand Down
30 changes: 29 additions & 1 deletion tests/config/format-test.js
Expand Up @@ -57,7 +57,28 @@ const espreeDisabledTests = new Set(
].map((directory) => path.join(__dirname, "../format/js", directory))
);
const acornDisabledTests = espreeDisabledTests;
const meriyahDisabledTests = espreeDisabledTests;
const meriyahDisabledTests = new Set([
...espreeDisabledTests,
// Meriyah does not support decorator auto accessors syntax.
// But meriyah can parse it as an ordinary class property.
// So meriyah does not throw parsing error for it.
...[
"basic.js",
"computed.js",
"private.js",
"static-computed.js",
"static-private.js",
"static.js",
"with-semicolon-1.js",
"with-semicolon-2.js",
].map((filename) =>
path.join(__dirname, "../format/js/decorator-auto-accessors", filename)
),
path.join(
__dirname,
"../format/js/babel-plugins/decorator-auto-accessors.js"
),
]);

const isUnstable = (filename, options) => {
const testFunction = unstableTests.get(filename);
Expand Down Expand Up @@ -216,6 +237,13 @@ function runSpec(fixtures, parsers, options) {
: format(code, formatOptions);

for (const currentParser of allParsers) {
if (
(currentParser === "espree" && espreeDisabledTests.has(filename)) ||
(currentParser === "meriyah" && meriyahDisabledTests.has(filename)) ||
(currentParser === "acorn" && acornDisabledTests.has(filename))
) {
continue;
}
runTest({
parsers,
name,
Expand Down
36 changes: 36 additions & 0 deletions tests/format/js/babel-plugins/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -534,6 +534,42 @@ typeof 1m === "decimal128";
================================================================================
`;

exports[`decorator-auto-accessors.js [acorn] format 1`] = `
"Unexpected token (2:12)
1 | class C extends HTMLElement {
> 2 | accessor clicked = false;
| ^
3 | }
4 |"
`;

exports[`decorator-auto-accessors.js [espree] format 1`] = `
"Unexpected token clicked (2:12)
1 | class C extends HTMLElement {
> 2 | accessor clicked = false;
| ^
3 | }
4 |"
`;

exports[`decorator-auto-accessors.js format 1`] = `
====================================options=====================================
parsers: ["babel", "babel-ts", "babel-flow"]
printWidth: 80
| printWidth
=====================================input======================================
class C extends HTMLElement {
accessor clicked = false;
}

=====================================output=====================================
class C extends HTMLElement {
accessor clicked = false;
}

================================================================================
`;

exports[`decorators.js [acorn] format 1`] = `
"Unexpected character '@' (3:1)
1 | // https://babeljs.io/docs/en/babel-plugin-proposal-decorators
Expand Down
3 changes: 3 additions & 0 deletions tests/format/js/babel-plugins/decorator-auto-accessors.js
@@ -0,0 +1,3 @@
class C extends HTMLElement {
accessor clicked = false;
}
2 changes: 2 additions & 0 deletions tests/format/js/babel-plugins/jsfmt.spec.js
Expand Up @@ -26,6 +26,7 @@ run_spec(__dirname, ["babel", "babel-ts", "babel-flow"], {
"module-blocks.js",
"async-do-expressions.js",
"regex-v-flag.js",
"decorator-auto-accessors.js",
],
espree: [
"decimal.js",
Expand All @@ -50,6 +51,7 @@ run_spec(__dirname, ["babel", "babel-ts", "babel-flow"], {
"module-blocks.js",
"async-do-expressions.js",
"regex-v-flag.js",
"decorator-auto-accessors.js",
],
meriyah: [
"decimal.js",
Expand Down