From bbe0cf09fc60c130fc63a7176e563781582612b8 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 15 Sep 2020 06:28:06 +0900 Subject: [PATCH] Throw a syntax error for a parameter properties in not constructor (#12061) --- packages/babel-parser/src/parser/statement.js | 2 +- .../src/plugins/typescript/index.js | 7 +- .../input.ts | 11 + .../output.json | 199 ++++++++++++++++++ .../function/parameter-properties/input.ts | 9 + .../function/parameter-properties/output.json | 165 +++++++++++++++ 6 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/function/parameter-properties/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/function/parameter-properties/output.json diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index a9c903e525d1..bee813c59196 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1083,7 +1083,7 @@ export default class StatementParser extends ExpressionParser { node.id = this.parseFunctionId(); } - this.parseFunctionParams(node); + this.parseFunctionParams(node, /* allowModifiers */ false); // For the smartPipelines plugin: Disable topic references from outer // contexts within the function body. They are permitted in function diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index bd983377f14e..f18b78f10906 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -90,6 +90,8 @@ const TSErrors = Object.freeze({ "Template literal types cannot have any substitution", TypeAnnotationAfterAssign: "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`", + UnexpectedParameterModifier: + "A parameter property is only allowed in a constructor implementation.", UnexpectedReadonly: "'readonly' type modifier is only permitted on array and tuple literal types.", UnexpectedTypeAnnotation: "Did not expect a type annotation here.", @@ -1709,9 +1711,12 @@ export default (superClass: Class): Class => let accessibility: ?N.Accessibility; let readonly = false; - if (allowModifiers) { + if (allowModifiers !== undefined) { accessibility = this.parseAccessModifier(); readonly = !!this.tsParseModifier(["readonly"]); + if (allowModifiers === false && (accessibility || readonly)) { + this.raise(startPos, TSErrors.UnexpectedParameterModifier); + } } const left = this.parseMaybeDefault(); diff --git a/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/input.ts b/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/input.ts new file mode 100644 index 000000000000..234633fd9484 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/input.ts @@ -0,0 +1,11 @@ +class C { + not_constructor( + readonly r, + public pu: number, + protected po?, + private pi?: number, + public readonly pur, + // Also works on AssignmentPattern + readonly x = 0, + public y?: number = 0) {} +} diff --git a/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/output.json b/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/output.json new file mode 100644 index 000000000000..58e506aa9ece --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/output.json @@ -0,0 +1,199 @@ +{ + "type": "File", + "start":0,"end":261,"loc":{"start":{"line":1,"column":0},"end":{"line":11,"column":1}}, + "errors": [ + "SyntaxError: A parameter property is only allowed in a constructor implementation. (3:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (4:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (5:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (6:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (7:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (9:8)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (10:8)" + ], + "program": { + "type": "Program", + "start":0,"end":261,"loc":{"start":{"line":1,"column":0},"end":{"line":11,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":261,"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":"C"}, + "name": "C" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":8,"end":261,"loc":{"start":{"line":1,"column":8},"end":{"line":11,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":14,"end":259,"loc":{"start":{"line":2,"column":4},"end":{"line":10,"column":33}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":29,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":19},"identifierName":"not_constructor"}, + "name": "not_constructor" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "TSParameterProperty", + "start":39,"end":49,"loc":{"start":{"line":3,"column":8},"end":{"line":3,"column":18}}, + "readonly": true, + "parameter": { + "type": "Identifier", + "start":48,"end":49,"loc":{"start":{"line":3,"column":17},"end":{"line":3,"column":18},"identifierName":"r"}, + "name": "r" + } + }, + { + "type": "TSParameterProperty", + "start":59,"end":76,"loc":{"start":{"line":4,"column":8},"end":{"line":4,"column":25}}, + "accessibility": "public", + "parameter": { + "type": "Identifier", + "start":66,"end":76,"loc":{"start":{"line":4,"column":15},"end":{"line":4,"column":25},"identifierName":"pu"}, + "name": "pu", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":68,"end":76,"loc":{"start":{"line":4,"column":17},"end":{"line":4,"column":25}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":70,"end":76,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":25}} + } + } + } + }, + { + "type": "TSParameterProperty", + "start":86,"end":99,"loc":{"start":{"line":5,"column":8},"end":{"line":5,"column":21}}, + "accessibility": "protected", + "parameter": { + "type": "Identifier", + "start":96,"end":99,"loc":{"start":{"line":5,"column":18},"end":{"line":5,"column":21},"identifierName":"po"}, + "name": "po", + "optional": true + } + }, + { + "type": "TSParameterProperty", + "start":109,"end":128,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":27}}, + "accessibility": "private", + "parameter": { + "type": "Identifier", + "start":117,"end":128,"loc":{"start":{"line":6,"column":16},"end":{"line":6,"column":27},"identifierName":"pi"}, + "name": "pi", + "optional": true, + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":120,"end":128,"loc":{"start":{"line":6,"column":19},"end":{"line":6,"column":27}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":122,"end":128,"loc":{"start":{"line":6,"column":21},"end":{"line":6,"column":27}} + } + } + } + }, + { + "type": "TSParameterProperty", + "start":138,"end":157,"loc":{"start":{"line":7,"column":8},"end":{"line":7,"column":27}}, + "accessibility": "public", + "readonly": true, + "parameter": { + "type": "Identifier", + "start":154,"end":157,"loc":{"start":{"line":7,"column":24},"end":{"line":7,"column":27},"identifierName":"pur"}, + "name": "pur" + } + }, + { + "type": "TSParameterProperty", + "start":210,"end":224,"loc":{"start":{"line":9,"column":8},"end":{"line":9,"column":22}}, + "readonly": true, + "parameter": { + "type": "AssignmentPattern", + "start":219,"end":224,"loc":{"start":{"line":9,"column":17},"end":{"line":9,"column":22}}, + "left": { + "type": "Identifier", + "start":219,"end":220,"loc":{"start":{"line":9,"column":17},"end":{"line":9,"column":18},"identifierName":"x"}, + "name": "x" + }, + "right": { + "type": "NumericLiteral", + "start":223,"end":224,"loc":{"start":{"line":9,"column":21},"end":{"line":9,"column":22}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + } + }, + "leadingComments": [ + { + "type": "CommentLine", + "value": " Also works on AssignmentPattern", + "start":167,"end":201,"loc":{"start":{"line":8,"column":8},"end":{"line":8,"column":42}} + } + ] + }, + { + "type": "TSParameterProperty", + "start":234,"end":255,"loc":{"start":{"line":10,"column":8},"end":{"line":10,"column":29}}, + "accessibility": "public", + "parameter": { + "type": "AssignmentPattern", + "start":241,"end":255,"loc":{"start":{"line":10,"column":15},"end":{"line":10,"column":29}}, + "left": { + "type": "Identifier", + "start":241,"end":251,"loc":{"start":{"line":10,"column":15},"end":{"line":10,"column":25},"identifierName":"y"}, + "name": "y", + "optional": true, + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":243,"end":251,"loc":{"start":{"line":10,"column":17},"end":{"line":10,"column":25}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":245,"end":251,"loc":{"start":{"line":10,"column":19},"end":{"line":10,"column":25}} + } + } + }, + "right": { + "type": "NumericLiteral", + "start":254,"end":255,"loc":{"start":{"line":10,"column":28},"end":{"line":10,"column":29}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + } + } + } + ], + "body": { + "type": "BlockStatement", + "start":257,"end":259,"loc":{"start":{"line":10,"column":31},"end":{"line":10,"column":33}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentLine", + "value": " Also works on AssignmentPattern", + "start":167,"end":201,"loc":{"start":{"line":8,"column":8},"end":{"line":8,"column":42}} + } + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/input.ts b/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/input.ts new file mode 100644 index 000000000000..db1c3c478db4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/input.ts @@ -0,0 +1,9 @@ +function foo( + readonly r, + public pu: number, + protected po?, + private pi?: number, + public readonly pur, + readonly x = 0, + public y?: number = 0 +) {} diff --git a/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/output.json b/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/output.json new file mode 100644 index 000000000000..f3a3c8a823c6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/function/parameter-properties/output.json @@ -0,0 +1,165 @@ +{ + "type": "File", + "start":0,"end":158,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":4}}, + "errors": [ + "SyntaxError: A parameter property is only allowed in a constructor implementation. (2:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (3:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (4:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (5:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (6:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (7:2)", + "SyntaxError: A parameter property is only allowed in a constructor implementation. (8:2)" + ], + "program": { + "type": "Program", + "start":0,"end":158,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":4}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "FunctionDeclaration", + "start":0,"end":158,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":4}}, + "id": { + "type": "Identifier", + "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"foo"}, + "name": "foo" + }, + "generator": false, + "async": false, + "params": [ + { + "type": "TSParameterProperty", + "start":16,"end":26,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":12}}, + "readonly": true, + "parameter": { + "type": "Identifier", + "start":25,"end":26,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":12},"identifierName":"r"}, + "name": "r" + } + }, + { + "type": "TSParameterProperty", + "start":30,"end":47,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":19}}, + "accessibility": "public", + "parameter": { + "type": "Identifier", + "start":37,"end":47,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":19},"identifierName":"pu"}, + "name": "pu", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":39,"end":47,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":19}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":41,"end":47,"loc":{"start":{"line":3,"column":13},"end":{"line":3,"column":19}} + } + } + } + }, + { + "type": "TSParameterProperty", + "start":51,"end":64,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":15}}, + "accessibility": "protected", + "parameter": { + "type": "Identifier", + "start":61,"end":64,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":15},"identifierName":"po"}, + "name": "po", + "optional": true + } + }, + { + "type": "TSParameterProperty", + "start":68,"end":87,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":21}}, + "accessibility": "private", + "parameter": { + "type": "Identifier", + "start":76,"end":87,"loc":{"start":{"line":5,"column":10},"end":{"line":5,"column":21},"identifierName":"pi"}, + "name": "pi", + "optional": true, + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":79,"end":87,"loc":{"start":{"line":5,"column":13},"end":{"line":5,"column":21}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":81,"end":87,"loc":{"start":{"line":5,"column":15},"end":{"line":5,"column":21}} + } + } + } + }, + { + "type": "TSParameterProperty", + "start":91,"end":110,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":21}}, + "accessibility": "public", + "readonly": true, + "parameter": { + "type": "Identifier", + "start":107,"end":110,"loc":{"start":{"line":6,"column":18},"end":{"line":6,"column":21},"identifierName":"pur"}, + "name": "pur" + } + }, + { + "type": "TSParameterProperty", + "start":114,"end":128,"loc":{"start":{"line":7,"column":2},"end":{"line":7,"column":16}}, + "readonly": true, + "parameter": { + "type": "AssignmentPattern", + "start":123,"end":128,"loc":{"start":{"line":7,"column":11},"end":{"line":7,"column":16}}, + "left": { + "type": "Identifier", + "start":123,"end":124,"loc":{"start":{"line":7,"column":11},"end":{"line":7,"column":12},"identifierName":"x"}, + "name": "x" + }, + "right": { + "type": "NumericLiteral", + "start":127,"end":128,"loc":{"start":{"line":7,"column":15},"end":{"line":7,"column":16}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + } + } + }, + { + "type": "TSParameterProperty", + "start":132,"end":153,"loc":{"start":{"line":8,"column":2},"end":{"line":8,"column":23}}, + "accessibility": "public", + "parameter": { + "type": "AssignmentPattern", + "start":139,"end":153,"loc":{"start":{"line":8,"column":9},"end":{"line":8,"column":23}}, + "left": { + "type": "Identifier", + "start":139,"end":149,"loc":{"start":{"line":8,"column":9},"end":{"line":8,"column":19},"identifierName":"y"}, + "name": "y", + "optional": true, + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":141,"end":149,"loc":{"start":{"line":8,"column":11},"end":{"line":8,"column":19}}, + "typeAnnotation": { + "type": "TSNumberKeyword", + "start":143,"end":149,"loc":{"start":{"line":8,"column":13},"end":{"line":8,"column":19}} + } + } + }, + "right": { + "type": "NumericLiteral", + "start":152,"end":153,"loc":{"start":{"line":8,"column":22},"end":{"line":8,"column":23}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + } + } + } + ], + "body": { + "type": "BlockStatement", + "start":156,"end":158,"loc":{"start":{"line":9,"column":2},"end":{"line":9,"column":4}}, + "body": [], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file