From 1f6cd941fdaa37c25da86eb86601b46037773e35 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 17:09:56 -0800 Subject: [PATCH] Changed tests to error when actual contextual typing is broken. --- .../taggedTemplateContextualTyping1.js | 46 +++++-- .../taggedTemplateContextualTyping1.types | 121 +++++++++++------- .../taggedTemplateContextualTyping2.js | 39 ++++-- .../taggedTemplateContextualTyping2.types | 93 +++++++++----- .../taggedTemplateContextualTyping1.ts | 17 ++- .../taggedTemplateContextualTyping2.ts | 17 ++- 6 files changed, 228 insertions(+), 105 deletions(-) diff --git a/tests/baselines/reference/taggedTemplateContextualTyping1.js b/tests/baselines/reference/taggedTemplateContextualTyping1.js index 1ac371a8ae4..1d8b79e4c32 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping1.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.js @@ -1,15 +1,20 @@ //// [taggedTemplateContextualTyping1.ts] -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +type FuncType = (x: (p: T) => T) => typeof x; + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; function tempTag1(...rest: any[]): T { return undefined; } -tempTag1 `${ x => x }${ 10 }`; -tempTag1 `${ x => x }${ y => y }${ 10 }`; -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; //// [taggedTemplateContextualTyping1.js] @@ -20,7 +25,28 @@ function tempTag1() { } return undefined; } -tempTag1 `${function (x) { return x; }}${10}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${10}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${10}`; +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${undefined}`; +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${undefined}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping1.types b/tests/baselines/reference/taggedTemplateContextualTyping1.types index bb8e6a1a87c..a87d5eaa7a4 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping1.types +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.types @@ -1,37 +1,40 @@ === tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts === -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +type FuncType = (x: (p: T) => T) => typeof x; +>FuncType : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: T) => T ->x : T ->T : T ->T : T +>f : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T >x : T >T : T >T : T -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: T) => T ->x : T ->T : T ->T : T ->h : (y: T) => T ->y : T ->T : T ->T : T +>f : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T +>h : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T >x : T >T : T >T : T function tempTag1(...rest: any[]): T { ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >rest : any[] >T : T @@ -40,38 +43,62 @@ function tempTag1(...rest: any[]): T { >undefined : undefined } -tempTag1 `${ x => x }${ 10 }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(undefined); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T -tempTag1 `${ x => x }${ y => y }${ 10 }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number ->y => y : (y: number) => number ->y : number ->y : number - -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number ->(y: number) => y : (y: number) => number ->y : number ->y : number +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>(y: (p: T) => T) => { y(undefined); return y } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T >undefined : undefined -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->(x: number) => x : (x: number) => number ->x : number ->x : number ->y => y : (y: number) => number ->y : number ->y : number +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>(x: (p: T) => T) => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(undefined); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T >undefined : undefined diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.js b/tests/baselines/reference/taggedTemplateContextualTyping2.js index c24f5fffb59..df026399c10 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping2.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.js @@ -1,14 +1,21 @@ //// [taggedTemplateContextualTyping2.ts] -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +type FuncType1 = (x: (p: T) => T) => typeof x; +type FuncType2 = (x: (p: T) => T) => typeof x; + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; function tempTag2(...rest: any[]): any { return undefined; } -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; //// [taggedTemplateContextualTyping2.js] function tempTag2() { @@ -18,6 +25,22 @@ function tempTag2() { } return undefined; } -tempTag2 `${function (x) { return x; }}${0}`; -tempTag2 `${function (x) { return x; }}${function (y) { return y; }}${"hello"}`; -tempTag2 `${function (x) { return x; }}${0}`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${function (x) { + x(undefined); + return x; +}}${0}`; +tempTag2 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(null); + return y; +}}${"hello"}`; +tempTag2 `${function (x) { + x(undefined); + return x; +}}${undefined}${"hello"}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.types b/tests/baselines/reference/taggedTemplateContextualTyping2.types index d7088735bc3..9ca7386dc34 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping2.types +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.types @@ -1,49 +1,84 @@ === tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts === -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +type FuncType1 = (x: (p: T) => T) => typeof x; +>FuncType1 : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +type FuncType2 = (x: (p: T) => T) => typeof x; +>FuncType2 : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>S : S +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: number) => number ->x : number +>f : (x: (p: T) => T) => (p: T) => T +>FuncType1 : (x: (p: T) => T) => (p: T) => T >x : number -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: string) => string ->x : string ->h : (y: string) => string ->y : string +>f : (x: (p: T) => T) => (p: T) => T +>FuncType2 : (x: (p: T) => T) => (p: T) => T +>h : (x: (p: T) => T) => (p: T) => T +>FuncType2 : (x: (p: T) => T) => (p: T) => T >x : string function tempTag2(...rest: any[]): any { ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >rest : any[] return undefined; >undefined : undefined } -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T -tempTag2 `${ x => x }${ y => y }${ "hello" }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: string) => string ->x : string ->x : string ->y => y : (y: string) => string ->y : string ->y : string +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : string +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(null); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(null) : number +>y : (p: T) => T +>y : (p: T) => T -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : string +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>undefined : undefined diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts index 1e35b3c9b4b..c15d911ee52 100644 --- a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts @@ -1,12 +1,17 @@ // @target: ES6 -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +type FuncType = (x: (p: T) => T) => typeof x; + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; function tempTag1(...rest: any[]): T { return undefined; } -tempTag1 `${ x => x }${ 10 }`; -tempTag1 `${ x => x }${ y => y }${ 10 }`; -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts index 260a3bc0741..24fcf4a04df 100644 --- a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts @@ -1,11 +1,18 @@ // @target: ES6 -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +type FuncType1 = (x: (p: T) => T) => typeof x; +type FuncType2 = (x: (p: T) => T) => typeof x; + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; function tempTag2(...rest: any[]): any { return undefined; } -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; \ No newline at end of file +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; \ No newline at end of file