From 579ab3fc818ac05412e6faae0587545016890cad Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Mon, 4 Oct 2021 11:08:14 -0400 Subject: [PATCH] Add the `decoratorsAutoAccessors` parser plugin (#13681) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Huáng Jùnliàng Co-authored-by: Nicolò Ribaudo --- .../babel-generator/src/generators/classes.ts | 43 +++++++++++ packages/babel-parser/ast/spec.md | 12 +++ packages/babel-parser/src/parser/statement.js | 57 +++++++++++++- packages/babel-parser/src/types.js | 17 ++++- .../_no-plugin/auto-accessors/input.js | 3 + .../_no-plugin/auto-accessors/options.json | 4 + .../accessor-named-constructor/input.js | 3 + .../accessor-named-constructor/output.json | 44 +++++++++++ .../basic-accessor-with-newline/input.js | 4 + .../basic-accessor-with-newline/output.json | 53 +++++++++++++ .../basic-accessor/input.js | 3 + .../basic-accessor/output.json | 41 ++++++++++ .../input.js | 3 + .../output.json | 45 +++++++++++ .../computed-accessor-with-newline/input.js | 4 + .../output.json | 57 ++++++++++++++ .../computed-accessor/input.js | 3 + .../computed-accessor/output.json | 45 +++++++++++ .../computed-static-accesor/input.js | 3 + .../computed-static-accesor/output.json | 45 +++++++++++ .../field-named-accessor/input.js | 3 + .../field-named-accessor/output.json | 49 ++++++++++++ .../input.js | 3 + .../output.json | 56 ++++++++++++++ .../invalid-static-keyword-order/input.js | 3 + .../invalid-static-keyword-order/output.json | 56 ++++++++++++++ .../method-named-accessor/input.js | 3 + .../method-named-accessor/output.json | 51 +++++++++++++ .../not-allowed-on-methods/input.js | 5 ++ .../not-allowed-on-methods/options.json | 3 + .../decorator-auto-accessors/options.json | 5 ++ .../private-accessor/input.js | 3 + .../private-accessor/output.json | 45 +++++++++++ .../private-static-accessor/input.js | 3 + .../private-static-accessor/output.json | 45 +++++++++++ .../static-accessor-with-newline/input.js | 4 + .../static-accessor-with-newline/output.json | 53 +++++++++++++ .../static-accessor/input.js | 3 + .../static-accessor/output.json | 41 ++++++++++ .../src/path/generated/asserts.ts | 4 + .../src/path/generated/validators.ts | 4 + .../src/asserts/generated/index.ts | 12 +++ .../src/ast-types/generated/index.ts | 28 ++++++- .../src/builders/generated/index.ts | 15 ++++ .../src/builders/generated/uppercase.js | 1 + .../src/constants/generated/index.ts | 1 + .../src/converters/toComputedKey.ts | 1 + packages/babel-types/src/definitions/core.ts | 74 +++++++++++++++++++ .../src/validators/generated/index.ts | 36 +++++++++ .../src/validators/isReferenced.ts | 1 + 50 files changed, 1095 insertions(+), 5 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/output.json diff --git a/packages/babel-generator/src/generators/classes.ts b/packages/babel-generator/src/generators/classes.ts index 5829039e9473..f6f072d95f41 100644 --- a/packages/babel-generator/src/generators/classes.ts +++ b/packages/babel-generator/src/generators/classes.ts @@ -115,6 +115,49 @@ export function ClassProperty(this: Printer, node: t.ClassProperty) { this.semicolon(); } +export function ClassAccessorProperty( + this: Printer, + node: t.ClassAccessorProperty, +) { + this.printJoin(node.decorators, node); + + // catch up to property key, avoid line break + // between member modifiers and the property key. + this.source("end", node.key.loc); + + this.tsPrintClassMemberModifiers(node, /* isField */ true); + + this.word("accessor"); + this.printInnerComments(node); + this.space(); + + if (node.computed) { + this.token("["); + this.print(node.key, node); + this.token("]"); + } else { + this._variance(node); + this.print(node.key, node); + } + + // TS + if (node.optional) { + this.token("?"); + } + if (node.definite) { + this.token("!"); + } + + this.print(node.typeAnnotation, node); + if (node.value) { + this.space(); + this.token("="); + this.space(); + this.print(node.value, node); + } + this.semicolon(); +} + export function ClassPrivateProperty( this: Printer, node: t.ClassPrivateProperty, diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index 8205526f5ec6..aabdc572c4d9 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -1213,6 +1213,18 @@ interface ClassPrivateProperty <: Node { } ``` +## ClassAccessorProperty + +```js +interface ClassAccessorProperty <: Node { + type: "ClassAccessorProperty"; + key: Expression | PrivateName; + value: Expression; + static: boolean; + computed: boolean; +} +``` + ## StaticBlock ```js diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 7cd39dd4bc2e..baa85e1f1049 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1518,8 +1518,9 @@ export default class StatementParser extends ExpressionParser { ) { const publicMethod: $FlowSubtype = member; const privateMethod: $FlowSubtype = member; - const publicProp: $FlowSubtype = member; - const privateProp: $FlowSubtype = member; + const publicProp: $FlowSubtype = member; + const privateProp: $FlowSubtype = member; + const accessorProp: $FlowSubtype = member; const method: typeof publicMethod | typeof privateMethod = publicMethod; const publicMember: typeof publicMethod | typeof publicProp = publicMethod; @@ -1674,6 +1675,18 @@ export default class StatementParser extends ExpressionParser { } this.checkGetterSetterParams(publicMethod); + } else if ( + isContextual && + key.name === "accessor" && + !this.isLineTerminator() + ) { + this.expectPlugin("decoratorAutoAccessors"); + this.resetPreviousNodeTrailingComments(key); + + // The so-called parsed name would have been "accessor": get the real name. + const isPrivate = this.match(tt.privateName); + this.parseClassElementName(publicProp); + this.pushClassAccessorProperty(classBody, accessorProp, isPrivate); } else if (this.isLineTerminator()) { // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) if (isPrivate) { @@ -1759,6 +1772,34 @@ export default class StatementParser extends ExpressionParser { ); } + pushClassAccessorProperty( + classBody: N.ClassBody, + prop: N.ClassAccessorProperty, + isPrivate: boolean, + ) { + if (!isPrivate && !prop.computed) { + // Not private, so not node is not a PrivateName and we can safely cast + const key = (prop.key: N.Expression); + + if (key.name === "constructor" || key.value === "constructor") { + // Non-computed field, which is either an identifier named "constructor" + // or a string literal named "constructor" + this.raise(prop.key.start, Errors.ConstructorClassField); + } + } + + const node = this.parseClassAccessorProperty(prop); + classBody.body.push(node); + + if (isPrivate) { + this.classScope.declarePrivateName( + this.getPrivateNameSV(node.key), + CLASS_ELEMENT_OTHER, + node.key.start, + ); + } + } + pushClassMethod( classBody: N.ClassBody, method: N.ClassMethod, @@ -1843,8 +1884,18 @@ export default class StatementParser extends ExpressionParser { return this.finishNode(node, "ClassProperty"); } + parseClassAccessorProperty( + node: N.ClassAccessorProperty, + ): N.ClassAccessorProperty { + this.parseInitializer(node); + this.semicolon(); + return this.finishNode(node, "ClassAccessorProperty"); + } + // https://tc39.es/ecma262/#prod-Initializer - parseInitializer(node: N.ClassProperty | N.ClassPrivateProperty): void { + parseInitializer( + node: N.ClassProperty | N.ClassPrivateProperty | N.ClassAccessorProperty, + ): void { this.scope.enter(SCOPE_CLASS | SCOPE_SUPER); this.expressionScope.enter(newExpressionScope()); this.prodParam.enter(PARAM); diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index f967774c78d3..a45516782e3b 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -782,7 +782,8 @@ export type ClassMember = | ClassMethod | ClassPrivateMethod | ClassProperty - | ClassPrivateProperty; + | ClassPrivateProperty + | ClassAccessorProperty; export type MethodLike = | ObjectMethod @@ -855,6 +856,20 @@ export type ClassPrivateProperty = NodeBase & { variance?: ?FlowVariance, }; +export type ClassAccessorProperty = ClassMemberBase & + DeclarationBase & { + type: "ClassAccessorProperty", + key: Expression | PrivateName, + value: ?Expression, + + typeAnnotation?: ?TypeAnnotationBase, // TODO: Not in spec + variance?: ?FlowVariance, // TODO: Not in spec + + // TypeScript only: (TODO: Not in spec) + readonly?: true, + definite?: true, + }; + export type OptClassDeclaration = ClassBase & DeclarationBase & HasDecorators & { diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/input.js b/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/input.js new file mode 100644 index 000000000000..735a7a78e304 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/options.json b/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/options.json new file mode 100644 index 000000000000..9a09fd42aaca --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/auto-accessors/options.json @@ -0,0 +1,4 @@ +{ + "throws": "This experimental syntax requires enabling the parser plugin: \"decoratorAutoAccessors\". (2:11)", + "plugins": [] +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/input.js new file mode 100644 index 000000000000..fa4a4b67422e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor constructor; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/output.json new file mode 100644 index 000000000000..6860810b0dda --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/accessor-named-constructor/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Classes may not have a field named 'constructor'. (2:11)" + ], + "program": { + "type": "Program", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":37,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":23}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":34,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":22},"identifierName":"constructor"}, + "name": "constructor" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/input.js new file mode 100644 index 000000000000..30bf86a73fd0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + accessor + bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/output.json new file mode 100644 index 000000000000..4c9daf45e5b4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor-with-newline/output.json @@ -0,0 +1,53 @@ +{ + "type": "File", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":31,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":25,"end":29,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":6}}, + "static": false, + "key": { + "type": "Identifier", + "start":25,"end":28,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/input.js new file mode 100644 index 000000000000..735a7a78e304 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/output.json new file mode 100644 index 000000000000..378b00ee57ee --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/basic-accessor/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":29,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":27,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":26,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/input.js new file mode 100644 index 000000000000..27dd24f5bb98 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor ["constructor"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/output.json new file mode 100644 index 000000000000..2705e4929c5d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-named-constructor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":41,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":39,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}}, + "static": false, + "key": { + "type": "StringLiteral", + "start":24,"end":37,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":25}}, + "extra": { + "rawValue": "constructor", + "raw": "\"constructor\"" + }, + "value": "constructor" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/input.js new file mode 100644 index 000000000000..a067c2ad5c2d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + accessor + ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/output.json new file mode 100644 index 000000000000..8b7e59c2ee0a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor-with-newline/output.json @@ -0,0 +1,57 @@ +{ + "type": "File", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":35,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":25,"end":33,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":10}}, + "static": false, + "computed": true, + "key": { + "type": "StringLiteral", + "start":26,"end":31,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":8}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/input.js new file mode 100644 index 000000000000..f77d3f867281 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/output.json new file mode 100644 index 000000000000..d15e333f0317 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":33,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}}, + "static": false, + "key": { + "type": "StringLiteral", + "start":24,"end":29,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":17}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/input.js new file mode 100644 index 000000000000..03a1bfe9b8d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/output.json new file mode 100644 index 000000000000..709fa0b48133 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/computed-static-accesor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":40,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":38,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":26}}, + "static": true, + "key": { + "type": "StringLiteral", + "start":31,"end":36,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":24}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/input.js new file mode 100644 index 000000000000..fba4a91f8875 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor = 123; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/output.json new file mode 100644 index 000000000000..6f6c5d059cc5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/field-named-accessor/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":31,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start":25,"end":28,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":16}}, + "extra": { + "rawValue": 123, + "raw": "123" + }, + "value": 123 + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/input.js new file mode 100644 index 000000000000..7443f54725f1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor static bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/output.json new file mode 100644 index 000000000000..fcca9f53576d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order-newline/output.json @@ -0,0 +1,56 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Missing semicolon. (2:17)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":29,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":17},"identifierName":"static"}, + "name": "static" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "static": false, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/input.js new file mode 100644 index 000000000000..7443f54725f1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor static bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/output.json new file mode 100644 index 000000000000..fcca9f53576d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/invalid-static-keyword-order/output.json @@ -0,0 +1,56 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Missing semicolon. (2:17)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":29,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":17},"identifierName":"static"}, + "name": "static" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "static": false, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/input.js new file mode 100644 index 000000000000..d4092463f89a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor() {} +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/output.json new file mode 100644 index 000000000000..b55c19130b12 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/method-named-accessor/output.json @@ -0,0 +1,51 @@ +{ + "type": "File", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":29,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":14,"end":27,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":25,"end":27,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":15}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/input.js new file mode 100644 index 000000000000..4e41f3511da0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/input.js @@ -0,0 +1,5 @@ +class Foo { + accessor bar() { + + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/options.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/options.json new file mode 100644 index 000000000000..a1c98245e1ed --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/not-allowed-on-methods/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:14)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/options.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/options.json new file mode 100644 index 000000000000..315ab0d08848 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + "decoratorAutoAccessors" + ] +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/input.js new file mode 100644 index 000000000000..9127772fc36b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor #bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/output.json new file mode 100644 index 000000000000..cfbbc328b782 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":30,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":28,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":16}}, + "static": false, + "key": { + "type": "PrivateName", + "start":23,"end":27,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":15}}, + "id": { + "type": "Identifier", + "start":24,"end":27,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":15},"identifierName":"bar"}, + "name": "bar" + } + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/input.js new file mode 100644 index 000000000000..eda1665ae885 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor #bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/output.json new file mode 100644 index 000000000000..45bf2d0afe81 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/private-static-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":37,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":23}}, + "static": true, + "key": { + "type": "PrivateName", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "id": { + "type": "Identifier", + "start":31,"end":34,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":22},"identifierName":"bar"}, + "name": "bar" + } + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/input.js new file mode 100644 index 000000000000..e297f3f665b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + static accessor + bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/output.json new file mode 100644 index 000000000000..b4301f09e1a4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor-with-newline/output.json @@ -0,0 +1,53 @@ +{ + "type": "File", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":38,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": true, + "key": { + "type": "Identifier", + "start":21,"end":29,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":17},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":32,"end":36,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":6}}, + "static": false, + "key": { + "type": "Identifier", + "start":32,"end":35,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/input.js new file mode 100644 index 000000000000..10777835cd1c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/output.json new file mode 100644 index 000000000000..ca4c9c4e761e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorator-auto-accessors/static-accessor/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":34,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":22}}, + "static": true, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-traverse/src/path/generated/asserts.ts b/packages/babel-traverse/src/path/generated/asserts.ts index a0f0c50093b6..1a05e6516c65 100644 --- a/packages/babel-traverse/src/path/generated/asserts.ts +++ b/packages/babel-traverse/src/path/generated/asserts.ts @@ -6,6 +6,7 @@ import * as t from "@babel/types"; import NodePath from "../index"; export interface NodePathAssetions { + assertAccessor(opts?: object): asserts this is NodePath; assertAnyTypeAnnotation( opts?: object, ): asserts this is NodePath; @@ -61,6 +62,9 @@ export interface NodePathAssetions { ): asserts this is NodePath; assertCatchClause(opts?: object): asserts this is NodePath; assertClass(opts?: object): asserts this is NodePath; + assertClassAccessorProperty( + opts?: object, + ): asserts this is NodePath; assertClassBody(opts?: object): asserts this is NodePath; assertClassDeclaration( opts?: object, diff --git a/packages/babel-traverse/src/path/generated/validators.ts b/packages/babel-traverse/src/path/generated/validators.ts index acf716d9452a..c552da721622 100644 --- a/packages/babel-traverse/src/path/generated/validators.ts +++ b/packages/babel-traverse/src/path/generated/validators.ts @@ -7,6 +7,7 @@ import NodePath from "../index"; import type { VirtualTypeAliases } from "./virtual-types"; export interface NodePathValidators { + isAccessor(opts?: object): this is NodePath; isAnyTypeAnnotation(opts?: object): this is NodePath; isArgumentPlaceholder(opts?: object): this is NodePath; isArrayExpression(opts?: object): this is NodePath; @@ -38,6 +39,9 @@ export interface NodePathValidators { isCallExpression(opts?: object): this is NodePath; isCatchClause(opts?: object): this is NodePath; isClass(opts?: object): this is NodePath; + isClassAccessorProperty( + opts?: object, + ): this is NodePath; isClassBody(opts?: object): this is NodePath; isClassDeclaration(opts?: object): this is NodePath; isClassExpression(opts?: object): this is NodePath; diff --git a/packages/babel-types/src/asserts/generated/index.ts b/packages/babel-types/src/asserts/generated/index.ts index 777fb70fd339..57cfb9a37291 100644 --- a/packages/babel-types/src/asserts/generated/index.ts +++ b/packages/babel-types/src/asserts/generated/index.ts @@ -506,6 +506,12 @@ export function assertClassProperty( ): asserts node is t.ClassProperty { assert("ClassProperty", node, opts); } +export function assertClassAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): asserts node is t.ClassAccessorProperty { + assert("ClassAccessorProperty", node, opts); +} export function assertClassPrivateProperty( node: object | null | undefined, opts?: object | null, @@ -1694,6 +1700,12 @@ export function assertModuleSpecifier( ): asserts node is t.ModuleSpecifier { assert("ModuleSpecifier", node, opts); } +export function assertAccessor( + node: object | null | undefined, + opts?: object | null, +): asserts node is t.Accessor { + assert("Accessor", node, opts); +} export function assertPrivate( node: object | null | undefined, opts?: object | null, diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index 395812181aa3..5e6547f5e991 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -65,6 +65,7 @@ export type Node = | BreakStatement | CallExpression | CatchClause + | ClassAccessorProperty | ClassBody | ClassDeclaration | ClassExpression @@ -988,6 +989,24 @@ export interface ClassProperty extends BaseNode { variance?: Variance | null; } +export interface ClassAccessorProperty extends BaseNode { + type: "ClassAccessorProperty"; + key: Identifier | StringLiteral | NumericLiteral | Expression | PrivateName; + value?: Expression | null; + typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; + decorators?: Array | null; + computed?: boolean; + static?: boolean; + abstract?: boolean | null; + accessibility?: "public" | "private" | "protected" | null; + declare?: boolean | null; + definite?: boolean | null; + optional?: boolean | null; + override?: boolean; + readonly?: boolean | null; + variance?: Variance | null; +} + export interface ClassPrivateProperty extends BaseNode { type: "ClassPrivateProperty"; key: PrivateName; @@ -2094,6 +2113,7 @@ export type Standardized = | OptionalMemberExpression | OptionalCallExpression | ClassProperty + | ClassAccessorProperty | ClassPrivateProperty | ClassPrivateMethod | PrivateName @@ -2366,7 +2386,11 @@ export type UserWhitespacable = | ObjectTypeSpreadProperty; export type Method = ObjectMethod | ClassMethod | ClassPrivateMethod; export type ObjectMember = ObjectMethod | ObjectProperty; -export type Property = ObjectProperty | ClassProperty | ClassPrivateProperty; +export type Property = + | ObjectProperty + | ClassProperty + | ClassAccessorProperty + | ClassPrivateProperty; export type UnaryLike = UnaryExpression | SpreadElement; export type Pattern = AssignmentPattern | ArrayPattern | ObjectPattern; export type Class = ClassExpression | ClassDeclaration; @@ -2386,6 +2410,7 @@ export type ModuleSpecifier = | ImportSpecifier | ExportNamespaceSpecifier | ExportDefaultSpecifier; +export type Accessor = ClassAccessorProperty; export type Private = ClassPrivateProperty | ClassPrivateMethod | PrivateName; export type Flow = | AnyTypeAnnotation @@ -2691,6 +2716,7 @@ export interface Aliases { ModuleDeclaration: ModuleDeclaration; ExportDeclaration: ExportDeclaration; ModuleSpecifier: ModuleSpecifier; + Accessor: Accessor; Private: Private; Flow: Flow; FlowType: FlowType; diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index a59d1301e976..5ba1190e4145 100644 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -525,6 +525,21 @@ export function classProperty( ): t.ClassProperty { return builder.apply("ClassProperty", arguments); } +export function classAccessorProperty( + key: + | t.Identifier + | t.StringLiteral + | t.NumericLiteral + | t.Expression + | t.PrivateName, + value?: t.Expression | null, + typeAnnotation?: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop | null, + decorators?: Array | null, + computed?: boolean, + _static?: boolean, +): t.ClassAccessorProperty { + return builder.apply("ClassAccessorProperty", arguments); +} export function classPrivateProperty( key: t.PrivateName, value: t.Expression | null | undefined, diff --git a/packages/babel-types/src/builders/generated/uppercase.js b/packages/babel-types/src/builders/generated/uppercase.js index 257a1b083d8b..97000d2ba7c6 100644 --- a/packages/babel-types/src/builders/generated/uppercase.js +++ b/packages/babel-types/src/builders/generated/uppercase.js @@ -91,6 +91,7 @@ export { optionalMemberExpression as OptionalMemberExpression, optionalCallExpression as OptionalCallExpression, classProperty as ClassProperty, + classAccessorProperty as ClassAccessorProperty, classPrivateProperty as ClassPrivateProperty, classPrivateMethod as ClassPrivateMethod, privateName as PrivateName, diff --git a/packages/babel-types/src/constants/generated/index.ts b/packages/babel-types/src/constants/generated/index.ts index 774d7a8fb4cd..4db3a1bc8c8a 100644 --- a/packages/babel-types/src/constants/generated/index.ts +++ b/packages/babel-types/src/constants/generated/index.ts @@ -39,6 +39,7 @@ export const CLASS_TYPES = FLIPPED_ALIAS_KEYS["Class"]; export const MODULEDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ModuleDeclaration"]; export const EXPORTDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ExportDeclaration"]; export const MODULESPECIFIER_TYPES = FLIPPED_ALIAS_KEYS["ModuleSpecifier"]; +export const ACCESSOR_TYPES = FLIPPED_ALIAS_KEYS["Accessor"]; export const PRIVATE_TYPES = FLIPPED_ALIAS_KEYS["Private"]; export const FLOW_TYPES = FLIPPED_ALIAS_KEYS["Flow"]; export const FLOWTYPE_TYPES = FLIPPED_ALIAS_KEYS["FlowType"]; diff --git a/packages/babel-types/src/converters/toComputedKey.ts b/packages/babel-types/src/converters/toComputedKey.ts index d82d266af12d..4db773ddb56d 100644 --- a/packages/babel-types/src/converters/toComputedKey.ts +++ b/packages/babel-types/src/converters/toComputedKey.ts @@ -8,6 +8,7 @@ export default function toComputedKey( | t.ObjectProperty | t.ClassMethod | t.ClassProperty + | t.ClassAccessorProperty | t.MemberExpression | t.OptionalMemberExpression, // @ts-expect-error todo(flow->ts): maybe check the type of node before accessing .key and .property diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index f03ebc9b218a..5c38150c6a46 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -2126,6 +2126,80 @@ defineType("ClassProperty", { }, }); +defineType("ClassAccessorProperty", { + visitor: ["key", "value", "typeAnnotation", "decorators"], + builder: [ + "key", + "value", + "typeAnnotation", + "decorators", + "computed", + "static", + ], + aliases: ["Property", "Accessor"], + fields: { + ...classMethodOrPropertyCommon, + key: { + validate: chain( + (function () { + const normal = assertNodeType( + "Identifier", + "StringLiteral", + "NumericLiteral", + "PrivateName", + ); + const computed = assertNodeType("Expression"); + + return function (node: any, key: string, val: any) { + const validator = node.computed ? computed : normal; + validator(node, key, val); + }; + })(), + assertNodeType( + "Identifier", + "StringLiteral", + "NumericLiteral", + "Expression", + "PrivateName", + ), + ), + }, + value: { + validate: assertNodeType("Expression"), + optional: true, + }, + definite: { + validate: assertValueType("boolean"), + optional: true, + }, + typeAnnotation: { + validate: process.env.BABEL_8_BREAKING + ? assertNodeType("TypeAnnotation", "TSTypeAnnotation") + : assertNodeType("TypeAnnotation", "TSTypeAnnotation", "Noop"), + optional: true, + }, + decorators: { + validate: chain( + assertValueType("array"), + assertEach(assertNodeType("Decorator")), + ), + optional: true, + }, + readonly: { + validate: assertValueType("boolean"), + optional: true, + }, + declare: { + validate: assertValueType("boolean"), + optional: true, + }, + variance: { + validate: assertNodeType("Variance"), + optional: true, + }, + }, +}); + defineType("ClassPrivateProperty", { visitor: ["key", "value", "decorators", "typeAnnotation"], builder: ["key", "value", "decorators", "static"], diff --git a/packages/babel-types/src/validators/generated/index.ts b/packages/babel-types/src/validators/generated/index.ts index bb5a1444f7af..c9ad115da496 100644 --- a/packages/babel-types/src/validators/generated/index.ts +++ b/packages/babel-types/src/validators/generated/index.ts @@ -1399,6 +1399,23 @@ export function isClassProperty( return false; } +export function isClassAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): node is t.ClassAccessorProperty { + if (!node) return false; + + const nodeType = (node as t.Node).type; + if (nodeType === "ClassAccessorProperty") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isClassPrivateProperty( node: object | null | undefined, opts?: object | null, @@ -4277,6 +4294,7 @@ export function isStandardized( "OptionalMemberExpression" === nodeType || "OptionalCallExpression" === nodeType || "ClassProperty" === nodeType || + "ClassAccessorProperty" === nodeType || "ClassPrivateProperty" === nodeType || "ClassPrivateMethod" === nodeType || "PrivateName" === nodeType || @@ -5052,6 +5070,7 @@ export function isProperty( if ( "ObjectProperty" === nodeType || "ClassProperty" === nodeType || + "ClassAccessorProperty" === nodeType || "ClassPrivateProperty" === nodeType ) { if (typeof opts === "undefined") { @@ -5187,6 +5206,23 @@ export function isModuleSpecifier( return false; } +export function isAccessor( + node: object | null | undefined, + opts?: object | null, +): node is t.Accessor { + if (!node) return false; + + const nodeType = (node as t.Node).type; + if ("ClassAccessorProperty" === nodeType) { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isPrivate( node: object | null | undefined, opts?: object | null, diff --git a/packages/babel-types/src/validators/isReferenced.ts b/packages/babel-types/src/validators/isReferenced.ts index 46c9cce7f6c3..cf77c9c44966 100644 --- a/packages/babel-types/src/validators/isReferenced.ts +++ b/packages/babel-types/src/validators/isReferenced.ts @@ -63,6 +63,7 @@ export default function isReferenced( // yes: class { [NODE] = value; } // yes: class { key = NODE; } case "ClassProperty": + case "ClassAccessorProperty": if (parent.key === node) { return !!parent.computed; }