Parse generic function types in import type argument lists (#31079)

* Parenthesize in import type node factory

* And now parse unparenthesized generic functions so we can handle parsing the older output
This commit is contained in:
Wesley Wigham 2019-04-23 14:48:31 -07:00 committed by GitHub
parent 8fc6640f55
commit d7f03fb0fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 206 additions and 2 deletions

View File

@ -845,7 +845,7 @@ namespace ts {
const node = <ImportTypeNode>createSynthesizedNode(SyntaxKind.ImportType);
node.argument = argument;
node.qualifier = qualifier;
node.typeArguments = asNodeArray(typeArguments);
node.typeArguments = parenthesizeTypeParameters(typeArguments);
node.isTypeOf = isTypeOf;
return node;
}

View File

@ -2922,7 +2922,9 @@ namespace ts {
if (parseOptional(SyntaxKind.DotToken)) {
node.qualifier = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
}
node.typeArguments = tryParseTypeArguments();
if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
}
return finishNode(node);
}

View File

@ -0,0 +1,41 @@
//// [tests/cases/compiler/importTypeGenericArrowTypeParenthesized.ts] ////
//// [module.d.ts]
declare module "module" {
export interface Modifier<T> { }
export function fn<T>(x: T): Modifier<T>;
}
//// [index.ts]
import { fn } from "module";
export const fail1 = fn(<T>(x: T): T => x);
export const fail2 = fn(function<T>(x: T): T {
return x;
});
export const works1 = fn((x: number) => x);
type MakeItWork = <T>(x: T) => T;
export const works2 = fn<MakeItWork>(x => x);
//// [index.js]
"use strict";
exports.__esModule = true;
var module_1 = require("module");
exports.fail1 = module_1.fn(function (x) { return x; });
exports.fail2 = module_1.fn(function (x) {
return x;
});
exports.works1 = module_1.fn(function (x) { return x; });
exports.works2 = module_1.fn(function (x) { return x; });
//// [index.d.ts]
/// <reference path="module.d.ts" />
export declare const fail1: import("module").Modifier<(<T>(x: T) => T)>;
export declare const fail2: import("module").Modifier<(<T>(x: T) => T)>;
export declare const works1: import("module").Modifier<(x: number) => number>;
declare type MakeItWork = <T>(x: T) => T;
export declare const works2: import("module").Modifier<MakeItWork>;
export {};

View File

@ -0,0 +1,62 @@
=== tests/cases/compiler/module.d.ts ===
declare module "module" {
>"module" : Symbol("module", Decl(module.d.ts, 0, 0))
export interface Modifier<T> { }
>Modifier : Symbol(Modifier, Decl(module.d.ts, 0, 25))
>T : Symbol(T, Decl(module.d.ts, 1, 30))
export function fn<T>(x: T): Modifier<T>;
>fn : Symbol(fn, Decl(module.d.ts, 1, 36))
>T : Symbol(T, Decl(module.d.ts, 3, 23))
>x : Symbol(x, Decl(module.d.ts, 3, 26))
>T : Symbol(T, Decl(module.d.ts, 3, 23))
>Modifier : Symbol(Modifier, Decl(module.d.ts, 0, 25))
>T : Symbol(T, Decl(module.d.ts, 3, 23))
}
=== tests/cases/compiler/index.ts ===
import { fn } from "module";
>fn : Symbol(fn, Decl(index.ts, 0, 8))
export const fail1 = fn(<T>(x: T): T => x);
>fail1 : Symbol(fail1, Decl(index.ts, 2, 12))
>fn : Symbol(fn, Decl(index.ts, 0, 8))
>T : Symbol(T, Decl(index.ts, 2, 25))
>x : Symbol(x, Decl(index.ts, 2, 28))
>T : Symbol(T, Decl(index.ts, 2, 25))
>T : Symbol(T, Decl(index.ts, 2, 25))
>x : Symbol(x, Decl(index.ts, 2, 28))
export const fail2 = fn(function<T>(x: T): T {
>fail2 : Symbol(fail2, Decl(index.ts, 3, 12))
>fn : Symbol(fn, Decl(index.ts, 0, 8))
>T : Symbol(T, Decl(index.ts, 3, 33))
>x : Symbol(x, Decl(index.ts, 3, 36))
>T : Symbol(T, Decl(index.ts, 3, 33))
>T : Symbol(T, Decl(index.ts, 3, 33))
return x;
>x : Symbol(x, Decl(index.ts, 3, 36))
});
export const works1 = fn((x: number) => x);
>works1 : Symbol(works1, Decl(index.ts, 7, 12))
>fn : Symbol(fn, Decl(index.ts, 0, 8))
>x : Symbol(x, Decl(index.ts, 7, 26))
>x : Symbol(x, Decl(index.ts, 7, 26))
type MakeItWork = <T>(x: T) => T;
>MakeItWork : Symbol(MakeItWork, Decl(index.ts, 7, 43))
>T : Symbol(T, Decl(index.ts, 8, 19))
>x : Symbol(x, Decl(index.ts, 8, 22))
>T : Symbol(T, Decl(index.ts, 8, 19))
>T : Symbol(T, Decl(index.ts, 8, 19))
export const works2 = fn<MakeItWork>(x => x);
>works2 : Symbol(works2, Decl(index.ts, 9, 12))
>fn : Symbol(fn, Decl(index.ts, 0, 8))
>MakeItWork : Symbol(MakeItWork, Decl(index.ts, 7, 43))
>x : Symbol(x, Decl(index.ts, 9, 37))
>x : Symbol(x, Decl(index.ts, 9, 37))

