From c8dc2bdef02a50d1bfcfef61683ca1dafeab36be Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 12:43:45 -0800 Subject: [PATCH 01/10] Completion entry details of union of methods with no call signature Fixes #928 --- src/services/services.ts | 14 ++++++++++++-- .../fourslash/completionEntryForUnionMethod.ts | 8 ++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/completionEntryForUnionMethod.ts diff --git a/src/services/services.ts b/src/services/services.ts index d208eb87e96..9522d3cb3d4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2764,7 +2764,8 @@ module ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.UnionProperty) { - return forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => { + // If any of the property includes the declaration of property - the kind is property + var unionPropetyKind = forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => { var rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & SymbolFlags.Property) { return ScriptElementKind.memberVariableElement; @@ -2772,7 +2773,16 @@ module ts { if (rootSymbolFlags & SymbolFlags.GetAccessor) return ScriptElementKind.memberVariableElement; if (rootSymbolFlags & SymbolFlags.SetAccessor) return ScriptElementKind.memberVariableElement; Debug.assert((rootSymbolFlags & SymbolFlags.Method) !== undefined); - }) || ScriptElementKind.memberFunctionElement; + }); + if (!unionPropetyKind) { + // If this was union of all methods, make sure it has call signatures before we call it method + var typeOfUnionProperty = typeInfoResolver.getTypeOfSymbol(symbol); + if (typeOfUnionProperty.getCallSignatures().length) { + return ScriptElementKind.memberFunctionElement; + } + return ScriptElementKind.memberVariableElement; + } + return unionPropetyKind; } return ScriptElementKind.memberVariableElement; } diff --git a/tests/cases/fourslash/completionEntryForUnionMethod.ts b/tests/cases/fourslash/completionEntryForUnionMethod.ts new file mode 100644 index 00000000000..6eb68342d1f --- /dev/null +++ b/tests/cases/fourslash/completionEntryForUnionMethod.ts @@ -0,0 +1,8 @@ +/// + +////var y: Array|Array; +////y.map/**/( + +goTo.marker(); +verify.quickInfoIs("(property) map: ((callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | ((callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[])"); +verify.completionListContains('map', "(property) map: ((callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | ((callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[])"); \ No newline at end of file From c5b4051f3ae186fdcc723923a4846a86f5ccba8f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Nov 2014 13:33:43 -0800 Subject: [PATCH 02/10] Test cases for contextual typing of union type members --- .../contextualTypeWithUnionTypeMembers.js | 207 +++++++++ .../contextualTypeWithUnionTypeMembers.types | 438 ++++++++++++++++++ ...lTypeWithUnionTypeObjectLiteral.errors.txt | 130 ++++++ ...ontextualTypeWithUnionTypeObjectLiteral.js | 115 +++++ .../contextualTypeWithUnionTypeMembers.ts | 119 +++++ ...ontextualTypeWithUnionTypeObjectLiteral.ts | 59 +++ 6 files changed, 1068 insertions(+) create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeMembers.js create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeMembers.types create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.js create mode 100644 tests/cases/conformance/types/union/contextualTypeWithUnionTypeMembers.ts create mode 100644 tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeMembers.js b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.js new file mode 100644 index 00000000000..b04c804ad7e --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.js @@ -0,0 +1,207 @@ +//// [contextualTypeWithUnionTypeMembers.ts] +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface I1 { + commonMethodType(a: string): string; + commonPropertyType: string; + commonMethodWithTypeParameter(a: T): T; + + methodOnlyInI1(a: string): string; + propertyOnlyInI1: string; +} +interface I2 { + commonMethodType(a: string): string; + commonPropertyType: string; + commonMethodWithTypeParameter(a: T): T; + + methodOnlyInI2(a: string): string; + propertyOnlyInI2: string; +} + +// Let S be the set of types in U that has a property P. +// If S is not empty, U has a property P of a union type of the types of P from each type in S. +var i1: I1; +var i2: I2; +var i1Ori2: I1 | I2 = i1; +var i1Ori2: I1 | I2 = i2; +var i1Ori2: I1 | I2 = { // Like i1 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", +}; +var i1Ori2: I1 | I2 = { // Like i2 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", +}; +var i1Ori2: I1 | I2 = { // Like i1 and i2 both + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", +}; + +var arrayI1OrI2: Array | I2> = [i1, i2, { // Like i1 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + }, + { // Like i2 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", + }, { // Like i1 and i2 both + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", + }]; + +interface I11 { + commonMethodDifferentReturnType(a: string, b: number): string; + commonPropertyDifferentType: string; +} +interface I21 { + commonMethodDifferentReturnType(a: string, b: number): number; + commonPropertyDifferentType: number; +} +var i11: I11; +var i21: I21; +var i11Ori21: I11 | I21 = i11; +var i11Ori21: I11 | I21 = i21; +var i11Ori21: I11 | I21 = { + // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello", +}; +var i11Ori21: I11 | I21 = { + // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10, +}; +var arrayOrI11OrI21: Array = [i11, i21, i11 || i21, { + // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello", + }, { + // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10, + }]; + +//// [contextualTypeWithUnionTypeMembers.js] +// Let S be the set of types in U that has a property P. +// If S is not empty, U has a property P of a union type of the types of P from each type in S. +var i1; +var i2; +var i1Ori2 = i1; +var i1Ori2 = i2; +var i1Ori2 = { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI1: function (a) { return a; }, + propertyOnlyInI1: "Hello" +}; +var i1Ori2 = { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI2: function (a) { return a; }, + propertyOnlyInI2: "Hello" +}; +var i1Ori2 = { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI1: function (a) { return a; }, + propertyOnlyInI1: "Hello", + methodOnlyInI2: function (a) { return a; }, + propertyOnlyInI2: "Hello" +}; +var arrayI1OrI2 = [i1, i2, { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI1: function (a) { return a; }, + propertyOnlyInI1: "Hello" +}, { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI2: function (a) { return a; }, + propertyOnlyInI2: "Hello" +}, { + commonPropertyType: "hello", + commonMethodType: function (a) { return a; }, + commonMethodWithTypeParameter: function (a) { return a; }, + methodOnlyInI1: function (a) { return a; }, + propertyOnlyInI1: "Hello", + methodOnlyInI2: function (a) { return a; }, + propertyOnlyInI2: "Hello" +}]; +var i11; +var i21; +var i11Ori21 = i11; +var i11Ori21 = i21; +var i11Ori21 = { + // Like i1 + commonMethodDifferentReturnType: function (a, b) { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello" +}; +var i11Ori21 = { + // Like i2 + commonMethodDifferentReturnType: function (a, b) { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10 +}; +var arrayOrI11OrI21 = [i11, i21, i11 || i21, { + // Like i1 + commonMethodDifferentReturnType: function (a, b) { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello" +}, { + // Like i2 + commonMethodDifferentReturnType: function (a, b) { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10 +}]; diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types new file mode 100644 index 00000000000..93e01910870 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types @@ -0,0 +1,438 @@ +=== tests/cases/conformance/types/union/contextualTypeWithUnionTypeMembers.ts === +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface I1 { +>I1 : I1 +>T : T + + commonMethodType(a: string): string; +>commonMethodType : (a: string) => string +>a : string + + commonPropertyType: string; +>commonPropertyType : string + + commonMethodWithTypeParameter(a: T): T; +>commonMethodWithTypeParameter : (a: T) => T +>a : T +>T : T +>T : T + + methodOnlyInI1(a: string): string; +>methodOnlyInI1 : (a: string) => string +>a : string + + propertyOnlyInI1: string; +>propertyOnlyInI1 : string +} +interface I2 { +>I2 : I2 +>T : T + + commonMethodType(a: string): string; +>commonMethodType : (a: string) => string +>a : string + + commonPropertyType: string; +>commonPropertyType : string + + commonMethodWithTypeParameter(a: T): T; +>commonMethodWithTypeParameter : (a: T) => T +>a : T +>T : T +>T : T + + methodOnlyInI2(a: string): string; +>methodOnlyInI2 : (a: string) => string +>a : string + + propertyOnlyInI2: string; +>propertyOnlyInI2 : string +} + +// Let S be the set of types in U that has a property P. +// If S is not empty, U has a property P of a union type of the types of P from each type in S. +var i1: I1; +>i1 : I1 +>I1 : I1 + +var i2: I2; +>i2 : I2 +>I2 : I2 + +var i1Ori2: I1 | I2 = i1; +>i1Ori2 : I1 | I2 +>I1 : I1 +>I2 : I2 +>i1 : I1 + +var i1Ori2: I1 | I2 = i2; +>i1Ori2 : I1 | I2 +>I1 : I1 +>I2 : I2 +>i2 : I2 + +var i1Ori2: I1 | I2 = { // Like i1 +>i1Ori2 : I1 | I2 +>I1 : I1 +>I2 : I2 +>{ // Like i1 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello",} : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI1: (a: string) => string; propertyOnlyInI1: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI1: a => a, +>methodOnlyInI1 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI1: "Hello", +>propertyOnlyInI1 : string + +}; +var i1Ori2: I1 | I2 = { // Like i2 +>i1Ori2 : I1 | I2 +>I1 : I1 +>I2 : I2 +>{ // Like i2 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI2: a => a, propertyOnlyInI2: "Hello",} : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI2: (a: string) => string; propertyOnlyInI2: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI2: a => a, +>methodOnlyInI2 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI2: "Hello", +>propertyOnlyInI2 : string + +}; +var i1Ori2: I1 | I2 = { // Like i1 and i2 both +>i1Ori2 : I1 | I2 +>I1 : I1 +>I2 : I2 +>{ // Like i1 and i2 both commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello", methodOnlyInI2: a => a, propertyOnlyInI2: "Hello",} : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI1: (a: string) => string; propertyOnlyInI1: string; methodOnlyInI2: (a: string) => string; propertyOnlyInI2: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI1: a => a, +>methodOnlyInI1 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI1: "Hello", +>propertyOnlyInI1 : string + + methodOnlyInI2: a => a, +>methodOnlyInI2 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI2: "Hello", +>propertyOnlyInI2 : string + +}; + +var arrayI1OrI2: Array | I2> = [i1, i2, { // Like i1 +>arrayI1OrI2 : (I1 | I2)[] +>Array : T[] +>I1 : I1 +>I2 : I2 +>[i1, i2, { // Like i1 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello", }, { // Like i2 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI2: a => a, propertyOnlyInI2: "Hello", }, { // Like i1 and i2 both commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello", methodOnlyInI2: a => a, propertyOnlyInI2: "Hello", }] : (I1 | I2)[] +>i1 : I1 +>i2 : I2 +>{ // Like i1 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello", } : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI1: (a: string) => string; propertyOnlyInI1: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI1: a => a, +>methodOnlyInI1 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI1: "Hello", +>propertyOnlyInI1 : string + + }, + { // Like i2 +>{ // Like i2 commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI2: a => a, propertyOnlyInI2: "Hello", } : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI2: (a: string) => string; propertyOnlyInI2: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI2: a => a, +>methodOnlyInI2 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI2: "Hello", +>propertyOnlyInI2 : string + + }, { // Like i1 and i2 both +>{ // Like i1 and i2 both commonPropertyType: "hello", commonMethodType: a=> a, commonMethodWithTypeParameter: a => a, methodOnlyInI1: a => a, propertyOnlyInI1: "Hello", methodOnlyInI2: a => a, propertyOnlyInI2: "Hello", } : { commonPropertyType: string; commonMethodType: (a: string) => string; commonMethodWithTypeParameter: (a: number) => number; methodOnlyInI1: (a: string) => string; propertyOnlyInI1: string; methodOnlyInI2: (a: string) => string; propertyOnlyInI2: string; } + + commonPropertyType: "hello", +>commonPropertyType : string + + commonMethodType: a=> a, +>commonMethodType : (a: string) => string +>a=> a : (a: string) => string +>a : string +>a : string + + commonMethodWithTypeParameter: a => a, +>commonMethodWithTypeParameter : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + methodOnlyInI1: a => a, +>methodOnlyInI1 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI1: "Hello", +>propertyOnlyInI1 : string + + methodOnlyInI2: a => a, +>methodOnlyInI2 : (a: string) => string +>a => a : (a: string) => string +>a : string +>a : string + + propertyOnlyInI2: "Hello", +>propertyOnlyInI2 : string + + }]; + +interface I11 { +>I11 : I11 + + commonMethodDifferentReturnType(a: string, b: number): string; +>commonMethodDifferentReturnType : (a: string, b: number) => string +>a : string +>b : number + + commonPropertyDifferentType: string; +>commonPropertyDifferentType : string +} +interface I21 { +>I21 : I21 + + commonMethodDifferentReturnType(a: string, b: number): number; +>commonMethodDifferentReturnType : (a: string, b: number) => number +>a : string +>b : number + + commonPropertyDifferentType: number; +>commonPropertyDifferentType : number +} +var i11: I11; +>i11 : I11 +>I11 : I11 + +var i21: I21; +>i21 : I21 +>I21 : I21 + +var i11Ori21: I11 | I21 = i11; +>i11Ori21 : I11 | I21 +>I11 : I11 +>I21 : I21 +>i11 : I11 + +var i11Ori21: I11 | I21 = i21; +>i11Ori21 : I11 | I21 +>I11 : I11 +>I21 : I21 +>i21 : I21 + +var i11Ori21: I11 | I21 = { +>i11Ori21 : I11 | I21 +>I11 : I11 +>I21 : I21 +>{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } + + // Like i1 + commonMethodDifferentReturnType: (a, b) => { +>commonMethodDifferentReturnType : (a: any, b: any) => any +>(a, b) => { var z = a.charAt(b); return z; } : (a: any, b: any) => any +>a : any +>b : any + + var z = a.charAt(b); +>z : any +>a.charAt(b) : any +>a.charAt : any +>a : any +>charAt : any +>b : any + + return z; +>z : any + + }, + commonPropertyDifferentType: "hello", +>commonPropertyDifferentType : string + +}; +var i11Ori21: I11 | I21 = { +>i11Ori21 : I11 | I21 +>I11 : I11 +>I21 : I21 +>{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10,} : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; } + + // Like i2 + commonMethodDifferentReturnType: (a, b) => { +>commonMethodDifferentReturnType : (a: any, b: any) => any +>(a, b) => { var z = a.charCodeAt(b); return z; } : (a: any, b: any) => any +>a : any +>b : any + + var z = a.charCodeAt(b); +>z : any +>a.charCodeAt(b) : any +>a.charCodeAt : any +>a : any +>charCodeAt : any +>b : any + + return z; +>z : any + + }, + commonPropertyDifferentType: 10, +>commonPropertyDifferentType : number + +}; +var arrayOrI11OrI21: Array = [i11, i21, i11 || i21, { +>arrayOrI11OrI21 : (I11 | I21)[] +>Array : T[] +>I11 : I11 +>I21 : I21 +>[i11, i21, i11 || i21, { // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", }, { // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, }] : ({ commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } | { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; })[] +>i11 : I11 +>i21 : I21 +>i11 || i21 : I11 | I21 +>i11 : I11 +>i21 : I21 +>{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } + + // Like i1 + commonMethodDifferentReturnType: (a, b) => { +>commonMethodDifferentReturnType : (a: any, b: any) => any +>(a, b) => { var z = a.charAt(b); return z; } : (a: any, b: any) => any +>a : any +>b : any + + var z = a.charAt(b); +>z : any +>a.charAt(b) : any +>a.charAt : any +>a : any +>charAt : any +>b : any + + return z; +>z : any + + }, + commonPropertyDifferentType: "hello", +>commonPropertyDifferentType : string + + }, { +>{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; } + + // Like i2 + commonMethodDifferentReturnType: (a, b) => { +>commonMethodDifferentReturnType : (a: any, b: any) => any +>(a, b) => { var z = a.charCodeAt(b); return z; } : (a: any, b: any) => any +>a : any +>b : any + + var z = a.charCodeAt(b); +>z : any +>a.charCodeAt(b) : any +>a.charCodeAt : any +>a : any +>charCodeAt : any +>b : any + + return z; +>z : any + + }, + commonPropertyDifferentType: 10, +>commonPropertyDifferentType : number + + }]; diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt new file mode 100644 index 00000000000..9ef73eaf337 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt @@ -0,0 +1,130 @@ +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(14,5): error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. + Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. + Types of property 'prop' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(20,5): error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. + Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. + Types of property 'prop' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(21,5): error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. + Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'. + Types of property 'prop' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(25,5): error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. + Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'. + Types of property 'prop' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(29,5): error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. + Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'. + Types of property 'prop' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I11 | I21'. + Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I21'. + Types of property 'commonMethodDifferentReturnType' are incompatible. + Type '(a: any, b: any) => string | number' is not assignable to type '(a: string, b: number) => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts (6 errors) ==== + var str: string; + var num: number; + var strOrNumber: string | number = str || num; + var objStr: { prop: string }; + var objNum: { prop: number }; + var objStrOrNum1: { prop: string } | { prop: number } = objStr || objNum; + var objStrOrNum2: { prop: string | number } = objStr || objNum; + // Below is error because : + // Spec says: + // S is a union type and each constituent type of S is assignable to T. + // T is a union type and S is assignable to at least one constituent type of T. + // In case of objStrOrNum3, the S is not union Type but object Literal so we go to next step. + // Since T is union Type we only allow the assignment of either object with property of type string or object with property of type number but do not allow object with property of type string | number + var objStrOrNum3: { prop: string } | { prop: number } = { + ~~~~~~~~~~~~ +!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. +!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. +!!! error TS2323: Types of property 'prop' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + prop: strOrNumber + }; + var objStrOrNum4: { prop: string | number } = { + prop: strOrNumber + }; + var objStrOrNum5: { prop: string; anotherP: string; } | { prop: number } = { prop: strOrNumber }; + ~~~~~~~~~~~~ +!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. +!!! error TS2323: Types of property 'prop' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = { + ~~~~~~~~~~~~ +!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'. +!!! error TS2323: Types of property 'prop' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + prop: strOrNumber, + anotherP: str + }; + var objStrOrNum7: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + ~~~~~~~~~~~~ +!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'. +!!! error TS2323: Types of property 'prop' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + prop: strOrNumber, + anotherP: str + }; + var objStrOrNum8: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + ~~~~~~~~~~~~ +!!! error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +!!! error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'. +!!! error TS2323: Types of property 'prop' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + prop: strOrNumber, + anotherP: str, + anotherP1: num + }; + interface I11 { + commonMethodDifferentReturnType(a: string, b: number): string; + } + interface I21 { + commonMethodDifferentReturnType(a: string, b: number): number; + } + var i11: I11; + var i21: I21; + var i11Ori21: I11 | I21 = i11; + var i11Ori21: I11 | I21 = i21; + var i11Ori21: I11 | I21 = { // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, + }; + var i11Ori21: I11 | I21 = { // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, + }; + var strOrNumber: string | number; + var i11Ori21: I11 | I21 = { // Like i1 and i2 both + ~~~~~~~~ +!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I11 | I21'. +!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I21'. +!!! error TS2323: Types of property 'commonMethodDifferentReturnType' are incompatible. +!!! error TS2323: Type '(a: any, b: any) => string | number' is not assignable to type '(a: string, b: number) => number'. +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + commonMethodDifferentReturnType: (a, b) => strOrNumber, + }; \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.js b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.js new file mode 100644 index 00000000000..dc8f07823b6 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.js @@ -0,0 +1,115 @@ +//// [contextualTypeWithUnionTypeObjectLiteral.ts] +var str: string; +var num: number; +var strOrNumber: string | number = str || num; +var objStr: { prop: string }; +var objNum: { prop: number }; +var objStrOrNum1: { prop: string } | { prop: number } = objStr || objNum; +var objStrOrNum2: { prop: string | number } = objStr || objNum; +// Below is error because : +// Spec says: +// S is a union type and each constituent type of S is assignable to T. +// T is a union type and S is assignable to at least one constituent type of T. +// In case of objStrOrNum3, the S is not union Type but object Literal so we go to next step. +// Since T is union Type we only allow the assignment of either object with property of type string or object with property of type number but do not allow object with property of type string | number +var objStrOrNum3: { prop: string } | { prop: number } = { + prop: strOrNumber +}; +var objStrOrNum4: { prop: string | number } = { + prop: strOrNumber +}; +var objStrOrNum5: { prop: string; anotherP: string; } | { prop: number } = { prop: strOrNumber }; +var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum7: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum8: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + prop: strOrNumber, + anotherP: str, + anotherP1: num +}; +interface I11 { + commonMethodDifferentReturnType(a: string, b: number): string; +} +interface I21 { + commonMethodDifferentReturnType(a: string, b: number): number; +} +var i11: I11; +var i21: I21; +var i11Ori21: I11 | I21 = i11; +var i11Ori21: I11 | I21 = i21; +var i11Ori21: I11 | I21 = { // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, +}; +var i11Ori21: I11 | I21 = { // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, +}; +var strOrNumber: string | number; +var i11Ori21: I11 | I21 = { // Like i1 and i2 both + commonMethodDifferentReturnType: (a, b) => strOrNumber, +}; + +//// [contextualTypeWithUnionTypeObjectLiteral.js] +var str; +var num; +var strOrNumber = str || num; +var objStr; +var objNum; +var objStrOrNum1 = objStr || objNum; +var objStrOrNum2 = objStr || objNum; +// Below is error because : +// Spec says: +// S is a union type and each constituent type of S is assignable to T. +// T is a union type and S is assignable to at least one constituent type of T. +// In case of objStrOrNum3, the S is not union Type but object Literal so we go to next step. +// Since T is union Type we only allow the assignment of either object with property of type string or object with property of type number but do not allow object with property of type string | number +var objStrOrNum3 = { + prop: strOrNumber +}; +var objStrOrNum4 = { + prop: strOrNumber +}; +var objStrOrNum5 = { prop: strOrNumber }; +var objStrOrNum6 = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum7 = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum8 = { + prop: strOrNumber, + anotherP: str, + anotherP1: num +}; +var i11; +var i21; +var i11Ori21 = i11; +var i11Ori21 = i21; +var i11Ori21 = { + commonMethodDifferentReturnType: function (a, b) { + var z = a.charAt(b); + return z; + } +}; +var i11Ori21 = { + commonMethodDifferentReturnType: function (a, b) { + var z = a.charCodeAt(b); + return z; + } +}; +var strOrNumber; +var i11Ori21 = { + commonMethodDifferentReturnType: function (a, b) { return strOrNumber; } +}; diff --git a/tests/cases/conformance/types/union/contextualTypeWithUnionTypeMembers.ts b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeMembers.ts new file mode 100644 index 00000000000..4799fb5e04b --- /dev/null +++ b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeMembers.ts @@ -0,0 +1,119 @@ +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface I1 { + commonMethodType(a: string): string; + commonPropertyType: string; + commonMethodWithTypeParameter(a: T): T; + + methodOnlyInI1(a: string): string; + propertyOnlyInI1: string; +} +interface I2 { + commonMethodType(a: string): string; + commonPropertyType: string; + commonMethodWithTypeParameter(a: T): T; + + methodOnlyInI2(a: string): string; + propertyOnlyInI2: string; +} + +// Let S be the set of types in U that has a property P. +// If S is not empty, U has a property P of a union type of the types of P from each type in S. +var i1: I1; +var i2: I2; +var i1Ori2: I1 | I2 = i1; +var i1Ori2: I1 | I2 = i2; +var i1Ori2: I1 | I2 = { // Like i1 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", +}; +var i1Ori2: I1 | I2 = { // Like i2 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", +}; +var i1Ori2: I1 | I2 = { // Like i1 and i2 both + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", +}; + +var arrayI1OrI2: Array | I2> = [i1, i2, { // Like i1 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + }, + { // Like i2 + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", + }, { // Like i1 and i2 both + commonPropertyType: "hello", + commonMethodType: a=> a, + commonMethodWithTypeParameter: a => a, + methodOnlyInI1: a => a, + propertyOnlyInI1: "Hello", + methodOnlyInI2: a => a, + propertyOnlyInI2: "Hello", + }]; + +interface I11 { + commonMethodDifferentReturnType(a: string, b: number): string; + commonPropertyDifferentType: string; +} +interface I21 { + commonMethodDifferentReturnType(a: string, b: number): number; + commonPropertyDifferentType: number; +} +var i11: I11; +var i21: I21; +var i11Ori21: I11 | I21 = i11; +var i11Ori21: I11 | I21 = i21; +var i11Ori21: I11 | I21 = { + // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello", +}; +var i11Ori21: I11 | I21 = { + // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10, +}; +var arrayOrI11OrI21: Array = [i11, i21, i11 || i21, { + // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, + commonPropertyDifferentType: "hello", + }, { + // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, + commonPropertyDifferentType: 10, + }]; \ No newline at end of file diff --git a/tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts new file mode 100644 index 00000000000..b6b328a5d09 --- /dev/null +++ b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts @@ -0,0 +1,59 @@ +var str: string; +var num: number; +var strOrNumber: string | number = str || num; +var objStr: { prop: string }; +var objNum: { prop: number }; +var objStrOrNum1: { prop: string } | { prop: number } = objStr || objNum; +var objStrOrNum2: { prop: string | number } = objStr || objNum; +// Below is error because : +// Spec says: +// S is a union type and each constituent type of S is assignable to T. +// T is a union type and S is assignable to at least one constituent type of T. +// In case of objStrOrNum3, the S is not union Type but object Literal so we go to next step. +// Since T is union Type we only allow the assignment of either object with property of type string or object with property of type number but do not allow object with property of type string | number +var objStrOrNum3: { prop: string } | { prop: number } = { + prop: strOrNumber +}; +var objStrOrNum4: { prop: string | number } = { + prop: strOrNumber +}; +var objStrOrNum5: { prop: string; anotherP: string; } | { prop: number } = { prop: strOrNumber }; +var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum7: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + prop: strOrNumber, + anotherP: str +}; +var objStrOrNum8: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { + prop: strOrNumber, + anotherP: str, + anotherP1: num +}; +interface I11 { + commonMethodDifferentReturnType(a: string, b: number): string; +} +interface I21 { + commonMethodDifferentReturnType(a: string, b: number): number; +} +var i11: I11; +var i21: I21; +var i11Ori21: I11 | I21 = i11; +var i11Ori21: I11 | I21 = i21; +var i11Ori21: I11 | I21 = { // Like i1 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charAt(b); + return z; + }, +}; +var i11Ori21: I11 | I21 = { // Like i2 + commonMethodDifferentReturnType: (a, b) => { + var z = a.charCodeAt(b); + return z; + }, +}; +var strOrNumber: string | number; +var i11Ori21: I11 | I21 = { // Like i1 and i2 both + commonMethodDifferentReturnType: (a, b) => strOrNumber, +}; \ No newline at end of file From c4e632746edcc5a8742b243d4b336fe4d2871c6c Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Nov 2014 14:49:15 -0800 Subject: [PATCH 03/10] Fix the logic in getting the contextual signature of union type as per spec Fixes #1054 --- src/compiler/checker.ts | 35 +++++-- ...ntextualTypeWithUnionTypeCallSignatures.js | 86 ++++++++++++++++ ...xtualTypeWithUnionTypeCallSignatures.types | 99 +++++++++++++++++++ .../contextualTypeWithUnionTypeMembers.types | 98 +++++++++--------- ...lTypeWithUnionTypeObjectLiteral.errors.txt | 12 +-- ...ntextualTypeWithUnionTypeCallSignatures.ts | 36 +++++++ 6 files changed, 305 insertions(+), 61 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types create mode 100644 tests/cases/conformance/types/union/contextualTypeWithUnionTypeCallSignatures.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cf00022c6f0..8fdbe13806b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4879,8 +4879,9 @@ module ts { // Return the contextual signature for a given expression node. A contextual type provides a // contextual signature if it has a single call signature and if that call signature is non-generic. - // If the contextual type is a union type and each constituent type that has a contextual signature - // provides the same contextual signature, then the union type provides that contextual signature. + // If the contextual type is a union type, get the signature from each type possible and if they are + // all identical ignoring their return type, the result is same signature but with return type as + // union type of return types from these signatures function getContextualSignature(node: Expression): Signature { var type = getContextualType(node); if (!type) { @@ -4889,19 +4890,41 @@ module ts { if (!(type.flags & TypeFlags.Union)) { return getNonGenericSignature(type); } - var result: Signature; + var signatureList: Signature[]; var types = (type).types; for (var i = 0; i < types.length; i++) { + // The signature set of all constituent type with call signatures should match + // So number of signatures allowed is either 0 or 1 + if (signatureList && + getSignaturesOfObjectOrUnionType(types[i], SignatureKind.Call).length > 1) { + return undefined; + } + var signature = getNonGenericSignature(types[i]); if (signature) { - if (!result) { - result = signature; + if (!signatureList) { + // This signature will contribute to contextual union signature + signatureList = [signature]; } - else if (!compareSignatures(result, signature, /*compareReturnTypes*/ true, compareTypes)) { + else if (!compareSignatures(signatureList[0], signature, /*compareReturnTypes*/ false, compareTypes)) { + // Signatures arent identical, do not use return undefined; } + else { + // Use this signature for contextual union signature + signatureList.push(signature); + } } } + + // Result is union of signatures collected (return type is union of return types of this signature set) + var result: Signature; + if (signatureList) { + result = cloneSignature(signatureList[0]); + // Clear resolved return type we possibly got from cloneSignature + result.resolvedReturnType = undefined; + result.unionSignatures = signatureList; + } return result; } diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js new file mode 100644 index 00000000000..2e21235ea0a --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js @@ -0,0 +1,86 @@ +//// [contextualTypeWithUnionTypeCallSignatures.ts] +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. + +// Let S be the set of types in U that have call signatures. +// If S is not empty and the sets of call signatures of the types in S are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in S. + +interface IWithNoCallSignatures { + foo: string; +} +interface IWithCallSignatures { + (a: number): string; +} +interface IWithCallSignatures2 { + (a: number): number; +} +interface IWithCallSignatures3 { + (b: string): number; +} +interface IWithCallSignatures4 { + (a: number): string; + (a: string, b: number): number; +} + +// With no call signature | callSignatures +var x: IWithNoCallSignatures | IWithCallSignatures = a => a.toString(); + +// With call signatures with different return type +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a.toString(); // Like iWithCallSignatures +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a; // Like iWithCallSignatures2 + +// With call signatures of mismatching parameter type +var x3: IWithCallSignatures | IWithCallSignatures3 = a => /*here a should be any*/ a.toString(); + +// With call signature count mismatch +var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any*/ a.toString(); + +//// [contextualTypeWithUnionTypeCallSignatures.js] +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +// With no call signature | callSignatures +var x = function (a) { return a.toString(); }; +// With call signatures with different return type +var x2 = function (a) { return a.toString(); }; // Like iWithCallSignatures +var x2 = function (a) { return a; }; // Like iWithCallSignatures2 +// With call signatures of mismatching parameter type +var x3 = function (a /*here a should be any*/) { return a.toString(); }; +// With call signature count mismatch +var x4 = function (a //When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. + +// Let S be the set of types in U that have call signatures. +// If S is not empty and the sets of call signatures of the types in S are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in S. + +interface IWithNoCallSignatures { + foo: string; +} +interface IWithCallSignatures { + (a: number): string; +} +interface IWithCallSignatures2 { + (a: number): number; +} +interface IWithCallSignatures3 { + (b: string): number; +} +interface IWithCallSignatures4 { + (a: number): string; + (a: string, b: number): number; +} + +// With no call signature | callSignatures +var x: IWithNoCallSignatures | IWithCallSignatures = a => a.toString(); + +// With call signatures with different return type +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a.toString(); // Like iWithCallSignatures +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a; // Like iWithCallSignatures2 + +// With call signatures of mismatching parameter type +var x3: IWithCallSignatures | IWithCallSignatures3 = a => /*here a should be any*/ a.toString(); + +// With call signature count mismatch +var x4: IWithCallSignatures | IWithCallSignatures4 = a => + ) { return a.toString(); }; diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types new file mode 100644 index 00000000000..02dfecf5c08 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types @@ -0,0 +1,99 @@ +=== tests/cases/conformance/types/union/contextualTypeWithUnionTypeCallSignatures.ts === +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. + +// Let S be the set of types in U that have call signatures. +// If S is not empty and the sets of call signatures of the types in S are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in S. + +interface IWithNoCallSignatures { +>IWithNoCallSignatures : IWithNoCallSignatures + + foo: string; +>foo : string +} +interface IWithCallSignatures { +>IWithCallSignatures : IWithCallSignatures + + (a: number): string; +>a : number +} +interface IWithCallSignatures2 { +>IWithCallSignatures2 : IWithCallSignatures2 + + (a: number): number; +>a : number +} +interface IWithCallSignatures3 { +>IWithCallSignatures3 : IWithCallSignatures3 + + (b: string): number; +>b : string +} +interface IWithCallSignatures4 { +>IWithCallSignatures4 : IWithCallSignatures4 + + (a: number): string; +>a : number + + (a: string, b: number): number; +>a : string +>b : number +} + +// With no call signature | callSignatures +var x: IWithNoCallSignatures | IWithCallSignatures = a => a.toString(); +>x : IWithNoCallSignatures | IWithCallSignatures +>IWithNoCallSignatures : IWithNoCallSignatures +>IWithCallSignatures : IWithCallSignatures +>a => a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string + +// With call signatures with different return type +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a.toString(); // Like iWithCallSignatures +>x2 : IWithCallSignatures | IWithCallSignatures2 +>IWithCallSignatures : IWithCallSignatures +>IWithCallSignatures2 : IWithCallSignatures2 +>a => a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string + +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a; // Like iWithCallSignatures2 +>x2 : IWithCallSignatures | IWithCallSignatures2 +>IWithCallSignatures : IWithCallSignatures +>IWithCallSignatures2 : IWithCallSignatures2 +>a => a : (a: number) => number +>a : number +>a : number + +// With call signatures of mismatching parameter type +var x3: IWithCallSignatures | IWithCallSignatures3 = a => /*here a should be any*/ a.toString(); +>x3 : IWithCallSignatures | IWithCallSignatures3 +>IWithCallSignatures : IWithCallSignatures +>IWithCallSignatures3 : IWithCallSignatures3 +>a => /*here a should be any*/ a.toString() : (a: any) => any +>a : any +>a.toString() : any +>a.toString : any +>a : any +>toString : any + +// With call signature count mismatch +var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any*/ a.toString(); +>x4 : IWithCallSignatures | IWithCallSignatures4 +>IWithCallSignatures : IWithCallSignatures +>IWithCallSignatures4 : IWithCallSignatures4 +>a => /*here a should be any*/ a.toString() : (a: any) => any +>a : any +>a.toString() : any +>a.toString : any +>a : any +>toString : any + diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types index 93e01910870..522d4a4a555 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types +++ b/tests/baselines/reference/contextualTypeWithUnionTypeMembers.types @@ -321,25 +321,25 @@ var i11Ori21: I11 | I21 = { >i11Ori21 : I11 | I21 >I11 : I11 >I21 : I21 ->{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } +>{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: string, b: number) => string; commonPropertyDifferentType: string; } // Like i1 commonMethodDifferentReturnType: (a, b) => { ->commonMethodDifferentReturnType : (a: any, b: any) => any ->(a, b) => { var z = a.charAt(b); return z; } : (a: any, b: any) => any ->a : any ->b : any +>commonMethodDifferentReturnType : (a: string, b: number) => string +>(a, b) => { var z = a.charAt(b); return z; } : (a: string, b: number) => string +>a : string +>b : number var z = a.charAt(b); ->z : any ->a.charAt(b) : any ->a.charAt : any ->a : any ->charAt : any ->b : any +>z : string +>a.charAt(b) : string +>a.charAt : (pos: number) => string +>a : string +>charAt : (pos: number) => string +>b : number return z; ->z : any +>z : string }, commonPropertyDifferentType: "hello", @@ -350,25 +350,25 @@ var i11Ori21: I11 | I21 = { >i11Ori21 : I11 | I21 >I11 : I11 >I21 : I21 ->{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10,} : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; } +>{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10,} : { commonMethodDifferentReturnType: (a: string, b: number) => number; commonPropertyDifferentType: number; } // Like i2 commonMethodDifferentReturnType: (a, b) => { ->commonMethodDifferentReturnType : (a: any, b: any) => any ->(a, b) => { var z = a.charCodeAt(b); return z; } : (a: any, b: any) => any ->a : any ->b : any +>commonMethodDifferentReturnType : (a: string, b: number) => number +>(a, b) => { var z = a.charCodeAt(b); return z; } : (a: string, b: number) => number +>a : string +>b : number var z = a.charCodeAt(b); ->z : any ->a.charCodeAt(b) : any ->a.charCodeAt : any ->a : any ->charCodeAt : any ->b : any +>z : number +>a.charCodeAt(b) : number +>a.charCodeAt : (index: number) => number +>a : string +>charCodeAt : (index: number) => number +>b : number return z; ->z : any +>z : number }, commonPropertyDifferentType: 10, @@ -380,56 +380,56 @@ var arrayOrI11OrI21: Array = [i11, i21, i11 || i21, { >Array : T[] >I11 : I11 >I21 : I21 ->[i11, i21, i11 || i21, { // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", }, { // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, }] : ({ commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } | { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; })[] +>[i11, i21, i11 || i21, { // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", }, { // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, }] : (I11 | I21)[] >i11 : I11 >i21 : I21 >i11 || i21 : I11 | I21 >i11 : I11 >i21 : I21 ->{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: string; } +>{ // Like i1 commonMethodDifferentReturnType: (a, b) => { var z = a.charAt(b); return z; }, commonPropertyDifferentType: "hello", } : { commonMethodDifferentReturnType: (a: string, b: number) => string; commonPropertyDifferentType: string; } // Like i1 commonMethodDifferentReturnType: (a, b) => { ->commonMethodDifferentReturnType : (a: any, b: any) => any ->(a, b) => { var z = a.charAt(b); return z; } : (a: any, b: any) => any ->a : any ->b : any +>commonMethodDifferentReturnType : (a: string, b: number) => string +>(a, b) => { var z = a.charAt(b); return z; } : (a: string, b: number) => string +>a : string +>b : number var z = a.charAt(b); ->z : any ->a.charAt(b) : any ->a.charAt : any ->a : any ->charAt : any ->b : any +>z : string +>a.charAt(b) : string +>a.charAt : (pos: number) => string +>a : string +>charAt : (pos: number) => string +>b : number return z; ->z : any +>z : string }, commonPropertyDifferentType: "hello", >commonPropertyDifferentType : string }, { ->{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, } : { commonMethodDifferentReturnType: (a: any, b: any) => any; commonPropertyDifferentType: number; } +>{ // Like i2 commonMethodDifferentReturnType: (a, b) => { var z = a.charCodeAt(b); return z; }, commonPropertyDifferentType: 10, } : { commonMethodDifferentReturnType: (a: string, b: number) => number; commonPropertyDifferentType: number; } // Like i2 commonMethodDifferentReturnType: (a, b) => { ->commonMethodDifferentReturnType : (a: any, b: any) => any ->(a, b) => { var z = a.charCodeAt(b); return z; } : (a: any, b: any) => any ->a : any ->b : any +>commonMethodDifferentReturnType : (a: string, b: number) => number +>(a, b) => { var z = a.charCodeAt(b); return z; } : (a: string, b: number) => number +>a : string +>b : number var z = a.charCodeAt(b); ->z : any ->a.charCodeAt(b) : any ->a.charCodeAt : any ->a : any ->charCodeAt : any ->b : any +>z : number +>a.charCodeAt(b) : number +>a.charCodeAt : (index: number) => number +>a : string +>charCodeAt : (index: number) => number +>b : number return z; ->z : any +>z : number }, commonPropertyDifferentType: 10, diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt index 9ef73eaf337..6ca334ef311 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt +++ b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt @@ -23,10 +23,10 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts( Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I11 | I21'. - Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I21'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. + Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'. Types of property 'commonMethodDifferentReturnType' are incompatible. - Type '(a: any, b: any) => string | number' is not assignable to type '(a: string, b: number) => number'. + Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. @@ -120,10 +120,10 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts( var strOrNumber: string | number; var i11Ori21: I11 | I21 = { // Like i1 and i2 both ~~~~~~~~ -!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I11 | I21'. -!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: any, b: any) => string | number; }' is not assignable to type 'I21'. +!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. +!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'. !!! error TS2323: Types of property 'commonMethodDifferentReturnType' are incompatible. -!!! error TS2323: Type '(a: any, b: any) => string | number' is not assignable to type '(a: string, b: number) => number'. +!!! error TS2323: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'. !!! error TS2323: Type 'string | number' is not assignable to type 'number'. !!! error TS2323: Type 'string' is not assignable to type 'number'. commonMethodDifferentReturnType: (a, b) => strOrNumber, diff --git a/tests/cases/conformance/types/union/contextualTypeWithUnionTypeCallSignatures.ts b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeCallSignatures.ts new file mode 100644 index 00000000000..fccf5381017 --- /dev/null +++ b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeCallSignatures.ts @@ -0,0 +1,36 @@ +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. + +// Let S be the set of types in U that have call signatures. +// If S is not empty and the sets of call signatures of the types in S are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in S. + +interface IWithNoCallSignatures { + foo: string; +} +interface IWithCallSignatures { + (a: number): string; +} +interface IWithCallSignatures2 { + (a: number): number; +} +interface IWithCallSignatures3 { + (b: string): number; +} +interface IWithCallSignatures4 { + (a: number): string; + (a: string, b: number): number; +} + +// With no call signature | callSignatures +var x: IWithNoCallSignatures | IWithCallSignatures = a => a.toString(); + +// With call signatures with different return type +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a.toString(); // Like iWithCallSignatures +var x2: IWithCallSignatures | IWithCallSignatures2 = a => a; // Like iWithCallSignatures2 + +// With call signatures of mismatching parameter type +var x3: IWithCallSignatures | IWithCallSignatures3 = a => /*here a should be any*/ a.toString(); + +// With call signature count mismatch +var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any*/ a.toString(); \ No newline at end of file From a5cea935aff3aa91b73ae4bb76c76fd536465f99 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Nov 2014 15:33:32 -0800 Subject: [PATCH 04/10] Tests for contextual index signature of union type Let S be the set of types in U that has a string index signature. If S is not empty, U has a string index signature of a union type of the types of the string index signatures from each type in S. Let S be the set of types in U that has a numeric index signature. If S is not empty, U has a numeric index signature of a union type of the types of the numeric index signatures from each type in S. --- ...textualTypeWithUnionTypeIndexSignatures.js | 80 +++++++++ ...tualTypeWithUnionTypeIndexSignatures.types | 166 ++++++++++++++++++ ...textualTypeWithUnionTypeIndexSignatures.ts | 54 ++++++ 3 files changed, 300 insertions(+) create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.js create mode 100644 tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.types create mode 100644 tests/cases/conformance/types/union/contextualTypeWithUnionTypeIndexSignatures.ts diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.js b/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.js new file mode 100644 index 00000000000..2c07f461424 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.js @@ -0,0 +1,80 @@ +//// [contextualTypeWithUnionTypeIndexSignatures.ts] +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface SomeType { + (a: number): number; +} +interface SomeType2 { + (a: number): string; +} + +interface IWithNoStringIndexSignature { + foo: string; +} +interface IWithNoNumberIndexSignature { + 0: string; +} +interface IWithStringIndexSignature1 { + [a: string]: SomeType; +} +interface IWithStringIndexSignature2 { + [a: string]: SomeType2; +} +interface IWithNumberIndexSignature1 { + [a: number]: SomeType; +} +interface IWithNumberIndexSignature2 { + [a: number]: SomeType2; +} + +// When an object literal is contextually typed by a type that includes a string index signature, +// the resulting type of the object literal includes a string index signature with the union type of +// the types of the properties declared in the object literal, or the Undefined type if the object literal +// is empty.Likewise, when an object literal is contextually typed by a type that includes a numeric index +// signature, the resulting type of the object literal includes a numeric index signature with the union type +// of the types of the numerically named properties(section 3.7.4) declared in the object literal, +// or the Undefined type if the object literal declares no numerically named properties. + +// Let S be the set of types in U that has a string index signature. +// If S is not empty, U has a string index signature of a union type of +// the types of the string index signatures from each type in S. +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { z: a => a }; // a should be number +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: a => a }; // a should be any +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: "hello" }; +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a.toString() }; // a should be number +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a }; // a should be number + + +// Let S be the set of types in U that has a numeric index signature. +// If S is not empty, U has a numeric index signature of a union type of +// the types of the numeric index signatures from each type in S. +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 1: a => a }; // a should be number +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: a => a }; // a should be any +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: "hello" }; +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a.toString() }; // a should be number +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a }; // a should be number + +//// [contextualTypeWithUnionTypeIndexSignatures.js] +// When an object literal is contextually typed by a type that includes a string index signature, +// the resulting type of the object literal includes a string index signature with the union type of +// the types of the properties declared in the object literal, or the Undefined type if the object literal +// is empty.Likewise, when an object literal is contextually typed by a type that includes a numeric index +// signature, the resulting type of the object literal includes a numeric index signature with the union type +// of the types of the numerically named properties(section 3.7.4) declared in the object literal, +// or the Undefined type if the object literal declares no numerically named properties. +// Let S be the set of types in U that has a string index signature. +// If S is not empty, U has a string index signature of a union type of +// the types of the string index signatures from each type in S. +var x = { z: function (a) { return a; } }; // a should be number +var x = { foo: function (a) { return a; } }; // a should be any +var x = { foo: "hello" }; +var x2 = { z: function (a) { return a.toString(); } }; // a should be number +var x2 = { z: function (a) { return a; } }; // a should be number +// Let S be the set of types in U that has a numeric index signature. +// If S is not empty, U has a numeric index signature of a union type of +// the types of the numeric index signatures from each type in S. +var x3 = { 1: function (a) { return a; } }; // a should be number +var x3 = { 0: function (a) { return a; } }; // a should be any +var x3 = { 0: "hello" }; +var x4 = { 1: function (a) { return a.toString(); } }; // a should be number +var x4 = { 1: function (a) { return a; } }; // a should be number diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.types b/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.types new file mode 100644 index 00000000000..8a91fe18698 --- /dev/null +++ b/tests/baselines/reference/contextualTypeWithUnionTypeIndexSignatures.types @@ -0,0 +1,166 @@ +=== tests/cases/conformance/types/union/contextualTypeWithUnionTypeIndexSignatures.ts === +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface SomeType { +>SomeType : SomeType + + (a: number): number; +>a : number +} +interface SomeType2 { +>SomeType2 : SomeType2 + + (a: number): string; +>a : number +} + +interface IWithNoStringIndexSignature { +>IWithNoStringIndexSignature : IWithNoStringIndexSignature + + foo: string; +>foo : string +} +interface IWithNoNumberIndexSignature { +>IWithNoNumberIndexSignature : IWithNoNumberIndexSignature + + 0: string; +} +interface IWithStringIndexSignature1 { +>IWithStringIndexSignature1 : IWithStringIndexSignature1 + + [a: string]: SomeType; +>a : string +>SomeType : SomeType +} +interface IWithStringIndexSignature2 { +>IWithStringIndexSignature2 : IWithStringIndexSignature2 + + [a: string]: SomeType2; +>a : string +>SomeType2 : SomeType2 +} +interface IWithNumberIndexSignature1 { +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 + + [a: number]: SomeType; +>a : number +>SomeType : SomeType +} +interface IWithNumberIndexSignature2 { +>IWithNumberIndexSignature2 : IWithNumberIndexSignature2 + + [a: number]: SomeType2; +>a : number +>SomeType2 : SomeType2 +} + +// When an object literal is contextually typed by a type that includes a string index signature, +// the resulting type of the object literal includes a string index signature with the union type of +// the types of the properties declared in the object literal, or the Undefined type if the object literal +// is empty.Likewise, when an object literal is contextually typed by a type that includes a numeric index +// signature, the resulting type of the object literal includes a numeric index signature with the union type +// of the types of the numerically named properties(section 3.7.4) declared in the object literal, +// or the Undefined type if the object literal declares no numerically named properties. + +// Let S be the set of types in U that has a string index signature. +// If S is not empty, U has a string index signature of a union type of +// the types of the string index signatures from each type in S. +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { z: a => a }; // a should be number +>x : IWithNoStringIndexSignature | IWithStringIndexSignature1 +>IWithNoStringIndexSignature : IWithNoStringIndexSignature +>IWithStringIndexSignature1 : IWithStringIndexSignature1 +>{ z: a => a } : { [x: string]: (a: number) => number; z: (a: number) => number; } +>z : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: a => a }; // a should be any +>x : IWithNoStringIndexSignature | IWithStringIndexSignature1 +>IWithNoStringIndexSignature : IWithNoStringIndexSignature +>IWithStringIndexSignature1 : IWithStringIndexSignature1 +>{ foo: a => a } : { [x: string]: (a: any) => any; foo: (a: any) => any; } +>foo : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: "hello" }; +>x : IWithNoStringIndexSignature | IWithStringIndexSignature1 +>IWithNoStringIndexSignature : IWithNoStringIndexSignature +>IWithStringIndexSignature1 : IWithStringIndexSignature1 +>{ foo: "hello" } : { [x: string]: string; foo: string; } +>foo : string + +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a.toString() }; // a should be number +>x2 : IWithStringIndexSignature1 | IWithStringIndexSignature2 +>IWithStringIndexSignature1 : IWithStringIndexSignature1 +>IWithStringIndexSignature2 : IWithStringIndexSignature2 +>{ z: a => a.toString() } : { [x: string]: (a: number) => string; z: (a: number) => string; } +>z : (a: number) => string +>a => a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string + +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a }; // a should be number +>x2 : IWithStringIndexSignature1 | IWithStringIndexSignature2 +>IWithStringIndexSignature1 : IWithStringIndexSignature1 +>IWithStringIndexSignature2 : IWithStringIndexSignature2 +>{ z: a => a } : { [x: string]: (a: number) => number; z: (a: number) => number; } +>z : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + +// Let S be the set of types in U that has a numeric index signature. +// If S is not empty, U has a numeric index signature of a union type of +// the types of the numeric index signatures from each type in S. +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 1: a => a }; // a should be number +>x3 : IWithNoNumberIndexSignature | IWithNumberIndexSignature1 +>IWithNoNumberIndexSignature : IWithNoNumberIndexSignature +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 +>{ 1: a => a } : { [x: number]: (a: number) => number; 1: (a: number) => number; } +>a => a : (a: number) => number +>a : number +>a : number + +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: a => a }; // a should be any +>x3 : IWithNoNumberIndexSignature | IWithNumberIndexSignature1 +>IWithNoNumberIndexSignature : IWithNoNumberIndexSignature +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 +>{ 0: a => a } : { [x: number]: (a: any) => any; 0: (a: any) => any; } +>a => a : (a: any) => any +>a : any +>a : any + +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: "hello" }; +>x3 : IWithNoNumberIndexSignature | IWithNumberIndexSignature1 +>IWithNoNumberIndexSignature : IWithNoNumberIndexSignature +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 +>{ 0: "hello" } : { [x: number]: string; 0: string; } + +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a.toString() }; // a should be number +>x4 : IWithNumberIndexSignature1 | IWithNumberIndexSignature2 +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 +>IWithNumberIndexSignature2 : IWithNumberIndexSignature2 +>{ 1: a => a.toString() } : { [x: number]: (a: number) => string; 1: (a: number) => string; } +>a => a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string + +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a }; // a should be number +>x4 : IWithNumberIndexSignature1 | IWithNumberIndexSignature2 +>IWithNumberIndexSignature1 : IWithNumberIndexSignature1 +>IWithNumberIndexSignature2 : IWithNumberIndexSignature2 +>{ 1: a => a } : { [x: number]: (a: number) => number; 1: (a: number) => number; } +>a => a : (a: number) => number +>a : number +>a : number + diff --git a/tests/cases/conformance/types/union/contextualTypeWithUnionTypeIndexSignatures.ts b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeIndexSignatures.ts new file mode 100644 index 00000000000..9132c61f4fe --- /dev/null +++ b/tests/cases/conformance/types/union/contextualTypeWithUnionTypeIndexSignatures.ts @@ -0,0 +1,54 @@ +//When used as a contextual type, a union type U has those members that are present in any of +// its constituent types, with types that are unions of the respective members in the constituent types. +interface SomeType { + (a: number): number; +} +interface SomeType2 { + (a: number): string; +} + +interface IWithNoStringIndexSignature { + foo: string; +} +interface IWithNoNumberIndexSignature { + 0: string; +} +interface IWithStringIndexSignature1 { + [a: string]: SomeType; +} +interface IWithStringIndexSignature2 { + [a: string]: SomeType2; +} +interface IWithNumberIndexSignature1 { + [a: number]: SomeType; +} +interface IWithNumberIndexSignature2 { + [a: number]: SomeType2; +} + +// When an object literal is contextually typed by a type that includes a string index signature, +// the resulting type of the object literal includes a string index signature with the union type of +// the types of the properties declared in the object literal, or the Undefined type if the object literal +// is empty.Likewise, when an object literal is contextually typed by a type that includes a numeric index +// signature, the resulting type of the object literal includes a numeric index signature with the union type +// of the types of the numerically named properties(section 3.7.4) declared in the object literal, +// or the Undefined type if the object literal declares no numerically named properties. + +// Let S be the set of types in U that has a string index signature. +// If S is not empty, U has a string index signature of a union type of +// the types of the string index signatures from each type in S. +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { z: a => a }; // a should be number +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: a => a }; // a should be any +var x: IWithNoStringIndexSignature | IWithStringIndexSignature1 = { foo: "hello" }; +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a.toString() }; // a should be number +var x2: IWithStringIndexSignature1 | IWithStringIndexSignature2 = { z: a => a }; // a should be number + + +// Let S be the set of types in U that has a numeric index signature. +// If S is not empty, U has a numeric index signature of a union type of +// the types of the numeric index signatures from each type in S. +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 1: a => a }; // a should be number +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: a => a }; // a should be any +var x3: IWithNoNumberIndexSignature | IWithNumberIndexSignature1 = { 0: "hello" }; +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a.toString() }; // a should be number +var x4: IWithNumberIndexSignature1 | IWithNumberIndexSignature2 = { 1: a => a }; // a should be number \ No newline at end of file From e79229b88d591222c0f22cb7030aa0ed34d44334 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 13:44:10 -0800 Subject: [PATCH 05/10] Update some documentation as per code review feedback --- src/services/services.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 7de0e654a1e..39199329cb7 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2784,25 +2784,24 @@ module ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.UnionProperty) { - // If any of the property includes the declaration of property - the kind is property - var unionPropetyKind = forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => { + // If union property is result of union of non method (property/accessors), it is labeled as property + var unionPropertyKind = forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => { var rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & SymbolFlags.Property) { + if (rootSymbolFlags & (SymbolFlags.Property | SymbolFlags.GetAccessor | SymbolFlags.SetAccessor)) { return ScriptElementKind.memberVariableElement; } - if (rootSymbolFlags & SymbolFlags.GetAccessor) return ScriptElementKind.memberVariableElement; - if (rootSymbolFlags & SymbolFlags.SetAccessor) return ScriptElementKind.memberVariableElement; - Debug.assert((rootSymbolFlags & SymbolFlags.Method) !== undefined); + Debug.assert(!!(rootSymbolFlags & SymbolFlags.Method)); }); - if (!unionPropetyKind) { - // If this was union of all methods, make sure it has call signatures before we call it method + if (!unionPropertyKind) { + // If this was union of all methods, + //make sure it has call signatures before we can label it as method var typeOfUnionProperty = typeInfoResolver.getTypeOfSymbol(symbol); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } return ScriptElementKind.memberVariableElement; } - return unionPropetyKind; + return unionPropertyKind; } return ScriptElementKind.memberVariableElement; } From 12370332a1324a68436a09296d6246c98b3307be Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 15:19:27 -0800 Subject: [PATCH 06/10] Show narrowed type in quickInfo/completion entry Fixes #927 --- src/compiler/checker.ts | 2 +- src/compiler/types.ts | 2 +- src/services/services.ts | 5 +- .../completionEntryOnNarrowedType.ts | 20 ++++++++ .../fourslash/quickInfoOnNarrowedType.ts | 22 ++++++++ .../quickInfoOnNarrowedTypeInModule.ts | 51 +++++++++++++++++++ 6 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/completionEntryOnNarrowedType.ts create mode 100644 tests/cases/fourslash/quickInfoOnNarrowedType.ts create mode 100644 tests/cases/fourslash/quickInfoOnNarrowedTypeInModule.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2567b54de4a..a3485a26052 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -85,7 +85,7 @@ module ts { checkProgram: checkProgram, emitFiles: invokeEmitter, getParentOfSymbol: getParentOfSymbol, - getTypeOfSymbol: getTypeOfSymbol, + getNarrowedTypeOfSymbol: getNarrowedTypeOfSymbol, getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol, getPropertiesOfType: getPropertiesOfType, getPropertyOfType: getPropertyOfType, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 973c06d6e2d..020b6432c7f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -701,7 +701,7 @@ module ts { checkProgram(): void; emitFiles(targetSourceFile?: SourceFile): EmitResult; getParentOfSymbol(symbol: Symbol): Symbol; - getTypeOfSymbol(symbol: Symbol): Type; + getNarrowedTypeOfSymbol(symbol: Symbol, node: Node): Type; getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol; diff --git a/src/services/services.ts b/src/services/services.ts index d6465084fa4..95cf7c5d763 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2689,14 +2689,13 @@ module ts { var symbol = lookUp(activeCompletionSession.symbols, entryName); if (symbol) { - var type = session.typeChecker.getTypeOfSymbol(symbol); - Debug.assert(type !== undefined, "Could not find type for symbol"); var completionEntry = createCompletionEntry(symbol, session.typeChecker); // TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind' // which is permissible given that it is backwards compatible; but really we should consider // passing the meaning for the node so that we don't report that a suggestion for a value is an interface. // We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration. var location = getTouchingPropertyName(sourceFile, position); + Debug.assert(session.typeChecker.getNarrowedTypeOfSymbol(symbol, location) !== undefined, "Could not find type for symbol"); var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All); return { name: entryName, @@ -2859,7 +2858,7 @@ module ts { symbolKind = ScriptElementKind.memberVariableElement; } - var type = typeResolver.getTypeOfSymbol(symbol); + var type = typeResolver.getNarrowedTypeOfSymbol(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccess) { var right = (location.parent).right; diff --git a/tests/cases/fourslash/completionEntryOnNarrowedType.ts b/tests/cases/fourslash/completionEntryOnNarrowedType.ts new file mode 100644 index 00000000000..714d3390e76 --- /dev/null +++ b/tests/cases/fourslash/completionEntryOnNarrowedType.ts @@ -0,0 +1,20 @@ +/// + +////function foo(strOrNum: string | number) { +//// /*1*/ +//// if (typeof strOrNum === "number") { +//// /*2*/ +//// } +//// else { +//// /*3*/ +//// } +////} + +goTo.marker('1'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string | number"); + +goTo.marker('2'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: number"); + +goTo.marker('3'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnNarrowedType.ts b/tests/cases/fourslash/quickInfoOnNarrowedType.ts new file mode 100644 index 00000000000..bc1d8126d76 --- /dev/null +++ b/tests/cases/fourslash/quickInfoOnNarrowedType.ts @@ -0,0 +1,22 @@ +/// + +////function foo(strOrNum: string | number) { +//// if (typeof /*1*/strOrNum === "number") { +//// return /*2*/strOrNum; +//// } +//// else { +//// return /*3*/strOrNum.length; +//// } +////} + +goTo.marker('1'); +verify.quickInfoIs('(parameter) strOrNum: string | number'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string | number"); + +goTo.marker('2'); +verify.quickInfoIs('(parameter) strOrNum: number'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: number"); + +goTo.marker('3'); +verify.quickInfoIs('(parameter) strOrNum: string'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string"); diff --git a/tests/cases/fourslash/quickInfoOnNarrowedTypeInModule.ts b/tests/cases/fourslash/quickInfoOnNarrowedTypeInModule.ts new file mode 100644 index 00000000000..79d794a9c0d --- /dev/null +++ b/tests/cases/fourslash/quickInfoOnNarrowedTypeInModule.ts @@ -0,0 +1,51 @@ +/// + +////var strOrNum: string | number; +////module m { +//// var nonExportedStrOrNum: string | number; +//// export var exportedStrOrNum: string | number; +//// var num: number; +//// var str: string; +//// if (typeof /*1*/nonExportedStrOrNum === "number") { +//// num = /*2*/nonExportedStrOrNum; +//// } +//// else { +//// str = /*3*/nonExportedStrOrNum.length; +//// } +//// if (typeof /*4*/exportedStrOrNum === "number") { +//// strOrNum = /*5*/exportedStrOrNum; +//// } +//// else { +//// strOrNum = /*6*/exportedStrOrNum; +//// } +////} +////if (typeof m./*7*/exportedStrOrNum === "number") { +//// strOrNum = m./*8*/exportedStrOrNum; +////} +////else { +//// strOrNum = m./*9*/exportedStrOrNum; +////} + +goTo.marker('1'); +verify.quickInfoIs('(var) nonExportedStrOrNum: string | number'); +verify.completionListContains("nonExportedStrOrNum", "(var) nonExportedStrOrNum: string | number"); + +goTo.marker('2'); +verify.quickInfoIs('(var) nonExportedStrOrNum: number'); +verify.completionListContains("nonExportedStrOrNum", "(var) nonExportedStrOrNum: number"); + +goTo.marker('3'); +verify.quickInfoIs('(var) nonExportedStrOrNum: string'); +verify.completionListContains("nonExportedStrOrNum", "(var) nonExportedStrOrNum: string"); + +['4', '5', '6', '7', '8', '9'].forEach((marker, index, arr) => { + goTo.marker(marker); + verify.quickInfoIs('(var) m.exportedStrOrNum: string | number'); + verify.completionListContains("exportedStrOrNum", "(var) m.exportedStrOrNum: string | number"); +}); + +['7', '8', '9'].forEach((marker, index, arr) => { + goTo.marker(marker); + verify.quickInfoIs('(var) m.exportedStrOrNum: string | number'); + verify.memberListContains("exportedStrOrNum", "(var) m.exportedStrOrNum: string | number"); +}); \ No newline at end of file From 1e4f0b81fa627478277683399346734dc936ecbf Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 15:38:47 -0800 Subject: [PATCH 07/10] Verify breakpoints in type alias syntax --- .../reference/bpSpan_typealias.baseline | 88 +++++++++++++++++++ .../breakpointValidationTypeAlias.ts | 15 ++++ 2 files changed, 103 insertions(+) create mode 100644 tests/baselines/reference/bpSpan_typealias.baseline create mode 100644 tests/cases/fourslash/breakpointValidationTypeAlias.ts diff --git a/tests/baselines/reference/bpSpan_typealias.baseline b/tests/baselines/reference/bpSpan_typealias.baseline new file mode 100644 index 00000000000..51030bfb0a5 --- /dev/null +++ b/tests/baselines/reference/bpSpan_typealias.baseline @@ -0,0 +1,88 @@ + +1 >module m2 { + + ~~~~~~~~~~~~ => Pos: (0 to 11) SpanInfo: {"start":0,"length":164} + >module m2 { + > module m { + > export class c { + > } + > } + > type a = m.c; + > export type b = m.c; + > var x: a = new m.c(); + > var y: b = new m.c(); + >} + >:=> (line 1, col 0) to (line 10, col 1) +-------------------------------- +2 > module m { + + ~~~~~~~~~~~~~~~ => Pos: (12 to 26) SpanInfo: {"start":16,"length":51} + >module m { + > export class c { + > } + > } + >:=> (line 2, col 4) to (line 5, col 5) +-------------------------------- +3 > export class c { + + ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (27 to 51) SpanInfo: {"start":35,"length":26} + >export class c { + > } + >:=> (line 3, col 8) to (line 4, col 9) +-------------------------------- +4 > } + + ~~~~~~~~~~ => Pos: (52 to 61) SpanInfo: {"start":60,"length":1} + >} + >:=> (line 4, col 8) to (line 4, col 9) +-------------------------------- +5 > } + + ~~~~~~ => Pos: (62 to 67) SpanInfo: {"start":66,"length":1} + >} + >:=> (line 5, col 4) to (line 5, col 5) +-------------------------------- +6 > type a = m.c; + + ~~~~~~~~~~~~~~~~~~ => Pos: (68 to 85) SpanInfo: {"start":16,"length":51} + >module m { + > export class c { + > } + > } + >:=> (line 2, col 4) to (line 5, col 5) +-------------------------------- +7 > export type b = m.c; + + ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (86 to 110) SpanInfo: {"start":16,"length":51} + >module m { + > export class c { + > } + > } + >:=> (line 2, col 4) to (line 5, col 5) +-------------------------------- +8 > var x: a = new m.c(); + + ~~~~~~~~~~~~~~ => Pos: (111 to 124) SpanInfo: {"start":115,"length":20} + >var x: a = new m.c() + >:=> (line 8, col 4) to (line 8, col 24) +8 > var x: a = new m.c(); + + ~~~~~~~~~~~~ => Pos: (125 to 136) SpanInfo: {"start":126,"length":9} + >new m.c() + >:=> (line 8, col 15) to (line 8, col 24) +-------------------------------- +9 > var y: b = new m.c(); + + ~~~~~~~~~~~~~~ => Pos: (137 to 150) SpanInfo: {"start":141,"length":20} + >var y: b = new m.c() + >:=> (line 9, col 4) to (line 9, col 24) +9 > var y: b = new m.c(); + + ~~~~~~~~~~~~ => Pos: (151 to 162) SpanInfo: {"start":152,"length":9} + >new m.c() + >:=> (line 9, col 15) to (line 9, col 24) +-------------------------------- +10 >} + ~ => Pos: (163 to 163) SpanInfo: {"start":163,"length":1} + >} + >:=> (line 10, col 0) to (line 10, col 1) \ No newline at end of file diff --git a/tests/cases/fourslash/breakpointValidationTypeAlias.ts b/tests/cases/fourslash/breakpointValidationTypeAlias.ts new file mode 100644 index 00000000000..f2319c1f8d6 --- /dev/null +++ b/tests/cases/fourslash/breakpointValidationTypeAlias.ts @@ -0,0 +1,15 @@ +/// + +// @BaselineFile: bpSpan_typealias.baseline +// @Filename: bpSpan_typealias.ts +////module m2 { +//// module m { +//// export class c { +//// } +//// } +//// type a = m.c; +//// export type b = m.c; +//// var x: a = new m.c(); +//// var y: b = new m.c(); +////} +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file From 61c45816c47d72d9612647b0a44ffe306cc61e7f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 15:40:28 -0800 Subject: [PATCH 08/10] Type aliases cannot have breakpoints --- src/services/breakpoints.ts | 3 ++- .../baselines/reference/bpSpan_typealias.baseline | 14 ++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index aa8ec8217ce..f8688b3c479 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -194,8 +194,9 @@ module ts.BreakpointResolver { // span in statement return spanInNode((node).statement); - // No breakpoint in interface + // No breakpoint in interface, type alias case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: return undefined; // Tokens: diff --git a/tests/baselines/reference/bpSpan_typealias.baseline b/tests/baselines/reference/bpSpan_typealias.baseline index 51030bfb0a5..88e60b55e47 100644 --- a/tests/baselines/reference/bpSpan_typealias.baseline +++ b/tests/baselines/reference/bpSpan_typealias.baseline @@ -44,21 +44,11 @@ -------------------------------- 6 > type a = m.c; - ~~~~~~~~~~~~~~~~~~ => Pos: (68 to 85) SpanInfo: {"start":16,"length":51} - >module m { - > export class c { - > } - > } - >:=> (line 2, col 4) to (line 5, col 5) + ~~~~~~~~~~~~~~~~~~ => Pos: (68 to 85) SpanInfo: undefined -------------------------------- 7 > export type b = m.c; - ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (86 to 110) SpanInfo: {"start":16,"length":51} - >module m { - > export class c { - > } - > } - >:=> (line 2, col 4) to (line 5, col 5) + ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (86 to 110) SpanInfo: undefined -------------------------------- 8 > var x: a = new m.c(); From e4c88eeae10f254b87ae6fec7686955e3636166e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 15:49:59 -0800 Subject: [PATCH 09/10] Breakpoint validation for Let and cost --- .../baselines/reference/bpSpan_const.baseline | 176 ++++++++++++++++++ tests/baselines/reference/bpSpan_let.baseline | 94 ++++++++++ .../fourslash/breakpointValidationConst.ts | 25 +++ .../fourslash/breakpointValidationLet.ts | 17 ++ 4 files changed, 312 insertions(+) create mode 100644 tests/baselines/reference/bpSpan_const.baseline create mode 100644 tests/baselines/reference/bpSpan_let.baseline create mode 100644 tests/cases/fourslash/breakpointValidationConst.ts create mode 100644 tests/cases/fourslash/breakpointValidationLet.ts diff --git a/tests/baselines/reference/bpSpan_const.baseline b/tests/baselines/reference/bpSpan_const.baseline new file mode 100644 index 00000000000..bee7d930955 --- /dev/null +++ b/tests/baselines/reference/bpSpan_const.baseline @@ -0,0 +1,176 @@ + +1 >const c1 = false; + + ~~~~~~~~~~~~~~~~~~ => Pos: (0 to 17) SpanInfo: {"start":0,"length":16} + >const c1 = false + >:=> (line 1, col 0) to (line 1, col 16) +-------------------------------- +2 >const c2: number = 23; + + ~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (18 to 40) SpanInfo: {"start":18,"length":21} + >const c2: number = 23 + >:=> (line 2, col 0) to (line 2, col 21) +-------------------------------- +3 >const c3 = 0, c4 :string = "", c5 = null; + + ~~~~~~~~~~~~~ => Pos: (41 to 53) SpanInfo: {"start":41,"length":12} + >const c3 = 0 + >:=> (line 3, col 0) to (line 3, col 12) +3 >const c3 = 0, c4 :string = "", c5 = null; + + ~~~~~~~~~~~~~~~~~ => Pos: (54 to 70) SpanInfo: {"start":55,"length":15} + >c4 :string = "" + >:=> (line 3, col 14) to (line 3, col 29) +3 >const c3 = 0, c4 :string = "", c5 = null; + + ~~~~~~~~~~~~ => Pos: (71 to 82) SpanInfo: {"start":72,"length":9} + >c5 = null + >:=> (line 3, col 31) to (line 3, col 40) +-------------------------------- +4 >for(const c4 = 0; c4 < 9; ) { break; } + + ~~~~~~~~~~~~~~~~~ => Pos: (83 to 99) SpanInfo: {"start":87,"length":12} + >const c4 = 0 + >:=> (line 4, col 4) to (line 4, col 16) +4 >for(const c4 = 0; c4 < 9; ) { break; } + + ~~~~~~~~~~~~ => Pos: (100 to 111) SpanInfo: {"start":101,"length":6} + >c4 < 9 + >:=> (line 4, col 18) to (line 4, col 24) +4 >for(const c4 = 0; c4 < 9; ) { break; } + + ~~~~~~~~~~ => Pos: (112 to 121) SpanInfo: {"start":113,"length":5} + >break + >:=> (line 4, col 30) to (line 4, col 35) +-------------------------------- +5 >for(const c5 = 0, c6 = 0; c5 < c6; ) { break; } + + ~~~~~~~~~~~~~~~~~ => Pos: (122 to 138) SpanInfo: {"start":126,"length":12} + >const c5 = 0 + >:=> (line 5, col 4) to (line 5, col 16) +5 >for(const c5 = 0, c6 = 0; c5 < c6; ) { break; } + + ~~~~~~~~ => Pos: (139 to 146) SpanInfo: {"start":140,"length":6} + >c6 = 0 + >:=> (line 5, col 18) to (line 5, col 24) +5 >for(const c5 = 0, c6 = 0; c5 < c6; ) { break; } + + ~~~~~~~~~~~~~ => Pos: (147 to 159) SpanInfo: {"start":148,"length":7} + >c5 < c6 + >:=> (line 5, col 26) to (line 5, col 33) +5 >for(const c5 = 0, c6 = 0; c5 < c6; ) { break; } + + ~~~~~~~~~~=> Pos: (160 to 169) SpanInfo: {"start":161,"length":5} + >break + >:=> (line 5, col 39) to (line 5, col 44) +-------------------------------- +6 >module M { + + ~~~~~~~~~~~ => Pos: (170 to 180) SpanInfo: {"start":170,"length":133} + >module M { + > export const cc1 = false; + > export const cc2: number = 23; + > export const cc3 = 0, cc4 :string = "", cc5 = null; + >} + >:=> (line 6, col 0) to (line 10, col 1) +-------------------------------- +7 > export const cc1 = false; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (181 to 210) SpanInfo: {"start":185,"length":24} + >export const cc1 = false + >:=> (line 7, col 4) to (line 7, col 28) +-------------------------------- +8 > export const cc2: number = 23; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (211 to 245) SpanInfo: {"start":215,"length":29} + >export const cc2: number = 23 + >:=> (line 8, col 4) to (line 8, col 33) +-------------------------------- +9 > export const cc3 = 0, cc4 :string = "", cc5 = null; + + ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (246 to 270) SpanInfo: {"start":250,"length":20} + >export const cc3 = 0 + >:=> (line 9, col 4) to (line 9, col 24) +9 > export const cc3 = 0, cc4 :string = "", cc5 = null; + + ~~~~~~~~~~~~~~~~~~ => Pos: (271 to 288) SpanInfo: {"start":272,"length":16} + >cc4 :string = "" + >:=> (line 9, col 26) to (line 9, col 42) +9 > export const cc3 = 0, cc4 :string = "", cc5 = null; + + ~~~~~~~~~~~~~=> Pos: (289 to 301) SpanInfo: {"start":290,"length":10} + >cc5 = null + >:=> (line 9, col 44) to (line 9, col 54) +-------------------------------- +10 >} + + ~~ => Pos: (302 to 303) SpanInfo: {"start":302,"length":1} + >} + >:=> (line 10, col 0) to (line 10, col 1) +-------------------------------- +11 >const enum E { + + ~~~~~~~~~~~~~~~ => Pos: (304 to 318) SpanInfo: {"start":304,"length":52} + >const enum E { + > A = 1, + > B = 2, + > C = A | B + >} + >:=> (line 11, col 0) to (line 15, col 1) +-------------------------------- +12 > A = 1, + + ~~~~~~~~~~~ => Pos: (319 to 329) SpanInfo: {"start":323,"length":5} + >A = 1 + >:=> (line 12, col 4) to (line 12, col 9) +-------------------------------- +13 > B = 2, + + ~~~~~~~~~~~ => Pos: (330 to 340) SpanInfo: {"start":334,"length":5} + >B = 2 + >:=> (line 13, col 4) to (line 13, col 9) +-------------------------------- +14 > C = A | B + + ~~~~~~~~~~~~~~ => Pos: (341 to 354) SpanInfo: {"start":345,"length":9} + >C = A | B + >:=> (line 14, col 4) to (line 14, col 13) +-------------------------------- +15 >} + + ~~ => Pos: (355 to 356) SpanInfo: {"start":355,"length":1} + >} + >:=> (line 15, col 0) to (line 15, col 1) +-------------------------------- +16 >const enum E2 { + + ~~~~~~~~~~~~~~~~ => Pos: (357 to 372) SpanInfo: {"start":357,"length":41} + >const enum E2 { + > A = 1, + > B, + > C + >} + >:=> (line 16, col 0) to (line 20, col 1) +-------------------------------- +17 > A = 1, + + ~~~~~~~~~~~ => Pos: (373 to 383) SpanInfo: {"start":377,"length":5} + >A = 1 + >:=> (line 17, col 4) to (line 17, col 9) +-------------------------------- +18 > B, + + ~~~~~~~ => Pos: (384 to 390) SpanInfo: {"start":388,"length":1} + >B + >:=> (line 18, col 4) to (line 18, col 5) +-------------------------------- +19 > C + + ~~~~~~ => Pos: (391 to 396) SpanInfo: {"start":395,"length":1} + >C + >:=> (line 19, col 4) to (line 19, col 5) +-------------------------------- +20 >} + ~ => Pos: (397 to 397) SpanInfo: {"start":397,"length":1} + >} + >:=> (line 20, col 0) to (line 20, col 1) \ No newline at end of file diff --git a/tests/baselines/reference/bpSpan_let.baseline b/tests/baselines/reference/bpSpan_let.baseline new file mode 100644 index 00000000000..dff12280a96 --- /dev/null +++ b/tests/baselines/reference/bpSpan_let.baseline @@ -0,0 +1,94 @@ + +1 >let l1; + + ~~~~~~~~ => Pos: (0 to 7) SpanInfo: undefined +-------------------------------- +2 >let l2: number; + + ~~~~~~~~~~~~~~~~ => Pos: (8 to 23) SpanInfo: undefined +-------------------------------- +3 >let l3, l4, l5 :string, l6; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (24 to 51) SpanInfo: undefined +-------------------------------- +4 >let l7 = false; + + ~~~~~~~~~~~~~~~~ => Pos: (52 to 67) SpanInfo: {"start":52,"length":14} + >let l7 = false + >:=> (line 4, col 0) to (line 4, col 14) +-------------------------------- +5 >let l8: number = 23; + + ~~~~~~~~~~~~~~~~~~~~~ => Pos: (68 to 88) SpanInfo: {"start":68,"length":19} + >let l8: number = 23 + >:=> (line 5, col 0) to (line 5, col 19) +-------------------------------- +6 >let l9 = 0, l10 :string = "", l11 = null; + + ~~~~~~~~~~~ => Pos: (89 to 99) SpanInfo: {"start":89,"length":10} + >let l9 = 0 + >:=> (line 6, col 0) to (line 6, col 10) +6 >let l9 = 0, l10 :string = "", l11 = null; + + ~~~~~~~~~~~~~~~~~~ => Pos: (100 to 117) SpanInfo: {"start":101,"length":16} + >l10 :string = "" + >:=> (line 6, col 12) to (line 6, col 28) +6 >let l9 = 0, l10 :string = "", l11 = null; + + ~~~~~~~~~~~~~ => Pos: (118 to 130) SpanInfo: {"start":119,"length":10} + >l11 = null + >:=> (line 6, col 30) to (line 6, col 40) +-------------------------------- +7 >for(let l11 in {}) { } + + ~~~~~~~~~~~~~~~~~~~~ => Pos: (131 to 150) SpanInfo: {"start":131,"length":18} + >for(let l11 in {}) + >:=> (line 7, col 0) to (line 7, col 18) +7 >for(let l11 in {}) { } + + ~~~ => Pos: (151 to 153) SpanInfo: undefined +-------------------------------- +8 >for(let l12 = 0; l12 < 9; l12++) { } + + ~~~~~~~~~~~~~~~~ => Pos: (154 to 169) SpanInfo: {"start":158,"length":11} + >let l12 = 0 + >:=> (line 8, col 4) to (line 8, col 15) +8 >for(let l12 = 0; l12 < 9; l12++) { } + + ~~~~~~~~~ => Pos: (170 to 178) SpanInfo: {"start":171,"length":7} + >l12 < 9 + >:=> (line 8, col 17) to (line 8, col 24) +8 >for(let l12 = 0; l12 < 9; l12++) { } + + ~~~~~~~~~ => Pos: (179 to 187) SpanInfo: {"start":180,"length":5} + >l12++ + >:=> (line 8, col 26) to (line 8, col 31) +8 >for(let l12 = 0; l12 < 9; l12++) { } + + ~~~ => Pos: (188 to 190) SpanInfo: undefined +-------------------------------- +9 >module M { + + ~~~~~~~~~~~ => Pos: (191 to 201) SpanInfo: {"start":191,"length":55} + >module M { + > let ll1 = "s"; + > export let ll2 = 0; + >} + >:=> (line 9, col 0) to (line 12, col 1) +-------------------------------- +10 > let ll1 = "s"; + + ~~~~~~~~~~~~~~~~~~~ => Pos: (202 to 220) SpanInfo: {"start":206,"length":13} + >let ll1 = "s" + >:=> (line 10, col 4) to (line 10, col 17) +-------------------------------- +11 > export let ll2 = 0; + + ~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (221 to 244) SpanInfo: {"start":225,"length":18} + >export let ll2 = 0 + >:=> (line 11, col 4) to (line 11, col 22) +-------------------------------- +12 >} + ~ => Pos: (245 to 245) SpanInfo: {"start":245,"length":1} + >} + >:=> (line 12, col 0) to (line 12, col 1) \ No newline at end of file diff --git a/tests/cases/fourslash/breakpointValidationConst.ts b/tests/cases/fourslash/breakpointValidationConst.ts new file mode 100644 index 00000000000..bc3b530a8c2 --- /dev/null +++ b/tests/cases/fourslash/breakpointValidationConst.ts @@ -0,0 +1,25 @@ +/// + +// @BaselineFile: bpSpan_const.baseline +// @Filename: bpSpan_const.ts +////const c1 = false; +////const c2: number = 23; +////const c3 = 0, c4 :string = "", c5 = null; +////for(const c4 = 0; c4 < 9; ) { break; } +////for(const c5 = 0, c6 = 0; c5 < c6; ) { break; } +////module M { +//// export const cc1 = false; +//// export const cc2: number = 23; +//// export const cc3 = 0, cc4 :string = "", cc5 = null; +////} +////const enum E { +//// A = 1, +//// B = 2, +//// C = A | B +////} +////const enum E2 { +//// A = 1, +//// B, +//// C +////} +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file diff --git a/tests/cases/fourslash/breakpointValidationLet.ts b/tests/cases/fourslash/breakpointValidationLet.ts new file mode 100644 index 00000000000..cec696850cd --- /dev/null +++ b/tests/cases/fourslash/breakpointValidationLet.ts @@ -0,0 +1,17 @@ +/// + +// @BaselineFile: bpSpan_let.baseline +// @Filename: bpSpan_let.ts +////let l1; +////let l2: number; +////let l3, l4, l5 :string, l6; +////let l7 = false; +////let l8: number = 23; +////let l9 = 0, l10 :string = "", l11 = null; +////for(let l11 in {}) { } +////for(let l12 = 0; l12 < 9; l12++) { } +////module M { +//// let ll1 = "s"; +//// export let ll2 = 0; +////} +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file From 8ab038f1a37bcb2e45c6fcb90086a25ece534659 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Nov 2014 18:02:29 -0800 Subject: [PATCH 10/10] Fixed the merge conflicts that went undetected in github --- src/compiler/checker.ts | 2 +- src/services/services.ts | 23 +++--- ...lTypeWithUnionTypeObjectLiteral.errors.txt | 74 +++++++++---------- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8885a7e5b25..cd7ada607f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4318,7 +4318,7 @@ module ts { function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { var type = getTypeOfSymbol(symbol); // Only narrow when symbol is variable of a structured type - if (symbol.flags & SymbolFlags.Variable && type.flags & TypeFlags.Structured) { + if (node && (symbol.flags & SymbolFlags.Variable && type.flags & TypeFlags.Structured)) { while (true) { var child = node; node = node.parent; diff --git a/src/services/services.ts b/src/services/services.ts index eebf59f2fd9..4f3e84661ad 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2310,7 +2310,7 @@ module ts { return undefined; } - function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker): CompletionEntry { + function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker, location: Node): CompletionEntry { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) @@ -2325,7 +2325,7 @@ module ts { // We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration. return { name: displayName, - kind: getSymbolKind(symbol, typeChecker), + kind: getSymbolKind(symbol, typeChecker, location), kindModifiers: getSymbolModifiers(symbol) }; } @@ -2396,6 +2396,7 @@ module ts { }; host.log("getCompletionsAtPosition: Syntactic work: " + (new Date().getTime() - syntacticStart)); + var location = getTouchingPropertyName(sourceFile, position); // Populate the completion list var semanticStart = new Date().getTime(); if (isRightOfDot) { @@ -2477,7 +2478,7 @@ module ts { function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void { var start = new Date().getTime(); forEach(symbols, symbol => { - var entry = createCompletionEntry(symbol, session.typeChecker); + var entry = createCompletionEntry(symbol, session.typeChecker, location); if (entry && !lookUp(session.symbols, entry.name)) { session.entries.push(entry); session.symbols[entry.name] = symbol; @@ -2689,12 +2690,12 @@ module ts { var symbol = lookUp(activeCompletionSession.symbols, entryName); if (symbol) { - var completionEntry = createCompletionEntry(symbol, session.typeChecker); + var location = getTouchingPropertyName(sourceFile, position); + var completionEntry = createCompletionEntry(symbol, session.typeChecker, location); // TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind' // which is permissible given that it is backwards compatible; but really we should consider // passing the meaning for the node so that we don't report that a suggestion for a value is an interface. // We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration. - var location = getTouchingPropertyName(sourceFile, position); Debug.assert(session.typeChecker.getNarrowedTypeOfSymbol(symbol, location) !== undefined, "Could not find type for symbol"); var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All); return { @@ -2740,7 +2741,7 @@ module ts { } // TODO(drosen): use contextual SemanticMeaning. - function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker): string { + function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker, location?: Node): string { var flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return ScriptElementKind.classElement; @@ -2749,7 +2750,7 @@ module ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver); + var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -2759,7 +2760,7 @@ module ts { return result; } - function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker) { + function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker, location: Node) { if (typeResolver.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; } @@ -2794,7 +2795,7 @@ module ts { if (!unionPropertyKind) { // If this was union of all methods, //make sure it has call signatures before we can label it as method - var typeOfUnionProperty = typeInfoResolver.getTypeOfSymbol(symbol); + var typeOfUnionProperty = typeInfoResolver.getNarrowedTypeOfSymbol(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -2858,7 +2859,7 @@ module ts { var displayParts: SymbolDisplayPart[] = []; var documentation: SymbolDisplayPart[]; var symbolFlags = symbol.flags; - var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver); + var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver, location); var hasAddedSymbolInfo: boolean; // Class at constructor site need to be shown as constructor apart from property,method, vars if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Import) { @@ -3113,7 +3114,7 @@ module ts { } } else { - symbolKind = getSymbolKind(symbol, typeResolver); + symbolKind = getSymbolKind(symbol, typeResolver, location); } } diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt index 6ca334ef311..8be323f9af4 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt +++ b/tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt @@ -1,29 +1,29 @@ -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(14,5): error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(14,5): error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(20,5): error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(20,5): error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(21,5): error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(21,5): error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'. Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(25,5): error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(25,5): error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'. Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(29,5): error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(29,5): error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'. Types of property 'prop' are incompatible. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. +tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2322: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'. Types of property 'commonMethodDifferentReturnType' are incompatible. Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'. @@ -47,11 +47,11 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts( // Since T is union Type we only allow the assignment of either object with property of type string or object with property of type number but do not allow object with property of type string | number var objStrOrNum3: { prop: string } | { prop: number } = { ~~~~~~~~~~~~ -!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. -!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. -!!! error TS2323: Types of property 'prop' are incompatible. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; } | { prop: number; }'. +!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. prop: strOrNumber }; var objStrOrNum4: { prop: string | number } = { @@ -59,38 +59,38 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts( }; var objStrOrNum5: { prop: string; anotherP: string; } | { prop: number } = { prop: strOrNumber }; ~~~~~~~~~~~~ -!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. -!!! error TS2323: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. -!!! error TS2323: Types of property 'prop' are incompatible. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = { ~~~~~~~~~~~~ -!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. -!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'. -!!! error TS2323: Types of property 'prop' are incompatible. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. prop: strOrNumber, anotherP: str }; var objStrOrNum7: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { ~~~~~~~~~~~~ -!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. -!!! error TS2323: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'. -!!! error TS2323: Types of property 'prop' are incompatible. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. prop: strOrNumber, anotherP: str }; var objStrOrNum8: { prop: string; anotherP: string; } | { prop: number; anotherP1: number } = { ~~~~~~~~~~~~ -!!! error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. -!!! error TS2323: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'. -!!! error TS2323: Types of property 'prop' are incompatible. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'. +!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. prop: strOrNumber, anotherP: str, anotherP1: num @@ -120,11 +120,11 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts( var strOrNumber: string | number; var i11Ori21: I11 | I21 = { // Like i1 and i2 both ~~~~~~~~ -!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. -!!! error TS2323: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'. -!!! error TS2323: Types of property 'commonMethodDifferentReturnType' are incompatible. -!!! error TS2323: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'. -!!! error TS2323: Type 'string | number' is not assignable to type 'number'. -!!! error TS2323: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'. +!!! error TS2322: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'. +!!! error TS2322: Types of property 'commonMethodDifferentReturnType' are incompatible. +!!! error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. commonMethodDifferentReturnType: (a, b) => strOrNumber, }; \ No newline at end of file