From b409888cbcce4b0c393d9fa7b255905b5a6efcad Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:01:24 -0700 Subject: [PATCH 01/20] Added tests. --- .../taggedTemplatesWithTypeArguments1.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts new file mode 100644 index 0000000000000..90509938dbc58 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts @@ -0,0 +1,44 @@ +// @target: esnext + +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; \ No newline at end of file From 23567ee05daa02b3acf1ad3e19431c8415701908 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:01:34 -0700 Subject: [PATCH 02/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments1.errors.txt | 82 ++++++++ .../taggedTemplatesWithTypeArguments1.js | 66 +++++++ .../taggedTemplatesWithTypeArguments1.symbols | 136 +++++++++++++ .../taggedTemplatesWithTypeArguments1.types | 181 ++++++++++++++++++ 4 files changed, 465 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.js create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.types diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt new file mode 100644 index 0000000000000..700c98d54fe81 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt @@ -0,0 +1,82 @@ +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,50): error TS1005: ',' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,30): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,53): error TS1128: Declaration or statement expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(41,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + + +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (10 errors) ==== + declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + + interface Stuff { + x: number; + y: string; + z: boolean; + } + + export const a = f ` + ~~~~~~~~~~ + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + hello + ~~~~~~~~~ + ${stuff => stuff.x} + ~~~~~~~~~~~~~~~~~~~~~~~ + brave + ~~~~~~~~~ + ${stuff => stuff.y} + ~~~~~~~~~~~~~~~~~~~~~~~ + world + ~~~~~~~~~ + ${stuff => stuff.z} + ~~~~~~~~~~~~~~~~~~~~~~~ + `; + ~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. + + declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + + export const b = g ` + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + ~ +!!! error TS1005: ',' expected. + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} + `; + + declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } + } + + export const c = obj["prop"] `${(input) => { ...input }}` + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + ~~~ +!!! error TS1128: Declaration or statement expected. + c.returnedProp.x; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + c.returnedProp.y; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + c.returnedProp.z; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js new file mode 100644 index 0000000000000..629571b4db0a2 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -0,0 +1,66 @@ +//// [taggedTemplatesWithTypeArguments1.ts] +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; + +//// [taggedTemplatesWithTypeArguments1.js] +export const a = f < Stuff > ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export const b = g < Stuff, number, string, boolean; + > ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export const c = obj["prop"] < Stuff > `${(input) => { input; }}`; +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols new file mode 100644 index 0000000000000..85170aad228e3 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -0,0 +1,136 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 22)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>callbacks : Symbol(callbacks, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 49)) +>Array : Symbol(Array, Decl(lib.es2016.array.include.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 1 more) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 71)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) + + x: number; +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + + y: string; +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + + z: boolean; +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +} + +export const a = f ` +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments1.ts, 8, 12)) +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) + +`; + +declare function g( +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + + strs: TemplateStringsArray, +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 35)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments1.ts, 18, 31)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 8)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>u : Symbol(u, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 23)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 28)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>v : Symbol(v, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 43)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 48)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + +export const b = g ` +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 12)) +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>number : Symbol(number, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 25)) +>string : Symbol(string, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 33)) +>boolean : Symbol(boolean, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 41)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) + +`; + +declare let obj: { +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 14)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 41)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 46)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + + returnedObjProp: { +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + + lastOne: T +>lastOne : Symbol(lastOne, Decl(taggedTemplatesWithTypeArguments1.ts, 32, 26)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>"prop" : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) + +c.returnedProp.x; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + +c.returnedProp.y; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + +c.returnedProp.z; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types new file mode 100644 index 0000000000000..9999bb67bd8cb --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -0,0 +1,181 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>callbacks : ((x: T) => any)[] +>Array : T[] +>x : T +>T : T + +interface Stuff { +>Stuff : Stuff + + x: number; +>x : number + + y: string; +>y : string + + z: boolean; +>z : boolean +} + +export const a = f ` +>a : boolean +>f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean +>ff : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>Stuff : any +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: any) => any +>stuff : any +>stuff.x : any +>stuff : any +>x : any + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: any) => any +>stuff : any +>stuff.y : any +>stuff : any +>y : any + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: any) => any +>stuff : any +>stuff.z : any +>stuff : any +>z : any + +`; + +declare function g( +>g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Input : Input +>T : T +>U : U +>V : V + + strs: TemplateStringsArray, +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : (i: Input) => T +>i : Input +>Input : Input +>T : T +>u : (i: Input) => U +>i : Input +>Input : Input +>U : U +>v : (i: Input) => V +>i : Input +>Input : Input +>V : V +>T : T +>U : U +>V : V + +export const b = g ` +>b : boolean +>gg : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Stuff : any +>number : any +>string : any +>boolean : any +>> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean +> : any +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: any) => any +>stuff : any +>stuff.x : any +>stuff : any +>x : any + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: any) => any +>stuff : any +>stuff.y : any +>stuff : any +>y : any + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: any) => any +>stuff : any +>stuff.z : any +>stuff : any +>z : any + +`; + +declare let obj: { +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>x : (input: T) => T +>input : T +>T : T +>T : T + + returnedObjProp: { +>returnedObjProp : { lastOne: T; } + + lastOne: T +>lastOne : T +>T : T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +>c : boolean +>obj["prop"] `${(input) => { ...input }}` : boolean +>obj["prop"]obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +>"prop" : "prop" +>Stuff : any +>`${(input) => { ...input }}` : string +>(input) => { ...input } : (input: any) => void +>input : any +>input : any + +c.returnedProp.x; +>c.returnedProp.x : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>x : any + +c.returnedProp.y; +>c.returnedProp.y : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>y : any + +c.returnedProp.z; +>c.returnedProp.z : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>z : any + From 60b6d3fbce4f25d099995e2a62a9252f8546d5bf Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:14:13 -0700 Subject: [PATCH 03/20] Fixed up test. Thanks arrow functions... --- .../taggedTemplatesWithTypeArguments1.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts index 90509938dbc58..2f3fc71e65d04 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts @@ -32,13 +32,16 @@ export const b = g ` declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } -export const c = obj["prop"] `${(input) => { ...input }}` -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; \ No newline at end of file +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; \ No newline at end of file From da7967a3cf535c131791e94f52bc0eb6d872fae3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:15:02 -0700 Subject: [PATCH 04/20] Added basic support for parsing/emitting type arguments in tagged template expressions. --- src/compiler/emitter.ts | 1 + src/compiler/parser.ts | 36 +++++++++++++++++++++++++++--------- src/compiler/types.ts | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 289f332cd33f3..2b01f2fdda1bc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1462,6 +1462,7 @@ namespace ts { function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { emitExpression(node.tag); + emitTypeArguments(node, node.typeArguments); writeSpace(); emitExpression(node.template); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 74d54ed28fb14..29d57c846f5d9 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -223,6 +223,7 @@ namespace ts { visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.TaggedTemplateExpression: return visitNode(cbNode, (node).tag) || + visitNodes(cbNode, cbNodes, (node).typeArguments) || visitNode(cbNode, (node).template); case SyntaxKind.TypeAssertionExpression: return visitNode(cbNode, (node).type) || @@ -4362,18 +4363,28 @@ namespace ts { continue; } - if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) { - const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, expression.pos); - tagExpression.tag = expression; - tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral - ? parseLiteralNode() - : parseTemplateExpression(); - expression = finishNode(tagExpression); + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined); continue; } return expression; } + + } + + function isTemplateStartOfTaggedTemplate() { + return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; + } + + function parseTaggedTemplateRest(tag: LeftHandSideExpression, typeArguments: NodeArray | undefined) { + const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, tag.pos); + tagExpression.tag = tag; + tagExpression.typeArguments = typeArguments; + tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral + ? parseLiteralNode() + : parseTemplateExpression(); + return finishNode(tagExpression); } function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { @@ -4389,6 +4400,11 @@ namespace ts { return expression; } + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, typeArguments); + continue; + } + const callExpr = createNode(SyntaxKind.CallExpression, expression.pos); callExpr.expression = expression; callExpr.typeArguments = typeArguments; @@ -4436,8 +4452,10 @@ namespace ts { function canFollowTypeArgumentsInExpression(): boolean { switch (token()) { case SyntaxKind.OpenParenToken: // foo( - // this case are the only case where this token can legally follow a type argument - // list. So we definitely want to treat this as a type arg list. + case SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` + case SyntaxKind.TemplateHead: // foo `...${100}...` + // these are the only tokens can legally follow a type argument + // list. So we definitely want to treat them as type arg lists. case SyntaxKind.DotToken: // foo. case SyntaxKind.CloseParenToken: // foo) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 987d403e7cd9e..f96ea05cb12d7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1726,6 +1726,7 @@ namespace ts { export interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } From 090f6bd77c53f2fe945dfefba69a1f7a99fe6ab8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:23:05 -0700 Subject: [PATCH 05/20] Accepted baselines. --- .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + ...ggedTemplatesWithTypeArguments1.errors.txt | 92 +++++----- .../taggedTemplatesWithTypeArguments1.js | 34 ++-- .../taggedTemplatesWithTypeArguments1.symbols | 62 +++++-- .../taggedTemplatesWithTypeArguments1.types | 157 ++++++++++-------- 6 files changed, 205 insertions(+), 142 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2e8e3f3871df3..ae99f93ae1a47 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 378949d5b5b07..c419eceaf95fa 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt index 700c98d54fe81..6b732dbf4aa9f 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt @@ -1,16 +1,18 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,50): error TS1005: ',' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,30): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,53): error TS1128: Declaration or statement expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(41,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(11,22): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(13,22): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(15,22): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(24,22): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(26,22): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(28,22): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(38,19): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,19): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,19): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(43,19): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(44,19): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(45,19): error TS2339: Property 'z' does not exist on type '{}'. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (10 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (12 errors) ==== declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; interface Stuff { @@ -20,63 +22,63 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3) } export const a = f ` - ~~~~~~~~~~ - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. hello - ~~~~~~~~~ ${stuff => stuff.x} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. brave - ~~~~~~~~~ ${stuff => stuff.y} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. world - ~~~~~~~~~ ${stuff => stuff.z} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. `; - ~ -!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. declare function g( strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; export const b = g ` - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. - ~ -!!! error TS1005: ',' expected. hello ${stuff => stuff.x} + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. brave ${stuff => stuff.y} + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. world ${stuff => stuff.z} + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. `; declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } - export const c = obj["prop"] `${(input) => { ...input }}` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. - ~~~ -!!! error TS1128: Declaration or statement expected. - c.returnedProp.x; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. - c.returnedProp.y; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. - c.returnedProp.z; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. \ No newline at end of file + export let c = obj["prop"] `${(input) => ({ ...input })}` + c.returnedObjProp.x; + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. + c.returnedObjProp.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. + c.returnedObjProp.z; + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. + + c = obj.prop `${(input) => ({ ...input })}` + c.returnedObjProp.x; + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. + c.returnedObjProp.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. + c.returnedObjProp.z; + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js index 629571b4db0a2..9d2474da8be53 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -31,19 +31,22 @@ export const b = g ` declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } -export const c = obj["prop"] `${(input) => { ...input }}` -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; //// [taggedTemplatesWithTypeArguments1.js] -export const a = f < Stuff > ` +export const a = f ` hello ${stuff => stuff.x} brave @@ -51,8 +54,7 @@ export const a = f < Stuff > ` world ${stuff => stuff.z} `; -export const b = g < Stuff, number, string, boolean; - > ` +export const b = g ` hello ${stuff => stuff.x} brave @@ -60,7 +62,11 @@ export const b = g < Stuff, number, string, boolean; world ${stuff => stuff.z} `; -export const c = obj["prop"] < Stuff > `${(input) => { input; }}`; -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; +export let c = obj["prop"] `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; +c = obj.prop `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols index 85170aad228e3..c90089e50cc41 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -25,6 +25,7 @@ interface Stuff { export const a = f ` >a : Symbol(a, Decl(taggedTemplatesWithTypeArguments1.ts, 8, 12)) >f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) hello ${stuff => stuff.x} @@ -74,9 +75,7 @@ declare function g( export const b = g ` >b : Symbol(b, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 12)) >g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) ->number : Symbol(number, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 25)) ->string : Symbol(string, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 33)) ->boolean : Symbol(boolean, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 41)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) hello ${stuff => stuff.x} @@ -108,29 +107,56 @@ declare let obj: { >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) - returnedObjProp: { + returnedObjProp: T >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) - - lastOne: T ->lastOne : Symbol(lastOne, Decl(taggedTemplatesWithTypeArguments1.ts, 32, 26)) >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) - } } } -export const c = obj["prop"] `${(input) => { ...input }}` ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) >"prop" : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) ->input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) ->input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) -c.returnedProp.x; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c.returnedObjProp.x; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) -c.returnedProp.y; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c.returnedObjProp.y; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c.returnedObjProp.z; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) -c.returnedProp.z; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c = obj.prop `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>obj.prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) + +c.returnedObjProp.x; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c.returnedObjProp.y; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c.returnedObjProp.z; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types index 9999bb67bd8cb..74f916d0efab9 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -23,35 +23,34 @@ interface Stuff { } export const a = f ` ->a : boolean ->f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean ->fa : void +>f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : void >f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void ->Stuff : any +>Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: any) => any ->stuff : any +>stuff => stuff.x : (stuff: {}) => any +>stuff : {} >stuff.x : any ->stuff : any +>stuff : {} >x : any brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: any) => any ->stuff : any +>stuff => stuff.y : (stuff: {}) => any +>stuff : {} >stuff.y : any ->stuff : any +>stuff : {} >y : any world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: any) => any ->stuff : any +>stuff => stuff.z : (stuff: {}) => any +>stuff : {} >stuff.z : any ->stuff : any +>stuff : {} >z : any `; @@ -85,48 +84,43 @@ declare function g( >V : V export const b = g ` ->b : boolean ->gb : any +>g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : any >g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V ->Stuff : any ->number : any ->string : any ->boolean : any ->> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean -> : any +>Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: any) => any ->stuff : any +>stuff => stuff.x : (stuff: {}) => any +>stuff : {} >stuff.x : any ->stuff : any +>stuff : {} >x : any brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: any) => any ->stuff : any +>stuff => stuff.y : (stuff: {}) => any +>stuff : {} >stuff.y : any ->stuff : any +>stuff : {} >y : any world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: any) => any ->stuff : any +>stuff => stuff.z : (stuff: {}) => any +>stuff : {} >stuff.z : any ->stuff : any +>stuff : {} >z : any `; declare let obj: { ->obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } prop: (strs: TemplateStringsArray, x: (input: T) => T) => { ->prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >T : T >strs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray @@ -135,47 +129,80 @@ declare let obj: { >T : T >T : T - returnedObjProp: { ->returnedObjProp : { lastOne: T; } - - lastOne: T ->lastOne : T + returnedObjProp: T +>returnedObjProp : T >T : T - } } } -export const c = obj["prop"] `${(input) => { ...input }}` ->c : boolean ->obj["prop"] `${(input) => { ...input }}` : boolean ->obj["prop"]obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } ->obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : { returnedObjProp: {}; } +>obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >"prop" : "prop" ->Stuff : any ->`${(input) => { ...input }}` : string ->(input) => { ...input } : (input: any) => void ->input : any ->input : any - -c.returnedProp.x; ->c.returnedProp.x : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: {}) => {} +>input : {} +>({ ...input }) : {} +>{ ...input } : {} +>input : {} + +c.returnedObjProp.x; +>c.returnedObjProp.x : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>x : any + +c.returnedObjProp.y; +>c.returnedObjProp.y : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>y : any + +c.returnedObjProp.z; +>c.returnedObjProp.z : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>z : any + +c = obj.prop `${(input) => ({ ...input })}` +>c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c : { returnedObjProp: {}; } +>obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>obj.prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: {}) => {} +>input : {} +>({ ...input }) : {} +>{ ...input } : {} +>input : {} + +c.returnedObjProp.x; +>c.returnedObjProp.x : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >x : any -c.returnedProp.y; ->c.returnedProp.y : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +c.returnedObjProp.y; +>c.returnedObjProp.y : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >y : any -c.returnedProp.z; ->c.returnedProp.z : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +c.returnedObjProp.z; +>c.returnedObjProp.z : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >z : any From 7aa916a5cb477e1c7a6361c642770d67bb38c4c6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:35:32 -0700 Subject: [PATCH 06/20] Strip away type arguments from tagged templates when emitting. --- src/compiler/factory.ts | 8 +++++--- src/compiler/transformers/ts.ts | 11 +++++++++++ src/compiler/visitor.ts | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 765c3c9cb4a26..7dd7216725a9b 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1032,17 +1032,19 @@ namespace ts { : node; } - export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); + node.typeArguments = typeArguments; node.template = template; return node; } - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { return node.tag !== tag + || node.typeArguments !== typeArguments || node.template !== template - ? updateNode(createTaggedTemplate(tag, template), node) + ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) : node; } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6cb4be16c74ac..f29829d46078e 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -502,6 +502,9 @@ namespace ts { case SyntaxKind.NewExpression: return visitNewExpression(node); + case SyntaxKind.TaggedTemplateExpression: + return visitTaggedTemplateExpression(node); + case SyntaxKind.NonNullExpression: // TypeScript non-null expressions are removed, but their subtrees are preserved. return visitNonNullExpression(node); @@ -2547,6 +2550,14 @@ namespace ts { visitNodes(node.arguments, visitor, isExpression)); } + function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { + return updateTaggedTemplate( + node, + visitNode(node.tag, visitor, isExpression), + /*typeArguments*/ undefined, + visitNode(node.template, visitor, isExpression)); + } + /** * Determines whether to emit an enum declaration. * diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 7a70eb02e8e97..284d870caa1e6 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -478,6 +478,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: return updateTaggedTemplate(node, visitNode((node).tag, visitor, isExpression), + visitNodes((node).typeArguments, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); case SyntaxKind.TypeAssertionExpression: From 4785acb8cd6a5529c77e26320a98b5aaee962cb6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:35:42 -0700 Subject: [PATCH 07/20] Accepted baselines. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++-- tests/baselines/reference/api/typescript.d.ts | 4 ++-- .../reference/taggedTemplatesWithTypeArguments1.js | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ae99f93ae1a47..a250dcf69619f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3517,8 +3517,8 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c419eceaf95fa..4e15b26a13dbd 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3517,8 +3517,8 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js index 9d2474da8be53..b31d327020813 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -46,7 +46,7 @@ c.returnedObjProp.y; c.returnedObjProp.z; //// [taggedTemplatesWithTypeArguments1.js] -export const a = f ` +export const a = f ` hello ${stuff => stuff.x} brave @@ -54,7 +54,7 @@ export const a = f ` world ${stuff => stuff.z} `; -export const b = g ` +export const b = g ` hello ${stuff => stuff.x} brave @@ -62,11 +62,11 @@ export const b = g ` world ${stuff => stuff.z} `; -export let c = obj["prop"] `${(input) => ({ ...input })}`; +export let c = obj["prop"] `${(input) => ({ ...input })}`; c.returnedObjProp.x; c.returnedObjProp.y; c.returnedObjProp.z; -c = obj.prop `${(input) => ({ ...input })}`; +c = obj.prop `${(input) => ({ ...input })}`; c.returnedObjProp.x; c.returnedObjProp.y; c.returnedObjProp.z; From 82e09c908e3cf80cea12d2eb05a458a9a2b87811 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:43:49 -0700 Subject: [PATCH 08/20] Perform checking and resolution of tagged template type arguments. --- src/compiler/checker.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d009a956c43ee..60fcf10304146 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17749,7 +17749,11 @@ namespace ts { let typeArguments: NodeArray; - if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) { + if (isTaggedTemplate) { + typeArguments = (node as TaggedTemplateExpression).typeArguments; + forEach(typeArguments, checkSourceElement); + } + else if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. @@ -17866,7 +17870,7 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); @@ -18660,6 +18664,7 @@ namespace ts { } function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type { + checkGrammarTypeArguments(node, node.typeArguments); if (languageVersion < ScriptTarget.ES2015) { checkExternalEmitHelpers(node, ExternalEmitHelpers.MakeTemplateObject); } From fe8615d0a8ebbffc55a5f177d638f46259e57bb7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:44:07 -0700 Subject: [PATCH 09/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments1.errors.txt | 84 ---------- .../taggedTemplatesWithTypeArguments1.symbols | 24 +++ .../taggedTemplatesWithTypeArguments1.types | 154 +++++++++--------- 3 files changed, 101 insertions(+), 161 deletions(-) delete mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt deleted file mode 100644 index 6b732dbf4aa9f..0000000000000 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt +++ /dev/null @@ -1,84 +0,0 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(11,22): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(13,22): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(15,22): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(24,22): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(26,22): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(28,22): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(38,19): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,19): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,19): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(43,19): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(44,19): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(45,19): error TS2339: Property 'z' does not exist on type '{}'. - - -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (12 errors) ==== - declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; - - interface Stuff { - x: number; - y: string; - z: boolean; - } - - export const a = f ` - hello - ${stuff => stuff.x} - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - brave - ${stuff => stuff.y} - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - world - ${stuff => stuff.z} - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - `; - - declare function g( - strs: TemplateStringsArray, - t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; - - export const b = g ` - hello - ${stuff => stuff.x} - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - brave - ${stuff => stuff.y} - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - world - ${stuff => stuff.z} - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - `; - - declare let obj: { - prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: T - } - } - - export let c = obj["prop"] `${(input) => ({ ...input })}` - c.returnedObjProp.x; - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - c.returnedObjProp.y; - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - c.returnedObjProp.z; - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - - c = obj.prop `${(input) => ({ ...input })}` - c.returnedObjProp.x; - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - c.returnedObjProp.y; - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - c.returnedObjProp.z; - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols index c90089e50cc41..798d2e18c68ac 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -30,17 +30,23 @@ export const a = f ` hello ${stuff => stuff.x} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) brave ${stuff => stuff.y} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) world ${stuff => stuff.z} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) `; @@ -80,17 +86,23 @@ export const b = g ` hello ${stuff => stuff.x} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) brave ${stuff => stuff.y} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) world ${stuff => stuff.z} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) `; @@ -122,19 +134,25 @@ export let c = obj["prop"] `${(input) => ({ ...input })}` >input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) c = obj.prop `${(input) => ({ ...input })}` >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) @@ -146,17 +164,23 @@ c = obj.prop `${(input) => ({ ...input })}` >input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types index 74f916d0efab9..afa83c1b89051 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -31,27 +31,27 @@ export const a = f ` hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: {}) => any ->stuff : {} ->stuff.x : any ->stuff : {} ->x : any +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: {}) => any ->stuff : {} ->stuff.y : any ->stuff : {} ->y : any +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: {}) => any ->stuff : {} ->stuff.z : any ->stuff : {} ->z : any +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean `; @@ -84,35 +84,35 @@ declare function g( >V : V export const b = g ` ->b : any ->g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : any +>b : string | number | boolean +>g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string | number | boolean >g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V >Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: {}) => any ->stuff : {} ->stuff.x : any ->stuff : {} ->x : any +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: {}) => any ->stuff : {} ->stuff.y : any ->stuff : {} ->y : any +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: {}) => any ->stuff : {} ->stuff.z : any ->stuff : {} ->z : any +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean `; @@ -136,73 +136,73 @@ declare let obj: { } export let c = obj["prop"] `${(input) => ({ ...input })}` ->c : { returnedObjProp: {}; } ->obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c : { returnedObjProp: Stuff; } +>obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } >obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >"prop" : "prop" >Stuff : Stuff >`${(input) => ({ ...input })}` : string ->(input) => ({ ...input }) : (input: {}) => {} ->input : {} ->({ ...input }) : {} ->{ ...input } : {} ->input : {} +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff c.returnedObjProp.x; ->c.returnedObjProp.x : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->x : any +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number c.returnedObjProp.y; ->c.returnedObjProp.y : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->y : any +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string c.returnedObjProp.z; ->c.returnedObjProp.z : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->z : any +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean c = obj.prop `${(input) => ({ ...input })}` ->c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } ->c : { returnedObjProp: {}; } ->obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } +>c : { returnedObjProp: Stuff; } +>obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } >obj.prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >Stuff : Stuff >`${(input) => ({ ...input })}` : string ->(input) => ({ ...input }) : (input: {}) => {} ->input : {} ->({ ...input }) : {} ->{ ...input } : {} ->input : {} +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff c.returnedObjProp.x; ->c.returnedObjProp.x : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->x : any +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number c.returnedObjProp.y; ->c.returnedObjProp.y : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->y : any +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string c.returnedObjProp.z; ->c.returnedObjProp.z : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->z : any +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean From 6107e05e8cdeefc598d49ec10f21c61dc325a0e2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 15:56:59 -0700 Subject: [PATCH 10/20] Added test for tagged templates in new expressions. --- .../taggedTemplatesWithTypeArguments2.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts new file mode 100644 index 0000000000000..9c9bb8ee9386c --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -0,0 +1,20 @@ +// @target: esnext +// @strict: true + +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); From 2510c19fbd64baba32d9b4c656c9902163fb10d7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 15:59:23 -0700 Subject: [PATCH 11/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 66 +++++++++++++++++ .../taggedTemplatesWithTypeArguments2.js | 25 +++++++ .../taggedTemplatesWithTypeArguments2.symbols | 42 +++++++++++ .../taggedTemplatesWithTypeArguments2.types | 70 +++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.js create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.types diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt new file mode 100644 index 0000000000000..958fb6715d165 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -0,0 +1,66 @@ +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,60): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,68): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68): error TS1005: ')' expected. + + +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (15 errors) ==== + export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; + } + + export interface SomethingNewable { + new (...args: T[]): any; + } + + declare const tag: SomethingTaggable; + + const a = new tag `${100} ${200}`("hello", "world"); + + const b = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + + const c = new tag `${100} ${200}`("hello", "world"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + + const d = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js new file mode 100644 index 0000000000000..3d2012eb0acdb --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -0,0 +1,25 @@ +//// [taggedTemplatesWithTypeArguments2.ts] +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); + + +//// [taggedTemplatesWithTypeArguments2.js] +const a = new tag `${100} ${200}`("hello", "world"); +const b = new tag(`${"hello"} ${"world"}`(100, 200)); +const c = new tag(`${100} ${200}`("hello", "world")); +const d = new tag(`${"hello"} ${"world"}`(100, 200)); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols new file mode 100644 index 0000000000000..720b03dd32563 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 8)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 32)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) +} + +export interface SomethingNewable { +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) + + new (...args: T[]): any; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 12)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +} + +declare const tag: SomethingTaggable; +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + +const a = new tag `${100} ${200}`("hello", "world"); +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments2.ts, 10, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments2.ts, 12, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const c = new tag `${100} ${200}`("hello", "world"); +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments2.ts, 14, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : Symbol(d, Decl(taggedTemplatesWithTypeArguments2.ts, 16, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types new file mode 100644 index 0000000000000..bc05e62fcdcd7 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : SomethingTaggable + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : T +>t : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>args : T[] +>T : T +>SomethingNewable : SomethingNewable +} + +export interface SomethingNewable { +>SomethingNewable : SomethingNewable + + new (...args: T[]): any; +>T : T +>args : T[] +>T : T +} + +declare const tag: SomethingTaggable; +>tag : SomethingTaggable +>SomethingTaggable : SomethingTaggable + +const a = new tag `${100} ${200}`("hello", "world"); +>a : any +>new tag `${100} ${200}`("hello", "world") : any +>tag `${100} ${200}` : SomethingNewable +>tag : SomethingTaggable +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}`(100, 200) : any +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + +const c = new tag `${100} ${200}`("hello", "world"); +>c : any +>new tag `${100} ${200}`("hello", "world") : any +>tag : SomethingTaggable +>`${100} ${200}`("hello", "world") : any +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}`(100, 200) : any +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + From eb8eeafc224758690e8e7fefec94ac0bde60efe9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 16:04:25 -0700 Subject: [PATCH 12/20] Allow parsing tagged templates with type arguments in new expressions. --- src/compiler/parser.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 29d57c846f5d9..f5dd8fa764dc3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4684,9 +4684,23 @@ namespace ts { return finishNode(node); } + let expression: MemberExpression = parsePrimaryExpression(); + let typeArguments; + while (true) { + expression = parseMemberExpressionRest(expression); + typeArguments = tryParse(parseTypeArgumentsInExpression); + if (isTemplateStartOfTaggedTemplate()) { + Debug.assert(!!typeArguments, + "Expected a type argument list; all plain tagged template starts should be consumed in 'parseMemberExpressionRest'"); + expression = parseTaggedTemplateRest(expression, typeArguments); + typeArguments = undefined; + } + break; + } + const node = createNode(SyntaxKind.NewExpression, fullStart); - node.expression = parseMemberExpressionOrHigher(); - node.typeArguments = tryParse(parseTypeArgumentsInExpression); + node.expression = expression; + node.typeArguments = typeArguments; if (node.typeArguments || token() === SyntaxKind.OpenParenToken) { node.arguments = parseArgumentList(); } From a2073f121758a8c8478ebea80e99a52d0f124ca4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 16:04:47 -0700 Subject: [PATCH 13/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 54 ++++--------------- .../taggedTemplatesWithTypeArguments2.js | 6 +-- .../taggedTemplatesWithTypeArguments2.types | 8 +-- 3 files changed, 17 insertions(+), 51 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 958fb6715d165..51b8bd34e0c61 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -1,21 +1,9 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,60): error TS1005: ')' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,68): error TS1005: ')' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2347: Untyped function calls may not accept type arguments. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (15 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (3 errors) ==== export interface SomethingTaggable { (t: TemplateStringsArray, ...args: T[]): SomethingNewable; } @@ -29,38 +17,14 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68 const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. const c = new tag `${100} ${200}`("hello", "world"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. +!!! error TS2347: Untyped function calls may not accept type arguments. const d = new tag `${"hello"} ${"world"}`(100, 200); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 3d2012eb0acdb..33e9fef3d7fb9 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -20,6 +20,6 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); -const b = new tag(`${"hello"} ${"world"}`(100, 200)); -const c = new tag(`${100} ${200}`("hello", "world")); -const d = new tag(`${"hello"} ${"world"}`(100, 200)); +const b = new tag `${"hello"} ${"world"}`(100, 200); +const c = (new tag `${100} ${200}`)("hello", "world"); +const d = (new tag `${"hello"} ${"world"}`)(100, 200); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index bc05e62fcdcd7..cd4ff1c6e13e9 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -38,8 +38,8 @@ const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); >b : any >new tag `${"hello"} ${"world"}`(100, 200) : any +>tag `${"hello"} ${"world"}` : any >tag : SomethingTaggable ->`${"hello"} ${"world"}`(100, 200) : any >`${"hello"} ${"world"}` : string >"hello" : "hello" >"world" : "world" @@ -49,8 +49,9 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); >c : any >new tag `${100} ${200}`("hello", "world") : any +>new tag `${100} ${200}` : any +>tag `${100} ${200}` : SomethingNewable >tag : SomethingTaggable ->`${100} ${200}`("hello", "world") : any >`${100} ${200}` : string >100 : 100 >200 : 200 @@ -60,8 +61,9 @@ const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); >d : any >new tag `${"hello"} ${"world"}`(100, 200) : any +>new tag `${"hello"} ${"world"}` : any +>tag `${"hello"} ${"world"}` : any >tag : SomethingTaggable ->`${"hello"} ${"world"}`(100, 200) : any >`${"hello"} ${"world"}` : string >"hello" : "hello" >"world" : "world" From 4bfb1a3aa14972e536247feac316546d9965e790 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Apr 2018 14:09:42 -0700 Subject: [PATCH 14/20] Avoid breaking change by introducing overloads for 'createTaggedTemplate'/'updateTaggedTemplate'. --- src/compiler/factory.ts | 27 ++++++++++++++++++++------- src/compiler/parser.ts | 1 - 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 7dd7216725a9b..e3191930c0e5e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1032,19 +1032,32 @@ namespace ts { : node; } - export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + /** @internal */ + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); - node.typeArguments = typeArguments; - node.template = template; + if (template) { + node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray); + node.template = template!; + } + else { + node.typeArguments = undefined; + node.template = typeArgumentsOrTemplate as TemplateLiteral; + } return node; } - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { return node.tag !== tag - || node.typeArguments !== typeArguments - || node.template !== template - ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) + || (template + ? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template + : node.typeArguments !== undefined || node.template !== typeArgumentsOrTemplate) + ? updateNode(createTaggedTemplate(tag, typeArgumentsOrTemplate, template), node) : node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f5dd8fa764dc3..4cf4c6e4c6709 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4370,7 +4370,6 @@ namespace ts { return expression; } - } function isTemplateStartOfTaggedTemplate() { From 78e98c37841b17ce7d5c540050cc1e4925458d1c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Apr 2018 14:15:36 -0700 Subject: [PATCH 15/20] Accepted baselines. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 6 ++++-- tests/baselines/reference/api/typescript.d.ts | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a250dcf69619f..06ecede8c881e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3517,8 +3517,10 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 4e15b26a13dbd..9d99813cfe17d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3517,8 +3517,10 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; From 8e27f4693cfe1b3e9905e37ffc9c4d37f51c3456 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 10:34:31 -0700 Subject: [PATCH 16/20] Added test for ASI concerns. --- .../templates/taggedTemplatesWithTypeArguments2.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts index 9c9bb8ee9386c..432e7a217487d 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -18,3 +18,14 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); \ No newline at end of file From e21a8b8cfd70cd8709613a4dd4085cc98ad8a46a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 10:34:43 -0700 Subject: [PATCH 17/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 12 ++++++++++- .../taggedTemplatesWithTypeArguments2.js | 21 ++++++++++++++++++- .../taggedTemplatesWithTypeArguments2.symbols | 13 ++++++++++++ .../taggedTemplatesWithTypeArguments2.types | 17 +++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 51b8bd34e0c61..9dcc630e71b70 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -27,4 +27,14 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30 const d = new tag `${"hello"} ${"world"}`(100, 200); ~~~~~~~ !!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. - \ No newline at end of file + + /** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ + const e = new tag + `hello`(); \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 33e9fef3d7fb9..879c274e52fca 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -16,10 +16,29 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); - + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); const c = (new tag `${100} ${200}`)("hello", "world"); const d = (new tag `${"hello"} ${"world"}`)(100, 200); +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag `hello`(); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols index 720b03dd32563..049b844bdf2b3 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -40,3 +40,16 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); >d : Symbol(d, Decl(taggedTemplatesWithTypeArguments2.ts, 16, 5)) >tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : Symbol(e, Decl(taggedTemplatesWithTypeArguments2.ts, 26, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +`hello`(); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index cd4ff1c6e13e9..07afb0becc63c 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -70,3 +70,20 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); >100 : 100 >200 : 200 +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : any +>new tag`hello`() : any +>tag`hello` : SomethingNewable +>tag : SomethingTaggable + +`hello`(); +>`hello` : "hello" + From 7f96fec9d97c88ef95d0aad803db817c8d391e22 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 14:27:48 -0700 Subject: [PATCH 18/20] Added test in case 'super' is ever possibly parsed as a tagged template string. --- .../templates/taggedTemplatesWithTypeArguments2.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts index 432e7a217487d..a7a0044d93dcf 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -28,4 +28,14 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); * ``` */ const e = new tag -`hello`(); \ No newline at end of file +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} \ No newline at end of file From 70feb7b10ba771a8b137b643046dbb85350cd090 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 14:29:53 -0700 Subject: [PATCH 19/20] Avoid duplicate code when checking for tagged templates. --- src/compiler/checker.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 60fcf10304146..b65d153aa4529 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17749,15 +17749,11 @@ namespace ts { let typeArguments: NodeArray; - if (isTaggedTemplate) { - typeArguments = (node as TaggedTemplateExpression).typeArguments; - forEach(typeArguments, checkSourceElement); - } - else if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { + if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if ((node).expression.kind !== SyntaxKind.SuperKeyword) { + if (isTaggedTemplate || (node).expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } From 87bb96d7b24f6cb27dafddde6de80476d3a4dd5a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 15:15:53 -0700 Subject: [PATCH 20/20] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 25 +++++++++++++-- .../taggedTemplatesWithTypeArguments2.js | 19 +++++++++++- .../taggedTemplatesWithTypeArguments2.symbols | 28 +++++++++++++++++ .../taggedTemplatesWithTypeArguments2.types | 31 +++++++++++++++++++ 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 9dcc630e71b70..4460743303153 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -1,9 +1,12 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2347: Untyped function calls may not accept type arguments. tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(35,5): error TS2377: Constructors for derived classes must contain a 'super' call. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,14): error TS1034: 'super' must be followed by an argument list or member access. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (3 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (6 errors) ==== export interface SomethingTaggable { (t: TemplateStringsArray, ...args: T[]): SomethingNewable; } @@ -37,4 +40,22 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30 * ``` */ const e = new tag - `hello`(); \ No newline at end of file + `hello`(); + + class SomeBase { + a!: A; b!: B; c!: C; + } + + class SomeDerived extends SomeBase { + constructor() { + ~~~~~~~~~~~~~~~ + super `hello world`; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~ +!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. + ~ +!!! error TS1034: 'super' must be followed by an argument list or member access. + } + ~~~~~ +!!! error TS2377: Constructors for derived classes must contain a 'super' call. + } \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 879c274e52fca..bc170467fa8be 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -26,7 +26,17 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); * ``` */ const e = new tag -`hello`(); +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); @@ -42,3 +52,10 @@ const d = (new tag `${"hello"} ${"world"}`)(100, 200); * ``` */ const e = new tag `hello`(); +class SomeBase { +} +class SomeDerived extends SomeBase { + constructor() { + super. `hello world`; + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols index 049b844bdf2b3..631770a30ddc7 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -53,3 +53,31 @@ const e = new tag >tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) `hello`(); + +class SomeBase { +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) + + a!: A; b!: B; c!: C; +>a : Symbol(SomeBase.a, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 25)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>b : Symbol(SomeBase.b, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 10)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>c : Symbol(SomeBase.c, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) +} + +class SomeDerived extends SomeBase { +>SomeDerived : Symbol(SomeDerived, Decl(taggedTemplatesWithTypeArguments2.ts, 31, 1)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + + constructor() { + super `hello world`; +>super : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index 07afb0becc63c..8aef2009d1b4f 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -87,3 +87,34 @@ const e = new tag `hello`(); >`hello` : "hello" +class SomeBase { +>SomeBase : SomeBase +>A : A +>B : B +>C : C + + a!: A; b!: B; c!: C; +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +} + +class SomeDerived extends SomeBase { +>SomeDerived : SomeDerived +>T : T +>SomeBase : SomeBase +>T : T + + constructor() { + super `hello world`; +>super `hello world` : any +>super : any +>super : SomeBase +> : any +>T : T +>`hello world` : "hello world" + } +}