diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 66667fc38f..afe13976d1 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -70,6 +70,8 @@ const TSErrors = makeErrorTemplates( { AbstractMethodHasImplementation: "Method '%0' cannot have an implementation because it is marked abstract.", + AbstractPropertyHasInitializer: + "Property '%0' cannot have an initializer because it is marked abstract.", AccesorCannotDeclareThisParameter: "'get' and 'set' accessors cannot declare 'this' parameters.", AccesorCannotHaveTypeParameters: "An accessor cannot have type parameters.", @@ -2612,6 +2614,16 @@ export default (superClass: Class): Class => if (this.state.isAmbientContext && this.match(tt.eq)) { this.raise(this.state.start, TSErrors.DeclareClassFieldHasInitializer); } + if (node.abstract && this.match(tt.eq)) { + const { key } = node; + this.raise( + this.state.start, + TSErrors.AbstractPropertyHasInitializer, + key.type === "Identifier" && !node.computed + ? key.name + : `[${this.input.slice(key.start, key.end)}]`, + ); + } return super.parseClassProperty(node); } @@ -3201,7 +3213,7 @@ export default (superClass: Class): Class => this.raise( method.start, TSErrors.AbstractMethodHasImplementation, - key.type === "Identifier" + key.type === "Identifier" && !method.computed ? key.name : `[${this.input.slice(key.start, key.end)}]`, ); diff --git a/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/input.ts b/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/input.ts new file mode 100644 index 0000000000..620ad2217d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/input.ts @@ -0,0 +1,7 @@ +abstract class Foo { + abstract prop = 1 + abstract [Bar.foo] = 2 + abstract [Bar] = 3 + abstract 2 = 4 + abstract "c" = 5 +} diff --git a/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/output.json b/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/output.json new file mode 100644 index 0000000000..455fbc2055 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/abstract-property-initializer/output.json @@ -0,0 +1,160 @@ +{ + "type": "File", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "errors": [ + "SyntaxError: Property 'prop' cannot have an initializer because it is marked abstract. (2:16)", + "SyntaxError: Property '[Bar.foo]' cannot have an initializer because it is marked abstract. (3:21)", + "SyntaxError: Property '[Bar]' cannot have an initializer because it is marked abstract. (4:17)", + "SyntaxError: Property '[2]' cannot have an initializer because it is marked abstract. (5:13)", + "SyntaxError: Property '[\"c\"]' cannot have an initializer because it is marked abstract. (6:15)" + ], + "program": { + "type": "Program", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "abstract": true, + "id": { + "type": "Identifier", + "start":15,"end":18,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":18},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":19,"end":124,"loc":{"start":{"line":1,"column":19},"end":{"line":7,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":23,"end":40,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}}, + "abstract": true, + "static": false, + "key": { + "type": "Identifier", + "start":32,"end":36,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":15},"identifierName":"prop"}, + "name": "prop" + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start":39,"end":40,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":19}}, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ClassProperty", + "start":43,"end":65,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":24}}, + "abstract": true, + "static": false, + "computed": true, + "key": { + "type": "MemberExpression", + "start":53,"end":60,"loc":{"start":{"line":3,"column":12},"end":{"line":3,"column":19}}, + "object": { + "type": "Identifier", + "start":53,"end":56,"loc":{"start":{"line":3,"column":12},"end":{"line":3,"column":15},"identifierName":"Bar"}, + "name": "Bar" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":57,"end":60,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":19},"identifierName":"foo"}, + "name": "foo" + } + }, + "value": { + "type": "NumericLiteral", + "start":64,"end":65,"loc":{"start":{"line":3,"column":23},"end":{"line":3,"column":24}}, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + } + }, + { + "type": "ClassProperty", + "start":68,"end":86,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":20}}, + "abstract": true, + "static": false, + "computed": true, + "key": { + "type": "Identifier", + "start":78,"end":81,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":15},"identifierName":"Bar"}, + "name": "Bar" + }, + "value": { + "type": "NumericLiteral", + "start":85,"end":86,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":20}}, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + }, + { + "type": "ClassProperty", + "start":89,"end":103,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":16}}, + "abstract": true, + "static": false, + "key": { + "type": "NumericLiteral", + "start":98,"end":99,"loc":{"start":{"line":5,"column":11},"end":{"line":5,"column":12}}, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start":102,"end":103,"loc":{"start":{"line":5,"column":15},"end":{"line":5,"column":16}}, + "extra": { + "rawValue": 4, + "raw": "4" + }, + "value": 4 + } + }, + { + "type": "ClassProperty", + "start":106,"end":122,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":18}}, + "abstract": true, + "static": false, + "key": { + "type": "StringLiteral", + "start":115,"end":118,"loc":{"start":{"line":6,"column":11},"end":{"line":6,"column":14}}, + "extra": { + "rawValue": "c", + "raw": "\"c\"" + }, + "value": "c" + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start":121,"end":122,"loc":{"start":{"line":6,"column":17},"end":{"line":6,"column":18}}, + "extra": { + "rawValue": 5, + "raw": "5" + }, + "value": 5 + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file