Skip to content

Commit

Permalink
[ts] Allow ...<...> followed by newline and strict keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Jun 2, 2022
1 parent d4d08d9 commit 177201b
Show file tree
Hide file tree
Showing 6 changed files with 735 additions and 11 deletions.
28 changes: 17 additions & 11 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -39,6 +39,7 @@ import type { ExpressionErrors } from "../../parser/util";
import { PARAM } from "../../util/production-parameter";
import { Errors, ParseErrorEnum } from "../../parse-error";
import { cloneIdentifier } from "../../parser/node";
import { isStrictReservedWord } from "../../util/identifier";

const getOwn = (object, key) =>
Object.hasOwnProperty.call(object, key) && object[key];
Expand Down Expand Up @@ -2429,11 +2430,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}

const typeArguments = this.tsParseTypeArgumentsInExpression();
if (!typeArguments) throw this.unexpected();
if (!typeArguments) return;

if (isOptionalCall && !this.match(tt.parenL)) {
missingParenErrorLoc = this.state.curPosition();
throw this.unexpected();
return;
}

if (tokenIsTemplate(this.state.type)) {
Expand Down Expand Up @@ -2469,19 +2470,24 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishCallExpression(node, state.optionalChainMember);
}

// TODO: This doesn't exactly match what TS does when it comes to ASI.
// For example,
// a<b>
// if (0);
// is not valid TS code (https://github.com/microsoft/TypeScript/issues/48654)
// However, it should correctly parse anything that is correctly parsed by TS.
const tokenType = this.state.type;
if (
tsTokenCanStartExpression(this.state.type) &&
this.state.type !== tt.parenL
tsTokenCanStartExpression(tokenType) &&
tokenType !== tt.parenL &&
// If the next token is a strict-mode keyword, tsc parses this as an
// instantiation expression to prevent things like
// a = b<c>
// let d;
// from benig parsed as relational expressions.
!(
tokenIsIdentifier(tokenType) &&
isStrictReservedWord(this.state.value, true) &&
this.hasPrecedingLineBreak()
)
) {
// Bail out. We have something like a<b>c, which is not an expression with
// type arguments but an (a < b) > c comparison.
throw this.unexpected();
return;
}

