Use typeof function in the declaration emitter instead of unwinding first level

This commit is contained in:
Sheetal Nandi 2014-08-08 16:15:09 -07:00
parent 1347621d0c
commit 09ea12d95c
22 changed files with 84 additions and 85 deletions

View File

@ -942,10 +942,13 @@ module ts {
writeTypeofSymbol(type);
}
// Use 'typeof T' for types of functions and methods that circularly reference themselves
// TODO(shkamat): correct the usuage of typeof function - always on functions that are visible
else if (type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && typeStack && contains(typeStack, type)) {
else if (shouldWriteTypeOfFunctionSymbol()) {
writeTypeofSymbol(type);
}
else if (typeStack && contains(typeStack, type)) {
// Recursive usage, use any
writer.write("any");
}
else {
if (!typeStack) {
typeStack = [];
@ -954,6 +957,23 @@ module ts {
writeLiteralType(type, allowFunctionOrConstructorTypeLiteral);
typeStack.pop();
}
function shouldWriteTypeOfFunctionSymbol() {
if (type.symbol) {
var isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method && // typeof static method
ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
var isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
(type.symbol.parent || // is exported function symbol
ts.forEach(type.symbol.declarations, declaration =>
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
// typeof is allowed only for static/non local functions
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
(typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
}
}
}
}
function writeTypeofSymbol(type: ObjectType) {

View File

@ -2160,7 +2160,7 @@ module ts {
if (node.constraint && (node.parent.kind !== SyntaxKind.Method || !(node.parent.flags & NodeFlags.Private))) {
write(" extends ");
getSymbolVisibilityDiagnosticMessage = getTypeParameterConstraintVisibilityError;
resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.None, writer);
resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
}
@ -2179,7 +2179,7 @@ module ts {
function emitTypeOfTypeReference(node: Node) {
getSymbolVisibilityDiagnosticMessage = getHeritageClauseVisibilityError;
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType, writer);
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType | TypeFormatFlags.UseTypeOfFunction, writer);
function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {
var diagnosticMessage: DiagnosticMessage;
@ -2304,7 +2304,7 @@ module ts {
if (!(node.flags & NodeFlags.Private)) {
write(": ");
getSymbolVisibilityDiagnosticMessage = getVariableDeclarationTypeVisibilityError;
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
}
@ -2362,7 +2362,7 @@ module ts {
if (!(node.flags & NodeFlags.Private)) {
write(": ");
getSymbolVisibilityDiagnosticMessage = getAccessorDeclarationTypeVisibilityError;
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
write(";");
writeLine();
@ -2459,7 +2459,7 @@ module ts {
if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
write(": ");
getSymbolVisibilityDiagnosticMessage = getReturnTypeVisibilityError;
resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.None, writer);
resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
write(";");
writeLine();
@ -2534,7 +2534,7 @@ module ts {
if (!(node.parent.flags & NodeFlags.Private)) {
write(": ");
getSymbolVisibilityDiagnosticMessage = getParameterDeclarationTypeVisibilityError;
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {

View File

@ -626,6 +626,8 @@ module ts {
/** writes Array<T> instead T[] */
WriteArrayAsGenericType = 0x00000001, // Declarations
UseTypeOfFunction = 0x00000002, // instead of writing signature type of function use typeof
}
export enum SymbolAccessibility {

View File

@ -487,11 +487,11 @@ declare var i1_ncf: (b: number) => number;
declare var i1_ncr: number;
declare var i1_ncprop: number;
declare var i1_s_p: number;
declare var i1_s_f: (b: number) => number;
declare var i1_s_f: typeof c1.s2;
declare var i1_s_r: number;
declare var i1_s_prop: number;
declare var i1_s_nc_p: number;
declare var i1_s_ncf: (b: number) => number;
declare var i1_s_ncf: typeof c1.nc_s2;
declare var i1_s_ncr: number;
declare var i1_s_ncprop: number;
declare var i1_c: typeof c1;

View File

@ -131,10 +131,10 @@ export declare module C {
}
}
export declare var a: C.A<C.B>;
export declare var b: <T>(x: T) => C.A<C.B>;
export declare var c: <T>(x: T) => C.A<C.B>;
export declare var d: <T>(x: T) => C.A<C.B>[];
export declare var e: <T extends C.A<C.B>>(x: T) => C.A<C.B>[];
export declare var b: typeof C.F;
export declare var c: typeof C.F2;
export declare var d: typeof C.F3;
export declare var e: typeof C.F4;
export declare var x: C.A<C.B>;
export declare function f<T extends C.A<C.B>>(): void;
export declare var g: C.A<C.B>;
@ -142,4 +142,4 @@ export declare class h extends C.A<C.B> {
}
export interface i extends C.A<C.B> {
}
export declare var j: <T extends C.A<C.B>>(x: T) => T;
export declare var j: typeof C.F6;

View File

@ -64,39 +64,15 @@ function foo5(x) {
//// [declFileTypeofFunction.d.ts]
declare function f(n: {
(n: typeof f): string;
(n: {
(n: typeof g): number;
(n: typeof f): number;
}): string;
}): string;
declare function f(n: {
(n: typeof g): number;
(n: {
(n: typeof f): string;
(n: typeof g): string;
}): number;
}): string;
declare function g(n: {
(n: typeof g): number;
(n: {
(n: typeof f): string;
(n: typeof g): string;
}): number;
}): number;
declare function g(n: {
(n: typeof f): string;
(n: {
(n: typeof g): number;
(n: typeof f): number;
}): string;
}): number;
declare function f(n: typeof f): string;
declare function f(n: typeof g): string;
declare function g(n: typeof g): number;
declare function g(n: typeof f): number;
declare var b: any;
declare function b1(): () => typeof b1;
declare function foo(): () => typeof foo;
declare var foo1: () => typeof foo;
declare var foo2: () => typeof foo;
declare function b1(): typeof b1;
declare function foo(): typeof foo;
declare var foo1: typeof foo;
declare var foo2: typeof foo;
declare var foo3: any;
declare var x: any;
declare function foo5(x: number): (x: number) => number;

View File

@ -28,7 +28,6 @@ export module M.P {
export interface I { }
}
export import im = M.P.f;
// Bug 887180: Invalid .d.ts when an aliased entity is referenced, and a different entity is closer in scope
export var a = M.a; // emitted incorrectly as typeof f
export var b = M.b; // ok
export var c = M.c; // ok
@ -170,10 +169,10 @@ export declare module M.P {
}
}
export import im = M.P.f;
var a: () => void;
var a: typeof M.f;
var b: typeof M.C;
var c: typeof M.N;
var g: () => void;
var g: typeof c.g;
var d: typeof M.d;
}
export declare module M.Q {

View File

@ -9,7 +9,6 @@ module X.Y.base {
}
module X.Y.base.Z {
// Bug 887180
export var f = X.Y.base.f; // Should be base.f
export var C = X.Y.base.C; // Should be base.C
export var M = X.Y.base.M; // Should be base.M
@ -72,7 +71,7 @@ declare module X.Y.base {
}
}
declare module X.Y.base.Z {
var f: () => void;
var f: typeof base.f;
var C: typeof base.C;
var M: typeof base.M;
var E: typeof base.E;

View File

@ -111,7 +111,7 @@ declare module M.P {
f = 0,
}
var v: M.D;
var w: () => void;
var x: () => void;
var x: () => void;
var w: typeof D.f;
var x: typeof C.f;
var x: typeof C.f;
}

View File

@ -134,29 +134,26 @@ var f2 = function () {
//// [funcdecl.d.ts]
declare function simpleFunc(): string;
declare var simpleFuncVar: () => string;
declare var simpleFuncVar: typeof simpleFunc;
declare function anotherFuncNoReturn(): void;
declare var anotherFuncNoReturnVar: () => void;
declare var anotherFuncNoReturnVar: typeof anotherFuncNoReturn;
declare function withReturn(): string;
declare var withReturnVar: () => string;
declare var withReturnVar: typeof withReturn;
declare function withParams(a: string): string;
declare var withparamsVar: (a: string) => string;
declare var withparamsVar: typeof withParams;
declare function withMultiParams(a: number, b: any, c: Object): number;
declare var withMultiParamsVar: (a: number, b: any, c: Object) => number;
declare var withMultiParamsVar: typeof withMultiParams;
declare function withOptionalParams(a?: string): void;
declare var withOptionalParamsVar: (a?: string) => void;
declare var withOptionalParamsVar: typeof withOptionalParams;
declare function withInitializedParams(a: string, b0: any, b?: number, c?: string): void;
declare var withInitializedParamsVar: (a: string, b0: any, b?: number, c?: string) => void;
declare var withInitializedParamsVar: typeof withInitializedParams;
declare function withOptionalInitializedParams(a: string, c?: string): void;
declare var withOptionalInitializedParamsVar: (a: string, c?: string) => void;
declare var withOptionalInitializedParamsVar: typeof withOptionalInitializedParams;
declare function withRestParams(a: string, ...myRestParameter: number[]): number[];
declare var withRestParamsVar: (a: string, ...myRestParameter: number[]) => number[];
declare var withRestParamsVar: typeof withRestParams;
declare function overload1(n: number): string;
declare function overload1(s: string): string;
declare var withOverloadSignature: {
(n: number): string;
(s: string): string;
};
declare var withOverloadSignature: typeof overload1;
declare function f(n: () => void): void;
declare module m2 {
function foo(n: () => void): void;

View File

@ -1,4 +0,0 @@
==== tests/cases/compiler/functionExpressionReturningItself.ts (1 errors) ====
var x = function somefn() { return somefn; };
~
!!! Exported variable 'x' has or is using private name 'somefn'.

View File

@ -5,3 +5,7 @@ var x = function somefn() { return somefn; };
var x = function somefn() {
return somefn;
};
//// [functionExpressionReturningItself.d.ts]
declare var x: () => any;

View File

@ -10,4 +10,4 @@ function somefn() {
//// [functionReturningItself.d.ts]
declare function somefn(): () => typeof somefn;
declare function somefn(): typeof somefn;

View File

@ -33,6 +33,7 @@ declare module a {
function foo(x: number): number;
}
declare module c {
import b = a.foo;
var bVal: number;
var bVal2: (x: number) => number;
var bVal2: typeof b;
}

View File

@ -35,5 +35,5 @@ export declare module a {
export declare module c {
export import b = a.foo;
var bVal: number;
var bVal2: (x: number) => number;
var bVal2: typeof b;
}

View File

@ -33,5 +33,6 @@ export declare module a {
function foo(x: number): number;
}
export declare module c {
var bVal2: (x: number) => number;
import b = a.foo;
var bVal2: typeof b;
}

View File

@ -31,4 +31,4 @@ export declare module a {
}
export import b = a.foo;
export declare var bVal: number;
export declare var bVal2: (x: number) => number;
export declare var bVal2: typeof b;

View File

@ -27,5 +27,6 @@ exports.bVal2 = b;
export declare module a {
function foo(x: number): number;
}
import b = a.foo;
export declare var bVal: number;
export declare var bVal2: (x: number) => number;
export declare var bVal2: typeof b;

View File

@ -0,0 +1,10 @@
==== tests/cases/compiler/privacyCheckTypeOfFunction.ts (2 errors) ====
function foo() {
}
export var x: typeof foo;
~
!!! Exported variable 'x' has or is using private name 'foo'.
export var b = foo;
~
!!! Exported variable 'b' has or is using private name 'foo'.

View File

@ -10,8 +10,3 @@ function foo() {
}
exports.x;
exports.b = foo;
//// [privacyCheckTypeOfFunction.d.ts]
export declare var x: () => void;
export declare var b: () => void;

View File

@ -28,7 +28,6 @@ export module M.P {
export interface I { }
}
export import im = M.P.f;
// Bug 887180: Invalid .d.ts when an aliased entity is referenced, and a different entity is closer in scope
export var a = M.a; // emitted incorrectly as typeof f
export var b = M.b; // ok
export var c = M.c; // ok

View File

@ -9,7 +9,6 @@ module X.Y.base {
}
module X.Y.base.Z {
// Bug 887180
export var f = X.Y.base.f; // Should be base.f
export var C = X.Y.base.C; // Should be base.C
export var M = X.Y.base.M; // Should be base.M