Skip to content

Commit

Permalink
Parse static blocks with typescript plugin (#13243)
Browse files Browse the repository at this point in the history
* Support static blocks with typescript

* Add tests

* Reuse isStatic var

* Disallow parsing static blocks with modifiers

* Add tests

* Raise recoverable errors

* Address review

* Add tests for static static {}
  • Loading branch information
sosukesuzuki committed May 3, 2021
1 parent 175a51f commit ef87648
Show file tree
Hide file tree
Showing 26 changed files with 566 additions and 13 deletions.
43 changes: 30 additions & 13 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -131,6 +131,8 @@ const TSErrors = makeErrorTemplates(
"A 'set' accessor cannot have rest parameter.",
SetAccesorCannotHaveReturnType:
"A 'set' accessor cannot have a return type annotation.",
StaticBlockCannotHaveModifier:
"Static class blocks cannot have any modifier.",
TypeAnnotationAfterAssign:
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.",
TypeImportCannotSpecifyDefaultAndNamed:
Expand Down Expand Up @@ -2317,34 +2319,49 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.tsParseModifier(["public", "protected", "private"]);
}

tsHasSomeModifiers(member: any, modifiers: TsModifier[]): boolean {
return modifiers.some(modifier => {
if (tsIsAccessModifier(modifier)) {
return member.accessibility === modifier;
}
return !!member[modifier];
});
}

parseClassMember(
classBody: N.ClassBody,
member: any,
state: N.ParseClassMemberState,
): void {
this.tsParseModifiers(member, [
const invalidModifersForStaticBlocks = [
"declare",
"private",
"public",
"protected",
"override",
"static",
"abstract",
"readonly",
]);

const callParseClassMember = () => {
this.parseClassMemberWithIsStatic(
classBody,
member,
state,
!!member.static,
);
];
this.tsParseModifiers(
member,
invalidModifersForStaticBlocks.concat(["static"]),
);

const callParseClassMemberWithIsStatic = () => {
const isStatic = !!member.static;
if (isStatic && this.eat(tt.braceL)) {
if (this.tsHasSomeModifiers(member, invalidModifersForStaticBlocks)) {
this.raise(this.state.pos, TSErrors.StaticBlockCannotHaveModifier);
}
this.parseClassStaticBlock(classBody, ((member: any): N.StaticBlock));
} else {
this.parseClassMemberWithIsStatic(classBody, member, state, isStatic);
}
};
if (member.declare) {
this.tsInAmbientContext(callParseClassMember);
this.tsInAmbientContext(callParseClassMemberWithIsStatic);
} else {
callParseClassMember();
callParseClassMemberWithIsStatic();
}
}

Expand Down
@@ -0,0 +1,3 @@
class Foo {
static private {}
}
@@ -0,0 +1,40 @@
{
"type": "File",
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'private' modifier must precede 'static' modifier. (2:9)",
"SyntaxError: Static class blocks cannot have any modifier. (2:19)"
],
"program": {
"type": "Program",
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"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": "StaticBlock",
"start":14,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}},
"static": true,
"accessibility": "private",
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
static protected {}
}
@@ -0,0 +1,40 @@
{
"type": "File",
"start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'protected' modifier must precede 'static' modifier. (2:9)",
"SyntaxError: Static class blocks cannot have any modifier. (2:21)"
],
"program": {
"type": "Program",
"start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":35,"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":35,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}},
"body": [
{
"type": "StaticBlock",
"start":14,"end":33,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":21}},
"static": true,
"accessibility": "protected",
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
static public {}
}
@@ -0,0 +1,40 @@
{
"type": "File",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'public' modifier must precede 'static' modifier. (2:9)",
"SyntaxError: Static class blocks cannot have any modifier. (2:18)"
],
"program": {
"type": "Program",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":32,"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":32,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}},
"body": [
{
"type": "StaticBlock",
"start":14,"end":30,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":18}},
"static": true,
"accessibility": "public",
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
abstract static {}
}
@@ -0,0 +1,40 @@
{
"type": "File",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'static' modifier cannot be used with 'abstract' modifier. (2:11)",
"SyntaxError: Static class blocks cannot have any modifier. (2:20)"
],
"program": {
"type": "Program",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":34,"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":34,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}},
"body": [
{
"type": "StaticBlock",
"start":14,"end":32,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":20}},
"abstract": true,
"static": true,
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
override static {}
}
@@ -0,0 +1,40 @@
{
"type": "File",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'static' modifier must precede 'override' modifier. (2:11)",
"SyntaxError: Static class blocks cannot have any modifier. (2:20)"
],
"program": {
"type": "Program",
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":34,"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":34,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}},
"body": [
{
"type": "StaticBlock",
"start":14,"end":32,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":20}},
"override": true,
"static": true,
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
static static {}
}
@@ -0,0 +1,38 @@
{
"type": "File",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: Duplicate modifier: 'static'. (2:9)"
],
"program": {
"type": "Program",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":32,"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":32,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}},
"body": [
{
"type": "StaticBlock",
"start":14,"end":30,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":18}},
"static": true,
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
declare static {}
}
@@ -0,0 +1,39 @@
{
"type": "File",
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: Static class blocks cannot have any modifier. (2:19)"
],
"program": {
"type": "Program",
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"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": "StaticBlock",
"start":14,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}},
"declare": true,
"static": true,
"body": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,3 @@
class Foo {
readonly static {}
}

0 comments on commit ef87648

Please sign in to comment.