Skip to content

Commit e336701

Browse files
committed
Merge pull request #3763 from tinganho/typePredicateDeclEmit
Fixes emit of type predicate in declaration files
2 parents a3aa6e8 + 4e644e5 commit e336701

13 files changed

+435
-273
lines changed

src/compiler/checker.ts

Lines changed: 176 additions & 164 deletions
Large diffs are not rendered by default.

src/compiler/declarationEmitter.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ namespace ts {
188188
if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
189189
moduleElementEmitInfo = forEach(asynchronousSubModuleDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
190190
}
191-
191+
192192
// If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
193193
// then we don't need to write it at this point. We will write it when we actually see its declaration
194194
// Eg.
@@ -198,7 +198,7 @@ namespace ts {
198198
// we would write alias foo declaration when we visit it since it would now be marked as visible
199199
if (moduleElementEmitInfo) {
200200
if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) {
201-
// we have to create asynchronous output only after we have collected complete information
201+
// we have to create asynchronous output only after we have collected complete information
202202
// because it is possible to enable multiple bindings as asynchronously visible
203203
moduleElementEmitInfo.isVisible = true;
204204
}
@@ -353,6 +353,21 @@ namespace ts {
353353
return emitEntityName(<Identifier>type);
354354
case SyntaxKind.QualifiedName:
355355
return emitEntityName(<QualifiedName>type);
356+
case SyntaxKind.TypePredicate:
357+
return emitTypePredicate(<TypePredicateNode>type);
358+
}
359+
360+
function writeEntityName(entityName: EntityName | Expression) {
361+
if (entityName.kind === SyntaxKind.Identifier) {
362+
writeTextOfNode(currentSourceFile, entityName);
363+
}
364+
else {
365+
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
366+
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
367+
writeEntityName(left);
368+
write(".");
369+
writeTextOfNode(currentSourceFile, right);
370+
}
356371
}
357372

358373
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
@@ -362,19 +377,6 @@ namespace ts {
362377

363378
handleSymbolAccessibilityError(visibilityResult);
364379
writeEntityName(entityName);
365-
366-
function writeEntityName(entityName: EntityName | Expression) {
367-
if (entityName.kind === SyntaxKind.Identifier) {
368-
writeTextOfNode(currentSourceFile, entityName);
369-
}
370-
else {
371-
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
372-
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
373-
writeEntityName(left);
374-
write(".");
375-
writeTextOfNode(currentSourceFile, right);
376-
}
377-
}
378380
}
379381

380382
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
@@ -398,6 +400,12 @@ namespace ts {
398400
}
399401
}
400402

403+
function emitTypePredicate(type: TypePredicateNode) {
404+
writeTextOfNode(currentSourceFile, type.parameterName);
405+
write(" is ");
406+
emitType(type.type);
407+
}
408+
401409
function emitTypeQuery(type: TypeQueryNode) {
402410
write("typeof ");
403411
emitEntityName(type.exprName);
@@ -600,7 +608,7 @@ namespace ts {
600608
}
601609

602610
function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) {
603-
// note usage of writer. methods instead of aliases created, just to make sure we are using
611+
// note usage of writer. methods instead of aliases created, just to make sure we are using
604612
// correct writer especially to handle asynchronous alias writing
605613
emitJsDocComments(node);
606614
if (node.flags & NodeFlags.Export) {
@@ -642,7 +650,7 @@ namespace ts {
642650

643651
function writeImportDeclaration(node: ImportDeclaration) {
644652
if (!node.importClause && !(node.flags & NodeFlags.Export)) {
645-
// do not write non-exported import declarations that don't have import clauses
653+
// do not write non-exported import declarations that don't have import clauses
646654
return;
647655
}
648656
emitJsDocComments(node);
@@ -1517,7 +1525,7 @@ namespace ts {
15171525
}
15181526
}
15191527
}
1520-
}
1528+
}
15211529
}
15221530

