diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d5e5b5c67e4..9b54f771f21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2516,10 +2516,11 @@ module ts { } } - function getDeclaredTypeOfClass(symbol: Symbol): InterfaceType { + function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType { let links = getSymbolLinks(symbol); if (!links.declaredType) { - let type = links.declaredType = createObjectType(TypeFlags.Class, symbol); + let kind = symbol.flags & SymbolFlags.Class ? TypeFlags.Class : TypeFlags.Interface; + let type = links.declaredType = createObjectType(kind, symbol); let typeParameters = getTypeParametersOfClassOrInterface(symbol); if (typeParameters) { type.flags |= TypeFlags.Reference; @@ -2529,35 +2530,6 @@ module ts { (type).target = type; (type).typeArguments = type.typeParameters; } - - type.declaredProperties = getNamedMembers(symbol.members); - type.declaredCallSignatures = emptyArray; - type.declaredConstructSignatures = emptyArray; - type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); - } - return links.declaredType; - } - - function getDeclaredTypeOfInterface(symbol: Symbol): InterfaceType { - let links = getSymbolLinks(symbol); - if (!links.declaredType) { - let type = links.declaredType = createObjectType(TypeFlags.Interface, symbol); - let typeParameters = getTypeParametersOfClassOrInterface(symbol); - if (typeParameters) { - type.flags |= TypeFlags.Reference; - type.typeParameters = typeParameters; - (type).instantiations = {}; - (type).instantiations[getTypeListId(type.typeParameters)] = type; - (type).target = type; - (type).typeArguments = type.typeParameters; - } - - type.declaredProperties = getNamedMembers(symbol.members); - type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]); - type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]); - type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); } return links.declaredType; } @@ -2613,11 +2585,8 @@ module ts { function getDeclaredTypeOfSymbol(symbol: Symbol): Type { Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0); - if (symbol.flags & SymbolFlags.Class) { - return getDeclaredTypeOfClass(symbol); - } - if (symbol.flags & SymbolFlags.Interface) { - return getDeclaredTypeOfInterface(symbol); + if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { + return getDeclaredTypeOfClassOrInterface(symbol); } if (symbol.flags & SymbolFlags.TypeAlias) { return getDeclaredTypeOfTypeAlias(symbol); @@ -2666,15 +2635,28 @@ module ts { } } + function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers { + if (!(type).declaredProperties) { + var symbol = type.symbol; + (type).declaredProperties = getNamedMembers(symbol.members); + (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]); + (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]); + (type).declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); + (type).declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + } + return type; + } + function resolveClassOrInterfaceMembers(type: InterfaceType): void { - let members = type.symbol.members; - let callSignatures = type.declaredCallSignatures; - let constructSignatures = type.declaredConstructSignatures; - let stringIndexType = type.declaredStringIndexType; - let numberIndexType = type.declaredNumberIndexType; - let baseTypes = getBaseTypes(type); + let target = resolveDeclaredMembers(type); + let members = target.symbol.members; + let callSignatures = target.declaredCallSignatures; + let constructSignatures = target.declaredConstructSignatures; + let stringIndexType = target.declaredStringIndexType; + let numberIndexType = target.declaredNumberIndexType; + let baseTypes = getBaseTypes(target); if (baseTypes.length) { - members = createSymbolTable(type.declaredProperties); + members = createSymbolTable(target.declaredProperties); for (let baseType of baseTypes) { addInheritedMembers(members, getPropertiesOfObjectType(baseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(baseType, SignatureKind.Call)); @@ -2687,7 +2669,7 @@ module ts { } function resolveTypeReferenceMembers(type: TypeReference): void { - let target = type.target; + let target = resolveDeclaredMembers(type.target); let mapper = createTypeMapper(target.typeParameters, type.typeArguments); let members = createInstantiatedSymbolTable(target.declaredProperties, mapper); let callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature); @@ -2843,7 +2825,7 @@ module ts { callSignatures = getSignaturesOfSymbol(symbol); } if (symbol.flags & SymbolFlags.Class) { - let classType = getDeclaredTypeOfClass(symbol); + let classType = getDeclaredTypeOfClassOrInterface(symbol); constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); @@ -3084,7 +3066,7 @@ module ts { function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature { let links = getNodeLinks(declaration); if (!links.resolvedSignature) { - let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClass((declaration.parent).symbol) : undefined; + let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface((declaration.parent).symbol) : undefined; let typeParameters = classType ? classType.typeParameters : declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined; let parameters: Symbol[] = []; @@ -10152,7 +10134,7 @@ module ts { } let seen: Map<{ prop: Symbol; containingType: Type }> = {}; - forEach(type.declaredProperties, p => { seen[p.name] = { prop: p, containingType: type }; }); + forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen[p.name] = { prop: p, containingType: type }; }); let ok = true; for (let base of baseTypes) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bff15a1ab9d..353f63e4287 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1485,6 +1485,13 @@ module ts { // Class and interface types (TypeFlags.Class and TypeFlags.Interface) export interface InterfaceType extends ObjectType { typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) + } + + export interface InterfaceTypeWithBaseTypes extends InterfaceType { + baseTypes: ObjectType[]; + } + + export interface InterfaceTypeWithDeclaredMembers extends InterfaceType { declaredProperties: Symbol[]; // Declared members declaredCallSignatures: Signature[]; // Declared call signatures declaredConstructSignatures: Signature[]; // Declared construct signatures @@ -1492,10 +1499,6 @@ module ts { declaredNumberIndexType: Type; // Declared numeric index type } - export interface InterfaceTypeWithBaseTypes extends InterfaceType { - baseTypes: ObjectType[]; - } - // Type references (TypeFlags.Reference) export interface TypeReference extends ObjectType { target: GenericType; // Type reference target diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithClass.js b/tests/baselines/reference/circularTypeAliasForUnionWithClass.js new file mode 100644 index 00000000000..90a11364897 --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithClass.js @@ -0,0 +1,39 @@ +//// [circularTypeAliasForUnionWithClass.ts] +var v0: T0; +type T0 = string | I0; +class I0 { + x: T0; +} + +var v3: T3; +type T3 = string | I3; +class I3 { + [x: number]: T3; +} + +var v4: T4; +type T4 = string | I4; +class I4 { + [x: string]: T4; +} + + +//// [circularTypeAliasForUnionWithClass.js] +var v0; +var I0 = (function () { + function I0() { + } + return I0; +})(); +var v3; +var I3 = (function () { + function I3() { + } + return I3; +})(); +var v4; +var I4 = (function () { + function I4() { + } + return I4; +})(); diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithClass.symbols b/tests/baselines/reference/circularTypeAliasForUnionWithClass.symbols new file mode 100644 index 00000000000..ecfba63332d --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithClass.symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithClass.ts === +var v0: T0; +>v0 : Symbol(v0, Decl(circularTypeAliasForUnionWithClass.ts, 0, 3)) +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithClass.ts, 0, 11)) + +type T0 = string | I0; +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithClass.ts, 0, 11)) +>I0 : Symbol(I0, Decl(circularTypeAliasForUnionWithClass.ts, 1, 22)) + +class I0 { +>I0 : Symbol(I0, Decl(circularTypeAliasForUnionWithClass.ts, 1, 22)) + + x: T0; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithClass.ts, 2, 10)) +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithClass.ts, 0, 11)) +} + +var v3: T3; +>v3 : Symbol(v3, Decl(circularTypeAliasForUnionWithClass.ts, 6, 3)) +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithClass.ts, 6, 11)) + +type T3 = string | I3; +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithClass.ts, 6, 11)) +>I3 : Symbol(I3, Decl(circularTypeAliasForUnionWithClass.ts, 7, 22)) + +class I3 { +>I3 : Symbol(I3, Decl(circularTypeAliasForUnionWithClass.ts, 7, 22)) + + [x: number]: T3; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithClass.ts, 9, 5)) +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithClass.ts, 6, 11)) +} + +var v4: T4; +>v4 : Symbol(v4, Decl(circularTypeAliasForUnionWithClass.ts, 12, 3)) +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithClass.ts, 12, 11)) + +type T4 = string | I4; +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithClass.ts, 12, 11)) +>I4 : Symbol(I4, Decl(circularTypeAliasForUnionWithClass.ts, 13, 22)) + +class I4 { +>I4 : Symbol(I4, Decl(circularTypeAliasForUnionWithClass.ts, 13, 22)) + + [x: string]: T4; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithClass.ts, 15, 5)) +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithClass.ts, 12, 11)) +} + diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithClass.types b/tests/baselines/reference/circularTypeAliasForUnionWithClass.types new file mode 100644 index 00000000000..99a05f3d66a --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithClass.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithClass.ts === +var v0: T0; +>v0 : string | I0 +>T0 : string | I0 + +type T0 = string | I0; +>T0 : string | I0 +>I0 : I0 + +class I0 { +>I0 : I0 + + x: T0; +>x : string | I0 +>T0 : string | I0 +} + +var v3: T3; +>v3 : string | I3 +>T3 : string | I3 + +type T3 = string | I3; +>T3 : string | I3 +>I3 : I3 + +class I3 { +>I3 : I3 + + [x: number]: T3; +>x : number +>T3 : string | I3 +} + +var v4: T4; +>v4 : string | I4 +>T4 : string | I4 + +type T4 = string | I4; +>T4 : string | I4 +>I4 : I4 + +class I4 { +>I4 : I4 + + [x: string]: T4; +>x : string +>T4 : string | I4 +} + diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithInterface.js b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.js new file mode 100644 index 00000000000..60f4df9a8b6 --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.js @@ -0,0 +1,38 @@ +//// [circularTypeAliasForUnionWithInterface.ts] +var v0: T0; +type T0 = string | I0; +interface I0 { + x: T0; +} + +var v1: T1; +type T1 = string | I1; +interface I1 { + (): T1; +} + +var v2: T2; +type T2 = string | I2; +interface I2 { + new (): T2; +} + +var v3: T3; +type T3 = string | I3; +interface I3 { + [x: number]: T3; +} + +var v4: T4; +type T4 = string | I4; +interface I4 { + [x: string]: T4; +} + + +//// [circularTypeAliasForUnionWithInterface.js] +var v0; +var v1; +var v2; +var v3; +var v4; diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithInterface.symbols b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.symbols new file mode 100644 index 00000000000..29bc3098d91 --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.symbols @@ -0,0 +1,79 @@ +=== tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts === +var v0: T0; +>v0 : Symbol(v0, Decl(circularTypeAliasForUnionWithInterface.ts, 0, 3)) +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithInterface.ts, 0, 11)) + +type T0 = string | I0; +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithInterface.ts, 0, 11)) +>I0 : Symbol(I0, Decl(circularTypeAliasForUnionWithInterface.ts, 1, 22)) + +interface I0 { +>I0 : Symbol(I0, Decl(circularTypeAliasForUnionWithInterface.ts, 1, 22)) + + x: T0; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithInterface.ts, 2, 14)) +>T0 : Symbol(T0, Decl(circularTypeAliasForUnionWithInterface.ts, 0, 11)) +} + +var v1: T1; +>v1 : Symbol(v1, Decl(circularTypeAliasForUnionWithInterface.ts, 6, 3)) +>T1 : Symbol(T1, Decl(circularTypeAliasForUnionWithInterface.ts, 6, 11)) + +type T1 = string | I1; +>T1 : Symbol(T1, Decl(circularTypeAliasForUnionWithInterface.ts, 6, 11)) +>I1 : Symbol(I1, Decl(circularTypeAliasForUnionWithInterface.ts, 7, 22)) + +interface I1 { +>I1 : Symbol(I1, Decl(circularTypeAliasForUnionWithInterface.ts, 7, 22)) + + (): T1; +>T1 : Symbol(T1, Decl(circularTypeAliasForUnionWithInterface.ts, 6, 11)) +} + +var v2: T2; +>v2 : Symbol(v2, Decl(circularTypeAliasForUnionWithInterface.ts, 12, 3)) +>T2 : Symbol(T2, Decl(circularTypeAliasForUnionWithInterface.ts, 12, 11)) + +type T2 = string | I2; +>T2 : Symbol(T2, Decl(circularTypeAliasForUnionWithInterface.ts, 12, 11)) +>I2 : Symbol(I2, Decl(circularTypeAliasForUnionWithInterface.ts, 13, 22)) + +interface I2 { +>I2 : Symbol(I2, Decl(circularTypeAliasForUnionWithInterface.ts, 13, 22)) + + new (): T2; +>T2 : Symbol(T2, Decl(circularTypeAliasForUnionWithInterface.ts, 12, 11)) +} + +var v3: T3; +>v3 : Symbol(v3, Decl(circularTypeAliasForUnionWithInterface.ts, 18, 3)) +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithInterface.ts, 18, 11)) + +type T3 = string | I3; +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithInterface.ts, 18, 11)) +>I3 : Symbol(I3, Decl(circularTypeAliasForUnionWithInterface.ts, 19, 22)) + +interface I3 { +>I3 : Symbol(I3, Decl(circularTypeAliasForUnionWithInterface.ts, 19, 22)) + + [x: number]: T3; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithInterface.ts, 21, 5)) +>T3 : Symbol(T3, Decl(circularTypeAliasForUnionWithInterface.ts, 18, 11)) +} + +var v4: T4; +>v4 : Symbol(v4, Decl(circularTypeAliasForUnionWithInterface.ts, 24, 3)) +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithInterface.ts, 24, 11)) + +type T4 = string | I4; +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithInterface.ts, 24, 11)) +>I4 : Symbol(I4, Decl(circularTypeAliasForUnionWithInterface.ts, 25, 22)) + +interface I4 { +>I4 : Symbol(I4, Decl(circularTypeAliasForUnionWithInterface.ts, 25, 22)) + + [x: string]: T4; +>x : Symbol(x, Decl(circularTypeAliasForUnionWithInterface.ts, 27, 5)) +>T4 : Symbol(T4, Decl(circularTypeAliasForUnionWithInterface.ts, 24, 11)) +} + diff --git a/tests/baselines/reference/circularTypeAliasForUnionWithInterface.types b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.types new file mode 100644 index 00000000000..4325f9c774a --- /dev/null +++ b/tests/baselines/reference/circularTypeAliasForUnionWithInterface.types @@ -0,0 +1,79 @@ +=== tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts === +var v0: T0; +>v0 : string | I0 +>T0 : string | I0 + +type T0 = string | I0; +>T0 : string | I0 +>I0 : I0 + +interface I0 { +>I0 : I0 + + x: T0; +>x : string | I0 +>T0 : string | I0 +} + +var v1: T1; +>v1 : string | I1 +>T1 : string | I1 + +type T1 = string | I1; +>T1 : string | I1 +>I1 : I1 + +interface I1 { +>I1 : I1 + + (): T1; +>T1 : string | I1 +} + +var v2: T2; +>v2 : string | I2 +>T2 : string | I2 + +type T2 = string | I2; +>T2 : string | I2 +>I2 : I2 + +interface I2 { +>I2 : I2 + + new (): T2; +>T2 : string | I2 +} + +var v3: T3; +>v3 : string | I3 +>T3 : string | I3 + +type T3 = string | I3; +>T3 : string | I3 +>I3 : I3 + +interface I3 { +>I3 : I3 + + [x: number]: T3; +>x : number +>T3 : string | I3 +} + +var v4: T4; +>v4 : string | I4 +>T4 : string | I4 + +type T4 = string | I4; +>T4 : string | I4 +>I4 : I4 + +interface I4 { +>I4 : I4 + + [x: string]: T4; +>x : string +>T4 : string | I4 +} + diff --git a/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithClass.ts b/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithClass.ts new file mode 100644 index 00000000000..e7cca719f4b --- /dev/null +++ b/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithClass.ts @@ -0,0 +1,17 @@ +var v0: T0; +type T0 = string | I0; +class I0 { + x: T0; +} + +var v3: T3; +type T3 = string | I3; +class I3 { + [x: number]: T3; +} + +var v4: T4; +type T4 = string | I4; +class I4 { + [x: string]: T4; +} diff --git a/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts b/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts new file mode 100644 index 00000000000..c3eab454384 --- /dev/null +++ b/tests/cases/conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts @@ -0,0 +1,29 @@ +var v0: T0; +type T0 = string | I0; +interface I0 { + x: T0; +} + +var v1: T1; +type T1 = string | I1; +interface I1 { + (): T1; +} + +var v2: T2; +type T2 = string | I2; +interface I2 { + new (): T2; +} + +var v3: T3; +type T3 = string | I3; +interface I3 { + [x: number]: T3; +} + +var v4: T4; +type T4 = string | I4; +interface I4 { + [x: string]: T4; +}