fix parsing of leading union/intersection operator (#31265)

* fix parsing of leading union/intersection operator

Fixes: #30995

* test declaration emit
This commit is contained in:
Klaus Meinhardt 2019-05-08 23:09:11 +02:00 committed by Ron Buckton
parent a2c1fea20b
commit 0c9db717ad
8 changed files with 102 additions and 5 deletions

View File

@ -3124,15 +3124,16 @@ namespace ts {
}
function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode {
parseOptional(operator);
const start = scanner.getStartPos();
const hasLeadingOperator = parseOptional(operator);
let type = parseConstituentType();
if (token() === operator) {
if (token() === operator || hasLeadingOperator) {
const types = [type];
while (parseOptional(operator)) {
types.push(parseConstituentType());
}
const node = <UnionOrIntersectionTypeNode>createNode(kind, type.pos);
node.types = createNodeArray(types, type.pos);
const node = <UnionOrIntersectionTypeNode>createNode(kind, start);
node.types = createNodeArray(types, start);
type = finishNode(node);
}
return type;

View File

@ -37,6 +37,8 @@ namespace ts {
parsesCorrectly("callSignatureInRecordType", "{{(): number}}");
parsesCorrectly("methodInRecordType", "{{foo(): number}}");
parsesCorrectly("unionType", "{(number|string)}");
parsesCorrectly("unionTypeWithLeadingOperator", "{( | number | string )}");
parsesCorrectly("unionTypeWithOneElementAndLeadingOperator", "{( | number )}");
parsesCorrectly("topLevelNoParenUnionType", "{number|string}");
parsesCorrectly("functionType1", "{function()}");
parsesCorrectly("functionType2", "{function(string, boolean)}");

View File

@ -0,0 +1,37 @@
{
"kind": "ParenthesizedType",
"pos": 1,
"end": 22,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"type": {
"kind": "UnionType",
"pos": 2,
"end": 20,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"types": {
"0": {
"kind": "NumberKeyword",
"pos": 4,
"end": 11,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0
},
"1": {
"kind": "StringKeyword",
"pos": 13,
"end": 20,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0
},
"length": 2,
"pos": 2,
"end": 20
}
}
}

View File

@ -0,0 +1,29 @@
{
"kind": "ParenthesizedType",
"pos": 1,
"end": 13,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"type": {
"kind": "UnionType",
"pos": 2,
"end": 11,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0,
"types": {
"0": {
"kind": "NumberKeyword",
"pos": 4,
"end": 11,
"flags": "JSDoc",
"modifierFlagsCache": 0,
"transformFlags": 0
},
"length": 1,
"pos": 2,
"end": 11
}
}
}

View File

@ -5,6 +5,16 @@ type B =
| { type: "DECREMENT" };
type C = [| 0 | 1, | "foo" | "bar"];
export type D =
/*leading0*/
| /*leading1*/ 1 /*trailing1*/
| /*leading2*/ 2 /*trailing2*/;
//// [unionTypeWithLeadingOperator.js]
"use strict";
exports.__esModule = true;
//// [unionTypeWithLeadingOperator.d.ts]
export declare type D = /*leading1*/ 1 | /*leading2*/ 2;

View File

@ -14,3 +14,9 @@ type B =
type C = [| 0 | 1, | "foo" | "bar"];
>C : Symbol(C, Decl(unionTypeWithLeadingOperator.ts, 3, 26))
export type D =
>D : Symbol(D, Decl(unionTypeWithLeadingOperator.ts, 5, 36))
/*leading0*/
| /*leading1*/ 1 /*trailing1*/
| /*leading2*/ 2 /*trailing2*/;

View File

@ -14,3 +14,9 @@ type B =
type C = [| 0 | 1, | "foo" | "bar"];
>C : [0 | 1, "foo" | "bar"]
export type D =
>D : D
/*leading0*/
| /*leading1*/ 1 /*trailing1*/
| /*leading2*/ 2 /*trailing2*/;

View File

@ -1,6 +1,12 @@
// @declaration: true
type A = | string;
type B =
| { type: "INCREMENT" }
| { type: "DECREMENT" };
type C = [| 0 | 1, | "foo" | "bar"];
export type D =
/*leading0*/
| /*leading1*/ 1 /*trailing1*/
| /*leading2*/ 2 /*trailing2*/;