15231531
function emitNode(node: Node) {
@@ -1577,7 +1585,7 @@ namespace ts {
15771585
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
15781586
}
15791587
}
1580-
1588+
15811589
/* @internal */
15821590
export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) {
15831591
let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);

tests/baselines/reference/declFileFunctions.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ export function fooWithSingleOverload(a: any) {
2626
return a;
2727
}
2828

29+
export function fooWithTypePredicate(a: any): a is number {
30+
return true;
31+
}
32+
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
33+
return true;
34+
}
35+
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
36+
return true;
37+
}
38+
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
39+
return true;
40+
}
41+
2942
/** This comment should appear for nonExportedFoo*/
3043
function nonExportedFoo() {
3144
}
@@ -92,6 +105,26 @@ function fooWithSingleOverload(a) {
92105
return a;
93106
}
94107
exports.fooWithSingleOverload = fooWithSingleOverload;
108+
function fooWithTypePredicate(a) {
109+
return true;
110+
}
111+
exports.fooWithTypePredicate = fooWithTypePredicate;
112+
function fooWithTypePredicateAndMulitpleParams(a, b, c) {
113+
return true;
114+
}
115+
exports.fooWithTypePredicateAndMulitpleParams = fooWithTypePredicateAndMulitpleParams;
116+
function fooWithTypeTypePredicateAndGeneric(a) {
117+
return true;
118+
}
119+
exports.fooWithTypeTypePredicateAndGeneric = fooWithTypeTypePredicateAndGeneric;
120+
function fooWithTypeTypePredicateAndRestParam(a) {
121+
var rest = [];
122+
for (var _i = 1; _i < arguments.length; _i++) {
123+
rest[_i - 1] = arguments[_i];
124+
}
125+
return true;
126+
}
127+
exports.fooWithTypeTypePredicateAndRestParam = fooWithTypeTypePredicateAndRestParam;
95128
/** This comment should appear for nonExportedFoo*/
96129
function nonExportedFoo() {
97130
}
@@ -144,6 +177,10 @@ export declare function fooWithRestParameters(a: string, ...rests: string[]): st
144177
export declare function fooWithOverloads(a: string): string;
145178
export declare function fooWithOverloads(a: number): number;
146179
export declare function fooWithSingleOverload(a: string): string;
180+
export declare function fooWithTypePredicate(a: any): a is number;
181+
export declare function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number;
182+
export declare function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T;
183+
export declare function fooWithTypeTypePredicateAndRestParam(a: any, ...rest: any[]): a is number;
147184
//// [declFileFunctions_1.d.ts]
148185
/** This comment should appear for foo*/
149186
declare function globalfoo(): void;

tests/baselines/reference/declFileFunctions.symbols

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,49 +57,83 @@ export function fooWithSingleOverload(a: any) {
5757
>a : Symbol(a, Decl(declFileFunctions_0.ts, 21, 38))
5858
}
5959

60+
export function fooWithTypePredicate(a: any): a is number {
61+
>fooWithTypePredicate : Symbol(fooWithTypePredicate, Decl(declFileFunctions_0.ts, 23, 1))
62+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37))
63+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37))
64+
65+
return true;
66+
}
67+
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
68+
>fooWithTypePredicateAndMulitpleParams : Symbol(fooWithTypePredicateAndMulitpleParams, Decl(declFileFunctions_0.ts, 27, 1))
69+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54))
70+
>b : Symbol(b, Decl(declFileFunctions_0.ts, 28, 61))
71+
>c : Symbol(c, Decl(declFileFunctions_0.ts, 28, 69))
72+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54))
73+
74+
return true;
75+
}
76+
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
77+
>fooWithTypeTypePredicateAndGeneric : Symbol(fooWithTypeTypePredicateAndGeneric, Decl(declFileFunctions_0.ts, 30, 1))
78+
>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51))
79+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54))
80+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54))
81+
>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51))
82+
83+
return true;
84+
}
85+
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
86+
>fooWithTypeTypePredicateAndRestParam : Symbol(fooWithTypeTypePredicateAndRestParam, Decl(declFileFunctions_0.ts, 33, 1))
87+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53))
88+
>rest : Symbol(rest, Decl(declFileFunctions_0.ts, 34, 60))
89+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53))
90+
91+
return true;
92+
}
93+
6094
/** This comment should appear for nonExportedFoo*/
6195
function nonExportedFoo() {
62-
>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 23, 1))
96+
>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 36, 1))
6397
}
6498
/** This is comment for function signature*/
6599
function nonExportedFooWithParameters(/** this is comment about a*/a: string,
66-
>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 27, 1))
67-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38))
100+
>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 40, 1))
101+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38))
68102

