From cc456084230ed8d0f073494ca61a6ee39ae71cf6 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sat, 16 Mar 2019 13:41:52 +0800 Subject: [PATCH] Add `readonly` to TypeScript type modifier (#9529) * add readonly to TSTypeOperator * add more test cases for readonly --- .../babel-parser/src/plugins/typescript.js | 26 +- packages/babel-parser/src/types.js | 2 +- .../typescript/types/read-only-1/input.js | 1 + .../typescript/types/read-only-1/options.json | 7 + .../typescript/types/read-only-2/input.js | 1 + .../typescript/types/read-only-2/options.json | 7 + .../typescript/types/read-only-3/input.js | 1 + .../typescript/types/read-only-3/options.json | 7 + .../typescript/types/read-only-4/input.js | 1 + .../typescript/types/read-only-4/options.json | 7 + .../typescript/types/type-operator/input.js | 2 + .../types/type-operator/output.json | 253 +++++++++++++++++- 12 files changed, 306 insertions(+), 9 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-1/input.js create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-1/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-2/input.js create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-2/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-3/input.js create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-3/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-4/input.js create mode 100644 packages/babel-parser/test/fixtures/typescript/types/read-only-4/options.json diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index 3ef7ef4a58..dfe6695616 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -741,14 +741,34 @@ export default (superClass: Class): Class => return type; } - tsParseTypeOperator(operator: "keyof" | "unique"): N.TsTypeOperator { + tsParseTypeOperator( + operator: "keyof" | "unique" | "readonly", + ): N.TsTypeOperator { const node: N.TsTypeOperator = this.startNode(); this.expectContextual(operator); node.operator = operator; node.typeAnnotation = this.tsParseTypeOperatorOrHigher(); + + if (operator === "readonly") { + this.tsCheckTypeAnnotationForReadOnly(node); + } + return this.finishNode(node, "TSTypeOperator"); } + tsCheckTypeAnnotationForReadOnly(node: N.Node) { + switch (node.typeAnnotation.type) { + case "TSTupleType": + case "TSArrayType": + return; + default: + this.raise( + node.operator, + "'readonly' type modifier is only permitted on array and tuple literal types.", + ); + } + } + tsParseInferType(): N.TsInferType { const node = this.startNode(); this.expectContextual("infer"); @@ -759,7 +779,9 @@ export default (superClass: Class): Class => } tsParseTypeOperatorOrHigher(): N.TsType { - const operator = ["keyof", "unique"].find(kw => this.isContextual(kw)); + const operator = ["keyof", "unique", "readonly"].find(kw => + this.isContextual(kw), + ); return operator ? this.tsParseTypeOperator(operator) : this.isContextual("infer") diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index cc1fd01f30..5c49be4472 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -1288,7 +1288,7 @@ export type TsParenthesizedType = TsTypeBase & { export type TsTypeOperator = TsTypeBase & { type: "TSTypeOperator", - operator: "keyof" | "unique", + operator: "keyof" | "unique" | "readonly", typeAnnotation: TsType, }; diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-1/input.js b/packages/babel-parser/test/fixtures/typescript/types/read-only-1/input.js new file mode 100644 index 0000000000..5fa006c80b --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-1/input.js @@ -0,0 +1 @@ +type T30 = readonly string; // Error \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-1/options.json b/packages/babel-parser/test/fixtures/typescript/types/read-only-1/options.json new file mode 100644 index 0000000000..f3875581a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-1/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-2/input.js b/packages/babel-parser/test/fixtures/typescript/types/read-only-2/input.js new file mode 100644 index 0000000000..94eb468bff --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-2/input.js @@ -0,0 +1 @@ +type T31 = readonly T; // Error \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-2/options.json b/packages/babel-parser/test/fixtures/typescript/types/read-only-2/options.json new file mode 100644 index 0000000000..f3875581a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-2/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-3/input.js b/packages/babel-parser/test/fixtures/typescript/types/read-only-3/input.js new file mode 100644 index 0000000000..a2fa9e1204 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-3/input.js @@ -0,0 +1 @@ +type T32 = readonly readonly string[]; // Error diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-3/options.json b/packages/babel-parser/test/fixtures/typescript/types/read-only-3/options.json new file mode 100644 index 0000000000..f3875581a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-3/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-4/input.js b/packages/babel-parser/test/fixtures/typescript/types/read-only-4/input.js new file mode 100644 index 0000000000..940ffd7b8a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-4/input.js @@ -0,0 +1 @@ +type T33 = readonly Array; // Error diff --git a/packages/babel-parser/test/fixtures/typescript/types/read-only-4/options.json b/packages/babel-parser/test/fixtures/typescript/types/read-only-4/options.json new file mode 100644 index 0000000000..f3875581a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/read-only-4/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/type-operator/input.js b/packages/babel-parser/test/fixtures/typescript/types/type-operator/input.js index 1d23f962ef..386c859ca9 100644 --- a/packages/babel-parser/test/fixtures/typescript/types/type-operator/input.js +++ b/packages/babel-parser/test/fixtures/typescript/types/type-operator/input.js @@ -1,2 +1,4 @@ let x: keyof T; let y: unique symbol; +let z: readonly number[]; +let z1: readonly [number, number]; diff --git a/packages/babel-parser/test/fixtures/typescript/types/type-operator/output.json b/packages/babel-parser/test/fixtures/typescript/types/type-operator/output.json index 8439bf9920..4f8b2fb758 100644 --- a/packages/babel-parser/test/fixtures/typescript/types/type-operator/output.json +++ b/packages/babel-parser/test/fixtures/typescript/types/type-operator/output.json @@ -1,29 +1,29 @@ { "type": "File", "start": 0, - "end": 37, + "end": 98, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 2, - "column": 21 + "line": 4, + "column": 34 } }, "program": { "type": "Program", "start": 0, - "end": 37, + "end": 98, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 2, - "column": 21 + "line": 4, + "column": 34 } }, "sourceType": "module", @@ -239,6 +239,247 @@ } ], "kind": "let" + }, + { + "type": "VariableDeclaration", + "start": 38, + "end": 63, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 25 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 42, + "end": 62, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 24 + } + }, + "id": { + "type": "Identifier", + "start": 42, + "end": 62, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 24 + }, + "identifierName": "z" + }, + "name": "z", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 43, + "end": 62, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 24 + } + }, + "typeAnnotation": { + "type": "TSTypeOperator", + "start": 45, + "end": 62, + "loc": { + "start": { + "line": 3, + "column": 7 + }, + "end": { + "line": 3, + "column": 24 + } + }, + "operator": "readonly", + "typeAnnotation": { + "type": "TSArrayType", + "start": 54, + "end": 62, + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 24 + } + }, + "elementType": { + "type": "TSNumberKeyword", + "start": 54, + "end": 60, + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 22 + } + } + } + } + } + } + }, + "init": null + } + ], + "kind": "let" + }, + { + "type": "VariableDeclaration", + "start": 64, + "end": 98, + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 34 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 68, + "end": 97, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 33 + } + }, + "id": { + "type": "Identifier", + "start": 68, + "end": 97, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 33 + }, + "identifierName": "z1" + }, + "name": "z1", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 70, + "end": 97, + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 33 + } + }, + "typeAnnotation": { + "type": "TSTypeOperator", + "start": 72, + "end": 97, + "loc": { + "start": { + "line": 4, + "column": 8 + }, + "end": { + "line": 4, + "column": 33 + } + }, + "operator": "readonly", + "typeAnnotation": { + "type": "TSTupleType", + "start": 81, + "end": 97, + "loc": { + "start": { + "line": 4, + "column": 17 + }, + "end": { + "line": 4, + "column": 33 + } + }, + "elementTypes": [ + { + "type": "TSNumberKeyword", + "start": 82, + "end": 88, + "loc": { + "start": { + "line": 4, + "column": 18 + }, + "end": { + "line": 4, + "column": 24 + } + } + }, + { + "type": "TSNumberKeyword", + "start": 90, + "end": 96, + "loc": { + "start": { + "line": 4, + "column": 26 + }, + "end": { + "line": 4, + "column": 32 + } + } + } + ] + } + } + } + }, + "init": null + } + ], + "kind": "let" } ], "directives": []