Skip to content

Commit

Permalink
fix: Support auto accessors with TypeScript annotations (#15209)
Browse files Browse the repository at this point in the history
* fix

* add tests

* review

* review

* fix babel8 test

* review

* review

* update tests
  • Loading branch information
liuxingbaoyu committed Dec 22, 2022
1 parent d842911 commit 3a71c79
Show file tree
Hide file tree
Showing 35 changed files with 609 additions and 38 deletions.
6 changes: 3 additions & 3 deletions packages/babel-parser/src/parse-error/standard-errors.ts
Expand Up @@ -35,10 +35,10 @@ export default {
AwaitNotInAsyncContext:
"'await' is only allowed within async functions and at the top levels of modules.",
AwaitNotInAsyncFunction: "'await' is only allowed within async functions.",
BadGetterArity: "A 'get' accesor must not have any formal parameters.",
BadSetterArity: "A 'set' accesor must have exactly one formal parameter.",
BadGetterArity: "A 'get' accessor must not have any formal parameters.",
BadSetterArity: "A 'set' accessor must have exactly one formal parameter.",
BadSetterRestParameter:
"A 'set' accesor function argument must not be a rest parameter.",
"A 'set' accessor function argument must not be a rest parameter.",
ConstructorClassField: "Classes may not have a field named 'constructor'.",
ConstructorClassPrivateField:
"Classes may not have a private field named '#constructor'.",
Expand Down
23 changes: 20 additions & 3 deletions packages/babel-parser/src/plugins/typescript/index.ts
Expand Up @@ -94,6 +94,8 @@ const TSErrors = ParseErrorEnum`typescript`({
AccesorCannotDeclareThisParameter:
"'get' and 'set' accessors cannot declare 'this' parameters.",
AccesorCannotHaveTypeParameters: "An accessor cannot have type parameters.",
AccessorCannotBeOptional:
"An 'accessor' property cannot be declared optional.",
ClassMethodHasDeclare: "Class methods cannot have the 'declare' modifier.",
ClassMethodHasReadonly: "Class methods cannot have the 'readonly' modifier.",
ConstInitiailizerMustBeStringOrNumericLiteralOrLiteralEnumReference:
Expand Down Expand Up @@ -195,6 +197,7 @@ const TSErrors = ParseErrorEnum`typescript`({
"This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`.",
ReservedTypeAssertion:
"This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.",
// TODO: Accesor -> Accessor
SetAccesorCannotHaveOptionalParameter:
"A 'set' accessor cannot have an optional parameter.",
SetAccesorCannotHaveRestParameter:
Expand Down Expand Up @@ -3121,10 +3124,14 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
}

parseClassPropertyAnnotation(
node: N.ClassProperty | N.ClassPrivateProperty,
node: N.ClassProperty | N.ClassPrivateProperty | N.ClassAccessorProperty,
): void {
if (!node.optional && this.eat(tt.bang)) {
node.definite = true;
if (!node.optional) {
if (this.eat(tt.bang)) {
node.definite = true;
} else if (this.eat(tt.question)) {
node.optional = true;
}
}

const type = this.tsTryParseTypeAnnotation();
Expand Down Expand Up @@ -3178,6 +3185,16 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
return super.parseClassPrivateProperty(node);
}

parseClassAccessorProperty(
node: N.ClassAccessorProperty,
): N.ClassAccessorProperty {
this.parseClassPropertyAnnotation(node);
if (node.optional) {
this.raise(TSErrors.AccessorCannotBeOptional, { at: node });
}
return super.parseClassAccessorProperty(node);
}

pushClassMethod(
classBody: N.ClassBody,
method: N.ClassMethod,
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (1:3)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (1:3)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":31}},
"errors": [
"SyntaxError: A 'get' accesor must not have any formal parameters. (2:2)"
"SyntaxError: A 'get' accessor must not have any formal parameters. (2:2)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":29,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":29,"index":29}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (1:10)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (1:10)"
],
"program": {
"type": "Program",
Expand Down
@@ -1,44 +1,44 @@
{
"type": "File",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (1:3)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (1:3)"
],
"program": {
"type": "Program",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
"expression": {
"type": "ObjectExpression",
"start":1,"end":16,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":16,"index":16}},
"start":1,"end":16,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":16}},
"properties": [
{
"type": "Property",
"start":3,"end":14,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":14,"index":14}},
"start":3,"end":14,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":14}},
"method": false,
"key": {
"type": "Identifier",
"start":7,"end":8,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":8,"index":8},"identifierName":"s"},
"start":7,"end":8,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":8},"identifierName":"s"},
"name": "s"
},
"computed": false,
"kind": "set",
"value": {
"type": "FunctionExpression",
"start":8,"end":14,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":14,"index":14}},
"start":8,"end":14,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":14}},
"id": null,
"generator": false,
"async": false,
"expression": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14}},
"start":11,"end":14,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":14}},
"body": []
}
},
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}},
"errors": [
"SyntaxError: A 'set' accesor function argument must not be a rest parameter. (1:6)"
"SyntaxError: A 'set' accessor function argument must not be a rest parameter. (1:6)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (1:3)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (1:3)"
],
"program": {
"type": "Program",
Expand Down Expand Up @@ -53,4 +53,4 @@
}
]
}
}
}
Expand Up @@ -2,8 +2,8 @@
"type": "File",
"start":0,"end":85,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":18}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (3:3)",
"SyntaxError: A 'get' accesor must not have any formal parameters. (4:3)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (3:3)",
"SyntaxError: A 'get' accessor must not have any formal parameters. (4:3)"
],
"program": {
"type": "Program",
Expand Down Expand Up @@ -200,4 +200,4 @@
}
]
}
}
}
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":37,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":37}},
"errors": [
"SyntaxError: A 'get' accesor must not have any formal parameters. (2:2)"
"SyntaxError: A 'get' accessor must not have any formal parameters. (2:2)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":41,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":41}},
"errors": [
"SyntaxError: A 'get' accesor must not have any formal parameters. (2:2)"
"SyntaxError: A 'get' accessor must not have any formal parameters. (2:2)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":29,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":29}},
"errors": [
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (2:2)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (2:2)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":33,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":33}},
"errors": [
"SyntaxError: A 'set' accesor function argument must not be a rest parameter. (2:2)"
"SyntaxError: A 'set' accessor function argument must not be a rest parameter. (2:2)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":40,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":40}},
"errors": [
"SyntaxError: A 'get' accesor must not have any formal parameters. (2:2)",
"SyntaxError: A 'get' accessor must not have any formal parameters. (2:2)",
"SyntaxError: A getter cannot have a `this` parameter. (2:10)"
],
"program": {
Expand Down
Expand Up @@ -3,7 +3,7 @@
"start":0,"end":43,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":43}},
"errors": [
"SyntaxError: A setter cannot have a `this` parameter. (2:10)",
"SyntaxError: A 'set' accesor must have exactly one formal parameter. (2:2)"
"SyntaxError: A 'set' accessor must have exactly one formal parameter. (2:2)"
],
"program": {
"type": "Program",
Expand Down
@@ -0,0 +1,15 @@
abstract class Foo {
declare accessor prop7: number;
private accessor #p: any;

accessor a!;
abstract accessor #s;
accessor #d?;
abstract accessor f = 1;
readonly accessor g;
}

declare class C {
accessor x = 1;
#y = 1;
}
@@ -0,0 +1,6 @@
{
"plugins": [
"typescript",
"decoratorAutoAccessors"
]
}

0 comments on commit 3a71c79

Please sign in to comment.