From f4d3c1c6e0c0c73b09eee985a2ce802b6fe8773d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 26 Aug 2014 20:45:31 -0700 Subject: [PATCH 1/2] Deferred resolution of object literal members to support recursive types. --- src/compiler/checker.ts | 55 ++++++++++--------- .../reference/declFileTypeofFunction.js | 2 +- .../reference/declFileTypeofFunction.types | 4 +- .../recursiveFunctionTypes.errors.txt | 4 +- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b722f8593..d5fdf87841 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1799,27 +1799,37 @@ module ts { function resolveAnonymousTypeMembers(type: ObjectType) { var symbol = type.symbol; - var members = emptySymbols; - var callSignatures = emptyArray; - var constructSignatures = emptyArray; - if (symbol.flags & SymbolFlags.HasExports) { - members = symbol.exports; + if (symbol.flags & SymbolFlags.TypeLiteral) { + // Type literal + var members = symbol.members; + var callSignatures = getSignaturesOfSymbol(members["__call"]); + var constructSignatures = getSignaturesOfSymbol(members["__new"]); + var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); + var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); } - if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { - callSignatures = getSignaturesOfSymbol(symbol); - } - if (symbol.flags & SymbolFlags.Class) { - var classType = getDeclaredTypeOfClass(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); - if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType); - if (classType.baseTypes.length) { - var members = createSymbolTable(getNamedMembers(members)); - addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol))); + else { + // Combinations of function, class, enum and module + var members = emptySymbols; + var callSignatures = emptyArray; + var constructSignatures = emptyArray; + if (symbol.flags & SymbolFlags.HasExports) { + members = symbol.exports; } + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { + callSignatures = getSignaturesOfSymbol(symbol); + } + if (symbol.flags & SymbolFlags.Class) { + var classType = getDeclaredTypeOfClass(symbol); + constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); + if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType); + if (classType.baseTypes.length) { + var members = createSymbolTable(getNamedMembers(members)); + addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol))); + } + } + var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; } - var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; - - setObjectTypeMembers(type, members, callSignatures, constructSignatures, /* stringIndexType */ undefined, numberIndexType); + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); } function resolveObjectTypeMembers(type: ObjectType): ResolvedObjectType { @@ -2275,13 +2285,8 @@ module ts { function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type { var links = getNodeLinks(node); if (!links.resolvedType) { - var symbol = node.symbol; - var members = symbol.members; - var callSignatures = getSignaturesOfSymbol(members["__call"]); - var constructSignatures = getSignaturesOfSymbol(members["__new"]); - var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); - links.resolvedType = createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); + // Deferred resolution of members is handled by resolveObjectTypeMembers + links.resolvedType = createObjectType(TypeFlags.Anonymous, node.symbol); } return links.resolvedType; } diff --git a/tests/baselines/reference/declFileTypeofFunction.js b/tests/baselines/reference/declFileTypeofFunction.js index f488d418f6..67475c557d 100644 --- a/tests/baselines/reference/declFileTypeofFunction.js +++ b/tests/baselines/reference/declFileTypeofFunction.js @@ -68,7 +68,7 @@ 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 var b: () => any; declare function b1(): typeof b1; declare function foo(): typeof foo; declare var foo1: typeof foo; diff --git a/tests/baselines/reference/declFileTypeofFunction.types b/tests/baselines/reference/declFileTypeofFunction.types index a157f80074..6d134ac617 100644 --- a/tests/baselines/reference/declFileTypeofFunction.types +++ b/tests/baselines/reference/declFileTypeofFunction.types @@ -29,8 +29,8 @@ function g() { return undefined; } >undefined : undefined var b: () => typeof b; ->b : any ->b : any +>b : () => any +>b : () => any function b1() { >b1 : () => typeof b1 diff --git a/tests/baselines/reference/recursiveFunctionTypes.errors.txt b/tests/baselines/reference/recursiveFunctionTypes.errors.txt index 5068438a8c..c7d25d2986 100644 --- a/tests/baselines/reference/recursiveFunctionTypes.errors.txt +++ b/tests/baselines/reference/recursiveFunctionTypes.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/recursiveFunctionTypes.ts (12 errors) ==== +==== tests/cases/compiler/recursiveFunctionTypes.ts (13 errors) ==== function fn(): typeof fn { return 1; } ~ !!! Type 'number' is not assignable to type '() => typeof fn'. @@ -39,6 +39,8 @@ var f4: () => typeof f4; f4 = 3; // error + ~~ +!!! Type 'number' is not assignable to type '() => any'. function f5() { return f5; } From deaf8e4a78c5f92b19e62f9a32014cda7f8c8a5a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 27 Aug 2014 13:54:23 -0700 Subject: [PATCH 2/2] Addressing CR feedback. --- src/compiler/checker.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d5fdf87841..14511a3fff 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1800,7 +1800,6 @@ module ts { function resolveAnonymousTypeMembers(type: ObjectType) { var symbol = type.symbol; if (symbol.flags & SymbolFlags.TypeLiteral) { - // Type literal var members = symbol.members; var callSignatures = getSignaturesOfSymbol(members["__call"]); var constructSignatures = getSignaturesOfSymbol(members["__new"]); @@ -1810,8 +1809,8 @@ module ts { else { // Combinations of function, class, enum and module var members = emptySymbols; - var callSignatures = emptyArray; - var constructSignatures = emptyArray; + var callSignatures: Signature[] = emptyArray; + var constructSignatures: Signature[] = emptyArray; if (symbol.flags & SymbolFlags.HasExports) { members = symbol.exports; } @@ -1821,13 +1820,16 @@ module ts { if (symbol.flags & SymbolFlags.Class) { var classType = getDeclaredTypeOfClass(symbol); constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); - if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType); + if (!constructSignatures.length) { + constructSignatures = getDefaultConstructSignatures(classType); + } if (classType.baseTypes.length) { - var members = createSymbolTable(getNamedMembers(members)); + members = createSymbolTable(getNamedMembers(members)); addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol))); } } - var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; + var stringIndexType: Type = undefined; + var numberIndexType: Type = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; } setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); }