Parse declare modifier around accessibility modifiers (#11146)

* fix: parse declare modifiers around accessibility modifiers

* test: add tests

* fix: check duplicate modifiers in modified nodes

* fix flow error
This commit is contained in:
Huáng Jùnliàng 2020-02-20 23:29:47 -05:00 committed by GitHub
parent 3960f4de64
commit 223cee7246
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 649 additions and 17 deletions

View File

@ -135,27 +135,24 @@ export default (superClass: Class<Parser>): Class<Parser> =>
/** Parses a list of modifiers, in any order.
* If you need a specific order, you must call this function multiple times:
* this.tsParseModifiers(["public"]);
* this.tsParseModifiers(["abstract", "readonly"]);
* this.tsParseModifiers(node, ["public"]);
* this.tsParseModifiers(node, ["abstract", "readonly"]);
*/
tsParseModifiers<T: TsModifier>(
modified: { [key: TsModifier]: ?true },
allowedModifiers: T[],
): { [key: TsModifier]: ?true, __proto__: null } {
const modifiers = Object.create(null);
): void {
while (true) {
const startPos = this.state.start;
const modifier: ?T = this.tsParseModifier(allowedModifiers);
if (!modifier) break;
if (Object.hasOwnProperty.call(modifiers, modifier)) {
if (Object.hasOwnProperty.call(modified, modifier)) {
this.raise(startPos, `Duplicate modifier: '${modifier}'`);
}
modifiers[modifier] = true;
modified[modifier] = true;
}
return modifiers;
}
tsIsListTerminator(kind: ParsingContext): boolean {
@ -1922,8 +1919,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
state: { hadConstructor: boolean },
constructorAllowsSuper: boolean,
): void {
this.tsParseModifiers(member, ["declare"]);
const accessibility = this.parseAccessModifier();
if (accessibility) member.accessibility = accessibility;
this.tsParseModifiers(member, ["declare"]);
super.parseClassMember(classBody, member, state, constructorAllowsSuper);
}
@ -1935,19 +1934,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isStatic: boolean,
constructorAllowsSuper: boolean,
): void {
const modifiers = this.tsParseModifiers([
"abstract",
"readonly",
"declare",
]);
Object.assign(member, modifiers);
this.tsParseModifiers(member, ["abstract", "readonly", "declare"]);
const idx = this.tsTryParseIndexSignature(member);
if (idx) {
classBody.body.push(idx);
if (modifiers.abstract) {
if ((member: any).abstract) {
this.raise(
member.start,
"Index signatures cannot have the 'abstract' modifier",

View File

@ -0,0 +1,11 @@
class A {
declare static foo;
static declare foo0: string;
declare public foo1;
public declare foo2;
declare public static foo4;
public declare static foo3;
public static declare foo5;
}

View File

@ -0,0 +1,372 @@
{
"type": "File",
"start": 0,
"end": 202,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 11,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 202,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 11,
"column": 1
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 202,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 11,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "A"
},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 8,
"end": 202,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 11,
"column": 1
}
},
"body": [
{
"type": "ClassProperty",
"start": 12,
"end": 31,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 21
}
},
"declare": true,
"static": true,
"key": {
"type": "Identifier",
"start": 27,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 20
},
"identifierName": "foo"
},
"name": "foo"
},
"computed": false,
"value": null
},
{
"type": "ClassProperty",
"start": 34,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 30
}
},
"declare": true,
"static": true,
"key": {
"type": "Identifier",
"start": 49,
"end": 53,
"loc": {
"start": {
"line": 3,
"column": 17
},
"end": {
"line": 3,
"column": 21
},
"identifierName": "foo0"
},
"name": "foo0"
},
"computed": false,
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start": 53,
"end": 61,
"loc": {
"start": {
"line": 3,
"column": 21
},
"end": {
"line": 3,
"column": 29
}
},
"typeAnnotation": {
"type": "TSStringKeyword",
"start": 55,
"end": 61,
"loc": {
"start": {
"line": 3,
"column": 23
},
"end": {
"line": 3,
"column": 29
}
}
}
},
"value": null
},
{
"type": "ClassProperty",
"start": 66,
"end": 86,
"loc": {
"start": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 22
}
},
"accessibility": "public",
"declare": true,
"static": false,
"key": {
"type": "Identifier",
"start": 81,
"end": 85,
"loc": {
"start": {
"line": 5,
"column": 17
},
"end": {
"line": 5,
"column": 21
},
"identifierName": "foo1"
},
"name": "foo1"
},
"computed": false,
"value": null
},
{
"type": "ClassProperty",
"start": 89,
"end": 109,
"loc": {
"start": {
"line": 6,
"column": 2
},
"end": {
"line": 6,
"column": 22
}
},
"accessibility": "public",
"declare": true,
"static": false,
"key": {
"type": "Identifier",
"start": 104,
"end": 108,
"loc": {
"start": {
"line": 6,
"column": 17
},
"end": {
"line": 6,
"column": 21
},
"identifierName": "foo2"
},
"name": "foo2"
},
"computed": false,
"value": null
},
{
"type": "ClassProperty",
"start": 113,
"end": 140,
"loc": {
"start": {
"line": 8,
"column": 2
},
"end": {
"line": 8,
"column": 29
}
},
"accessibility": "public",
"declare": true,
"static": true,
"key": {
"type": "Identifier",
"start": 135,
"end": 139,
"loc": {
"start": {
"line": 8,
"column": 24
},
"end": {
"line": 8,
"column": 28
},
"identifierName": "foo4"
},
"name": "foo4"
},
"computed": false,
"value": null
},
{
"type": "ClassProperty",
"start": 143,
"end": 170,
"loc": {
"start": {
"line": 9,
"column": 2
},
"end": {
"line": 9,
"column": 29
}
},
"accessibility": "public",
"declare": true,
"static": true,
"key": {
"type": "Identifier",
"start": 165,
"end": 169,
"loc": {
"start": {
"line": 9,
"column": 24
},
"end": {
"line": 9,
"column": 28
},
"identifierName": "foo3"
},
"name": "foo3"
},
"computed": false,
"value": null
},
{
"type": "ClassProperty",
"start": 173,
"end": 200,
"loc": {
"start": {
"line": 10,
"column": 2
},
"end": {
"line": 10,
"column": 29
}
},
"accessibility": "public",
"declare": true,
"static": true,
"key": {
"type": "Identifier",
"start": 195,
"end": 199,
"loc": {
"start": {
"line": 10,
"column": 24
},
"end": {
"line": 10,
"column": 28
},
"identifierName": "foo5"
},
"name": "foo5"
},
"computed": false,
"value": null
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
class A {
declare public declare foo;
}

View File

@ -0,0 +1,125 @@
{
"type": "File",
"start": 0,
"end": 41,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"errors": [
"SyntaxError: Duplicate modifier: 'declare' (2:17)"
],
"program": {
"type": "Program",
"start": 0,
"end": 41,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "module",
"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": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "A"
},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 8,
"end": 41,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "ClassProperty",
"start": 12,
"end": 39,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 29
}
},
"declare": true,
"accessibility": "public",
"static": false,
"key": {
"type": "Identifier",
"start": 35,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 25
},
"end": {
"line": 2,
"column": 28
},
"identifierName": "foo"
},
"name": "foo"
},
"computed": false,
"value": null
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
class A {
declare public static declare foo;
}

View File

@ -0,0 +1,125 @@
{
"type": "File",
"start": 0,
"end": 48,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"errors": [
"SyntaxError: Duplicate modifier: 'declare' (2:24)"
],
"program": {
"type": "Program",
"start": 0,
"end": 48,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 48,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "A"
},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 8,
"end": 48,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "ClassProperty",
"start": 12,
"end": 46,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 36
}
},
"declare": true,
"accessibility": "public",
"static": true,
"key": {
"type": "Identifier",
"start": 42,
"end": 45,
"loc": {
"start": {
"line": 2,
"column": 32
},
"end": {
"line": 2,
"column": 35
},
"identifierName": "foo"
},
"name": "foo"
},
"computed": false,
"value": null
}
]
}
}
],
"directives": []
}
}