const node: N.TsInstantiationExpression = this.startNodeAt(
Expand Down
@@ -0,0 +1,11 @@
a<b> let

a<b> interface

async function G() {
a<b> await 0
}

a<b> await

a<b> yield
@@ -0,0 +1,3 @@
{
"sourceType": "script"
}
@@ -0,0 +1,185 @@
{
"type": "File",
"start":0,"end":89,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":11,"column":10,"index":89}},
"program": {
"type": "Program",
"start":0,"end":89,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":11,"column":10,"index":89}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":8,"index":8}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":8,"index":8}},
"left": {
"type": "BinaryExpression",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":3,"index":3}},
"left": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1},"identifierName":"a"},
"name": "a"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":2,"end":3,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":3,"index":3},"identifierName":"b"},
"name": "b"
}
},
"operator": ">",
"right": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":8,"index":8},"identifierName":"let"},
"name": "let"
}
}
},
{
"type": "ExpressionStatement",
"start":10,"end":24,"loc":{"start":{"line":3,"column":0,"index":10},"end":{"line":3,"column":14,"index":24}},
"expression": {
"type": "BinaryExpression",
"start":10,"end":24,"loc":{"start":{"line":3,"column":0,"index":10},"end":{"line":3,"column":14,"index":24}},
"left": {
"type": "BinaryExpression",
"start":10,"end":13,"loc":{"start":{"line":3,"column":0,"index":10},"end":{"line":3,"column":3,"index":13}},
"left": {
"type": "Identifier",
"start":10,"end":11,"loc":{"start":{"line":3,"column":0,"index":10},"end":{"line":3,"column":1,"index":11},"identifierName":"a"},
"name": "a"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":12,"end":13,"loc":{"start":{"line":3,"column":2,"index":12},"end":{"line":3,"column":3,"index":13},"identifierName":"b"},
"name": "b"
}
},
"operator": ">",
"right": {
"type": "Identifier",
"start":15,"end":24,"loc":{"start":{"line":3,"column":5,"index":15},"end":{"line":3,"column":14,"index":24},"identifierName":"interface"},
"name": "interface"
}
}
},
{
"type": "FunctionDeclaration",
"start":26,"end":65,"loc":{"start":{"line":5,"column":0,"index":26},"end":{"line":7,"column":1,"index":65}},
"id": {
"type": "Identifier",
"start":41,"end":42,"loc":{"start":{"line":5,"column":15,"index":41},"end":{"line":5,"column":16,"index":42},"identifierName":"G"},
"name": "G"
},
"generator": false,
"async": true,
"params": [],
"body": {
"type": "BlockStatement",
"start":45,"end":65,"loc":{"start":{"line":5,"column":19,"index":45},"end":{"line":7,"column":1,"index":65}},
"body": [
{
"type": "ExpressionStatement",
"start":51,"end":63,"loc":{"start":{"line":6,"column":4,"index":51},"end":{"line":6,"column":16,"index":63}},
"expression": {
"type": "BinaryExpression",
"start":51,"end":63,"loc":{"start":{"line":6,"column":4,"index":51},"end":{"line":6,"column":16,"index":63}},
"left": {
"type": "BinaryExpression",
"start":51,"end":54,"loc":{"start":{"line":6,"column":4,"index":51},"end":{"line":6,"column":7,"index":54}},
"left": {
"type": "Identifier",
"start":51,"end":52,"loc":{"start":{"line":6,"column":4,"index":51},"end":{"line":6,"column":5,"index":52},"identifierName":"a"},
"name": "a"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":53,"end":54,"loc":{"start":{"line":6,"column":6,"index":53},"end":{"line":6,"column":7,"index":54},"identifierName":"b"},
"name": "b"
}
},
"operator": ">",
"right": {
"type": "AwaitExpression",
"start":56,"end":63,"loc":{"start":{"line":6,"column":9,"index":56},"end":{"line":6,"column":16,"index":63}},
"argument": {
"type": "NumericLiteral",
"start":62,"end":63,"loc":{"start":{"line":6,"column":15,"index":62},"end":{"line":6,"column":16,"index":63}},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
}
}
],
"directives": []
}
},
{
"type": "ExpressionStatement",
"start":67,"end":77,"loc":{"start":{"line":9,"column":0,"index":67},"end":{"line":9,"column":10,"index":77}},
"expression": {
"type": "BinaryExpression",
"start":67,"end":77,"loc":{"start":{"line":9,"column":0,"index":67},"end":{"line":9,"column":10,"index":77}},
"left": {
"type": "BinaryExpression",
"start":67,"end":70,"loc":{"start":{"line":9,"column":0,"index":67},"end":{"line":9,"column":3,"index":70}},
"left": {
"type": "Identifier",
"start":67,"end":68,"loc":{"start":{"line":9,"column":0,"index":67},"end":{"line":9,"column":1,"index":68},"identifierName":"a"},
"name": "a"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":69,"end":70,"loc":{"start":{"line":9,"column":2,"index":69},"end":{"line":9,"column":3,"index":70},"identifierName":"b"},
"name": "b"
}
},
"operator": ">",
"right": {
"type": "Identifier",
"start":72,"end":77,"loc":{"start":{"line":9,"column":5,"index":72},"end":{"line":9,"column":10,"index":77},"identifierName":"await"},
"name": "await"
}
}
},
{
"type": "ExpressionStatement",
"start":79,"end":89,"loc":{"start":{"line":11,"column":0,"index":79},"end":{"line":11,"column":10,"index":89}},
"expression": {
"type": "BinaryExpression",
"start":79,"end":89,"loc":{"start":{"line":11,"column":0,"index":79},"end":{"line":11,"column":10,"index":89}},
"left": {
"type": "BinaryExpression",
"start":79,"end":82,"loc":{"start":{"line":11,"column":0,"index":79},"end":{"line":11,"column":3,"index":82}},
"left": {
"type": "Identifier",
"start":79,"end":80,"loc":{"start":{"line":11,"column":0,"index":79},"end":{"line":11,"column":1,"index":80},"identifierName":"a"},
"name": "a"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":81,"end":82,"loc":{"start":{"line":11,"column":2,"index":81},"end":{"line":11,"column":3,"index":82},"identifierName":"b"},
"name": "b"
}
},
"operator": ">",
"right": {
"type": "Identifier",
"start":84,"end":89,"loc":{"start":{"line":11,"column":5,"index":84},"end":{"line":11,"column":10,"index":89},"identifierName":"yield"},
"name": "yield"
}
}
}
],
"directives": []
}
}
@@ -0,0 +1,35 @@
a<b>
let A;

a<b>
interface B {}

class C {
_ = a<b>
static __;
}

class D {
_ = a<b>
public __;
}

class E {
_ = a<b>
private __;
}

class F {
_ = a<b>
protected __;
}

async function G() {
a<b>
await 0
}

function* H() {
a<b>
yield 0
}

0 comments on commit 177201b

Please sign in to comment.