View File

@ -0,0 +1,54 @@
=== tests/cases/compiler/module.d.ts ===
declare module "module" {
>"module" : typeof import("module")
export interface Modifier<T> { }
export function fn<T>(x: T): Modifier<T>;
>fn : <T>(x: T) => Modifier<T>
>x : T
}
=== tests/cases/compiler/index.ts ===
import { fn } from "module";
>fn : <T>(x: T) => import("module").Modifier<T>
export const fail1 = fn(<T>(x: T): T => x);
>fail1 : import("module").Modifier<(<T>(x: T) => T)>
>fn(<T>(x: T): T => x) : import("module").Modifier<(<T>(x: T) => T)>
>fn : <T>(x: T) => import("module").Modifier<T>
><T>(x: T): T => x : <T>(x: T) => T
>x : T
>x : T
export const fail2 = fn(function<T>(x: T): T {
>fail2 : import("module").Modifier<(<T>(x: T) => T)>
>fn(function<T>(x: T): T { return x;}) : import("module").Modifier<(<T>(x: T) => T)>
>fn : <T>(x: T) => import("module").Modifier<T>
>function<T>(x: T): T { return x;} : <T>(x: T) => T
>x : T
return x;
>x : T
});
export const works1 = fn((x: number) => x);
>works1 : import("module").Modifier<(x: number) => number>
>fn((x: number) => x) : import("module").Modifier<(x: number) => number>
>fn : <T>(x: T) => import("module").Modifier<T>
>(x: number) => x : (x: number) => number
>x : number
>x : number
type MakeItWork = <T>(x: T) => T;
>MakeItWork : MakeItWork
>x : T
export const works2 = fn<MakeItWork>(x => x);
>works2 : import("module").Modifier<MakeItWork>
>fn<MakeItWork>(x => x) : import("module").Modifier<MakeItWork>
>fn : <T>(x: T) => import("module").Modifier<T>
>x => x : <T>(x: T) => T
>x : T
>x : T

View File

@ -0,0 +1,7 @@
tests/cases/compiler/importTypeWithUnparenthesizedGenericFunctionParsed.ts(1,36): error TS2307: Cannot find module 'module'.
==== tests/cases/compiler/importTypeWithUnparenthesizedGenericFunctionParsed.ts (1 errors) ====
export declare const fail1: import("module").Modifier<<T>(x: T) => T>; // shouldn't be a parse error
~~~~~~~~
!!! error TS2307: Cannot find module 'module'.

View File

@ -0,0 +1,6 @@
//// [importTypeWithUnparenthesizedGenericFunctionParsed.ts]
export declare const fail1: import("module").Modifier<<T>(x: T) => T>; // shouldn't be a parse error
//// [importTypeWithUnparenthesizedGenericFunctionParsed.js]
"use strict";
exports.__esModule = true;

View File

@ -0,0 +1,8 @@
=== tests/cases/compiler/importTypeWithUnparenthesizedGenericFunctionParsed.ts ===
export declare const fail1: import("module").Modifier<<T>(x: T) => T>; // shouldn't be a parse error
>fail1 : Symbol(fail1, Decl(importTypeWithUnparenthesizedGenericFunctionParsed.ts, 0, 20))
>T : Symbol(T, Decl(importTypeWithUnparenthesizedGenericFunctionParsed.ts, 0, 55))
>x : Symbol(x, Decl(importTypeWithUnparenthesizedGenericFunctionParsed.ts, 0, 58))
>T : Symbol(T, Decl(importTypeWithUnparenthesizedGenericFunctionParsed.ts, 0, 55))
>T : Symbol(T, Decl(importTypeWithUnparenthesizedGenericFunctionParsed.ts, 0, 55))

View File

@ -0,0 +1,5 @@
=== tests/cases/compiler/importTypeWithUnparenthesizedGenericFunctionParsed.ts ===
export declare const fail1: import("module").Modifier<<T>(x: T) => T>; // shouldn't be a parse error
>fail1 : any
>x : T

View File

@ -0,0 +1,18 @@
// @declaration: true
// @filename: module.d.ts
declare module "module" {
export interface Modifier<T> { }
export function fn<T>(x: T): Modifier<T>;
}
// @filename: index.ts
import { fn } from "module";
export const fail1 = fn(<T>(x: T): T => x);
export const fail2 = fn(function<T>(x: T): T {
return x;
});
export const works1 = fn((x: number) => x);
type MakeItWork = <T>(x: T) => T;
export const works2 = fn<MakeItWork>(x => x);

View File

@ -0,0 +1 @@
export declare const fail1: import("module").Modifier<<T>(x: T) => T>; // shouldn't be a parse error