Skip to content

Commit

Permalink
Raise recoverable error for type members with invalid modifiers (#12785)
Browse files Browse the repository at this point in the history
  • Loading branch information
sosukesuzuki committed Feb 12, 2021
1 parent 8063fde commit c22e72e
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 5 deletions.
33 changes: 28 additions & 5 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -82,6 +82,7 @@ const TSErrors = Object.freeze({
IndexSignatureHasStatic: "Index signatures cannot have the 'static' modifier",
IndexSignatureHasDeclare:
"Index signatures cannot have the 'declare' modifier",
InvalidModifierOnTypeMember: "'%0' modifier cannot appear on a type member.",
InvalidTupleMemberLabel:
"Tuple members must be labeled with a simple identifier.",
MixedLabeledAndUnlabeledElements:
Expand All @@ -98,6 +99,8 @@ const TSErrors = Object.freeze({
"Private elements cannot have the 'abstract' modifier.",
PrivateElementHasAccessibility:
"Private elements cannot have an accessibility modifier ('%0')",
ReadonlyForMethodSignature:
"'readonly' modifier can only appear on a property declaration or index signature.",
TypeAnnotationAfterAssign:
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",
UnexpectedParameterModifier:
Expand Down Expand Up @@ -207,10 +210,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
accessibility?: N.Accessibility,
},
allowedModifiers: TsModifier[],
disallowedModifiers?: TsModifier[],
errorTemplate?: string,
): void {
for (;;) {
const startPos = this.state.start;
const modifier: ?TsModifier = this.tsParseModifier(allowedModifiers);
const modifier: ?TsModifier = this.tsParseModifier(
allowedModifiers.concat(disallowedModifiers ?? []),
);

if (!modifier) break;

Expand All @@ -226,6 +233,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
modified[modifier] = true;
}

if (disallowedModifiers?.includes(modifier)) {
this.raise(
startPos,
// $FlowIgnore
errorTemplate,
modifier,
);
}
}
}

Expand Down Expand Up @@ -537,7 +553,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.eat(tt.question)) node.optional = true;
const nodeAny: any = node;

if (!readonly && (this.match(tt.parenL) || this.isRelational("<"))) {
if (this.match(tt.parenL) || this.isRelational("<")) {
if (readonly) {
this.raise(node.start, TSErrors.ReadonlyForMethodSignature);
}
const method: N.TsMethodSignature = nodeAny;
this.tsFillSignature(tt.colon, method);
this.tsParseTypeMemberSemicolon();
Expand Down Expand Up @@ -573,16 +592,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

const readonly = !!this.tsParseModifier(["readonly"]);
this.tsParseModifiers(
node,
["readonly"],
["declare", "abstract", "private", "protected", "public", "static"],
TSErrors.InvalidModifierOnTypeMember,
);

const idx = this.tsTryParseIndexSignature(node);
if (idx) {
if (readonly) node.readonly = true;
return idx;
}

this.parsePropertyName(node, /* isPrivateNameAllowed */ false);
return this.tsParsePropertyOrMethodSignature(node, readonly);
return this.tsParsePropertyOrMethodSignature(node, !!node.readonly);
}

tsParseTypeLiteral(): N.TsTypeLiteral {
Expand Down
@@ -0,0 +1,9 @@
interface Foo {
private a();
public b();
protected c();
static d();
declare e();
abstract f();
readonly g();
}
@@ -0,0 +1,121 @@
{
"type": "File",
"start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}},
"errors": [
"SyntaxError: 'private' modifier cannot appear on a type member. (2:2)",
"SyntaxError: 'public' modifier cannot appear on a type member. (3:2)",
"SyntaxError: 'protected' modifier cannot appear on a type member. (4:2)",
"SyntaxError: 'static' modifier cannot appear on a type member. (5:2)",
"SyntaxError: 'declare' modifier cannot appear on a type member. (6:2)",
"SyntaxError: 'abstract' modifier cannot appear on a type member. (7:2)",
"SyntaxError: 'readonly' modifier can only appear on a property declaration or index signature. (8:2)"
],
"program": {
"type": "Program",
"start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start":0,"end":124,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}},
"id": {
"type": "Identifier",
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"Foo"},
"name": "Foo"
},
"body": {
"type": "TSInterfaceBody",
"start":14,"end":124,"loc":{"start":{"line":1,"column":14},"end":{"line":9,"column":1}},
"body": [
{
"type": "TSMethodSignature",
"start":18,"end":30,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":14}},
"accessibility": "private",
"key": {
"type": "Identifier",
"start":26,"end":27,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":11},"identifierName":"a"},
"name": "a"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":33,"end":44,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":13}},
"accessibility": "public",
"key": {
"type": "Identifier",
"start":40,"end":41,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":10},"identifierName":"b"},
"name": "b"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":47,"end":61,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":16}},
"accessibility": "protected",
"key": {
"type": "Identifier",
"start":57,"end":58,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13},"identifierName":"c"},
"name": "c"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":64,"end":75,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":13}},
"static": true,
"key": {
"type": "Identifier",
"start":71,"end":72,"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":10},"identifierName":"d"},
"name": "d"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":78,"end":90,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":14}},
"declare": true,
"key": {
"type": "Identifier",
"start":86,"end":87,"loc":{"start":{"line":6,"column":10},"end":{"line":6,"column":11},"identifierName":"e"},
"name": "e"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":93,"end":106,"loc":{"start":{"line":7,"column":2},"end":{"line":7,"column":15}},
"abstract": true,
"key": {
"type": "Identifier",
"start":102,"end":103,"loc":{"start":{"line":7,"column":11},"end":{"line":7,"column":12},"identifierName":"f"},
"name": "f"
},
"computed": false,
"parameters": []
},
{
"type": "TSMethodSignature",
"start":109,"end":122,"loc":{"start":{"line":8,"column":2},"end":{"line":8,"column":15}},
"readonly": true,
"key": {
"type": "Identifier",
"start":118,"end":119,"loc":{"start":{"line":8,"column":11},"end":{"line":8,"column":12},"identifierName":"g"},
"name": "g"
},
"computed": false,
"parameters": []
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,8 @@
interface Foo {
private a;
public b;
protected c;
static d;
declare e;
abstract f;
}
@@ -0,0 +1,102 @@
{
"type": "File",
"start":0,"end":96,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":1}},
"errors": [
"SyntaxError: 'private' modifier cannot appear on a type member. (2:2)",
"SyntaxError: 'public' modifier cannot appear on a type member. (3:2)",
"SyntaxError: 'protected' modifier cannot appear on a type member. (4:2)",
"SyntaxError: 'static' modifier cannot appear on a type member. (5:2)",
"SyntaxError: 'declare' modifier cannot appear on a type member. (6:2)",
"SyntaxError: 'abstract' modifier cannot appear on a type member. (7:2)"
],
"program": {
"type": "Program",
"start":0,"end":96,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start":0,"end":96,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":1}},
"id": {
"type": "Identifier",
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"Foo"},
"name": "Foo"
},
"body": {
"type": "TSInterfaceBody",
"start":14,"end":96,"loc":{"start":{"line":1,"column":14},"end":{"line":8,"column":1}},
"body": [
{
"type": "TSPropertySignature",
"start":18,"end":28,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":12}},
"accessibility": "private",
"key": {
"type": "Identifier",
"start":26,"end":27,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":11},"identifierName":"a"},
"name": "a"
},
"computed": false
},
{
"type": "TSPropertySignature",
"start":31,"end":40,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":11}},
"accessibility": "public",
"key": {
"type": "Identifier",
"start":38,"end":39,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":10},"identifierName":"b"},
"name": "b"
},
"computed": false
},
{
"type": "TSPropertySignature",
"start":43,"end":55,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":14}},
"accessibility": "protected",
"key": {
"type": "Identifier",
"start":53,"end":54,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13},"identifierName":"c"},
"name": "c"
},
"computed": false
},
{
"type": "TSPropertySignature",
"start":58,"end":67,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":11}},
"static": true,
"key": {
"type": "Identifier",
"start":65,"end":66,"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":10},"identifierName":"d"},
"name": "d"
},
"computed": false
},
{
"type": "TSPropertySignature",
"start":70,"end":80,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":12}},
"declare": true,
"key": {
"type": "Identifier",
"start":78,"end":79,"loc":{"start":{"line":6,"column":10},"end":{"line":6,"column":11},"identifierName":"e"},
"name": "e"
},
"computed": false
},
{
"type": "TSPropertySignature",
"start":83,"end":94,"loc":{"start":{"line":7,"column":2},"end":{"line":7,"column":13}},
"abstract": true,
"key": {
"type": "Identifier",
"start":92,"end":93,"loc":{"start":{"line":7,"column":11},"end":{"line":7,"column":12},"identifierName":"f"},
"name": "f"
},
"computed": false
}
]
}
}
],
"directives": []
}
}

0 comments on commit c22e72e

Please sign in to comment.