mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Use typeof function in the declaration emitter instead of unwinding first level
This commit is contained in:
parent
1347621d0c
commit
09ea12d95c
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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'.
|
||||
@ -5,3 +5,7 @@ var x = function somefn() { return somefn; };
|
||||
var x = function somefn() {
|
||||
return somefn;
|
||||
};
|
||||
|
||||
|
||||
//// [functionExpressionReturningItself.d.ts]
|
||||
declare var x: () => any;
|
||||
|
||||
@ -10,4 +10,4 @@ function somefn() {
|
||||
|
||||
|
||||
//// [functionReturningItself.d.ts]
|
||||
declare function somefn(): () => typeof somefn;
|
||||
declare function somefn(): typeof somefn;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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'.
|
||||
|
||||
@ -10,8 +10,3 @@ function foo() {
|
||||
}
|
||||
exports.x;
|
||||
exports.b = foo;
|
||||
|
||||
|
||||
//// [privacyCheckTypeOfFunction.d.ts]
|
||||
export declare var x: () => void;
|
||||
export declare var b: () => void;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user