From 1d86ce2edeb40cb348709750e2e91af557ecb173 Mon Sep 17 00:00:00 2001 From: sosukesuzuki Date: Wed, 7 Apr 2021 14:57:43 +0900 Subject: [PATCH] Avoid lookahead --- .../src/plugins/typescript/index.js | 60 ++++++++----------- .../interface/get-set-properties/output.json | 30 ++-------- .../get-set-type-parameters/output.json | 8 +-- 3 files changed, 32 insertions(+), 66 deletions(-) diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index e354c7c24b8b..f25eab816d45 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -188,12 +188,7 @@ export default (superClass: Class): Class => return this.match(tt.name); } - tsNextTokenCanFollowModifier() { - // Note: TypeScript's implementation is much more complicated because - // more things are considered modifiers there. - // This implementation only handles modifiers not handled by @babel/parser itself. And "static". - // TODO: Would be nice to avoid lookahead. Want a hasLineBreakUpNext() method... - this.next(); + tsTokenCanFollowModifier() { return ( (this.match(tt.bracketL) || this.match(tt.braceL) || @@ -205,6 +200,15 @@ export default (superClass: Class): Class => ); } + tsNextTokenCanFollowModifier() { + // Note: TypeScript's implementation is much more complicated because + // more things are considered modifiers there. + // This implementation only handles modifiers not handled by @babel/parser itself. And "static". + // TODO: Would be nice to avoid lookahead. Want a hasLineBreakUpNext() method... + this.next(); + return this.tsTokenCanFollowModifier(); + } + /** Parses a modifier matching one the given modifier names. */ tsParseModifier(allowedModifiers: T[]): ?T { if (!this.match(tt.name)) { @@ -532,8 +536,8 @@ export default (superClass: Class): Class => } tsParseTypeMemberSemicolon(): void { - if (!this.eat(tt.comma)) { - this.semicolon(); + if (!this.eat(tt.comma) && !this.isLineTerminator()) { + this.expect(tt.semi); } } @@ -587,6 +591,9 @@ export default (superClass: Class): Class => this.raise(node.start, TSErrors.ReadonlyForMethodSignature); } const method: N.TsMethodSignature = nodeAny; + if (method.kind && this.isRelational("<")) { + this.raise(this.state.pos, TSErrors.AccesorCannotHaveTypeParameters); + } this.tsFillSignature(tt.colon, method); this.tsParseTypeMemberSemicolon(); if (method.kind === "get") { @@ -617,33 +624,6 @@ export default (superClass: Class): Class => } } - tsParseMethodSignatureKind(node: any) { - if (!this.isContextual("get") && !this.isContextual("set")) { - return; - } - const kind = this.state.value; - if ( - this.tsTryParse(() => { - if (this.tsNextTokenCanFollowModifier()) { - // Check if a property is a method signature - const lookahead = this.lookahead(); - if (lookahead.type === tt.parenL) { - return true; - } - if (lookahead.type === tt.relational && lookahead.value === "<") { - this.raise( - this.state.pos, - TSErrors.AccesorCannotHaveTypeParameters, - ); - return true; - } - } - }) - ) { - node.kind = kind; - } - } - tsParseTypeMember(): N.TsTypeElement { const node: any = this.startNode(); @@ -677,8 +657,16 @@ export default (superClass: Class): Class => return idx; } - this.tsParseMethodSignatureKind(node); this.parsePropertyName(node, /* isPrivateNameAllowed */ false); + if ( + !node.computed && + node.key.type === "Identifier" && + (node.key.name === "get" || node.key.name === "set") && + this.tsTokenCanFollowModifier() + ) { + node.kind = node.key.name; + this.parsePropertyName(node, /* isPrivateNameAllowed */ false); + } return this.tsParsePropertyOrMethodSignature(node, !!node.readonly); } diff --git a/packages/babel-parser/test/fixtures/typescript/interface/get-set-properties/output.json b/packages/babel-parser/test/fixtures/typescript/interface/get-set-properties/output.json index b41b4bbd82e5..6f286bc4dfe2 100644 --- a/packages/babel-parser/test/fixtures/typescript/interface/get-set-properties/output.json +++ b/packages/babel-parser/test/fixtures/typescript/interface/get-set-properties/output.json @@ -1,10 +1,6 @@ { "type": "File", "start":0,"end":55,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, - "errors": [ - "SyntaxError: Missing semicolon (2:5)", - "SyntaxError: Missing semicolon (3:5)" - ], "program": { "type": "Program", "start":0,"end":55,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, @@ -25,23 +21,14 @@ "body": [ { "type": "TSPropertySignature", - "start":18,"end":21,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":5}}, - "key": { - "type": "Identifier", - "start":18,"end":21,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":5},"identifierName":"get"}, - "name": "get" - }, - "computed": false - }, - { - "type": "TSPropertySignature", - "start":22,"end":34,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":18}}, + "start":18,"end":34,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":18}}, "key": { "type": "Identifier", "start":22,"end":25,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":9},"identifierName":"foo"}, "name": "foo" }, "computed": false, + "kind": "get", "typeAnnotation": { "type": "TSTypeAnnotation", "start":25,"end":33,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":17}}, @@ -53,23 +40,14 @@ }, { "type": "TSPropertySignature", - "start":37,"end":40,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5}}, - "key": { - "type": "Identifier", - "start":37,"end":40,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5},"identifierName":"set"}, - "name": "set" - }, - "computed": false - }, - { - "type": "TSPropertySignature", - "start":41,"end":53,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":18}}, + "start":37,"end":53,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":18}}, "key": { "type": "Identifier", "start":41,"end":44,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":9},"identifierName":"bar"}, "name": "bar" }, "computed": false, + "kind": "set", "typeAnnotation": { "type": "TSTypeAnnotation", "start":44,"end":52,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":17}}, diff --git a/packages/babel-parser/test/fixtures/typescript/interface/get-set-type-parameters/output.json b/packages/babel-parser/test/fixtures/typescript/interface/get-set-type-parameters/output.json index 3bb72034eaa9..0548c7796bf0 100644 --- a/packages/babel-parser/test/fixtures/typescript/interface/get-set-type-parameters/output.json +++ b/packages/babel-parser/test/fixtures/typescript/interface/get-set-type-parameters/output.json @@ -2,8 +2,8 @@ "type": "File", "start":0,"end":58,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, "errors": [ - "SyntaxError: An accessor cannot have type parameters. (2:9)", - "SyntaxError: An accessor cannot have type parameters. (3:9)" + "SyntaxError: An accessor cannot have type parameters. (2:10)", + "SyntaxError: An accessor cannot have type parameters. (3:10)" ], "program": { "type": "Program", @@ -26,13 +26,13 @@ { "type": "TSMethodSignature", "start":18,"end":39,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":23}}, - "kind": "get", "key": { "type": "Identifier", "start":22,"end":25,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":9},"identifierName":"foo"}, "name": "foo" }, "computed": false, + "kind": "get", "typeParameters": { "type": "TSTypeParameterDeclaration", "start":25,"end":28,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":12}}, @@ -57,13 +57,13 @@ { "type": "TSMethodSignature", "start":42,"end":56,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":16}}, - "kind": "set", "key": { "type": "Identifier", "start":46,"end":49,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":9},"identifierName":"bar"}, "name": "bar" }, "computed": false, + "kind": "set", "typeParameters": { "type": "TSTypeParameterDeclaration", "start":49,"end":52,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":12}},