Skip to content

Commit 09ea12d

Browse files
committed
Use typeof function in the declaration emitter instead of unwinding first level
1 parent 1347621 commit 09ea12d

22 files changed

+84
-85
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -942,10 +942,13 @@ module ts {
942942
writeTypeofSymbol(type);
943943
}
944944
// Use 'typeof T' for types of functions and methods that circularly reference themselves
945-
// TODO(shkamat): correct the usuage of typeof function - always on functions that are visible
946-
else if (type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && typeStack && contains(typeStack, type)) {
945+
else if (shouldWriteTypeOfFunctionSymbol()) {
947946
writeTypeofSymbol(type);
948947
}
948+
else if (typeStack && contains(typeStack, type)) {
949+
// Recursive usage, use any
950+
writer.write("any");
951+
}
949952
else {
950953
if (!typeStack) {
951954
typeStack = [];
@@ -954,6 +957,23 @@ module ts {
954957
writeLiteralType(type, allowFunctionOrConstructorTypeLiteral);
955958
typeStack.pop();
956959
}
960+
961+
function shouldWriteTypeOfFunctionSymbol() {
962+
if (type.symbol) {
963+
var isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method && // typeof static method
964+
ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
965+
var isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
966+
(type.symbol.parent || // is exported function symbol
967+
ts.forEach(type.symbol.declarations, declaration =>
968+
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
969+
970+
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
971+
// typeof is allowed only for static/non local functions
972+
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
973+
(typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
974+
}
975+
}
976+
}
957977
}
958978

959979
function writeTypeofSymbol(type: ObjectType) {

src/compiler/emitter.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,7 +2160,7 @@ module ts {
21602160
if (node.constraint && (node.parent.kind !== SyntaxKind.Method || !(node.parent.flags & NodeFlags.Private))) {
21612161
write(" extends ");
21622162
getSymbolVisibilityDiagnosticMessage = getTypeParameterConstraintVisibilityError;
2163-
resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.None, writer);
2163+
resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
21642164
}
21652165
}
21662166

@@ -2179,7 +2179,7 @@ module ts {
21792179

21802180
function emitTypeOfTypeReference(node: Node) {
21812181
getSymbolVisibilityDiagnosticMessage = getHeritageClauseVisibilityError;
2182-
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType, writer);
2182+
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType | TypeFormatFlags.UseTypeOfFunction, writer);
21832183

21842184
function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {
21852185
var diagnosticMessage: DiagnosticMessage;
@@ -2304,7 +2304,7 @@ module ts {
23042304
if (!(node.flags & NodeFlags.Private)) {
23052305
write(": ");
23062306
getSymbolVisibilityDiagnosticMessage = getVariableDeclarationTypeVisibilityError;
2307-
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
2307+
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
23082308
}
23092309
}
23102310

@@ -2362,7 +2362,7 @@ module ts {
23622362
if (!(node.flags & NodeFlags.Private)) {
23632363
write(": ");
23642364
getSymbolVisibilityDiagnosticMessage = getAccessorDeclarationTypeVisibilityError;
2365-
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
2365+
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
23662366
}
23672367
write(";");
23682368
writeLine();
@@ -2459,7 +2459,7 @@ module ts {
24592459
if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
24602460
write(": ");
24612461
getSymbolVisibilityDiagnosticMessage = getReturnTypeVisibilityError;
2462-
resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.None, writer);
2462+
resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
24632463
}
24642464
write(";");
24652465
writeLine();
@@ -2534,7 +2534,7 @@ module ts {
25342534
if (!(node.parent.flags & NodeFlags.Private)) {
25352535
write(": ");
25362536
getSymbolVisibilityDiagnosticMessage = getParameterDeclarationTypeVisibilityError;
2537-
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
2537+
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
25382538
}
25392539

25402540
function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,8 @@ module ts {
626626

627627
/** writes Array<T> instead T[] */
628628
WriteArrayAsGenericType = 0x00000001, // Declarations
629+
630+
UseTypeOfFunction = 0x00000002, // instead of writing signature type of function use typeof
629631
}
630632

631633
export enum SymbolAccessibility {

tests/baselines/reference/commentsClassMembers.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,11 @@ declare var i1_ncf: (b: number) => number;
487487
declare var i1_ncr: number;
488488
declare var i1_ncprop: number;
489489
declare var i1_s_p: number;
490-
declare var i1_s_f: (b: number) => number;
490+
declare var i1_s_f: typeof c1.s2;
491491
declare var i1_s_r: number;
492492
declare var i1_s_prop: number;
493493
declare var i1_s_nc_p: number;
494-
declare var i1_s_ncf: (b: number) => number;
494+
declare var i1_s_ncf: typeof c1.nc_s2;
495495
declare var i1_s_ncr: number;
496496
declare var i1_s_ncprop: number;
497497
declare var i1_c: typeof c1;

tests/baselines/reference/declFileGenericType.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ export declare module C {
131131
}
132132
}
133133
export declare var a: C.A<C.B>;
134-
export declare var b: <T>(x: T) => C.A<C.B>;
135-
export declare var c: <T>(x: T) => C.A<C.B>;
136-
export declare var d: <T>(x: T) => C.A<C.B>[];
137-
export declare var e: <T extends C.A<C.B>>(x: T) => C.A<C.B>[];
134+
export declare var b: typeof C.F;
135+
export declare var c: typeof C.F2;
136+
export declare var d: typeof C.F3;
137+
export declare var e: typeof C.F4;
138138
export declare var x: C.A<C.B>;
139139
export declare function f<T extends C.A<C.B>>(): void;
140140
export declare var g: C.A<C.B>;
141141
export declare class h extends C.A<C.B> {
142142
}
143143
export interface i extends C.A<C.B> {
144144
}
145-
export declare var j: <T extends C.A<C.B>>(x: T) => T;
145+
export declare var j: typeof C.F6;

tests/baselines/reference/declFileTypeofFunction.js

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -64,39 +64,15 @@ function foo5(x) {
6464

6565

6666
//// [declFileTypeofFunction.d.ts]
67-
declare function f(n: {
68-
(n: typeof f): string;
69-
(n: {
70-
(n: typeof g): number;
71-
(n: typeof f): number;
72-
}): string;
73-
}): string;
74-
declare function f(n: {
75-
(n: typeof g): number;
76-
(n: {
77-
(n: typeof f): string;
78-
(n: typeof g): string;
79-
}): number;
80-
}): string;
81-
declare function g(n: {
82-
(n: typeof g): number;
83-
(n: {
84-
(n: typeof f): string;
85-
(n: typeof g): string;
86-
}): number;
87-
}): number;
88-
declare function g(n: {
89-
(n: typeof f): string;
90-
(n: {
91-
(n: typeof g): number;
92-
(n: typeof f): number;
93-
}): string;
94-
}): number;
67+
declare function f(n: typeof f): string;
68+
declare function f(n: typeof g): string;
69+
declare function g(n: typeof g): number;
70+
declare function g(n: typeof f): number;
9571
declare var b: any;
96-
declare function b1(): () => typeof b1;
97-
declare function foo(): () => typeof foo;
98-
declare var foo1: () => typeof foo;
99-
declare var foo2: () => typeof foo;
72+
declare function b1(): typeof b1;
73+
declare function foo(): typeof foo;
74+
declare var foo1: typeof foo;
75+
declare var foo2: typeof foo;
10076
declare var foo3: any;
10177
declare var x: any;
10278
declare function foo5(x: number): (x: number) => number;

tests/baselines/reference/declarationEmit_nameConflicts.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export module M.P {
2828
export interface I { }
2929
}
3030
export import im = M.P.f;
31-
// Bug 887180: Invalid .d.ts when an aliased entity is referenced, and a different entity is closer in scope
3231
export var a = M.a; // emitted incorrectly as typeof f
3332
export var b = M.b; // ok
3433
export var c = M.c; // ok
@@ -170,10 +169,10 @@ export declare module M.P {
170169
}
171170
}
172171
export import im = M.P.f;
173-
var a: () => void;
172+
var a: typeof M.f;
174173
var b: typeof M.C;
175174
var c: typeof M.N;
176-
var g: () => void;
175+
var g: typeof c.g;
177176
var d: typeof M.d;
178177
}
179178
export declare module M.Q {

tests/baselines/reference/declarationEmit_nameConflicts2.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ module X.Y.base {
99
}
1010

1111
module X.Y.base.Z {
12-
// Bug 887180
1312
export var f = X.Y.base.f; // Should be base.f
1413
export var C = X.Y.base.C; // Should be base.C
1514
export var M = X.Y.base.M; // Should be base.M
@@ -72,7 +71,7 @@ declare module X.Y.base {
7271
}
7372
}
7473
declare module X.Y.base.Z {
75-
var f: () => void;
74+
var f: typeof base.f;
7675
var C: typeof base.C;
7776
var M: typeof base.M;
7877
var E: typeof base.E;

tests/baselines/reference/declarationEmit_nameConflicts3.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ declare module M.P {
111111
f = 0,
112112
}
113113
var v: M.D;
114-
var w: () => void;
115-
var x: () => void;
116-
var x: () => void;
114+
var w: typeof D.f;
115+
var x: typeof C.f;
116+
var x: typeof C.f;
117117
}

tests/baselines/reference/funcdecl.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,29 +134,26 @@ var f2 = function () {
134134

135135
//// [funcdecl.d.ts]
136136
declare function simpleFunc(): string;
137-
declare var simpleFuncVar: () => string;
137+
declare var simpleFuncVar: typeof simpleFunc;
138138
declare function anotherFuncNoReturn(): void;
139-
declare var anotherFuncNoReturnVar: () => void;
139+
declare var anotherFuncNoReturnVar: typeof anotherFuncNoReturn;
140140
declare function withReturn(): string;
141-
declare var withReturnVar: () => string;
141+
declare var withReturnVar: typeof withReturn;
142142
declare function withParams(a: string): string;
143-
declare var withparamsVar: (a: string) => string;
143+
declare var withparamsVar: typeof withParams;
144144
declare function withMultiParams(a: number, b: any, c: Object): number;
145-
declare var withMultiParamsVar: (a: number, b: any, c: Object) => number;
145+
declare var withMultiParamsVar: typeof withMultiParams;
146146
declare function withOptionalParams(a?: string): void;
147-
declare var withOptionalParamsVar: (a?: string) => void;
147+
declare var withOptionalParamsVar: typeof withOptionalParams;
148148
declare function withInitializedParams(a: string, b0: any, b?: number, c?: string): void;
149-
declare var withInitializedParamsVar: (a: string, b0: any, b?: number, c?: string) => void;
149+
declare var withInitializedParamsVar: typeof withInitializedParams;
150150
declare function withOptionalInitializedParams(a: string, c?: string): void;
151-
declare var withOptionalInitializedParamsVar: (a: string, c?: string) => void;
151+
declare var withOptionalInitializedParamsVar: typeof withOptionalInitializedParams;
152152
declare function withRestParams(a: string, ...myRestParameter: number[]): number[];
153-
declare var withRestParamsVar: (a: string, ...myRestParameter: number[]) => number[];
153+
declare var withRestParamsVar: typeof withRestParams;
154154
declare function overload1(n: number): string;
155155
declare function overload1(s: string): string;
156-
declare var withOverloadSignature: {
157-
(n: number): string;
158-
(s: string): string;
159-
};
156+
declare var withOverloadSignature: typeof overload1;
160157
declare function f(n: () => void): void;
161158
declare module m2 {
162159
function foo(n: () => void): void;

0 commit comments

Comments
 (0)