69103
/** this is comment for b*/
70104
b: number) {
71-
>b : Symbol(b, Decl(declFileFunctions_0.ts, 29, 77))
105+
>b : Symbol(b, Decl(declFileFunctions_0.ts, 42, 77))
72106

73107
var d = a;
74-
>d : Symbol(d, Decl(declFileFunctions_0.ts, 32, 7))
75-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38))
108+
>d : Symbol(d, Decl(declFileFunctions_0.ts, 45, 7))
109+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38))
76110
}
77111
function nonExportedFooWithRestParameters(a: string, ...rests: string[]) {
78-
>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 33, 1))
79-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42))
80-
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52))
112+
>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 46, 1))
113+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42))
114+
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52))
81115

82116
return a + rests.join("");
83-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42))
117+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42))
84118
>rests.join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31))
85-
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52))
119+
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52))
86120
>join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31))
87121
}
88122

89123
function nonExportedFooWithOverloads(a: string): string;
90-
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
91-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 37))
124+
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
125+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 51, 37))
92126

93127
function nonExportedFooWithOverloads(a: number): number;
94-
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
95-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 39, 37))
128+
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
129+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 52, 37))
96130

97131
function nonExportedFooWithOverloads(a: any): any {
98-
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
99-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37))
132+
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
133+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37))
100134

101135
return a;
102-
>a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37))
136+
>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37))
103137
}
104138

105139
=== tests/cases/compiler/declFileFunctions_1.ts ===

tests/baselines/reference/declFileFunctions.types

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,44 @@ export function fooWithSingleOverload(a: any) {
6060
>a : any
6161
}
6262

63+
export function fooWithTypePredicate(a: any): a is number {
64+
>fooWithTypePredicate : (a: any) => a is number
65+
>a : any
66+
>a : any
67+
68+
return true;
69+
>true : boolean
70+
}
71+
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
72+
>fooWithTypePredicateAndMulitpleParams : (a: any, b: any, c: any) => a is number
73+
>a : any
74+
>b : any
75+
>c : any
76+
>a : any
77+
78+
return true;
79+
>true : boolean
80+
}
81+
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
82+
>fooWithTypeTypePredicateAndGeneric : <T>(a: any) => a is T
83+
>T : T
84+
>a : any
85+
>a : any
86+
>T : T
87+
88+
return true;
89+
>true : boolean
90+
}
91+
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
92+
>fooWithTypeTypePredicateAndRestParam : (a: any, ...rest: any[]) => a is number
93+
>a : any
94+
>rest : any[]
95+
>a : any
96+
97+
return true;
98+
>true : boolean
99+
}
100+
63101
/** This comment should appear for nonExportedFoo*/
64102
function nonExportedFoo() {
65103
>nonExportedFoo : () => void

tests/baselines/reference/isArray.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ var maybeArray: number | number[];
55

66
if (Array.isArray(maybeArray)) {
77
>Array.isArray(maybeArray) : boolean
8-
>Array.isArray : (arg: any) => boolean
8+
>Array.isArray : (arg: any) => arg is any[]
99
>Array : ArrayConstructor
10-
>isArray : (arg: any) => boolean
10+
>isArray : (arg: any) => arg is any[]
1111
>maybeArray : number | number[]
1212

1313
maybeArray.length; // OK

0 commit comments

Comments
 (0)