rescan gt/lt token after TsAsExpression is parsed (#11912)

* refactor: move inType checks to flow plugin

* polish: replace hardcoded char codes

* fix: rescan greater/less token after asExpression is parsed
This commit is contained in:
Huáng Jùnliàng 2020-08-04 17:00:21 -04:00 committed by GitHub
parent c29138fd72
commit a1eabb84ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 136 additions and 30 deletions

View File

@ -2135,6 +2135,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
(code === charCodes.greaterThan || code === charCodes.lessThan) (code === charCodes.greaterThan || code === charCodes.lessThan)
) { ) {
return this.finishOp(tt.relational, 1); return this.finishOp(tt.relational, 1);
} else if (this.state.inType && code === charCodes.questionMark) {
// allow double nullable types in Flow: ??string
return this.finishOp(tt.question, 1);
} else if (isIteratorStart(code, next)) { } else if (isIteratorStart(code, next)) {
this.state.isIterator = true; this.state.isIterator = true;
return super.readWord(); return super.readWord();

View File

@ -1884,6 +1884,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.typeAnnotation = this.tsNextThenParseType(); node.typeAnnotation = this.tsNextThenParseType();
} }
this.finishNode(node, "TSAsExpression"); this.finishNode(node, "TSAsExpression");
// rescan `<`, `>` because they were scanned when this.state.inType was true
this.reScan_lt_gt();
return this.parseExprOp( return this.parseExprOp(
node, node,
leftStartPos, leftStartPos,
@ -2628,13 +2630,27 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// ensure that inside types, we bypass the jsx parser plugin // ensure that inside types, we bypass the jsx parser plugin
getTokenFromCode(code: number): void { getTokenFromCode(code: number): void {
if (this.state.inType && (code === 62 || code === 60)) { if (
this.state.inType &&
(code === charCodes.greaterThan || code === charCodes.lessThan)
) {
return this.finishOp(tt.relational, 1); return this.finishOp(tt.relational, 1);
} else { } else {
return super.getTokenFromCode(code); return super.getTokenFromCode(code);
} }
} }
// used after we have finished parsing types
reScan_lt_gt() {
if (this.match(tt.relational)) {
const code = this.input.charCodeAt(this.state.start);
if (code === charCodes.lessThan || code === charCodes.greaterThan) {
this.state.pos -= 1;
this.readToken_lt_gt(code);
}
}
}
toAssignableList(exprList: N.Expression[]): $ReadOnlyArray<N.Pattern> { toAssignableList(exprList: N.Expression[]): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) { for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i]; const expr = exprList[i];

View File

@ -693,7 +693,7 @@ export default class Tokenizer extends ParserErrors {
// '?' // '?'
const next = this.input.charCodeAt(this.state.pos + 1); const next = this.input.charCodeAt(this.state.pos + 1);
const next2 = this.input.charCodeAt(this.state.pos + 2); const next2 = this.input.charCodeAt(this.state.pos + 2);
if (next === charCodes.questionMark && !this.state.inType) { if (next === charCodes.questionMark) {
if (next2 === charCodes.equalsTo) { if (next2 === charCodes.equalsTo) {
// '??=' // '??='
this.finishOp(tt.assign, 3); this.finishOp(tt.assign, 3);

View File

@ -1,4 +1,6 @@
x as T; x as T;
x < y as boolean; // (x < y) as boolean; x < y as boolean; // (x < y) as boolean;
x as boolean <= y; // (x as boolean) <= y;
x === 1 as number; // x === (1 as number); x === 1 as number; // x === (1 as number);
x as any as T; x as any as T;
x as boolean ?? y; // (x as boolean) ?? y;

View File

@ -1,9 +1,9 @@
{ {
"type": "File", "type": "File",
"start":0,"end":106,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":14}}, "start":0,"end":192,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":42}},
"program": { "program": {
"type": "Program", "type": "Program",
"start":0,"end":106,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":14}}, "start":0,"end":192,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":42}},
"sourceType": "module", "sourceType": "module",
"interpreter": null, "interpreter": null,
"body": [ "body": [
@ -70,27 +70,23 @@
"type": "BinaryExpression", "type": "BinaryExpression",
"start":49,"end":66,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":17}}, "start":49,"end":66,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":17}},
"left": { "left": {
"type": "Identifier",
"start":49,"end":50,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":1},"identifierName":"x"},
"name": "x"
},
"operator": "===",
"right": {
"type": "TSAsExpression", "type": "TSAsExpression",
"start":55,"end":66,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":17}}, "start":49,"end":61,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":12}},
"expression": { "expression": {
"type": "NumericLiteral", "type": "Identifier",
"start":55,"end":56,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":7}}, "start":49,"end":50,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":1},"identifierName":"x"},
"extra": { "name": "x"
"rawValue": 1,
"raw": "1"
},
"value": 1
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSNumberKeyword", "type": "TSBooleanKeyword",
"start":60,"end":66,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":17}} "start":54,"end":61,"loc":{"start":{"line":3,"column":5},"end":{"line":3,"column":12}}
} }
},
"operator": "<=",
"right": {
"type": "Identifier",
"start":65,"end":66,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":17},"identifierName":"y"},
"name": "y"
} }
}, },
"leadingComments": [ "leadingComments": [
@ -103,36 +99,81 @@
"trailingComments": [ "trailingComments": [
{ {
"type": "CommentLine", "type": "CommentLine",
"value": " x === (1 as number);", "value": " (x as boolean) <= y;",
"start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}} "start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}}
} }
] ]
}, },
{ {
"type": "ExpressionStatement", "type": "ExpressionStatement",
"start":92,"end":106,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":14}}, "start":92,"end":110,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":18}},
"expression": {
"type": "BinaryExpression",
"start":92,"end":109,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":17}},
"left": {
"type": "Identifier",
"start":92,"end":93,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":1},"identifierName":"x"},
"name": "x"
},
"operator": "===",
"right": {
"type": "TSAsExpression",
"start":98,"end":109,"loc":{"start":{"line":4,"column":6},"end":{"line":4,"column":17}},
"expression": {
"type": "NumericLiteral",
"start":98,"end":99,"loc":{"start":{"line":4,"column":6},"end":{"line":4,"column":7}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start":103,"end":109,"loc":{"start":{"line":4,"column":11},"end":{"line":4,"column":17}}
}
}
},
"leadingComments": [
{
"type": "CommentLine",
"value": " (x as boolean) <= y;",
"start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}}
}
],
"trailingComments": [
{
"type": "CommentLine",
"value": " x === (1 as number);",
"start":111,"end":134,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":42}}
}
]
},
{
"type": "ExpressionStatement",
"start":135,"end":149,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":14}},
"expression": { "expression": {
"type": "TSAsExpression", "type": "TSAsExpression",
"start":92,"end":105,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":13}}, "start":135,"end":148,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}},
"expression": { "expression": {
"type": "TSAsExpression", "type": "TSAsExpression",
"start":92,"end":100,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":8}}, "start":135,"end":143,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":8}},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start":92,"end":93,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":1},"identifierName":"x"}, "start":135,"end":136,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":1},"identifierName":"x"},
"name": "x" "name": "x"
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSAnyKeyword", "type": "TSAnyKeyword",
"start":97,"end":100,"loc":{"start":{"line":4,"column":5},"end":{"line":4,"column":8}} "start":140,"end":143,"loc":{"start":{"line":5,"column":5},"end":{"line":5,"column":8}}
} }
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSTypeReference", "type": "TSTypeReference",
"start":104,"end":105,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13}}, "start":147,"end":148,"loc":{"start":{"line":5,"column":12},"end":{"line":5,"column":13}},
"typeName": { "typeName": {
"type": "Identifier", "type": "Identifier",
"start":104,"end":105,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13},"identifierName":"T"}, "start":147,"end":148,"loc":{"start":{"line":5,"column":12},"end":{"line":5,"column":13},"identifierName":"T"},
"name": "T" "name": "T"
} }
} }
@ -141,7 +182,41 @@
{ {
"type": "CommentLine", "type": "CommentLine",
"value": " x === (1 as number);", "value": " x === (1 as number);",
"start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}} "start":111,"end":134,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":42}}
}
]
},
{
"type": "ExpressionStatement",
"start":150,"end":168,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":18}},
"expression": {
"type": "LogicalExpression",
"start":150,"end":167,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":17}},
"left": {
"type": "TSAsExpression",
"start":150,"end":162,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":12}},
"expression": {
"type": "Identifier",
"start":150,"end":151,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":1},"identifierName":"x"},
"name": "x"
},
"typeAnnotation": {
"type": "TSBooleanKeyword",
"start":155,"end":162,"loc":{"start":{"line":6,"column":5},"end":{"line":6,"column":12}}
}
},
"operator": "??",
"right": {
"type": "Identifier",
"start":166,"end":167,"loc":{"start":{"line":6,"column":16},"end":{"line":6,"column":17},"identifierName":"y"},
"name": "y"
}
},
"trailingComments": [
{
"type": "CommentLine",
"value": " (x as boolean) ?? y;",
"start":169,"end":192,"loc":{"start":{"line":6,"column":19},"end":{"line":6,"column":42}}
} }
] ]
} }
@ -156,8 +231,18 @@
}, },
{ {
"type": "CommentLine", "type": "CommentLine",
"value": " x === (1 as number);", "value": " (x as boolean) <= y;",
"start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}} "start":68,"end":91,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":42}}
},
{
"type": "CommentLine",
"value": " x === (1 as number);",
"start":111,"end":134,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":42}}
},
{
"type": "CommentLine",
"value": " (x as boolean) ?? y;",
"start":169,"end":192,"loc":{"start":{"line":6,"column":19},"end":{"line":6,"column":42}}
} }
] ]
} }