From 63ff6572ae92224a26012a58b847f2e845f492bc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 21 Apr 2020 08:09:25 -0700 Subject: [PATCH 01/38] Fix use-before-def with methods on esnext+useDefineForClassFields (#38033) * Fix use-before-def with methods on esnext+useDefineForClassFields It was incorrectly flagging methods as used before their definition, but this is allowed under any emit. * Add instance function test case --- src/compiler/checker.ts | 7 +- ...ertyToPropertyDeclarationESNext.errors.txt | 19 ++- ...eterPropertyToPropertyDeclarationESNext.js | 6 + ...ropertyToPropertyDeclarationESNext.symbols | 113 ++++++++++-------- ...rPropertyToPropertyDeclarationESNext.types | 18 +++ ...eterPropertyToPropertyDeclarationESNext.ts | 3 + 6 files changed, 108 insertions(+), 58 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30d4c5b7c2a..9b5013e3141 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1423,9 +1423,10 @@ namespace ts { return true; } if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { - if (compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields && getContainingClass(declaration)) { - return (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent)) && - !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); + if (compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields + && getContainingClass(declaration) + && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) { + return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); } else { return true; diff --git a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.errors.txt b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.errors.txt index 2010e92a2d8..b8d6ddc136c 100644 --- a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.errors.txt +++ b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.errors.txt @@ -1,10 +1,11 @@ tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(2,16): error TS2729: Property 'bar' is used before its initialization. tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(3,16): error TS2729: Property 'foo' is used before its initialization. -tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(9,17): error TS2729: Property 'baz' is used before its initialization. -tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(10,16): error TS2729: Property 'foo' is used before its initialization. +tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(6,19): error TS2729: Property 'm3' is used before its initialization. +tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(12,17): error TS2729: Property 'baz' is used before its initialization. +tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts(13,16): error TS2729: Property 'foo' is used before its initialization. -==== tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts (4 errors) ==== +==== tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts (5 errors) ==== class C { qux = this.bar // should error ~~~ @@ -13,20 +14,26 @@ tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterProper bar = this.foo // should error ~~~ !!! error TS2729: Property 'foo' is used before its initialization. -!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:8:17: 'foo' is declared here. +!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:11:17: 'foo' is declared here. quiz = this.bar // ok + quench = this.m1() // ok + quanch = this.m3() // should error + ~~ +!!! error TS2729: Property 'm3' is used before its initialization. +!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:10:5: 'm3' is declared here. m1() { this.foo // ok } + m3 = function() { } constructor(public foo: string) {} quim = this.baz // should error ~~~ !!! error TS2729: Property 'baz' is used before its initialization. -!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:10:5: 'baz' is declared here. +!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:13:5: 'baz' is declared here. baz = this.foo; // should error ~~~ !!! error TS2729: Property 'foo' is used before its initialization. -!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:8:17: 'foo' is declared here. +!!! related TS2728 tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts:11:17: 'foo' is declared here. quid = this.baz // ok m2() { this.foo // ok diff --git a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.js b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.js index f71361eb570..d4e0de0d8c5 100644 --- a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.js +++ b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.js @@ -3,9 +3,12 @@ class C { qux = this.bar // should error bar = this.foo // should error quiz = this.bar // ok + quench = this.m1() // ok + quanch = this.m3() // should error m1() { this.foo // ok } + m3 = function() { } constructor(public foo: string) {} quim = this.baz // should error baz = this.foo; // should error @@ -45,9 +48,12 @@ class C { qux = this.bar; // should error bar = this.foo; // should error quiz = this.bar; // ok + quench = this.m1(); // ok + quanch = this.m3(); // should error m1() { this.foo; // ok } + m3 = function () { }; constructor(foo) { this.foo = foo; } diff --git a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.symbols b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.symbols index 5fd56137bb8..27d3f243966 100644 --- a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.symbols +++ b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.symbols @@ -10,9 +10,9 @@ class C { bar = this.foo // should error >bar : Symbol(C.bar, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 1, 18)) ->this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) quiz = this.bar // ok >quiz : Symbol(C.quiz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 2, 18)) @@ -20,105 +20,120 @@ class C { >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) >bar : Symbol(C.bar, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 1, 18)) + quench = this.m1() // ok +>quench : Symbol(C.quench, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 3, 19)) +>this.m1 : Symbol(C.m1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 5, 22)) +>this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) +>m1 : Symbol(C.m1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 5, 22)) + + quanch = this.m3() // should error +>quanch : Symbol(C.quanch, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 4, 22)) +>this.m3 : Symbol(C.m3, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 5)) +>this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) +>m3 : Symbol(C.m3, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 5)) + m1() { ->m1 : Symbol(C.m1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 3, 19)) +>m1 : Symbol(C.m1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 5, 22)) this.foo // ok ->this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) } + m3 = function() { } +>m3 : Symbol(C.m3, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 5)) + constructor(public foo: string) {} ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) quim = this.baz // should error ->quim : Symbol(C.quim, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 38)) ->this.baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 19)) +>quim : Symbol(C.quim, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 38)) +>this.baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 11, 19)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 19)) +>baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 11, 19)) baz = this.foo; // should error ->baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 19)) ->this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 11, 19)) +>this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) quid = this.baz // ok ->quid : Symbol(C.quid, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 9, 19)) ->this.baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 19)) +>quid : Symbol(C.quid, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 12, 19)) +>this.baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 11, 19)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 8, 19)) +>baz : Symbol(C.baz, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 11, 19)) m2() { ->m2 : Symbol(C.m2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 19)) +>m2 : Symbol(C.m2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 13, 19)) this.foo // ok ->this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) >this : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) } } class D extends C { ->D : Symbol(D, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 14, 1)) +>D : Symbol(D, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 17, 1)) >C : Symbol(C, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 0, 0)) quill = this.foo // ok ->quill : Symbol(D.quill, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 16, 19)) ->this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) ->this : Symbol(D, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 14, 1)) ->foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 7, 16)) +>quill : Symbol(D.quill, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 19, 19)) +>this.foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) +>this : Symbol(D, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 17, 1)) +>foo : Symbol(C.foo, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 10, 16)) } class E { ->E : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 18, 1)) +>E : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 1)) bar = () => this.foo1 + this.foo2; // both ok ->bar : Symbol(E.bar, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 20, 9)) ->this.foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 38)) ->this : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 18, 1)) ->foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 38)) ->this.foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 23, 16)) ->this : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 18, 1)) ->foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 23, 16)) +>bar : Symbol(E.bar, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 23, 9)) +>this.foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 24, 38)) +>this : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 1)) +>foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 24, 38)) +>this.foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 26, 16)) +>this : Symbol(E, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 1)) +>foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 26, 16)) foo1 = ''; ->foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 21, 38)) +>foo1 : Symbol(E.foo1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 24, 38)) constructor(public foo2: string) {} ->foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 23, 16)) +>foo2 : Symbol(E.foo2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 26, 16)) } class F { ->F : Symbol(F, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 24, 1)) +>F : Symbol(F, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 27, 1)) Inner = class extends F { ->Inner : Symbol(F.Inner, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 26, 9)) ->F : Symbol(F, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 24, 1)) +>Inner : Symbol(F.Inner, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 29, 9)) +>F : Symbol(F, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 27, 1)) p2 = this.p1 ->p2 : Symbol((Anonymous class).p2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 27, 29)) ->this.p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 29, 5)) ->this : Symbol((Anonymous class), Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 27, 11)) ->p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 29, 5)) +>p2 : Symbol((Anonymous class).p2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 30, 29)) +>this.p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 32, 5)) +>this : Symbol((Anonymous class), Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 30, 11)) +>p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 32, 5)) } p1 = 0 ->p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 29, 5)) +>p1 : Symbol(F.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 32, 5)) } class G { ->G : Symbol(G, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 31, 1)) +>G : Symbol(G, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 34, 1)) Inner = class extends G { ->Inner : Symbol(G.Inner, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 32, 9)) ->G : Symbol(G, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 31, 1)) +>Inner : Symbol(G.Inner, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 35, 9)) +>G : Symbol(G, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 34, 1)) p2 = this.p1 ->p2 : Symbol((Anonymous class).p2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 33, 29)) ->this.p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 36, 16)) ->this : Symbol((Anonymous class), Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 33, 11)) ->p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 36, 16)) +>p2 : Symbol((Anonymous class).p2, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 36, 29)) +>this.p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 39, 16)) +>this : Symbol((Anonymous class), Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 36, 11)) +>p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 39, 16)) } constructor(public p1: number) {} ->p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 36, 16)) +>p1 : Symbol(G.p1, Decl(assignParameterPropertyToPropertyDeclarationESNext.ts, 39, 16)) } diff --git a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.types b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.types index 631b0dba5a4..d4b3cd9d958 100644 --- a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.types +++ b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationESNext.types @@ -20,6 +20,20 @@ class C { >this : this >bar : string + quench = this.m1() // ok +>quench : void +>this.m1() : void +>this.m1 : () => void +>this : this +>m1 : () => void + + quanch = this.m3() // should error +>quanch : void +>this.m3() : void +>this.m3 : () => void +>this : this +>m3 : () => void + m1() { >m1 : () => void @@ -28,6 +42,10 @@ class C { >this : this >foo : string } + m3 = function() { } +>m3 : () => void +>function() { } : () => void + constructor(public foo: string) {} >foo : string diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts index f4475f09ddf..d778149c428 100644 --- a/tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/assignParameterPropertyToPropertyDeclarationESNext.ts @@ -4,9 +4,12 @@ class C { qux = this.bar // should error bar = this.foo // should error quiz = this.bar // ok + quench = this.m1() // ok + quanch = this.m3() // should error m1() { this.foo // ok } + m3 = function() { } constructor(public foo: string) {} quim = this.baz // should error baz = this.foo; // should error From 1e48057b9e2290ac238f35d2474812b03efdd1b5 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 21 Apr 2020 21:02:56 +0300 Subject: [PATCH 02/38] fix(15398): skip adding line breaks when replacing JS checks directives (#38086) --- .../codefixes/disableJsDiagnostics.ts | 3 ++- .../codeFixDisableJsDiagnosticsInFile10.ts | 23 ++++++++++++++++++ .../codeFixDisableJsDiagnosticsInFile9.ts | 24 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile10.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile9.ts diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index a4feeaa2dbd..13b1fec32ee 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -16,6 +16,7 @@ namespace ts.codefix { return undefined; } + const newLineCharacter = sourceFile.checkJsDirective ? "" : getNewLineOrDefaultFromHost(host, formatContext.options); const fixes: CodeFixAction[] = [ // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file. createCodeFixActionWithoutFixAll( @@ -23,7 +24,7 @@ namespace ts.codefix { [createFileTextChanges(sourceFile.fileName, [ createTextChange(sourceFile.checkJsDirective ? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) - : createTextSpan(0, 0), `// @ts-nocheck${getNewLineOrDefaultFromHost(host, formatContext.options)}`), + : createTextSpan(0, 0), `// @ts-nocheck${newLineCharacter}`), ])], Diagnostics.Disable_checking_for_this_file), ]; diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile10.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile10.ts new file mode 100644 index 00000000000..ff1ba5c75b5 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile10.ts @@ -0,0 +1,23 @@ +/// + +// @allowjs: true +// @checkJs: true +// @noEmit: true + +// @filename: a.js +////let x = ""; +////[|x|] = 1; + +// verify.codeFixAvailable([ +// { description: ts.Diagnostics.Ignore_this_error_message.message }, +// { description: ts.Diagnostics.Disable_checking_for_this_file.message } +// ]); + +verify.codeFix({ + description: ts.Diagnostics.Disable_checking_for_this_file.message, + index: 1, + newFileContent: +`// @ts-nocheck +let x = ""; +x = 1;`, +}); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile9.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile9.ts new file mode 100644 index 00000000000..e7401e683b7 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile9.ts @@ -0,0 +1,24 @@ +/// + +// @allowjs: true +// @checkJs: true +// @noEmit: true + +// @filename: a.js +////// @ts-check +////let x = ""; +////[|x|] = 1; + +// verify.codeFixAvailable([ +// { description: ts.Diagnostics.Ignore_this_error_message.message }, +// { description: ts.Diagnostics.Disable_checking_for_this_file.message } +// ]); + +verify.codeFix({ + description: ts.Diagnostics.Disable_checking_for_this_file.message, + index: 1, + newFileContent: +`// @ts-nocheck +let x = ""; +x = 1;`, +}); From 6ea291a14267f8d3b12a01b4f950dfe66e975bf9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 21 Apr 2020 12:58:37 -0700 Subject: [PATCH 03/38] Remove superCallShouldBeFirst error (#37947) * Remove superCallShouldBeFirst error It seems redundant since TS gives an error on any use of `this` before super, and non-`this` uses before `super` should be fine. Fixes #37371 * Revert "Remove superCallShouldBeFirst error" This reverts commit 3c09153c8ad00d73d60e7000a0e6263a6028615a. * error except for target:"esnext" && useDefineForClassFields --- src/compiler/checker.ts | 5 +++-- ...vateNameBadSuperUseDefineForClassFields.js | 22 +++++++++++++++++++ ...ameBadSuperUseDefineForClassFields.symbols | 18 +++++++++++++++ ...eNameBadSuperUseDefineForClassFields.types | 22 +++++++++++++++++++ ...vateNameBadSuperUseDefineForClassFields.ts | 10 +++++++++ 5 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.js create mode 100644 tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.symbols create mode 100644 tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9b5013e3141..b65eca1f8a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29677,8 +29677,9 @@ namespace ts { // - The constructor declares parameter properties // or the containing class declares instance member variables with initializers. const superCallShouldBeFirst = - some((node.parent).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || - some(node.parameters, p => hasModifier(p, ModifierFlags.ParameterPropertyModifier)); + (compilerOptions.target !== ScriptTarget.ESNext || !compilerOptions.useDefineForClassFields) && + (some((node.parent).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || + some(node.parameters, p => hasModifier(p, ModifierFlags.ParameterPropertyModifier))); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. diff --git a/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.js b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.js new file mode 100644 index 00000000000..018c1eaaece --- /dev/null +++ b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.js @@ -0,0 +1,22 @@ +//// [privateNameBadSuperUseDefineForClassFields.ts] +class B {}; +class A extends B { + #x; + constructor() { + void 0; // Error: 'super' call must come first + super(); + } +} + + +//// [privateNameBadSuperUseDefineForClassFields.js] +class B { +} +; +class A extends B { + #x; + constructor() { + void 0; // Error: 'super' call must come first + super(); + } +} diff --git a/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.symbols b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.symbols new file mode 100644 index 00000000000..5e5115d7417 --- /dev/null +++ b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts === +class B {}; +>B : Symbol(B, Decl(privateNameBadSuperUseDefineForClassFields.ts, 0, 0)) + +class A extends B { +>A : Symbol(A, Decl(privateNameBadSuperUseDefineForClassFields.ts, 0, 11)) +>B : Symbol(B, Decl(privateNameBadSuperUseDefineForClassFields.ts, 0, 0)) + + #x; +>#x : Symbol(A.#x, Decl(privateNameBadSuperUseDefineForClassFields.ts, 1, 19)) + + constructor() { + void 0; // Error: 'super' call must come first + super(); +>super : Symbol(B, Decl(privateNameBadSuperUseDefineForClassFields.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.types b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.types new file mode 100644 index 00000000000..55432691aec --- /dev/null +++ b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts === +class B {}; +>B : B + +class A extends B { +>A : A +>B : B + + #x; +>#x : any + + constructor() { + void 0; // Error: 'super' call must come first +>void 0 : undefined +>0 : 0 + + super(); +>super() : void +>super : typeof B + } +} + diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts b/tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts new file mode 100644 index 00000000000..984b65a5695 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameBadSuperUseDefineForClassFields.ts @@ -0,0 +1,10 @@ +// @target: esnext +// @useDefineForClassFields: true +class B {}; +class A extends B { + #x; + constructor() { + void 0; // Error: 'super' call must come first + super(); + } +} From 136f728bb011ecf1bbf0ff2aac6dacc5cb6568cb Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 21 Apr 2020 13:13:50 -0700 Subject: [PATCH 04/38] Fix js declaration emit for inherited and this-typed inherited fields (#37970) --- src/compiler/checker.ts | 24 +++++++- ...InternalTypesProduceUniqueTypeParams.types | 4 +- .../reference/jsDeclarationsInterfaces.js | 4 +- .../reference/jsDeclarationsThisTypes.js | 59 +++++++++++++++++++ .../reference/jsDeclarationsThisTypes.symbols | 20 +++++++ .../reference/jsDeclarationsThisTypes.types | 20 +++++++ .../declarations/jsDeclarationsThisTypes.ts | 17 ++++++ 7 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationsThisTypes.js create mode 100644 tests/baselines/reference/jsDeclarationsThisTypes.symbols create mode 100644 tests/baselines/reference/jsDeclarationsThisTypes.types create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsThisTypes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b65eca1f8a3..8228f62fe0e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5459,7 +5459,7 @@ namespace ts { function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { if (type !== errorType && context.enclosingDeclaration) { const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); - if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && getTypeFromTypeNode(annotation) === type) { + if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && instantiateType(getTypeFromTypeNode(annotation), signature.mapper) === type) { const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled); if (result) { return result; @@ -6211,7 +6211,7 @@ namespace ts { ...!length(baseTypes) ? [] : [createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))], ...!length(implementsTypes) ? [] : [createHeritageClause(SyntaxKind.ImplementsKeyword, map(implementsTypes, b => serializeBaseType(b, staticBaseType, localName)))] ]; - const symbolProps = getPropertiesOfType(classType); + const symbolProps = getNonInterhitedProperties(classType, baseTypes, getPropertiesOfType(classType)); const publicSymbolProps = filter(symbolProps, s => { // `valueDeclaration` could be undefined if inherited from // a union/intersection base type, but inherited properties @@ -33482,6 +33482,26 @@ namespace ts { } } + function getNonInterhitedProperties(type: InterfaceType, baseTypes: BaseType[], properties: Symbol[]) { + if (!length(baseTypes)) { + return properties; + } + const seen = createUnderscoreEscapedMap(); + forEach(properties, p => { seen.set(p.escapedName, p); }); + + for (const base of baseTypes) { + const properties = getPropertiesOfType(getTypeWithThisArgument(base, type.thisType)); + for (const prop of properties) { + const existing = seen.get(prop.escapedName); + if (existing && !isPropertyIdenticalTo(existing, prop)) { + seen.delete(prop.escapedName); + } + } + } + + return arrayFrom(seen.values()); + } + function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean { const baseTypes = getBaseTypes(type); if (baseTypes.length < 2) { diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types index 142dedb2041..836c6ba044e 100644 --- a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types @@ -38,13 +38,13 @@ export const updateIfChanged = (t: T) => { >newU : U return Object.assign( ->Object.assign( >(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }) : ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>Object.assign( >(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }) : ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } >Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } >Object : ObjectConstructor >assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } >(key: K) => ->>(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : (key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; } +>>(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : (key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U) => T; set: (newU: U[K]) => T; } >key : K reduce>(u[key as keyof U] as Value, (v: Value) => { diff --git a/tests/baselines/reference/jsDeclarationsInterfaces.js b/tests/baselines/reference/jsDeclarationsInterfaces.js index 00e78c8286a..f7f68846d29 100644 --- a/tests/baselines/reference/jsDeclarationsInterfaces.js +++ b/tests/baselines/reference/jsDeclarationsInterfaces.js @@ -135,10 +135,10 @@ export interface B { export interface C { new (): string; new (x: T_1): U_1; - new (x: Q_4): T_1 & Q_4; + new (x: Q_6): T_1 & Q_6; (): number; (x: T_1): U_1; - (x: Q_3): T_1 & Q_3; + (x: Q_4): T_1 & Q_4; field: T_1 & U_1; optionalField?: T_1; readonly readonlyField: T_1 & U_1; diff --git a/tests/baselines/reference/jsDeclarationsThisTypes.js b/tests/baselines/reference/jsDeclarationsThisTypes.js new file mode 100644 index 00000000000..65858ab41dc --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsThisTypes.js @@ -0,0 +1,59 @@ +//// [index.js] +export class A { + /** @returns {this} */ + method() { + return this; + } +} +export default class Base extends A { + // This method is required to reproduce #35932 + verify() { } +} + +//// [index.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + /** @returns {this} */ + A.prototype.method = function () { + return this; + }; + return A; +}()); +exports.A = A; +var Base = /** @class */ (function (_super) { + __extends(Base, _super); + function Base() { + return _super !== null && _super.apply(this, arguments) || this; + } + // This method is required to reproduce #35932 + Base.prototype.verify = function () { }; + return Base; +}(A)); +exports["default"] = Base; + + +//// [index.d.ts] +export class A { + /** @returns {this} */ + method(): this; +} +export default class Base extends A { + verify(): void; +} diff --git a/tests/baselines/reference/jsDeclarationsThisTypes.symbols b/tests/baselines/reference/jsDeclarationsThisTypes.symbols new file mode 100644 index 00000000000..931bdd24a97 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsThisTypes.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +export class A { +>A : Symbol(A, Decl(index.js, 0, 0)) + + /** @returns {this} */ + method() { +>method : Symbol(A.method, Decl(index.js, 0, 16)) + + return this; +>this : Symbol(A, Decl(index.js, 0, 0)) + } +} +export default class Base extends A { +>Base : Symbol(Base, Decl(index.js, 5, 1)) +>A : Symbol(A, Decl(index.js, 0, 0)) + + // This method is required to reproduce #35932 + verify() { } +>verify : Symbol(Base.verify, Decl(index.js, 6, 37)) +} diff --git a/tests/baselines/reference/jsDeclarationsThisTypes.types b/tests/baselines/reference/jsDeclarationsThisTypes.types new file mode 100644 index 00000000000..801f1792656 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsThisTypes.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +export class A { +>A : A + + /** @returns {this} */ + method() { +>method : () => this + + return this; +>this : this + } +} +export default class Base extends A { +>Base : Base +>A : A + + // This method is required to reproduce #35932 + verify() { } +>verify : () => void +} diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsThisTypes.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsThisTypes.ts new file mode 100644 index 00000000000..bc2eae7dac6 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsThisTypes.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @outDir: /out +// @lib: es6 +// @declaration: true +// @filename: index.js + +export class A { + /** @returns {this} */ + method() { + return this; + } +} +export default class Base extends A { + // This method is required to reproduce #35932 + verify() { } +} \ No newline at end of file From a72e49e8750b7d56968db5fe577a6c5bec344d41 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 21 Apr 2020 13:29:45 -0700 Subject: [PATCH 05/38] Delay pulling on signature contextual type until absolutely needed (#37851) --- src/compiler/checker.ts | 16 +++---- ...edTypeContextualTypeNotCircular.errors.txt | 18 ++++++++ ...erseMappedTypeContextualTypeNotCircular.js | 18 ++++++++ ...appedTypeContextualTypeNotCircular.symbols | 42 +++++++++++++++++++ ...eMappedTypeContextualTypeNotCircular.types | 34 +++++++++++++++ ...erseMappedTypeContextualTypeNotCircular.ts | 11 +++++ 6 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.errors.txt create mode 100644 tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.js create mode 100644 tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.symbols create mode 100644 tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.types create mode 100644 tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8228f62fe0e..ac02f917827 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -55,7 +55,9 @@ namespace ts { const enum WideningKind { Normal, - GeneratorYield + FunctionReturn, + GeneratorNext, + GeneratorYield, } const enum TypeFacts { @@ -18092,7 +18094,7 @@ namespace ts { } function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) { - if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType) { + if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAny(declaration, type, wideningKind); @@ -27047,15 +27049,13 @@ namespace ts { } if (returnType || yieldType || nextType) { - const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); - if (!contextualSignature) { - if (yieldType) reportErrorsFromWidening(func, yieldType, WideningKind.GeneratorYield); - if (returnType) reportErrorsFromWidening(func, returnType); - if (nextType) reportErrorsFromWidening(func, nextType); - } + if (yieldType) reportErrorsFromWidening(func, yieldType, WideningKind.GeneratorYield); + if (returnType) reportErrorsFromWidening(func, returnType, WideningKind.FunctionReturn); + if (nextType) reportErrorsFromWidening(func, nextType, WideningKind.GeneratorNext); if (returnType && isUnitType(returnType) || yieldType && isUnitType(yieldType) || nextType && isUnitType(nextType)) { + const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); const contextualType = !contextualSignature ? undefined : contextualSignature === getSignatureFromDeclaration(func) ? isGenerator ? undefined : returnType : instantiateContextualType(getReturnTypeOfSignature(contextualSignature), func); diff --git a/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.errors.txt b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.errors.txt new file mode 100644 index 00000000000..d5462d0d0b7 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts(10,3): error TS2322: Type '(state: any, props: any) => {}' is not assignable to type 'Selector'. + + +==== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts (1 errors) ==== + type Selector = (state: S) => R; + + declare function createStructuredSelector( + selectors: {[K in keyof T]: Selector}, + ): Selector; + + const editable = () => ({}); + + const mapStateToProps = createStructuredSelector({ + editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error + ~~~~~~~~ +!!! error TS2322: Type '(state: any, props: any) => {}' is not assignable to type 'Selector'. +!!! related TS6500 tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts:10:3: The expected type comes from property 'editable' which is declared here on type '{ editable: Selector; }' + }); \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.js b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.js new file mode 100644 index 00000000000..66302e8e642 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.js @@ -0,0 +1,18 @@ +//// [reverseMappedTypeContextualTypeNotCircular.ts] +type Selector = (state: S) => R; + +declare function createStructuredSelector( + selectors: {[K in keyof T]: Selector}, +): Selector; + +const editable = () => ({}); + +const mapStateToProps = createStructuredSelector({ + editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error +}); + +//// [reverseMappedTypeContextualTypeNotCircular.js] +var editable = function () { return ({}); }; +var mapStateToProps = createStructuredSelector({ + editable: function (state, props) { return editable(); } +}); diff --git a/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.symbols b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.symbols new file mode 100644 index 00000000000..94dcef3f0a3 --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts === +type Selector = (state: S) => R; +>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0)) +>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 14)) +>R : Symbol(R, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 16)) +>state : Symbol(state, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 23)) +>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 14)) +>R : Symbol(R, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 16)) + +declare function createStructuredSelector( +>createStructuredSelector : Symbol(createStructuredSelector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 38)) +>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42)) +>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44)) + + selectors: {[K in keyof T]: Selector}, +>selectors : Symbol(selectors, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 48)) +>K : Symbol(K, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 3, 15)) +>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44)) +>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0)) +>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42)) +>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44)) +>K : Symbol(K, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 3, 15)) + +): Selector; +>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0)) +>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42)) +>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44)) + +const editable = () => ({}); +>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 6, 5)) + +const mapStateToProps = createStructuredSelector({ +>mapStateToProps : Symbol(mapStateToProps, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 8, 5)) +>createStructuredSelector : Symbol(createStructuredSelector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 38)) + + editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error +>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 8, 50)) +>state : Symbol(state, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 9, 13)) +>props : Symbol(props, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 9, 24)) +>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 6, 5)) + +}); diff --git a/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.types b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.types new file mode 100644 index 00000000000..8f5d92f3d7d --- /dev/null +++ b/tests/baselines/reference/reverseMappedTypeContextualTypeNotCircular.types @@ -0,0 +1,34 @@ +=== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts === +type Selector = (state: S) => R; +>Selector : Selector +>state : S + +declare function createStructuredSelector( +>createStructuredSelector : (selectors: { [K in keyof T]: Selector; }) => Selector + + selectors: {[K in keyof T]: Selector}, +>selectors : { [K in keyof T]: Selector; } + +): Selector; + +const editable = () => ({}); +>editable : () => {} +>() => ({}) : () => {} +>({}) : {} +>{} : {} + +const mapStateToProps = createStructuredSelector({ +>mapStateToProps : Selector +>createStructuredSelector({ editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error}) : Selector +>createStructuredSelector : (selectors: { [K in keyof T]: Selector; }) => Selector +>{ editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error} : { editable: (state: any, props: any) => {}; } + + editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error +>editable : (state: any, props: any) => {} +>(state: any, props: any) => editable() : (state: any, props: any) => {} +>state : any +>props : any +>editable() : {} +>editable : () => {} + +}); diff --git a/tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts b/tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts new file mode 100644 index 00000000000..e80b71610ac --- /dev/null +++ b/tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts @@ -0,0 +1,11 @@ +type Selector = (state: S) => R; + +declare function createStructuredSelector( + selectors: {[K in keyof T]: Selector}, +): Selector; + +const editable = () => ({}); + +const mapStateToProps = createStructuredSelector({ + editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector'", _not_ a circularity error +}); \ No newline at end of file From 9dd881ba6c4dccbf507cd062af1d8bbb73021e5f Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 21 Apr 2020 22:10:39 +0000 Subject: [PATCH 06/38] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 29 ++++++++++++------- .../diagnosticMessages.generated.json.lcl | 25 +++++++++++----- .../diagnosticMessages.generated.json.lcl | 9 ++++++ .../diagnosticMessages.generated.json.lcl | 21 ++++++++++---- .../diagnosticMessages.generated.json.lcl | 17 ++++++++--- .../diagnosticMessages.generated.json.lcl | 9 ++++++ .../diagnosticMessages.generated.json.lcl | 17 ++++++++--- .../diagnosticMessages.generated.json.lcl | 9 ++++++ .../diagnosticMessages.generated.json.lcl | 9 ++++++ 9 files changed, 113 insertions(+), 32 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 13031a428dc..581fe36aa7f 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1180,7 +1180,7 @@ - + @@ -3193,7 +3193,7 @@ - + @@ -4996,7 +4996,7 @@ - + @@ -5641,7 +5641,7 @@ - + @@ -7188,6 +7188,15 @@ + + + + + + + + + @@ -7399,7 +7408,7 @@ - + @@ -10312,7 +10321,7 @@ - + @@ -10759,7 +10768,7 @@ - + @@ -10768,7 +10777,7 @@ - + @@ -11107,7 +11116,7 @@ - + @@ -11668,7 +11677,7 @@ - + diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index d41aca93740..4f39a5a9347 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1180,7 +1180,7 @@ - + @@ -3193,7 +3193,7 @@ - + @@ -7188,6 +7188,15 @@ + + + + + + + + + @@ -7399,7 +7408,7 @@ - + @@ -7822,7 +7831,7 @@ - + @@ -10312,7 +10321,7 @@ - + @@ -10759,7 +10768,7 @@ - + @@ -10768,7 +10777,7 @@ - + @@ -11107,7 +11116,7 @@ - + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 4dcd83c6c97..4a84ecc9ba8 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -7185,6 +7185,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2a8fd334faf..81b11ca7e68 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -445,7 +445,7 @@ - + @@ -1189,7 +1189,7 @@ - + @@ -3205,7 +3205,7 @@ - + @@ -7200,6 +7200,15 @@ + + + + + + + + + @@ -10324,7 +10333,7 @@ - + @@ -11119,7 +11128,7 @@ - + @@ -11680,7 +11689,7 @@ - + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 5532d3dd2ad..0fed2ad218d 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -445,7 +445,7 @@ - + @@ -3205,7 +3205,7 @@ - + @@ -7200,6 +7200,15 @@ + + + + + + + + + @@ -7411,7 +7420,7 @@ - + @@ -11119,7 +11128,7 @@ - + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 43e653f9110..6f55deb823f 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -7188,6 +7188,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 40d74176e06..163d872a609 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -436,7 +436,7 @@ - + @@ -7188,6 +7188,15 @@ + + + + + + + + + @@ -7399,7 +7408,7 @@ - + @@ -10768,7 +10777,7 @@ - + @@ -11107,7 +11116,7 @@ - + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 50e3c9757c3..4861b65f463 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -7187,6 +7187,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 650602aae1a..0ad845dcd28 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -7181,6 +7181,15 @@ + + + + + + + + + From d571a09cf8b95dba36ef8ec85e56c3e8e9cb147c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:20:36 -0700 Subject: [PATCH 07/38] Navto covers all projects (#38027) * Remove needless structure/destructuring Just pass multiple arguments! Sheesh! * Basic working prototype * Cleaned up version 1. Add test 2. Change protocol. navto-all only happens when filename is undefined or missing. 3. Change location to earlier code path. This change was largely type-guided and resulted in some duplicated code, but I think it's less fault-prone. * remove temp notes * Single-project hits if projectFileName is provided and file is not * use original code as fallback --- src/server/protocol.ts | 8 ++- src/server/session.ts | 67 ++++++++++-------- .../unittests/tsserver/declarationFileMaps.ts | 68 +++++++++++++++++-- .../reference/api/tsserverlibrary.d.ts | 8 ++- 4 files changed, 116 insertions(+), 35 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 4c1292f8de4..b6cc2e4d8fd 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2784,7 +2784,7 @@ namespace ts.server.protocol { /** * Arguments for navto request message. */ - export interface NavtoRequestArgs extends FileRequestArgs { + export interface NavtoRequestArgs { /** * Search term to navigate to from current location; term can * be '.*' or an identifier prefix. @@ -2794,6 +2794,10 @@ namespace ts.server.protocol { * Optional limit on the number of items to return. */ maxResultCount?: number; + /** + * The file for the request (absolute pathname required). + */ + file?: string; /** * Optional flag to indicate we want results for just the current file * or the entire project. @@ -2809,7 +2813,7 @@ namespace ts.server.protocol { * match the search term given in argument 'searchTerm'. The * context for the search is given by the named file. */ - export interface NavtoRequest extends FileRequest { + export interface NavtoRequest extends Request { command: CommandTypes.Navto; arguments: NavtoRequestArgs; } diff --git a/src/server/session.ts b/src/server/session.ts index 590f0bb2cbc..3f0321074a9 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -304,7 +304,7 @@ namespace ts.server { projects, defaultProject, /*initialLocation*/ undefined, - ({ project }, tryAddToTodo) => { + (project, _, tryAddToTodo) => { for (const output of action(project)) { if (!contains(outputs, output, resultsEqual) && !tryAddToTodo(project, getLocation(output))) { outputs.push(output); @@ -329,7 +329,7 @@ namespace ts.server { projects, defaultProject, initialLocation, - ({ project, location }, tryAddToTodo) => { + (project, location, tryAddToTodo) => { for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments, hostPreferences.providePrefixAndSuffixTextForRename) || emptyArray) { if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) { outputs.push(output); @@ -358,7 +358,7 @@ namespace ts.server { projects, defaultProject, initialLocation, - ({ project, location }, getMappedLocation) => { + (project, location, getMappedLocation) => { for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) { const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition)); const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? @@ -408,7 +408,8 @@ namespace ts.server { } type CombineProjectOutputCallback = ( - where: ProjectAndLocation, + project: Project, + location: TLocation, getMappedLocation: (project: Project, location: DocumentPosition) => DocumentPosition | undefined, ) => void; @@ -422,9 +423,9 @@ namespace ts.server { let toDo: ProjectAndLocation[] | undefined; const seenProjects = createMap(); forEachProjectInProjects(projects, initialLocation && initialLocation.fileName, (project, path) => { - // TLocation shoud be either `DocumentPosition` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid. + // TLocation should be either `DocumentPosition` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid. const location = (initialLocation ? { fileName: path, pos: initialLocation.pos } : undefined) as TLocation; - toDo = callbackProjectAndLocation({ project, location }, projectService, toDo, seenProjects, cb); + toDo = callbackProjectAndLocation(project, location, projectService, toDo, seenProjects, cb); }); // After initial references are collected, go over every other project and see if it has a reference for the symbol definition. @@ -442,14 +443,16 @@ namespace ts.server { if (!addToSeen(seenProjects, project)) return; const definition = mapDefinitionInProject(defaultDefinition, project, getGeneratedDefinition, getSourceDefinition); if (definition) { - toDo = callbackProjectAndLocation({ project, location: definition as TLocation }, projectService, toDo, seenProjects, cb); + toDo = callbackProjectAndLocation(project, definition as TLocation, projectService, toDo, seenProjects, cb); } }); } } while (toDo && toDo.length) { - toDo = callbackProjectAndLocation(Debug.checkDefined(toDo.pop()), projectService, toDo, seenProjects, cb); + const next = toDo.pop(); + Debug.assertIsDefined(next); + toDo = callbackProjectAndLocation(next.project, next.location, projectService, toDo, seenProjects, cb); } } @@ -487,31 +490,33 @@ namespace ts.server { } function callbackProjectAndLocation( - projectAndLocation: ProjectAndLocation, + project: Project, + location: TLocation, projectService: ProjectService, toDo: ProjectAndLocation[] | undefined, seenProjects: Map, cb: CombineProjectOutputCallback, ): ProjectAndLocation[] | undefined { - const { project, location } = projectAndLocation; if (project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled // If this is not the file we were actually looking, return rest of the toDo if (isLocationProjectReferenceRedirect(project, location)) return toDo; - cb(projectAndLocation, (project, location) => { - addToSeen(seenProjects, projectAndLocation.project); - const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location); + cb(project, location, (innerProject, location) => { + addToSeen(seenProjects, project); + const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(innerProject, location); if (!originalLocation) return undefined; const originalScriptInfo = projectService.getScriptInfo(originalLocation.fileName)!; toDo = toDo || []; for (const project of originalScriptInfo.containingProjects) { - addToTodo({ project, location: originalLocation as TLocation }, toDo, seenProjects); + addToTodo(project, originalLocation as TLocation, toDo, seenProjects); } const symlinkedProjectsMap = projectService.getSymlinkedProjects(originalScriptInfo); if (symlinkedProjectsMap) { symlinkedProjectsMap.forEach((symlinkedProjects, symlinkedPath) => { - for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: { fileName: symlinkedPath, pos: originalLocation.pos } as TLocation }, toDo!, seenProjects); + for (const symlinkedProject of symlinkedProjects) { + addToTodo(symlinkedProject, { fileName: symlinkedPath, pos: originalLocation.pos } as TLocation, toDo!, seenProjects); + } }); } return originalLocation === location ? undefined : originalLocation; @@ -519,8 +524,8 @@ namespace ts.server { return toDo; } - function addToTodo(projectAndLocation: ProjectAndLocation, toDo: Push>, seenProjects: Map): void { - if (addToSeen(seenProjects, projectAndLocation.project)) toDo.push(projectAndLocation); + function addToTodo(project: Project, location: TLocation, toDo: Push>, seenProjects: Map): void { + if (addToSeen(seenProjects, project)) toDo.push({ project, location }); } function addToSeen(seenProjects: Map, project: Project) { @@ -1323,7 +1328,7 @@ namespace ts.server { // filter handles case when 'projects' is undefined projects = filter(projects, p => p.languageServiceEnabled && !p.isOrphan()); if (!ignoreNoProjectError && (!projects || !projects.length) && !symLinkedProjects) { - this.projectService.logErrorForScriptInfoNotFound(args.file); + this.projectService.logErrorForScriptInfoNotFound(args.file ?? args.projectFileName); return Errors.ThrowNoProject(); } return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217 @@ -1335,6 +1340,9 @@ namespace ts.server { if (project) { return project; } + if (!args.file) { + return Errors.ThrowNoProject(); + } } const info = this.projectService.getScriptInfo(args.file)!; return info.getDefaultProject(); @@ -1894,20 +1902,25 @@ namespace ts.server { } private getFullNavigateToItems(args: protocol.NavtoRequestArgs): readonly NavigateToItem[] { - const { currentFileOnly, searchValue, maxResultCount } = args; + const { currentFileOnly, searchValue, maxResultCount, projectFileName } = args; if (currentFileOnly) { - const { file, project } = this.getFileAndProject(args); + Debug.assertDefined(args.file); + const { file, project } = this.getFileAndProject(args as protocol.FileRequestArgs); return project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file); } - else { - return combineProjectOutputWhileOpeningReferencedProjects( - this.getProjects(args), - this.getDefaultProject(args), - project => - project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject()), - documentSpanLocation, + else if (!args.file && !projectFileName) { + return combineProjectOutputFromEveryProject( + this.projectService, + project => project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*filename*/ undefined, /*excludeDts*/ project.isNonTsProject()), navigateToItemIsEqualTo); } + const fileArgs = args as protocol.FileRequestArgs; + return combineProjectOutputWhileOpeningReferencedProjects( + this.getProjects(fileArgs), + this.getDefaultProject(fileArgs), + project => project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject()), + documentSpanLocation, + navigateToItemIsEqualTo); function navigateToItemIsEqualTo(a: NavigateToItem, b: NavigateToItem): boolean { if (a === b) { diff --git a/src/testRunner/unittests/tsserver/declarationFileMaps.ts b/src/testRunner/unittests/tsserver/declarationFileMaps.ts index 0fb08aa051b..c52e2ad807a 100644 --- a/src/testRunner/unittests/tsserver/declarationFileMaps.ts +++ b/src/testRunner/unittests/tsserver/declarationFileMaps.ts @@ -63,7 +63,7 @@ namespace ts.projectSystem { }; const aDts: File = { path: "/a/bin/a.d.ts", - // Need to mangle the sourceMappingURL part or it breaks the build + // ${""} is needed to mangle the sourceMappingURL part or it breaks the build content: `export declare function fnA(): void;\nexport interface IfaceA {\n}\nexport declare const instanceA: IfaceA;\n//# source${""}MappingURL=a.d.ts.map`, }; @@ -86,7 +86,7 @@ namespace ts.projectSystem { content: JSON.stringify(bDtsMapContent), }; const bDts: File = { - // Need to mangle the sourceMappingURL part or it breaks the build + // ${""} is need to mangle the sourceMappingURL part so it doesn't break the build path: "/b/bin/b.d.ts", content: `export declare function fnB(): void;\n//# source${""}MappingURL=b.d.ts.map`, }; @@ -114,7 +114,7 @@ namespace ts.projectSystem { }) }; - function makeSampleProjects(addUserTsConfig?: boolean) { + function makeSampleProjects(addUserTsConfig?: boolean, keepAllFiles?: boolean) { const host = createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), dummyFile]); const session = createSession(host); @@ -122,7 +122,9 @@ namespace ts.projectSystem { checkDeclarationFiles(bTs, session, [bDtsMap, bDts]); // Testing what happens if we delete the original sources. - host.deleteFile(bTs.path); + if (!keepAllFiles) { + host.deleteFile(bTs.path); + } openFilesForSession([userTs], session); const service = session.getProjectService(); @@ -322,6 +324,64 @@ namespace ts.projectSystem { verifyATsConfigOriginalProject(session); }); + it("navigateToAll -- when neither file nor project is specified", () => { + const session = makeSampleProjects(/*addUserTsConfig*/ true, /*keepAllFiles*/ true); + const response = executeSessionRequest(session, CommandNames.Navto, { file: undefined, searchValue: "fn" }); + assert.deepEqual(response, [ + { + ...protocolFileSpanFromSubstring({ + file: bTs, + text: "export function fnB() {}" + }), + name: "fnB", + matchKind: "prefix", + isCaseSensitive: true, + kind: ScriptElementKind.functionElement, + kindModifiers: "export", + }, + { + ...protocolFileSpanFromSubstring({ + file: aTs, + text: "export function fnA() {}" + }), + name: "fnA", + matchKind: "prefix", + isCaseSensitive: true, + kind: ScriptElementKind.functionElement, + kindModifiers: "export", + }, + { + ...protocolFileSpanFromSubstring({ + file: userTs, + text: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }" + }), + name: "fnUser", + matchKind: "prefix", + isCaseSensitive: true, + kind: ScriptElementKind.functionElement, + kindModifiers: "export", + } + ]); + }); + + it("navigateToAll -- when file is not specified but project is", () => { + const session = makeSampleProjects(/*addUserTsConfig*/ true, /*keepAllFiles*/ true); + const response = executeSessionRequest(session, CommandNames.Navto, { projectFileName: bTsconfig.path, file: undefined, searchValue: "fn" }); + assert.deepEqual(response, [ + { + ...protocolFileSpanFromSubstring({ + file: bTs, + text: "export function fnB() {}" + }), + name: "fnB", + matchKind: "prefix", + isCaseSensitive: true, + kind: ScriptElementKind.functionElement, + kindModifiers: "export", + } + ]); + }); + const referenceATs = (aTs: File): protocol.ReferencesResponseItem => makeReferenceItem({ file: aTs, isDefinition: true, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5e322bae86f..db6b0bc4905 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -8319,7 +8319,7 @@ declare namespace ts.server.protocol { /** * Arguments for navto request message. */ - interface NavtoRequestArgs extends FileRequestArgs { + interface NavtoRequestArgs { /** * Search term to navigate to from current location; term can * be '.*' or an identifier prefix. @@ -8329,6 +8329,10 @@ declare namespace ts.server.protocol { * Optional limit on the number of items to return. */ maxResultCount?: number; + /** + * The file for the request (absolute pathname required). + */ + file?: string; /** * Optional flag to indicate we want results for just the current file * or the entire project. @@ -8342,7 +8346,7 @@ declare namespace ts.server.protocol { * match the search term given in argument 'searchTerm'. The * context for the search is given by the named file. */ - interface NavtoRequest extends FileRequest { + interface NavtoRequest extends Request { command: CommandTypes.Navto; arguments: NavtoRequestArgs; } From 7d4fc7333105ef426a5a6605a75b5febff2d40be Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Tue, 21 Apr 2020 15:34:30 -0700 Subject: [PATCH 08/38] Fix preserveNewlines printer option when a list child has the same start or end as its parent (#37846) * Fix preserveNewlines printer option when a list child has the same start or end as its parent * Fix leading line separator calculation and JSX bug --- src/compiler/emitter.ts | 32 +++++++++++++------ src/compiler/utilities.ts | 14 ++++---- .../fourslash/textChangesPreserveNewlines8.ts | 29 +++++++++++++++++ 3 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 tests/cases/fourslash/textChangesPreserveNewlines8.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 94b03cfcb36..dc4b9ad5f2f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2366,16 +2366,10 @@ namespace ts { function emitParenthesizedExpression(node: ParenthesizedExpression) { const openParenPos = emitTokenWithComment(SyntaxKind.OpenParenToken, node.pos, writePunctuation, node); - const leadingNewlines = preserveSourceNewlines && getLeadingLineTerminatorCount(node, [node.expression], ListFormat.None); - if (leadingNewlines) { - writeLinesAndIndent(leadingNewlines, /*writeLinesIfNotIndenting*/ false); - } + const indented = writeLineSeparatorsAndIndentBefore(node.expression, node); emitExpression(node.expression); - const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(node, [node.expression], ListFormat.None); - if (trailingNewlines) { - writeLine(trailingNewlines); - } - decreaseIndentIf(leadingNewlines); + writeLineSeparatorsAfter(node.expression, node); + decreaseIndentIf(indented); emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression ? node.expression.end : openParenPos, writePunctuation, node); } @@ -3293,12 +3287,15 @@ namespace ts { writePunctuation("<"); if (isJsxOpeningElement(node)) { + const indented = writeLineSeparatorsAndIndentBefore(node.tagName, node); emitJsxTagName(node.tagName); emitTypeArguments(node, node.typeArguments); if (node.attributes.properties && node.attributes.properties.length > 0) { writeSpace(); } emit(node.attributes); + writeLineSeparatorsAfter(node.attributes, node); + decreaseIndentIf(indented); } writePunctuation(">"); @@ -4302,6 +4299,7 @@ namespace ts { return getEffectiveLines( includeComments => getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter( firstChild.pos, + parentNode.pos, currentSourceFile!, includeComments)); } @@ -4359,6 +4357,7 @@ namespace ts { return getEffectiveLines( includeComments => getLinesBetweenPositionAndNextNonWhitespaceCharacter( lastChild.end, + parentNode.end, currentSourceFile!, includeComments)); } @@ -4398,6 +4397,21 @@ namespace ts { return lines; } + function writeLineSeparatorsAndIndentBefore(node: Node, parent: Node): boolean { + const leadingNewlines = preserveSourceNewlines && getLeadingLineTerminatorCount(parent, [node], ListFormat.None); + if (leadingNewlines) { + writeLinesAndIndent(leadingNewlines, /*writeLinesIfNotIndenting*/ false); + } + return !!leadingNewlines; + } + + function writeLineSeparatorsAfter(node: Node, parent: Node) { + const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(parent, [node], ListFormat.None); + if (trailingNewlines) { + writeLine(trailingNewlines); + } + } + function synthesizedNodeStartsOnNewLine(node: Node, format: ListFormat) { if (nodeIsSynthesized(node)) { const startsOnNewLine = getStartsOnNewLine(node); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 080f2ed932e..bab1fe7b02b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4780,19 +4780,19 @@ namespace ts { return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos, /*stopAfterLineBreak*/ false, includeComments); } - export function getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter(pos: number, sourceFile: SourceFile, includeComments?: boolean) { + export function getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter(pos: number, stopPos: number, sourceFile: SourceFile, includeComments?: boolean) { const startPos = skipTrivia(sourceFile.text, pos, /*stopAfterLineBreak*/ false, includeComments); - const prevPos = getPreviousNonWhitespacePosition(startPos, sourceFile); - return getLinesBetweenPositions(sourceFile, prevPos || 0, startPos); + const prevPos = getPreviousNonWhitespacePosition(startPos, stopPos, sourceFile); + return getLinesBetweenPositions(sourceFile, prevPos ?? stopPos, startPos); } - export function getLinesBetweenPositionAndNextNonWhitespaceCharacter(pos: number, sourceFile: SourceFile, includeComments?: boolean) { + export function getLinesBetweenPositionAndNextNonWhitespaceCharacter(pos: number, stopPos: number, sourceFile: SourceFile, includeComments?: boolean) { const nextPos = skipTrivia(sourceFile.text, pos, /*stopAfterLineBreak*/ false, includeComments); - return getLinesBetweenPositions(sourceFile, pos, nextPos); + return getLinesBetweenPositions(sourceFile, pos, Math.min(stopPos, nextPos)); } - function getPreviousNonWhitespacePosition(pos: number, sourceFile: SourceFile) { - while (pos-- > 0) { + function getPreviousNonWhitespacePosition(pos: number, stopPos = 0, sourceFile: SourceFile) { + while (pos-- > stopPos) { if (!isWhiteSpaceLike(sourceFile.text.charCodeAt(pos))) { return pos; } diff --git a/tests/cases/fourslash/textChangesPreserveNewlines8.ts b/tests/cases/fourslash/textChangesPreserveNewlines8.ts new file mode 100644 index 00000000000..e74aef6c9d0 --- /dev/null +++ b/tests/cases/fourslash/textChangesPreserveNewlines8.ts @@ -0,0 +1,29 @@ +// #37813 + +/// + +////function foo() { +//// /*1*/var x: number +//// +//// x = 10; +//// return x;/*2*/ +////} + +goTo.select("1", "2"); +edit.applyRefactor({ + refactorName: "Extract Symbol", + actionName: "function_scope_1", + actionDescription: "Extract to function in global scope", + newContent: +`function foo() { + return /*RENAME*/newFunction(); +} + +function newFunction() { + var x: number; + + x = 10; + return x; +} +` +}); From 3c3b7dc4c3306d007046ee2c62373c72b452639a Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 21 Apr 2020 16:30:09 -0700 Subject: [PATCH 09/38] Update user baselines (#37995) Co-authored-by: typescript-bot --- tests/baselines/reference/docker/vue-next.log | 24 +++++++++---------- tests/baselines/reference/user/discord.js.log | 8 +++---- tests/baselines/reference/user/puppeteer.log | 6 +++-- tests/baselines/reference/user/webpack.log | 1 - 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/baselines/reference/docker/vue-next.log b/tests/baselines/reference/docker/vue-next.log index 7e673ffe7c8..b9bf1004dfd 100644 --- a/tests/baselines/reference/docker/vue-next.log +++ b/tests/baselines/reference/docker/vue-next.log @@ -1,7 +1,7 @@ Exit Code: 0 Standard output: -> @X.X.X-alpha.13 build /vue-next +> @X.X.X-beta.3 build /vue-next > node scripts/build.js "--types" Rolling up type definitions for compiler-core... Writing: /vue-next/temp/compiler-core.api.json @@ -41,18 +41,18 @@ created packages/compiler-core/dist/compiler-core.cjs.js in ?s created packages/compiler-core/dist/compiler-core.cjs.prod.js in ?s /vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.esm-bundler.js... created packages/compiler-dom/dist/compiler-dom.esm-bundler.js in ?s +/vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.esm-browser.js... +created packages/compiler-dom/dist/compiler-dom.esm-browser.js in ?s /vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.cjs.js... created packages/compiler-dom/dist/compiler-dom.cjs.js in ?s /vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.global.js... created packages/compiler-dom/dist/compiler-dom.global.js in ?s -/vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.esm.js... -created packages/compiler-dom/dist/compiler-dom.esm.js in ?s +/vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.esm-browser.prod.js... +created packages/compiler-dom/dist/compiler-dom.esm-browser.prod.js in ?s /vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.cjs.prod.js... created packages/compiler-dom/dist/compiler-dom.cjs.prod.js in ?s /vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.global.prod.js... created packages/compiler-dom/dist/compiler-dom.global.prod.js in ?s -/vue-next/packages/compiler-dom/src/index.ts → packages/compiler-dom/dist/compiler-dom.esm.prod.js... -created packages/compiler-dom/dist/compiler-dom.esm.prod.js in ?s /vue-next/packages/compiler-sfc/src/index.ts → packages/compiler-sfc/dist/compiler-sfc.cjs.js... (!) Unresolved dependencies https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency @@ -62,23 +62,23 @@ created packages/compiler-sfc/dist/compiler-sfc.cjs.js in ?s created packages/compiler-ssr/dist/compiler-ssr.cjs.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.esm-bundler.js... created packages/reactivity/dist/reactivity.esm-bundler.js in ?s +/vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.esm-browser.js... +created packages/reactivity/dist/reactivity.esm-browser.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.cjs.js... created packages/reactivity/dist/reactivity.cjs.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.global.js... created packages/reactivity/dist/reactivity.global.js in ?s -/vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.esm.js... -created packages/reactivity/dist/reactivity.esm.js in ?s +/vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.esm-browser.prod.js... +created packages/reactivity/dist/reactivity.esm-browser.prod.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.cjs.prod.js... created packages/reactivity/dist/reactivity.cjs.prod.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.global.prod.js... created packages/reactivity/dist/reactivity.global.prod.js in ?s -/vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.esm.prod.js... -created packages/reactivity/dist/reactivity.esm.prod.js in ?s /vue-next/packages/runtime-core/src/index.ts → packages/runtime-core/dist/runtime-core.esm-bundler.js... -[!] (plugin rpt2) Error: /vue-next/packages/runtime-core/src/componentOptions.ts(161,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. +[!] (plugin rpt2) Error: /vue-next/packages/runtime-core/src/componentOptions.ts(181,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'. packages/runtime-core/src/componentOptions.ts -Error: /vue-next/packages/runtime-core/src/componentOptions.ts(161,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. +Error: /vue-next/packages/runtime-core/src/componentOptions.ts(181,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'. at error (/vue-next/node_modules/rollup/dist/shared/rollup.js:10399:30) at throwPluginError (/vue-next/node_modules/rollup/dist/shared/rollup.js:16617:12) @@ -90,7 +90,7 @@ Error: /vue-next/packages/runtime-core/src/componentOptions.ts(161,18): semantic at forEach (/vue-next/node_modules/rollup-plugin-typescript2/node_modules/lodash/lodash.js:9342:14) at _.each (/vue-next/node_modules/rollup-plugin-typescript2/src/print-diagnostics.ts:9:2) at Object.transform (/vue-next/node_modules/rollup-plugin-typescript2/src/index.ts:242:5) -(node:17) UnhandledPromiseRejectionWarning: Error: Command failed with exit code 1 (EPERM): rollup -c --environment COMMIT:11654a6,NODE_ENV:production,TARGET:runtime-core,TYPES:true +(node:17) UnhandledPromiseRejectionWarning: Error: Command failed with exit code 1 (EPERM): rollup -c --environment COMMIT:6fefeaf,NODE_ENV:production,TARGET:runtime-core,TYPES:true at makeError (/vue-next/node_modules/execa/lib/error.js:59:11) at handlePromise (/vue-next/node_modules/execa/index.js:112:26) at processTicksAndRejections (internal/process/task_queues.js:97:5) diff --git a/tests/baselines/reference/user/discord.js.log b/tests/baselines/reference/user/discord.js.log index a56bd598bfe..66c4ff73cf8 100644 --- a/tests/baselines/reference/user/discord.js.log +++ b/tests/baselines/reference/user/discord.js.log @@ -5,10 +5,10 @@ node_modules/discord.js/typings/index.d.ts(18,30): error TS7016: Could not find node_modules/discord.js/typings/index.d.ts(96,37): error TS2694: Namespace 'NodeJS' has no exported member 'Immediate'. node_modules/discord.js/typings/index.d.ts(103,43): error TS2694: Namespace 'NodeJS' has no exported member 'Immediate'. node_modules/discord.js/typings/index.d.ts(107,79): error TS2694: Namespace 'NodeJS' has no exported member 'Immediate'. -node_modules/discord.js/typings/index.d.ts(1742,103): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. -node_modules/discord.js/typings/index.d.ts(1744,34): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. -node_modules/discord.js/typings/index.d.ts(1747,34): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. -node_modules/discord.js/typings/index.d.ts(2980,21): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. +node_modules/discord.js/typings/index.d.ts(1749,103): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. +node_modules/discord.js/typings/index.d.ts(1751,34): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. +node_modules/discord.js/typings/index.d.ts(1754,34): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. +node_modules/discord.js/typings/index.d.ts(2989,21): error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. diff --git a/tests/baselines/reference/user/puppeteer.log b/tests/baselines/reference/user/puppeteer.log index b0e6d8711bc..6135c34f414 100644 --- a/tests/baselines/reference/user/puppeteer.log +++ b/tests/baselines/reference/user/puppeteer.log @@ -1,9 +1,11 @@ Exit Code: 1 Standard output: +src/JSHandle.ts(440,5): error TS2322: Type 'unknown' is not assignable to type 'T'. + 'unknown' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. +src/JSHandle.ts(454,5): error TS2322: Type 'unknown' is not assignable to type 'T'. + 'T' could be instantiated with an arbitrary type which could be unrelated to 'unknown'. src/Launcher.js(181,17): error TS1003: Identifier expected. src/Launcher.js(359,17): error TS1003: Identifier expected. -src/PipeTransport.js(19,17): error TS1003: Identifier expected. -src/WebSocketTransport.js(19,17): error TS1003: Identifier expected. diff --git a/tests/baselines/reference/user/webpack.log b/tests/baselines/reference/user/webpack.log index 224a05ae6be..4b4f3e5ad7e 100644 --- a/tests/baselines/reference/user/webpack.log +++ b/tests/baselines/reference/user/webpack.log @@ -9,7 +9,6 @@ lib/wasm-async/AsyncWebAssemblyModulesPlugin.js(37,15): error TS2304: Cannot fin lib/wasm-async/AsyncWebAssemblyModulesPlugin.js(38,15): error TS2304: Cannot find name 'RuntimeTemplate'. lib/wasm-async/AsyncWebAssemblyModulesPlugin.js(39,15): error TS2304: Cannot find name 'ModuleGraph'. lib/wasm-async/AsyncWebAssemblyModulesPlugin.js(40,15): error TS2304: Cannot find name 'ChunkGraph'. -tooling/format-file-header.js(151,34): error TS2556: Expected 1-2 arguments, but got 0 or more. From 2784e03d7e5fa8969d9f53dc2b3635b5896ccf8b Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 22 Apr 2020 04:10:37 +0000 Subject: [PATCH 10/38] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6f55deb823f..563b2b5a06b 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -436,7 +436,7 @@ - + @@ -1180,7 +1180,7 @@ - + @@ -3193,7 +3193,7 @@ - + @@ -7408,7 +7408,7 @@ - + @@ -11116,7 +11116,7 @@ - + @@ -11677,7 +11677,7 @@ - + From 39beb1d011a6bc412a67e1dfa2ec1cb1de438b4f Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Wed, 22 Apr 2020 18:12:01 +0800 Subject: [PATCH 11/38] Add check for delete expression must be optional (#37921) * Add check for delete expression must be optional * Add more tests --- src/compiler/checker.ts | 15 +- src/compiler/diagnosticMessages.json | 4 + .../controlFlowDeleteOperator.errors.txt | 5 +- .../reference/deleteChain.errors.txt | 66 +++++++++ ...ionMustBeOptional(strict=false).errors.txt | 46 ++++++ ...eExpressionMustBeOptional(strict=false).js | 57 ++++++++ ...essionMustBeOptional(strict=false).symbols | 118 +++++++++++++++ ...pressionMustBeOptional(strict=false).types | 137 ++++++++++++++++++ ...sionMustBeOptional(strict=true).errors.txt | 52 +++++++ ...teExpressionMustBeOptional(strict=true).js | 58 ++++++++ ...ressionMustBeOptional(strict=true).symbols | 118 +++++++++++++++ ...xpressionMustBeOptional(strict=true).types | 137 ++++++++++++++++++ .../reference/privateNamesNoDelete.errors.txt | 5 +- .../deleteExpressionMustBeOptional.ts | 42 ++++++ 14 files changed, 856 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/deleteChain.errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types create mode 100644 tests/cases/compiler/deleteExpressionMustBeOptional.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac02f917827..89be1e0aa73 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27583,12 +27583,23 @@ namespace ts { } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); - if (symbol && isReadonlySymbol(symbol)) { - error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); + if (symbol) { + if (isReadonlySymbol(symbol)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); + } + + checkDeleteExpressionMustBeOptional(expr, getTypeOfSymbol(symbol)); } return booleanType; } + function checkDeleteExpressionMustBeOptional(expr: AccessExpression, type: Type) { + const AnyOrUnknownOrNeverFlags = TypeFlags.AnyOrUnknown | TypeFlags.Never; + if (strictNullChecks && !(type.flags & AnyOrUnknownOrNeverFlags) && !(getFalsyFlags(type) & TypeFlags.Undefined)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); + } + } + function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); return typeofType; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ab45cbe0cf4..4a7c6e8b461 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2963,6 +2963,10 @@ "category": "Error", "code": 2789 }, + "The operand of a 'delete' operator must be optional.": { + "category": "Error", + "code": 2790 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt index 91ec2aa0de8..f5a6823a778 100644 --- a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt +++ b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt @@ -1,7 +1,8 @@ +tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(10,12): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error TS2703: The operand of a 'delete' operator must be a property reference. -==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (1 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (2 errors) ==== function f() { let x: { a?: number | string, b: number | string } = { b: 1 }; x.a; @@ -12,6 +13,8 @@ tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error T x.b; delete x.a; delete x.b; + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. x.a; x.b; x; diff --git a/tests/baselines/reference/deleteChain.errors.txt b/tests/baselines/reference/deleteChain.errors.txt new file mode 100644 index 00000000000..dd716419573 --- /dev/null +++ b/tests/baselines/reference/deleteChain.errors.txt @@ -0,0 +1,66 @@ +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(2,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(3,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(6,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(7,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(10,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(11,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(14,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(15,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(16,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(19,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(20,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(23,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(24,9): error TS2790: The operand of a 'delete' operator must be optional. + + +==== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts (13 errors) ==== + declare const o1: undefined | { b: string }; + delete o1?.b; + ~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o1?.b); + ~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o2: undefined | { b: { c: string } }; + delete o2?.b.c; + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o2?.b.c); + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o3: { b: undefined | { c: string } }; + delete o3.b?.c; + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o3.b?.c); + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o4: { b?: { c: { d?: { e: string } } } }; + delete o4.b?.c.d?.e; + ~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o4.b?.c.d)?.e; + ~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o4.b?.c.d?.e); + ~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o5: { b?(): { c: { d?: { e: string } } } }; + delete o5.b?.().c.d?.e; + ~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o5.b?.().c.d?.e); + ~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o6: { b?: { c: { d?: { e: string } } } }; + delete o6.b?.['c'].d?.['e']; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o6.b?.['c'].d?.['e']); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt new file mode 100644 index 00000000000..8a876cb6350 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt @@ -0,0 +1,46 @@ +tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. + + +==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (1 errors) ==== + interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never + } + + interface AA { + [s: string]: number + } + + type BB = { + [P in keyof any]: number + } + + declare const f: Foo + declare const a: AA + declare const b: BB + + delete f.a + delete f.b + delete f.c + delete f.d + delete f.e + delete f.f + delete f.g + delete f.h + delete f.i + delete f.j + ~ +!!! error TS2339: Property 'j' does not exist on type 'Foo'. + + delete a.a + delete a.b + + delete b.a + delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js new file mode 100644 index 00000000000..268c76175bf --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js @@ -0,0 +1,57 @@ +//// [deleteExpressionMustBeOptional.ts] +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b + +//// [deleteExpressionMustBeOptional.js] +delete f.a; +delete f.b; +delete f.c; +delete f.d; +delete f.e; +delete f.f; +delete f.g; +delete f.h; +delete f.i; +delete f.j; +delete a.a; +delete a.b; +delete b.a; +delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols new file mode 100644 index 00000000000..aad7423a133 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols @@ -0,0 +1,118 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + + a: number +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + + b: number | undefined +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + + c: number | null +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + + d?: number +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + + e: number | undefined | null +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + + f?: number | undefined | null +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + + g: unknown +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + + h: any +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + + i: never +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +} + +interface AA { +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + + [s: string]: number +>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) +} + +type BB = { +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + + [P in keyof any]: number +>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) +} + +declare const f: Foo +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + +declare const a: AA +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + +declare const b: BB +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + +delete f.a +>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + +delete f.b +>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + +delete f.c +>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + +delete f.d +>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + +delete f.e +>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + +delete f.f +>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + +delete f.g +>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + +delete f.h +>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + +delete f.i +>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) + +delete f.j +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) + +delete a.a +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete a.b +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete b.a +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + +delete b.b +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types new file mode 100644 index 00000000000..371bb25e96d --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types @@ -0,0 +1,137 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { + a: number +>a : number + + b: number | undefined +>b : number + + c: number | null +>c : number +>null : null + + d?: number +>d : number + + e: number | undefined | null +>e : number +>null : null + + f?: number | undefined | null +>f : number +>null : null + + g: unknown +>g : unknown + + h: any +>h : any + + i: never +>i : never +} + +interface AA { + [s: string]: number +>s : string +} + +type BB = { +>BB : BB + + [P in keyof any]: number +} + +declare const f: Foo +>f : Foo + +declare const a: AA +>a : AA + +declare const b: BB +>b : BB + +delete f.a +>delete f.a : boolean +>f.a : number +>f : Foo +>a : number + +delete f.b +>delete f.b : boolean +>f.b : number +>f : Foo +>b : number + +delete f.c +>delete f.c : boolean +>f.c : number +>f : Foo +>c : number + +delete f.d +>delete f.d : boolean +>f.d : number +>f : Foo +>d : number + +delete f.e +>delete f.e : boolean +>f.e : number +>f : Foo +>e : number + +delete f.f +>delete f.f : boolean +>f.f : number +>f : Foo +>f : number + +delete f.g +>delete f.g : boolean +>f.g : unknown +>f : Foo +>g : unknown + +delete f.h +>delete f.h : boolean +>f.h : any +>f : Foo +>h : any + +delete f.i +>delete f.i : boolean +>f.i : never +>f : Foo +>i : never + +delete f.j +>delete f.j : boolean +>f.j : any +>f : Foo +>j : any + +delete a.a +>delete a.a : boolean +>a.a : number +>a : AA +>a : number + +delete a.b +>delete a.b : boolean +>a.b : number +>a : AA +>b : number + +delete b.a +>delete b.a : boolean +>b.a : number +>b : BB +>a : number + +delete b.b +>delete b.b : boolean +>b.b : number +>b : BB +>b : number + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt new file mode 100644 index 00000000000..b1cabc96009 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt @@ -0,0 +1,52 @@ +tests/cases/compiler/deleteExpressionMustBeOptional.ts(25,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/compiler/deleteExpressionMustBeOptional.ts(27,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. + + +==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (3 errors) ==== + interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never + } + + interface AA { + [s: string]: number + } + + type BB = { + [P in keyof any]: number + } + + declare const f: Foo + declare const a: AA + declare const b: BB + + delete f.a + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete f.b + delete f.c + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete f.d + delete f.e + delete f.f + delete f.g + delete f.h + delete f.i + delete f.j + ~ +!!! error TS2339: Property 'j' does not exist on type 'Foo'. + + delete a.a + delete a.b + + delete b.a + delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js new file mode 100644 index 00000000000..ca81456b4f4 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js @@ -0,0 +1,58 @@ +//// [deleteExpressionMustBeOptional.ts] +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b + +//// [deleteExpressionMustBeOptional.js] +"use strict"; +delete f.a; +delete f.b; +delete f.c; +delete f.d; +delete f.e; +delete f.f; +delete f.g; +delete f.h; +delete f.i; +delete f.j; +delete a.a; +delete a.b; +delete b.a; +delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols new file mode 100644 index 00000000000..aad7423a133 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols @@ -0,0 +1,118 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + + a: number +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + + b: number | undefined +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + + c: number | null +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + + d?: number +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + + e: number | undefined | null +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + + f?: number | undefined | null +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + + g: unknown +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + + h: any +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + + i: never +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +} + +interface AA { +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + + [s: string]: number +>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) +} + +type BB = { +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + + [P in keyof any]: number +>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) +} + +declare const f: Foo +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + +declare const a: AA +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + +declare const b: BB +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + +delete f.a +>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + +delete f.b +>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + +delete f.c +>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + +delete f.d +>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + +delete f.e +>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + +delete f.f +>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + +delete f.g +>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + +delete f.h +>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + +delete f.i +>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) + +delete f.j +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) + +delete a.a +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete a.b +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete b.a +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + +delete b.b +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types new file mode 100644 index 00000000000..a3d6f52b7c4 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types @@ -0,0 +1,137 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { + a: number +>a : number + + b: number | undefined +>b : number | undefined + + c: number | null +>c : number | null +>null : null + + d?: number +>d : number | undefined + + e: number | undefined | null +>e : number | null | undefined +>null : null + + f?: number | undefined | null +>f : number | null | undefined +>null : null + + g: unknown +>g : unknown + + h: any +>h : any + + i: never +>i : never +} + +interface AA { + [s: string]: number +>s : string +} + +type BB = { +>BB : BB + + [P in keyof any]: number +} + +declare const f: Foo +>f : Foo + +declare const a: AA +>a : AA + +declare const b: BB +>b : BB + +delete f.a +>delete f.a : boolean +>f.a : number +>f : Foo +>a : number + +delete f.b +>delete f.b : boolean +>f.b : number | undefined +>f : Foo +>b : number | undefined + +delete f.c +>delete f.c : boolean +>f.c : number | null +>f : Foo +>c : number | null + +delete f.d +>delete f.d : boolean +>f.d : number | undefined +>f : Foo +>d : number | undefined + +delete f.e +>delete f.e : boolean +>f.e : number | null | undefined +>f : Foo +>e : number | null | undefined + +delete f.f +>delete f.f : boolean +>f.f : number | null | undefined +>f : Foo +>f : number | null | undefined + +delete f.g +>delete f.g : boolean +>f.g : unknown +>f : Foo +>g : unknown + +delete f.h +>delete f.h : boolean +>f.h : any +>f : Foo +>h : any + +delete f.i +>delete f.i : boolean +>f.i : never +>f : Foo +>i : never + +delete f.j +>delete f.j : boolean +>f.j : any +>f : Foo +>j : any + +delete a.a +>delete a.a : boolean +>a.a : number +>a : AA +>a : number + +delete a.b +>delete a.b : boolean +>a.b : number +>a : AA +>b : number + +delete b.a +>delete b.a : boolean +>b.a : number +>b : BB +>a : number + +delete b.b +>delete b.b : boolean +>b.b : number +>b : BB +>b : number + diff --git a/tests/baselines/reference/privateNamesNoDelete.errors.txt b/tests/baselines/reference/privateNamesNoDelete.errors.txt index d593fe107a1..e2fc11cb4ac 100644 --- a/tests/baselines/reference/privateNamesNoDelete.errors.txt +++ b/tests/baselines/reference/privateNamesNoDelete.errors.txt @@ -1,12 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS18011: The operand of a 'delete' operator cannot be a private identifier. -==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (2 errors) ==== class A { #v = 1; constructor() { delete this.#v; // Error: The operand of a delete operator cannot be a private name. ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + ~~~~~~~ !!! error TS18011: The operand of a 'delete' operator cannot be a private identifier. } } diff --git a/tests/cases/compiler/deleteExpressionMustBeOptional.ts b/tests/cases/compiler/deleteExpressionMustBeOptional.ts new file mode 100644 index 00000000000..9f84d9ea2f1 --- /dev/null +++ b/tests/cases/compiler/deleteExpressionMustBeOptional.ts @@ -0,0 +1,42 @@ +// @strict: true, false + +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b \ No newline at end of file From 92a63741a288ff34f47df5505dbbd7ab19490493 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Wed, 22 Apr 2020 18:51:36 +0300 Subject: [PATCH 12/38] fix(38080): add outlining spans for TypeLiteral (#38089) --- src/services/outliningElementsCollector.ts | 1 + .../fourslash/getOutliningForTypeLiteral.ts | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/cases/fourslash/getOutliningForTypeLiteral.ts diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index dd71b48c49c..7c9e89052ab 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -199,6 +199,7 @@ namespace ts.OutliningElementsCollector { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.CaseBlock: + case SyntaxKind.TypeLiteral: return spanForNode(n); case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: diff --git a/tests/cases/fourslash/getOutliningForTypeLiteral.ts b/tests/cases/fourslash/getOutliningForTypeLiteral.ts new file mode 100644 index 00000000000..d0d6693ec39 --- /dev/null +++ b/tests/cases/fourslash/getOutliningForTypeLiteral.ts @@ -0,0 +1,24 @@ +/// + +////type A =[| { +//// a: number; +////}|] +//// +////type B =[| { +//// a:[| { +//// a1:[| { +//// a2:[| { +//// x: number; +//// y: number; +//// }|] +//// }|] +//// }|], +//// b:[| { +//// x: number; +//// }|], +//// c:[| { +//// x: number; +//// }|] +////}|] + +verify.outliningSpansInCurrentFile(test.ranges(), "code"); From d2016912b5f8778b25c8f7c2dc4e82dbd5e27843 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Wed, 22 Apr 2020 19:07:36 +0300 Subject: [PATCH 13/38] fix(37825): exclude private fields from completions in subclasses (#37906) --- src/services/completions.ts | 3 ++- .../completionListClassPrivateFields.ts | 15 +++++++++++++ .../completionListClassPrivateFields_JS.ts | 21 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/completionListClassPrivateFields.ts create mode 100644 tests/cases/fourslash/completionListClassPrivateFields_JS.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 2066c485ac8..bb08fe7d549 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2427,7 +2427,8 @@ namespace ts.Completions { return baseSymbols.filter(propertySymbol => !existingMemberNames.has(propertySymbol.escapedName) && !!propertySymbol.declarations && - !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private)); + !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private) && + !isPrivateIdentifierPropertyDeclaration(propertySymbol.valueDeclaration)); } /** diff --git a/tests/cases/fourslash/completionListClassPrivateFields.ts b/tests/cases/fourslash/completionListClassPrivateFields.ts new file mode 100644 index 00000000000..f7638047a67 --- /dev/null +++ b/tests/cases/fourslash/completionListClassPrivateFields.ts @@ -0,0 +1,15 @@ +/// + +////class A { +//// #private = 1; +////} +//// +////class B extends A { +//// /**/ +////} + +verify.completions({ + marker: "", + exact: completion.classElementKeywords, + isNewIdentifierLocation: true +}); diff --git a/tests/cases/fourslash/completionListClassPrivateFields_JS.ts b/tests/cases/fourslash/completionListClassPrivateFields_JS.ts new file mode 100644 index 00000000000..49c8d05af6a --- /dev/null +++ b/tests/cases/fourslash/completionListClassPrivateFields_JS.ts @@ -0,0 +1,21 @@ +/// + +// @allowJs: true +// @Filename: a.js +////class A { +//// #private = 1; +////} +//// +////class B extends A { +//// /**/ +////} + +verify.completions({ + marker: "", + exact: [ + { name: "A", sortText: completion.SortText.JavascriptIdentifiers }, + { name: "B", sortText: completion.SortText.JavascriptIdentifiers }, + ...completion.classElementInJsKeywords + ], + isNewIdentifierLocation: true +}); From f248567dabd1b9cc11bb53d815e79c80becaee51 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 22 Apr 2020 09:56:32 -0700 Subject: [PATCH 14/38] Filter undefined only in binding patterns in params (#38116) initialiser. But this is only correct when the initialiser is for a parameter. For example: ```ts declare let x: { s: string } | undefined; const { s } = x; ``` This PR removes undefined from the type of a binding pattern only when the binding pattern's parent is a parameter. This fixes the regression from 3.8. However, it's still not the ideal fix; we should be able to use control flow to solve this problem. Consider: ```ts const { s }: { s: string } | undefined = { s: 'hi' } declare function f({ s }: { s: string } | undefined = { s: 'hi' }): void ``` Neither line should have an error, but the first does in 3.8 and after this change. --- src/compiler/checker.ts | 2 +- ...rInitalizedVariablesFiltersUndefined.errors.txt | 14 ++++++++++++++ ...alTypeForInitalizedVariablesFiltersUndefined.js | 7 ++++++- ...eForInitalizedVariablesFiltersUndefined.symbols | 8 ++++++++ ...ypeForInitalizedVariablesFiltersUndefined.types | 8 ++++++++ ...alTypeForInitalizedVariablesFiltersUndefined.ts | 5 ++++- 6 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89be1e0aa73..9014e2f43f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7306,7 +7306,7 @@ namespace ts { parentType = getNonNullableType(parentType); } // Filter `undefined` from the type we check against if the parent has an initializer (which handles the `undefined` case implicitly) - else if (strictNullChecks && pattern.parent.initializer) { + else if (strictNullChecks && pattern.parent.initializer && isParameter(pattern.parent)) { parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined); } diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt new file mode 100644 index 00000000000..32ff831d2bd --- /dev/null +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt @@ -0,0 +1,14 @@ +tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts(7,9): error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. + + +==== tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts (1 errors) ==== + const fInferred = ({ a = 0 } = {}) => a; + // const fInferred: ({ a }?: { a?: number; }) => number + + const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; + + declare var t: { s: string } | undefined; + const { s } = t; + ~ +!!! error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js index 9c2a6eaa780..8311b6ff481 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js @@ -2,7 +2,11 @@ const fInferred = ({ a = 0 } = {}) => a; // const fInferred: ({ a }?: { a?: number; }) => number -const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; +const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; + +declare var t: { s: string } | undefined; +const { s } = t; + //// [contextualTypeForInitalizedVariablesFiltersUndefined.js] "use strict"; @@ -15,3 +19,4 @@ var fAnnotated = function (_a) { var _b = (_a === void 0 ? {} : _a).a, a = _b === void 0 ? 0 : _b; return a; }; +var s = t.s; diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols index 7b675719012..81ae53f9418 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols @@ -12,3 +12,11 @@ const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; >a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 3, 39)) >a : Symbol(a, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 3, 39)) +declare var t: { s: string } | undefined; +>t : Symbol(t, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 5, 11)) +>s : Symbol(s, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 5, 16)) + +const { s } = t; +>s : Symbol(s, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 6, 7)) +>t : Symbol(t, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 5, 11)) + diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types index d8278124ff0..58580fdacce 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types @@ -18,3 +18,11 @@ const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; >{} : {} >a : number +declare var t: { s: string } | undefined; +>t : { s: string; } | undefined +>s : string + +const { s } = t; +>s : any +>t : { s: string; } | undefined + diff --git a/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts b/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts index 268544f8192..cfa8d8d6824 100644 --- a/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts +++ b/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts @@ -2,4 +2,7 @@ const fInferred = ({ a = 0 } = {}) => a; // const fInferred: ({ a }?: { a?: number; }) => number -const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; \ No newline at end of file +const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; + +declare var t: { s: string } | undefined; +const { s } = t; From ef83109dbf122644bdba9a8cb97ea007c7668ea0 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 22 Apr 2020 14:28:11 -0400 Subject: [PATCH 15/38] Prefer a likely literal over anonymous type in --noImplicitAny codefixes (#36015) * Prefer a likely literal over anonymous type in --noImplicitAny codefixes Before trying to make an anonymous type for a type's usage, we'll first check if there is exactly one builtin primitive the usage is assignable to, and use it if so. Right now that's only `number` and `string` because `boolean` has no distinguishable members. A couple of implementation details: * `tryInsertTypeAnnotation` needed to know to insert a type _after_ a node's `exclamationToken` if it exists * This code area was written before `??` :wink: * Used unknown/any instead of void when applicable * Fix little whitespace change in tests/cases/fourslash/codeFixInferFromUsagePropertyAccessJS.ts * Undid some now-unnecessary unknown additions * Took advice on restricting void to just call expressions --- src/services/codefixes/inferFromUsage.ts | 11 ++++++----- src/services/textChanges.ts | 2 +- .../codeFixInferFromUsageParameterLiteral.ts | 10 ++++++++++ .../fourslash/codeFixInferFromUsagePropertyAccess.ts | 2 +- .../codeFixInferFromUsagePropertyAccessJS.ts | 2 +- .../fourslash/codeFixInferFromUsageVariableLiteral.ts | 9 +++++++++ 6 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 tests/cases/fourslash/codeFixInferFromUsageParameterLiteral.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageVariableLiteral.ts diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 0af71bbbb9c..7fa01819d22 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -603,7 +603,7 @@ namespace ts.codefix { switch (node.parent.kind) { case SyntaxKind.ExpressionStatement: - addCandidateType(usage, checker.getVoidType()); + inferTypeFromExpressionStatement(node, usage); break; case SyntaxKind.PostfixUnaryExpression: usage.isNumber = true; @@ -661,6 +661,10 @@ namespace ts.codefix { } } + function inferTypeFromExpressionStatement(node: Expression, usage: Usage): void { + addCandidateType(usage, isCallExpression(node) ? checker.getVoidType() : checker.getAnyType()); + } + function inferTypeFromPrefixUnaryExpression(node: PrefixUnaryExpression, usage: Usage): void { switch (node.operator) { case SyntaxKind.PlusPlusToken: @@ -960,10 +964,7 @@ namespace ts.codefix { if (usage.numberIndex) { types.push(checker.createArrayType(combineFromUsage(usage.numberIndex))); } - if (usage.properties && usage.properties.size - || usage.calls && usage.calls.length - || usage.constructs && usage.constructs.length - || usage.stringIndex) { + if (usage.properties?.size || usage.calls?.length || usage.constructs?.length || usage.stringIndex) { types.push(inferStructuralType(usage)); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index bf1dae65602..2b743f4d592 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -434,7 +434,7 @@ namespace ts.textChanges { } } else { - endNode = node.kind !== SyntaxKind.VariableDeclaration && node.questionToken ? node.questionToken : node.name; + endNode = (node.kind === SyntaxKind.VariableDeclaration ? node.exclamationToken : node.questionToken) ?? node.name; } this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " }); diff --git a/tests/cases/fourslash/codeFixInferFromUsageParameterLiteral.ts b/tests/cases/fourslash/codeFixInferFromUsageParameterLiteral.ts new file mode 100644 index 00000000000..16610635982 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageParameterLiteral.ts @@ -0,0 +1,10 @@ +/// + +// @noImplicitAny: true +//// function foo([|text |]) { +//// text.length; +//// text.indexOf("z"); +//// text.charAt(0); +//// } + +verify.rangeAfterCodeFix("text: string", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, /*index*/0); diff --git a/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts index 44d2e2d7b1c..41112b2409e 100644 --- a/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts +++ b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts @@ -12,4 +12,4 @@ //// return x.y.z ////} -verify.rangeAfterCodeFix("a: { b: { c: void; }; }, m: { n: () => number; }, x: { y: { z: number[]; }; }", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, /*index*/0); +verify.rangeAfterCodeFix("a: { b: { c: any; }; }, m: { n: () => number; }, x: { y: { z: number[]; }; }", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, /*index*/0); diff --git a/tests/cases/fourslash/codeFixInferFromUsagePropertyAccessJS.ts b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccessJS.ts index 357b1a991ba..ed9d4b33b37 100644 --- a/tests/cases/fourslash/codeFixInferFromUsagePropertyAccessJS.ts +++ b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccessJS.ts @@ -21,7 +21,7 @@ verify.codeFix({ index: 0, newFileContent: `/** - * @param {{ b: { c: void; }; }} a + * @param {{ b: { c: any; }; }} a * @param {{ n: () => number; }} m * @param {{ y: { z: number[]; }; }} x */ diff --git a/tests/cases/fourslash/codeFixInferFromUsageVariableLiteral.ts b/tests/cases/fourslash/codeFixInferFromUsageVariableLiteral.ts new file mode 100644 index 00000000000..2641b009636 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageVariableLiteral.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +//// let [|text! |]; +//// text.length; +//// text.indexOf("z"); +//// text.charAt(0); + +verify.rangeAfterCodeFix("text!: string", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, /*index*/0); From 032aa90289e52d6e49ba4abdb098b3bf6d55fa67 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 22 Apr 2020 15:45:15 -0700 Subject: [PATCH 16/38] Filter undefined from binding elements with initialisers without undefined in the type (#38122) * Filter undefined from binding elts w/o undefined-containing inits * use getTypeOfInitializer instead * improve comment based on Wesleys suggestion --- src/compiler/checker.ts | 4 ++-- ...ualTypeForInitalizedVariablesFiltersUndefined.errors.txt | 6 +++++- .../contextualTypeForInitalizedVariablesFiltersUndefined.js | 4 ++++ ...extualTypeForInitalizedVariablesFiltersUndefined.symbols | 5 +++++ ...ntextualTypeForInitalizedVariablesFiltersUndefined.types | 5 +++++ .../contextualTypeForInitalizedVariablesFiltersUndefined.ts | 1 + 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9014e2f43f9..ac46ee7e163 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7305,8 +7305,8 @@ namespace ts { if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { parentType = getNonNullableType(parentType); } - // Filter `undefined` from the type we check against if the parent has an initializer (which handles the `undefined` case implicitly) - else if (strictNullChecks && pattern.parent.initializer && isParameter(pattern.parent)) { + // Filter `undefined` from the type we check against if the parent has an initializer and that initializer is not possibly `undefined` + else if (strictNullChecks && pattern.parent.initializer && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer)) & TypeFacts.EQUndefined)) { parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined); } diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt index 32ff831d2bd..abab02a197c 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.errors.txt @@ -1,7 +1,8 @@ tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts(7,9): error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. +tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts(8,16): error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. -==== tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts (1 errors) ==== +==== tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts (2 errors) ==== const fInferred = ({ a = 0 } = {}) => a; // const fInferred: ({ a }?: { a?: number; }) => number @@ -11,4 +12,7 @@ tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts(7,9 const { s } = t; ~ !!! error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. + function fst({ s } = t) { } + ~ +!!! error TS2339: Property 's' does not exist on type '{ s: string; } | undefined'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js index 8311b6ff481..3003e420e5f 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.js @@ -6,6 +6,7 @@ const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; declare var t: { s: string } | undefined; const { s } = t; +function fst({ s } = t) { } //// [contextualTypeForInitalizedVariablesFiltersUndefined.js] @@ -20,3 +21,6 @@ var fAnnotated = function (_a) { return a; }; var s = t.s; +function fst(_a) { + var s = (_a === void 0 ? t : _a).s; +} diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols index 81ae53f9418..749fd47dd14 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.symbols @@ -20,3 +20,8 @@ const { s } = t; >s : Symbol(s, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 6, 7)) >t : Symbol(t, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 5, 11)) +function fst({ s } = t) { } +>fst : Symbol(fst, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 6, 16)) +>s : Symbol(s, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 7, 14)) +>t : Symbol(t, Decl(contextualTypeForInitalizedVariablesFiltersUndefined.ts, 5, 11)) + diff --git a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types index 58580fdacce..f2c72b1708d 100644 --- a/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types +++ b/tests/baselines/reference/contextualTypeForInitalizedVariablesFiltersUndefined.types @@ -26,3 +26,8 @@ const { s } = t; >s : any >t : { s: string; } | undefined +function fst({ s } = t) { } +>fst : ({ s }?: { s: string; } | undefined) => void +>s : any +>t : { s: string; } | undefined + diff --git a/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts b/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts index cfa8d8d6824..d6d23ba85b0 100644 --- a/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts +++ b/tests/cases/compiler/contextualTypeForInitalizedVariablesFiltersUndefined.ts @@ -6,3 +6,4 @@ const fAnnotated: typeof fInferred = ({ a = 0 } = {}) => a; declare var t: { s: string } | undefined; const { s } = t; +function fst({ s } = t) { } From ab0428c82e9ac16b825aa95d143ab02367c76b2e Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 22 Apr 2020 16:58:14 -0700 Subject: [PATCH 17/38] Update user baselines (#38109) Co-authored-by: typescript-bot --- tests/baselines/reference/docker/vue-next.log | 18 +++++++++--------- tests/baselines/reference/user/npm.log | 7 +++++++ tests/baselines/reference/user/puppeteer.log | 4 ---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/baselines/reference/docker/vue-next.log b/tests/baselines/reference/docker/vue-next.log index b9bf1004dfd..e8186149779 100644 --- a/tests/baselines/reference/docker/vue-next.log +++ b/tests/baselines/reference/docker/vue-next.log @@ -75,27 +75,27 @@ created packages/reactivity/dist/reactivity.cjs.prod.js in ?s /vue-next/packages/reactivity/src/index.ts → packages/reactivity/dist/reactivity.global.prod.js... created packages/reactivity/dist/reactivity.global.prod.js in ?s /vue-next/packages/runtime-core/src/index.ts → packages/runtime-core/dist/runtime-core.esm-bundler.js... -[!] (plugin rpt2) Error: /vue-next/packages/runtime-core/src/componentOptions.ts(181,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. +[!] (plugin rpt2) Error: /vue-next/packages/runtime-core/src/componentOptions.ts(182,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'. packages/runtime-core/src/componentOptions.ts -Error: /vue-next/packages/runtime-core/src/componentOptions.ts(181,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. +Error: /vue-next/packages/runtime-core/src/componentOptions.ts(182,18): semantic error TS2344: Type 'Function & T[key]["get"]' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'. - at error (/vue-next/node_modules/rollup/dist/shared/rollup.js:10399:30) - at throwPluginError (/vue-next/node_modules/rollup/dist/shared/rollup.js:16617:12) - at Object.error (/vue-next/node_modules/rollup/dist/shared/rollup.js:17634:24) - at Object.error (/vue-next/node_modules/rollup/dist/shared/rollup.js:16790:38) + at error (/vue-next/node_modules/rollup/dist/shared/rollup.js:160:30) + at throwPluginError (/vue-next/node_modules/rollup/dist/shared/rollup.js:16838:12) + at Object.error (/vue-next/node_modules/rollup/dist/shared/rollup.js:17857:24) + at Object.error (/vue-next/node_modules/rollup/dist/shared/rollup.js:17011:38) at RollupContext.error (/vue-next/node_modules/rollup-plugin-typescript2/src/rollupcontext.ts:37:18) at /vue-next/node_modules/rollup-plugin-typescript2/src/print-diagnostics.ts:41:11 at arrayEach (/vue-next/node_modules/rollup-plugin-typescript2/node_modules/lodash/lodash.js:516:11) at forEach (/vue-next/node_modules/rollup-plugin-typescript2/node_modules/lodash/lodash.js:9342:14) at _.each (/vue-next/node_modules/rollup-plugin-typescript2/src/print-diagnostics.ts:9:2) at Object.transform (/vue-next/node_modules/rollup-plugin-typescript2/src/index.ts:242:5) -(node:17) UnhandledPromiseRejectionWarning: Error: Command failed with exit code 1 (EPERM): rollup -c --environment COMMIT:6fefeaf,NODE_ENV:production,TARGET:runtime-core,TYPES:true +(node:18) UnhandledPromiseRejectionWarning: Error: Command failed with exit code 1 (EPERM): rollup -c --environment COMMIT:2acf3e8,NODE_ENV:production,TARGET:runtime-core,TYPES:true at makeError (/vue-next/node_modules/execa/lib/error.js:59:11) at handlePromise (/vue-next/node_modules/execa/index.js:112:26) at processTicksAndRejections (internal/process/task_queues.js:97:5) at async build (/vue-next/scripts/build.js:71:3) at async buildAll (/vue-next/scripts/build.js:50:5) at async run (/vue-next/scripts/build.js:40:5) -(node:17) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) -(node:17) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. +(node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) +(node:18) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. diff --git a/tests/baselines/reference/user/npm.log b/tests/baselines/reference/user/npm.log index 0bc07705d00..4da97268ad2 100644 --- a/tests/baselines/reference/user/npm.log +++ b/tests/baselines/reference/user/npm.log @@ -208,6 +208,11 @@ node_modules/npm/lib/config/lifecycle.js(23,24): error TS2339: Property 'config' node_modules/npm/lib/config/lifecycle.js(24,35): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. node_modules/npm/lib/config/lifecycle.js(25,23): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. node_modules/npm/lib/config/lifecycle.js(26,17): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. +node_modules/npm/lib/config/nerf-dart.js(16,10): error TS2790: The operand of a 'delete' operator must be optional. +node_modules/npm/lib/config/nerf-dart.js(17,10): error TS2790: The operand of a 'delete' operator must be optional. +node_modules/npm/lib/config/nerf-dart.js(18,10): error TS2790: The operand of a 'delete' operator must be optional. +node_modules/npm/lib/config/nerf-dart.js(19,10): error TS2790: The operand of a 'delete' operator must be optional. +node_modules/npm/lib/config/nerf-dart.js(20,10): error TS2790: The operand of a 'delete' operator must be optional. node_modules/npm/lib/config/pacote.js(23,26): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. node_modules/npm/lib/config/pacote.js(24,13): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. node_modules/npm/lib/config/pacote.js(25,15): error TS2339: Property 'config' does not exist on type 'typeof EventEmitter'. @@ -1227,6 +1232,8 @@ node_modules/npm/test/tap/correct-mkdir.js(114,16): error TS2532: Object is poss node_modules/npm/test/tap/correct-mkdir.js(115,16): error TS2532: Object is possibly 'undefined'. node_modules/npm/test/tap/correct-mkdir.js(131,3): error TS2322: Type '999' is not assignable to type 'string | undefined'. node_modules/npm/test/tap/correct-mkdir.js(132,3): error TS2322: Type '999' is not assignable to type 'string | undefined'. +node_modules/npm/test/tap/correct-mkdir.js(133,10): error TS2790: The operand of a 'delete' operator must be optional. +node_modules/npm/test/tap/correct-mkdir.js(134,10): error TS2790: The operand of a 'delete' operator must be optional. node_modules/npm/test/tap/cruft-test.js(6,20): error TS2307: Cannot find module 'tap' or its corresponding type declarations. node_modules/npm/test/tap/debug-logs.js(3,20): error TS2307: Cannot find module 'tap' or its corresponding type declarations. node_modules/npm/test/tap/debug-logs.js(4,21): error TS2307: Cannot find module 'tacks' or its corresponding type declarations. diff --git a/tests/baselines/reference/user/puppeteer.log b/tests/baselines/reference/user/puppeteer.log index 6135c34f414..bc838695979 100644 --- a/tests/baselines/reference/user/puppeteer.log +++ b/tests/baselines/reference/user/puppeteer.log @@ -1,9 +1,5 @@ Exit Code: 1 Standard output: -src/JSHandle.ts(440,5): error TS2322: Type 'unknown' is not assignable to type 'T'. - 'unknown' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'unknown'. -src/JSHandle.ts(454,5): error TS2322: Type 'unknown' is not assignable to type 'T'. - 'T' could be instantiated with an arbitrary type which could be unrelated to 'unknown'. src/Launcher.js(181,17): error TS1003: Identifier expected. src/Launcher.js(359,17): error TS1003: Identifier expected. From ef5f0ef58df8d7de2e88263b604c2ff6adee8a51 Mon Sep 17 00:00:00 2001 From: csigs Date: Thu, 23 Apr 2020 04:10:34 +0000 Subject: [PATCH 18/38] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index ea21fdee665..88cd2ac3e74 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1180,7 +1180,7 @@ - + @@ -3193,7 +3193,7 @@ - + @@ -7831,7 +7831,7 @@ - + @@ -10321,7 +10321,7 @@ - + @@ -11116,7 +11116,7 @@ - + @@ -11677,7 +11677,7 @@ - + From 9569e8aaa4997447a8675d89a50e53656e29e4a5 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 23 Apr 2020 11:59:38 -0700 Subject: [PATCH 19/38] Fix newline issues when adding multiple imports (#38119) * Add new import declarations in a single TextChanges call * Refactor --- src/compiler/core.ts | 22 ++++++++++++ src/services/codefixes/importFixes.ts | 36 +++++++++++-------- src/services/refactors/moveToNewFile.ts | 2 +- src/services/textChanges.ts | 18 ++++++++-- src/services/utilities.ts | 17 ++++++--- .../cases/fourslash/importNameCodeFix_all2.ts | 23 ++++++++++++ .../importNameCodeFix_exportEquals.ts | 1 - 7 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_all2.ts diff --git a/src/compiler/core.ts b/src/compiler/core.ts index a309eb97c1b..2841b80aedf 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -844,6 +844,28 @@ namespace ts { return to; } + /** + * Combines two arrays, values, or undefineds into the smallest container that can accommodate the resulting set: + * + * ``` + * undefined -> undefined -> undefined + * T -> undefined -> T + * T -> T -> T[] + * T[] -> undefined -> T[] (no-op) + * T[] -> T -> T[] (append) + * T[] -> T[] -> T[] (concatenate) + * ``` + */ + export function combine(xs: T | readonly T[] | undefined, ys: T | readonly T[] | undefined): T | readonly T[] | undefined; + export function combine(xs: T | T[] | undefined, ys: T | T[] | undefined): T | T[] | undefined; + export function combine(xs: T | T[] | undefined, ys: T | T[] | undefined) { + if (xs === undefined) return ys; + if (ys === undefined) return xs; + if (isArray(xs)) return isArray(ys) ? concatenate(xs, ys) : append(xs, ys); + if (isArray(ys)) return append(ys, xs); + return [xs, ys]; + } + /** * Gets the actual offset into an array for a relative offset. Negative offsets indicate a * position offset from the end of the array. diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 57fd8c1dc6a..060d409eaa9 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -45,7 +45,6 @@ namespace ts.codefix { // Keys are import clause node IDs. const addToExisting = createMap<{ readonly importClauseOrBindingPattern: ImportClause | ObjectBindingPattern, defaultImport: string | undefined; readonly namedImports: string[], canUseTypeOnlyImport: boolean }>(); const newImports = createMap>(); - let lastModuleSpecifier: string | undefined; return { addImportFromDiagnostic, addImportFromExportedSymbol, writeFixes }; function addImportFromDiagnostic(diagnostic: DiagnosticWithLocation, context: CodeFixContextBase) { @@ -97,7 +96,6 @@ namespace ts.codefix { let entry = newImports.get(moduleSpecifier); if (!entry) { newImports.set(moduleSpecifier, entry = { namedImports: [], namespaceLikeImport: undefined, typeOnly, useRequire }); - lastModuleSpecifier = moduleSpecifier; } else { // An import clause can only be type-only if every import fix contributing to it can be type-only. @@ -135,10 +133,15 @@ namespace ts.codefix { addToExisting.forEach(({ importClauseOrBindingPattern, defaultImport, namedImports, canUseTypeOnlyImport }) => { doAddExistingFix(changeTracker, sourceFile, importClauseOrBindingPattern, defaultImport, namedImports, canUseTypeOnlyImport); }); + + let newDeclarations: Statement | readonly Statement[] | undefined; newImports.forEach(({ useRequire, ...imports }, moduleSpecifier) => { - const addDeclarations = useRequire ? addNewRequires : addNewImports; - addDeclarations(changeTracker, sourceFile, moduleSpecifier, quotePreference, imports, /*blankLineBetween*/ lastModuleSpecifier === moduleSpecifier); + const getDeclarations = useRequire ? getNewRequires : getNewImports; + newDeclarations = combine(newDeclarations, getDeclarations(moduleSpecifier, quotePreference, imports)); }); + if (newDeclarations) { + insertImports(changeTracker, sourceFile, newDeclarations, /*blankLineBetween*/ true); + } } } @@ -631,11 +634,11 @@ namespace ts.codefix { } case ImportFixKind.AddNew: { const { importKind, moduleSpecifier, typeOnly, useRequire } = fix; - const addDeclarations = useRequire ? addNewRequires : addNewImports; + const getDeclarations = useRequire ? getNewRequires : getNewImports; const importsCollection = importKind === ImportKind.Default ? { defaultImport: symbolName, typeOnly } : importKind === ImportKind.Named ? { namedImports: [symbolName], typeOnly } : { namespaceLikeImport: { importKind, name: symbolName }, typeOnly }; - addDeclarations(changes, sourceFile, moduleSpecifier, quotePreference, importsCollection, /*blankLineBetween*/ true); + insertImports(changes, sourceFile, getDeclarations(moduleSpecifier, quotePreference, importsCollection), /*blankLineBetween*/ true); return [importKind === ImportKind.Default ? Diagnostics.Import_default_0_from_module_1 : Diagnostics.Import_0_from_module_1, symbolName, moduleSpecifier]; } default: @@ -717,13 +720,13 @@ namespace ts.codefix { readonly name: string; }; } - function addNewImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, moduleSpecifier: string, quotePreference: QuotePreference, imports: ImportsCollection, blankLineBetween: boolean): void { + function getNewImports(moduleSpecifier: string, quotePreference: QuotePreference, imports: ImportsCollection): Statement | readonly Statement[] { const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference); + let statements: Statement | readonly Statement[] | undefined; if (imports.defaultImport !== undefined || imports.namedImports?.length) { - insertImport(changes, sourceFile, - makeImport( - imports.defaultImport === undefined ? undefined : createIdentifier(imports.defaultImport), - imports.namedImports?.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference, imports.typeOnly), /*blankLineBetween*/ blankLineBetween); + statements = combine(statements, makeImport( + imports.defaultImport === undefined ? undefined : createIdentifier(imports.defaultImport), + imports.namedImports?.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference, imports.typeOnly)); } const { namespaceLikeImport, typeOnly } = imports; if (namespaceLikeImport) { @@ -741,12 +744,14 @@ namespace ts.codefix { createNamespaceImport(createIdentifier(namespaceLikeImport.name)), typeOnly), quotedModuleSpecifier); - insertImport(changes, sourceFile, declaration, /*blankLineBetween*/ blankLineBetween); + statements = combine(statements, declaration); } + return Debug.checkDefined(statements); } - function addNewRequires(changes: textChanges.ChangeTracker, sourceFile: SourceFile, moduleSpecifier: string, quotePreference: QuotePreference, imports: ImportsCollection, blankLineBetween: boolean) { + function getNewRequires(moduleSpecifier: string, quotePreference: QuotePreference, imports: ImportsCollection): Statement | readonly Statement[] { const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference); + let statements: Statement | readonly Statement[] | undefined; // const { default: foo, bar, etc } = require('./mod'); if (imports.defaultImport || imports.namedImports?.length) { const bindingElements = imports.namedImports?.map(name => createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name)) || []; @@ -754,13 +759,14 @@ namespace ts.codefix { bindingElements.unshift(createBindingElement(/*dotDotDotToken*/ undefined, "default", imports.defaultImport)); } const declaration = createConstEqualsRequireDeclaration(createObjectBindingPattern(bindingElements), quotedModuleSpecifier); - insertImport(changes, sourceFile, declaration, blankLineBetween); + statements = combine(statements, declaration); } // const foo = require('./mod'); if (imports.namespaceLikeImport) { const declaration = createConstEqualsRequireDeclaration(imports.namespaceLikeImport.name, quotedModuleSpecifier); - insertImport(changes, sourceFile, declaration, blankLineBetween); + statements = combine(statements, declaration); } + return Debug.checkDefined(statements); } function createConstEqualsRequireDeclaration(name: string | ObjectBindingPattern, quotedModuleSpecifier: StringLiteral): VariableStatement { diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index a9b8171cbc9..6a9e8df6bd7 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -121,7 +121,7 @@ namespace ts.refactor { const quotePreference = getQuotePreference(oldFile, preferences); const importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEs6ModuleSyntax, quotePreference); if (importsFromNewFile) { - insertImport(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true); + insertImports(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true); } deleteUnusedOldImports(oldFile, toMove.all, changes, usage.unusedImportsFromOldFile, checker); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 2b743f4d592..e5b34b8d508 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -349,11 +349,25 @@ namespace ts.textChanges { } public insertNodeAtTopOfFile(sourceFile: SourceFile, newNode: Statement, blankLineBetween: boolean): void { + this.insertAtTopOfFile(sourceFile, newNode, blankLineBetween); + } + + public insertNodesAtTopOfFile(sourceFile: SourceFile, newNodes: readonly Statement[], blankLineBetween: boolean): void { + this.insertAtTopOfFile(sourceFile, newNodes, blankLineBetween); + } + + private insertAtTopOfFile(sourceFile: SourceFile, insert: Statement | readonly Statement[], blankLineBetween: boolean): void { const pos = getInsertionPositionAtSourceFileTop(sourceFile); - this.insertNodeAt(sourceFile, pos, newNode, { + const options = { prefix: pos === 0 ? undefined : this.newLineCharacter, suffix: (isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""), - }); + }; + if (isArray(insert)) { + this.insertNodesAt(sourceFile, pos, insert, options); + } + else { + this.insertNodeAt(sourceFile, pos, insert, options); + } } public insertFirstParameter(sourceFile: SourceFile, parameters: NodeArray, newParam: ParameterDeclaration): void { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a621b10e838..4eb45265800 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1871,14 +1871,23 @@ namespace ts { return node.modifiers && find(node.modifiers, m => m.kind === kind); } - export function insertImport(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importDecl: Statement, blankLineBetween: boolean): void { - const importKindPredicate = importDecl.kind === SyntaxKind.VariableStatement ? isRequireVariableDeclarationStatement : isAnyImportSyntax; + export function insertImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, imports: Statement | readonly Statement[], blankLineBetween: boolean): void { + const decl = isArray(imports) ? imports[0] : imports; + const importKindPredicate = decl.kind === SyntaxKind.VariableStatement ? isRequireVariableDeclarationStatement : isAnyImportSyntax; const lastImportDeclaration = findLast(sourceFile.statements, statement => importKindPredicate(statement)); if (lastImportDeclaration) { - changes.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl); + if (isArray(imports)) { + changes.insertNodesAfter(sourceFile, lastImportDeclaration, imports); + } + else { + changes.insertNodeAfter(sourceFile, lastImportDeclaration, imports); + } + } + else if (isArray(imports)) { + changes.insertNodesAtTopOfFile(sourceFile, imports, blankLineBetween); } else { - changes.insertNodeAtTopOfFile(sourceFile, importDecl, blankLineBetween); + changes.insertNodeAtTopOfFile(sourceFile, imports, blankLineBetween); } } diff --git a/tests/cases/fourslash/importNameCodeFix_all2.ts b/tests/cases/fourslash/importNameCodeFix_all2.ts new file mode 100644 index 00000000000..6f7a9b3403c --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_all2.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /path.ts +////export declare function join(): void; + +// @Filename: /os.ts +////export declare function homedir(): void; + +// @Filename: /index.ts +//// +////join(); +////homedir(); + +goTo.file("/index.ts"); +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: `import { join } from "./path"; +import { homedir } from "./os"; + +join(); +homedir();` +}); diff --git a/tests/cases/fourslash/importNameCodeFix_exportEquals.ts b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts index 4ab87df7e76..e413c4d4e1d 100644 --- a/tests/cases/fourslash/importNameCodeFix_exportEquals.ts +++ b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts @@ -17,7 +17,6 @@ verify.codeFixAll({ fixAllDescription: "Add all missing imports", newFileContent: `import { b } from "./a"; - import a = require("./a"); a; From d7e437a409847ec4467cbc153fe9deb70722b33b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 23 Apr 2020 12:54:49 -0700 Subject: [PATCH 20/38] Have the `ChangeTracker` filter out edits that are no-ops (#38123) * Filter out edits that are no-ops in 'organize imports'. * Updated tests for 'organize imports'. * Always remove no-op changes from the change tracker. * Add a new `stringContainsAt` helper function to avoid traversing the entire file contents. * Combine `map`/`filter` sequence into `mapDefined`. * Fix up documentation. --- src/services/textChanges.ts | 19 +++++-- src/services/utilities.ts | 29 ++++++++++ .../unittests/services/organizeImports.ts | 54 +++++++++++++++---- 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index e5b34b8d508..245306ac109 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -887,7 +887,7 @@ namespace ts.textChanges { namespace changesToText { export function getTextChangesFromChanges(changes: readonly Change[], newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] { - return group(changes, c => c.sourceFile.path).map(changesInFile => { + return mapDefined(group(changes, c => c.sourceFile.path), changesInFile => { const sourceFile = changesInFile[0].sourceFile; // order changes by start position // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa. @@ -897,9 +897,20 @@ namespace ts.textChanges { Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`); } - const textChanges = normalized.map(c => - createTextChange(createTextSpanFromRange(c.range), computeNewText(c, sourceFile, newLineCharacter, formatContext, validate))); - return { fileName: sourceFile.fileName, textChanges }; + + const textChanges = mapDefined(normalized, c => { + const span = createTextSpanFromRange(c.range); + const newText = computeNewText(c, sourceFile, newLineCharacter, formatContext, validate); + + // Filter out redundant changes. + if (span.length === newText.length && stringContainsAt(sourceFile.text, newText, span.start)) { + return undefined; + } + + return createTextChange(span, newText); + }); + + return textChanges.length > 0 ? { fileName: sourceFile.fileName, textChanges } : undefined; }); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4eb45265800..58f53198f79 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2827,6 +2827,35 @@ namespace ts { return symbol.name; } + /** + * Useful to check whether a string contains another string at a specific index + * without allocating another string or traversing the entire contents of the outer string. + * + * This function is useful in place of either of the following: + * + * ```ts + * // Allocates + * haystack.substr(startIndex, needle.length) === needle + * + * // Full traversal + * haystack.indexOf(needle, startIndex) === startIndex + * ``` + * + * @param haystack The string that potentially contains `needle`. + * @param needle The string whose content might sit within `haystack`. + * @param startIndex The index within `haystack` to start searching for `needle`. + */ + export function stringContainsAt(haystack: string, needle: string, startIndex: number) { + const needleLength = needle.length; + if (needleLength + startIndex > haystack.length) { + return false; + } + for (let i = 0; i < needleLength; i++) { + if (needle.charCodeAt(i) !== haystack.charCodeAt(i + startIndex)) return false; + } + return true; + } + export function startsWithUnderscore(name: string): boolean { return name.charCodeAt(0) === CharacterCodes._; } diff --git a/src/testRunner/unittests/services/organizeImports.ts b/src/testRunner/unittests/services/organizeImports.ts index 6627616a67d..627928c03e8 100644 --- a/src/testRunner/unittests/services/organizeImports.ts +++ b/src/testRunner/unittests/services/organizeImports.ts @@ -285,6 +285,7 @@ namespace ts { }); }); + describe("Baselines", () => { const libFile = { @@ -327,6 +328,16 @@ export const Other = 1; assert.isEmpty(changes); }); + it("doesn't return any changes when the text would be identical", () => { + const testFile = { + path: "/a.ts", + content: `import { f } from 'foo';\nf();` + }; + const languageService = makeLanguageService(testFile); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); + assert.isEmpty(changes); + }); + testOrganizeImports("Renamed_used", { path: "/test.ts", @@ -366,6 +377,16 @@ D(); }, libFile); + it("doesn't return any changes when the text would be identical", () => { + const testFile = { + path: "/a.ts", + content: `import { f } from 'foo';\nf();` + }; + const languageService = makeLanguageService(testFile); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); + assert.isEmpty(changes); + }); + testOrganizeImports("Unused_All", { path: "/test.ts", @@ -377,14 +398,17 @@ import D from "lib"; }, libFile); - testOrganizeImports("Unused_Empty", - { + it("Unused_Empty", () => { + const testFile = { path: "/test.ts", content: ` import { } from "lib"; `, - }, - libFile); + }; + const languageService = makeLanguageService(testFile); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); + assert.isEmpty(changes); + }); testOrganizeImports("Unused_false_positive_module_augmentation", { @@ -414,25 +438,33 @@ declare module 'caseless' { test(name: KeyType): boolean; } }` - }); + }); - testOrganizeImports("Unused_false_positive_shorthand_assignment", - { + it("Unused_false_positive_shorthand_assignment", () => { + const testFile = { path: "/test.ts", content: ` import { x } from "a"; const o = { x }; ` - }); + }; + const languageService = makeLanguageService(testFile); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); + assert.isEmpty(changes); + }); - testOrganizeImports("Unused_false_positive_export_shorthand", - { + it("Unused_false_positive_export_shorthand", () => { + const testFile = { path: "/test.ts", content: ` import { x } from "a"; export { x }; ` - }); + }; + const languageService = makeLanguageService(testFile); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); + assert.isEmpty(changes); + }); testOrganizeImports("MoveToTop", { From 815dc90dc508b24a37b4b0c3fa7ece04f3596f84 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 23 Apr 2020 19:01:16 -0700 Subject: [PATCH 21/38] Issue an error on cross-file merges we cant emit (#38148) --- src/compiler/checker.ts | 7 +++- src/compiler/diagnosticMessages.json | 8 +++++ src/compiler/transformers/declarations.ts | 14 +++++++- src/compiler/types.ts | 1 + .../jsDeclarationsCrossfileMerge.errors.txt | 17 ++++++++++ .../reference/jsDeclarationsCrossfileMerge.js | 28 ++++++++++++++++ .../jsDeclarationsCrossfileMerge.symbols | 28 ++++++++++++++++ .../jsDeclarationsCrossfileMerge.types | 32 +++++++++++++++++++ .../jsDeclarationsCrossfileMerge.ts | 16 ++++++++++ 9 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationsCrossfileMerge.errors.txt create mode 100644 tests/baselines/reference/jsDeclarationsCrossfileMerge.js create mode 100644 tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols create mode 100644 tests/baselines/reference/jsDeclarationsCrossfileMerge.types create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac46ee7e163..6320ff7d128 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6029,14 +6029,19 @@ namespace ts { serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment))); } if (length(mergedMembers)) { + const containingFile = getSourceFileOfNode(context.enclosingDeclaration); const localName = getInternalSymbolName(symbol, symbolName); const nsBody = createModuleBlock([createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports(map(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { + createNamedExports(mapDefined(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { const name = unescapeLeadingUnderscores(s.escapedName); const localName = getInternalSymbolName(s, name); const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s); + if (containingFile && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile))) { + context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s); + return undefined; + } const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); includePrivateSymbol(target || s); const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4a7c6e8b461..17b3dd829bd 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4388,6 +4388,14 @@ "category": "Error", "code": 6231 }, + "Declaration augments declaration in another file. This cannot be serialized.": { + "category": "Error", + "code": 6232 + }, + "This is the declaration being augmented. Consider moving the augmenting declaration into the same file.": { + "category": "Error", + "code": 6233 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 70f70a98c3e..413ff8f8cd2 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -76,7 +76,8 @@ namespace ts { reportLikelyUnsafeImportRequiredError, moduleResolverHost: host, trackReferencedAmbientModule, - trackExternalModuleSymbolOfImportTypeNode + trackExternalModuleSymbolOfImportTypeNode, + reportNonlocalAugmentation }; let errorNameNode: DeclarationName | undefined; @@ -190,6 +191,17 @@ namespace ts { } } + function reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, symbol: Symbol) { + const primaryDeclaration = find(parentSymbol.declarations, d => getSourceFileOfNode(d) === containingFile)!; + const augmentingDeclarations = filter(symbol.declarations, d => getSourceFileOfNode(d) !== containingFile); + for (const augmentations of augmentingDeclarations) { + context.addDiagnostic(addRelatedInfo( + createDiagnosticForNode(augmentations, Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized), + createDiagnosticForNode(primaryDeclaration, Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file) + )); + } + } + function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) { const oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = (s) => ({ diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8e781b23ee7..70bc9b01528 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6468,6 +6468,7 @@ namespace ts { moduleResolverHost?: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string }; trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void; trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void; + reportNonlocalAugmentation?(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void; } export interface TextSpan { diff --git a/tests/baselines/reference/jsDeclarationsCrossfileMerge.errors.txt b/tests/baselines/reference/jsDeclarationsCrossfileMerge.errors.txt new file mode 100644 index 00000000000..cd0bc2e0a3d --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsCrossfileMerge.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/jsdoc/declarations/index.js(4,1): error TS6232: Declaration augments declaration in another file. This cannot be serialized. + + +==== tests/cases/conformance/jsdoc/declarations/index.js (1 errors) ==== + const m = require("./exporter"); + + module.exports = m.default; + module.exports.memberName = "thing"; + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS6232: Declaration augments declaration in another file. This cannot be serialized. +!!! related TS6233 /.src/tests/cases/conformance/jsdoc/declarations/exporter.js:1:10: This is the declaration being augmented. Consider moving the augmenting declaration into the same file. + +==== tests/cases/conformance/jsdoc/declarations/exporter.js (0 errors) ==== + function validate() {} + + export default validate; + \ No newline at end of file diff --git a/tests/baselines/reference/jsDeclarationsCrossfileMerge.js b/tests/baselines/reference/jsDeclarationsCrossfileMerge.js new file mode 100644 index 00000000000..9e99ba43fc5 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsCrossfileMerge.js @@ -0,0 +1,28 @@ +//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts] //// + +//// [index.js] +const m = require("./exporter"); + +module.exports = m.default; +module.exports.memberName = "thing"; + +//// [exporter.js] +function validate() {} + +export default validate; + + +//// [exporter.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function validate() { } +exports.default = validate; +//// [index.js] +var m = require("./exporter"); +module.exports = m.default; +module.exports.memberName = "thing"; + + +//// [index.d.ts] +declare const _exports: typeof import("./exporter").default; +export = _exports; diff --git a/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols b/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols new file mode 100644 index 00000000000..99455853c4c --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols @@ -0,0 +1,28 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +const m = require("./exporter"); +>m : Symbol(m, Decl(index.js, 0, 5)) +>require : Symbol(require) +>"./exporter" : Symbol("tests/cases/conformance/jsdoc/declarations/exporter", Decl(exporter.js, 0, 0)) + +module.exports = m.default; +>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0)) +>module : Symbol(export=, Decl(index.js, 0, 32)) +>exports : Symbol(export=, Decl(index.js, 0, 32)) +>m.default : Symbol(default, Decl(exporter.js, 0, 22)) +>m : Symbol(m, Decl(index.js, 0, 5)) +>default : Symbol(default, Decl(exporter.js, 0, 22)) + +module.exports.memberName = "thing"; +>module.exports.memberName : Symbol(memberName) +>module.exports : Symbol(memberName, Decl(index.js, 2, 27)) +>module : Symbol(module, Decl(index.js, 0, 32)) +>exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0)) +>memberName : Symbol(memberName, Decl(index.js, 2, 27)) + +=== tests/cases/conformance/jsdoc/declarations/exporter.js === +function validate() {} +>validate : Symbol(validate, Decl(exporter.js, 0, 0)) + +export default validate; +>validate : Symbol(validate, Decl(exporter.js, 0, 0)) + diff --git a/tests/baselines/reference/jsDeclarationsCrossfileMerge.types b/tests/baselines/reference/jsDeclarationsCrossfileMerge.types new file mode 100644 index 00000000000..8de95cf8567 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsCrossfileMerge.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +const m = require("./exporter"); +>m : typeof import("tests/cases/conformance/jsdoc/declarations/exporter") +>require("./exporter") : typeof import("tests/cases/conformance/jsdoc/declarations/exporter") +>require : any +>"./exporter" : "./exporter" + +module.exports = m.default; +>module.exports = m.default : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default +>module.exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default +>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default; } +>exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default +>m.default : { (): void; memberName: string; } +>m : typeof import("tests/cases/conformance/jsdoc/declarations/exporter") +>default : { (): void; memberName: string; } + +module.exports.memberName = "thing"; +>module.exports.memberName = "thing" : "thing" +>module.exports.memberName : string +>module.exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default +>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default; } +>exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default +>memberName : string +>"thing" : "thing" + +=== tests/cases/conformance/jsdoc/declarations/exporter.js === +function validate() {} +>validate : typeof validate + +export default validate; +>validate : typeof validate + diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts new file mode 100644 index 00000000000..7f1624e6d87 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts @@ -0,0 +1,16 @@ +// @allowJs: true +// @checkJs: true +// @target: es5 +// @lib: es6 +// @outDir: ./out +// @declaration: true +// @filename: index.js +const m = require("./exporter"); + +module.exports = m.default; +module.exports.memberName = "thing"; + +// @filename: exporter.js +function validate() {} + +export default validate; From a7d6825e25b44414adefdac0156b5c9d92a0d18b Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 23 Apr 2020 20:45:39 -0700 Subject: [PATCH 22/38] Fix temp vars referenced in parameter (#38130) * Fix temp vars referenced in parameter * Update error message --- src/compiler/checker.ts | 91 ++++- src/compiler/diagnosticMessages.json | 4 +- src/compiler/factory.ts | 13 +- src/compiler/transformer.ts | 57 ++- src/compiler/transformers/classFields.ts | 2 +- src/compiler/transformers/es2015.ts | 2 + src/compiler/transformers/es2020.ts | 380 +++++++++--------- src/compiler/types.ts | 15 + src/compiler/utilities.ts | 20 + src/compiler/visitor.ts | 97 ++++- src/compiler/visitorPublic.ts | 113 +++++- .../FunctionDeclaration3_es6.errors.txt | 4 +- .../reference/api/tsserverlibrary.d.ts | 3 +- tests/baselines/reference/api/typescript.d.ts | 3 +- .../asyncArrowFunction3_es2017.errors.txt | 4 +- .../asyncArrowFunction3_es5.errors.txt | 4 +- .../asyncArrowFunction3_es6.errors.txt | 4 +- ...syncFunctionDeclaration3_es2017.errors.txt | 4 +- .../asyncFunctionDeclaration3_es5.errors.txt | 4 +- .../asyncFunctionDeclaration3_es6.errors.txt | 4 +- ...pturedParametersInInitializers1.errors.txt | 12 +- ...pturedParametersInInitializers2.errors.txt | 16 +- .../capturedParametersInInitializers2.js | 4 +- .../circularOptionalityRemoval.errors.txt | 12 +- ...nParameterBindingPattern(target=es2015).js | 10 + ...ldInParameterBindingPattern(target=es5).js | 16 + ...nParameterBindingPattern(target=esnext).js | 10 + ...BindingPattern.2(target=es2015).errors.txt | 16 + ...terBindingPattern.2(target=es5).errors.txt | 16 + ...BindingPattern.2(target=esnext).errors.txt | 16 + ...ldInParameterInitializer(target=es2015).js | 10 + ...FieldInParameterInitializer(target=es5).js | 16 + ...ldInParameterInitializer(target=esnext).js | 10 + ...terInitializer.2(target=es2015).errors.txt | 15 + ...ameterInitializer.2(target=es5).errors.txt | 15 + ...terInitializer.2(target=esnext).errors.txt | 15 + ...rayBindingPatternAndAssignment3.errors.txt | 8 +- .../functionImplementationErrors.errors.txt | 8 +- ...nParameterBindingPattern(target=es2015).js | 9 + ...orInParameterBindingPattern(target=es5).js | 12 + ...nParameterBindingPattern(target=esnext).js | 9 + ...BindingPattern.2(target=es2015).errors.txt | 15 + ...terBindingPattern.2(target=es5).errors.txt | 15 + ...orInParameterInitializer(target=es2015).js | 9 + ...ratorInParameterInitializer(target=es5).js | 12 + ...orInParameterInitializer(target=esnext).js | 9 + ...terInitializer.2(target=es2015).errors.txt | 15 + ...ameterInitializer.2(target=es5).errors.txt | 15 + ...nParameterBindingPattern(target=es2015).js | 9 + ...ngInParameterBindingPattern(target=es5).js | 12 + ...nParameterBindingPattern(target=esnext).js | 9 + ...BindingPattern.2(target=es2015).errors.txt | 15 + ...terBindingPattern.2(target=es5).errors.txt | 15 + ...ngInParameterInitializer(target=es2015).js | 9 + ...iningInParameterInitializer(target=es5).js | 12 + ...ngInParameterInitializer(target=esnext).js | 9 + ...terInitializer.2(target=es2015).errors.txt | 15 + ...ameterInitializer.2(target=es5).errors.txt | 15 + ...nalParamReferencingOtherParams2.errors.txt | 4 +- ...nalParamReferencingOtherParams3.errors.txt | 4 +- ...ardReferencing.2(target=es2015).errors.txt | 25 ++ ...orwardReferencing.2(target=es5).errors.txt | 25 ++ ...rInitializersForwardReferencing.errors.txt | 40 +- ...InitializersForwardReferencing1.errors.txt | 21 +- ...ializersForwardReferencing1_es6.errors.txt | 12 +- ...fReferencesInFunctionParameters.errors.txt | 16 +- tests/baselines/reference/witness.errors.txt | 4 +- ...hStaticFieldInParameterBindingPattern.2.ts | 10 + ...hStaticFieldInParameterBindingPattern.3.ts | 11 + ...ithStaticFieldInParameterBindingPattern.ts | 5 + ...WithStaticFieldInParameterInitializer.2.ts | 10 + ...WithStaticFieldInParameterInitializer.3.ts | 11 + ...ssWithStaticFieldInParameterInitializer.ts | 5 + ...cingOperatorInParameterBindingPattern.2.ts | 10 + ...escingOperatorInParameterBindingPattern.ts | 6 + ...lescingOperatorInParameterInitializer.2.ts | 10 + ...oalescingOperatorInParameterInitializer.ts | 6 + ...onalChainingInParameterBindingPattern.2.ts | 10 + ...tionalChainingInParameterBindingPattern.ts | 6 + ...ptionalChainingInParameterInitializer.2.ts | 10 + .../optionalChainingInParameterInitializer.ts | 6 + ...rameterInitializersForwardReferencing.2.ts | 17 + 82 files changed, 1265 insertions(+), 312 deletions(-) create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es2015).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es5).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=esnext).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=esnext).errors.txt create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es2015).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es5).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=esnext).js create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=esnext).errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es2015).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es5).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=esnext).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es2015).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es5).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=esnext).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es2015).js create mode 100644 tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es5).js create mode 100644 tests/baselines/reference/optionalChainingInParameterBindingPattern(target=esnext).js create mode 100644 tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/optionalChainingInParameterInitializer(target=es2015).js create mode 100644 tests/baselines/reference/optionalChainingInParameterInitializer(target=es5).js create mode 100644 tests/baselines/reference/optionalChainingInParameterInitializer(target=esnext).js create mode 100644 tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es5).errors.txt create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es2015).errors.txt create mode 100644 tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es5).errors.txt create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.3.ts create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.ts create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.3.ts create mode 100644 tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.ts create mode 100644 tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts create mode 100644 tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts create mode 100644 tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts create mode 100644 tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts create mode 100644 tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6320ff7d128..52a667a1451 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1529,6 +1529,63 @@ namespace ts { } } + function useOuterVariableScopeInParameter(result: Symbol, location: Node, lastLocation: Node) { + const target = getEmitScriptTarget(compilerOptions); + const functionLocation = location; + if (isParameter(lastLocation) && functionLocation.body && result.valueDeclaration.pos >= functionLocation.body.pos && result.valueDeclaration.end <= functionLocation.body.end) { + // check for several cases where we introduce temporaries that require moving the name/initializer of the parameter to the body + // - static field in a class expression + // - optional chaining pre-es2020 + // - nullish coalesce pre-es2020 + // - spread assignment in binding pattern pre-es2017 + if (target >= ScriptTarget.ES2015) { + const links = getNodeLinks(functionLocation); + if (links.declarationRequiresScopeChange === undefined) { + links.declarationRequiresScopeChange = forEach(functionLocation.parameters, requiresScopeChange) || false; + } + return !links.declarationRequiresScopeChange; + } + } + return false; + + function requiresScopeChange(node: ParameterDeclaration): boolean { + return requiresScopeChangeWorker(node.name) + || !!node.initializer && requiresScopeChangeWorker(node.initializer); + } + + function requiresScopeChangeWorker(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: + // do not descend into these + return false; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyAssignment: + return requiresScopeChangeWorker((node as MethodDeclaration | AccessorDeclaration | PropertyAssignment).name); + case SyntaxKind.PropertyDeclaration: + // static properties in classes introduce temporary variables + if (hasStaticModifier(node)) { + return target < ScriptTarget.ESNext || !compilerOptions.useDefineForClassFields; + } + return requiresScopeChangeWorker((node as PropertyDeclaration).name); + default: + // null coalesce and optional chain pre-es2020 produce temporary variables + if (isNullishCoalesce(node) || isOptionalChain(node)) { + return target < ScriptTarget.ES2020; + } + if (isBindingElement(node) && node.dotDotDotToken && isObjectBindingPattern(node.parent)) { + return target < ScriptTarget.ES2017; + } + if (isTypeNode(node)) return false; + return forEachChild(node, requiresScopeChangeWorker) || false; + } + } + } + /** * Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and * the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with @@ -1563,7 +1620,7 @@ namespace ts { let lastLocation: Node | undefined; let lastSelfReferenceLocation: Node | undefined; let propertyWithInvalidInitializer: Node | undefined; - let associatedDeclarationForContainingInitializer: ParameterDeclaration | BindingElement | undefined; + let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined; let withinDeferredContext = false; const errorLocation = location; let grandparent: Node; @@ -1592,9 +1649,7 @@ namespace ts { } if (meaning & result.flags & SymbolFlags.Variable) { // expression inside parameter will lookup as normal variable scope when targeting es2015+ - const functionLocation = location; - if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && - functionLocation.body && result.valueDeclaration.pos >= functionLocation.body.pos && result.valueDeclaration.end <= functionLocation.body.end) { + if (useOuterVariableScopeInParameter(result, location, lastLocation)) { useResult = false; } else if (result.flags & SymbolFlags.FunctionScopedVariable) { @@ -1822,15 +1877,21 @@ namespace ts { location = getJSDocHost(location); break; case SyntaxKind.Parameter: - if (lastLocation && lastLocation === (location as ParameterDeclaration).initializer) { - associatedDeclarationForContainingInitializer = location as ParameterDeclaration; + if (lastLocation && ( + lastLocation === (location as ParameterDeclaration).initializer || + lastLocation === (location as ParameterDeclaration).name && isBindingPattern(lastLocation))) { + if (!associatedDeclarationForContainingInitializerOrBindingName) { + associatedDeclarationForContainingInitializerOrBindingName = location as ParameterDeclaration; + } } break; case SyntaxKind.BindingElement: - if (lastLocation && lastLocation === (location as BindingElement).initializer) { + if (lastLocation && ( + lastLocation === (location as BindingElement).initializer || + lastLocation === (location as BindingElement).name && isBindingPattern(lastLocation))) { const root = getRootDeclaration(location); if (root.kind === SyntaxKind.Parameter) { - associatedDeclarationForContainingInitializer = location as BindingElement; + associatedDeclarationForContainingInitializerOrBindingName = location as BindingElement; } } break; @@ -1941,17 +2002,17 @@ namespace ts { } } - // If we're in a parameter initializer, we can't reference the values of the parameter whose initializer we're within or parameters to the right - if (result && associatedDeclarationForContainingInitializer && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { + // If we're in a parameter initializer or binding name, we can't reference the values of the parameter whose initializer we're within or parameters to the right + if (result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { const candidate = getMergedSymbol(getLateBoundSymbol(result)); - const root = (getRootDeclaration(associatedDeclarationForContainingInitializer) as ParameterDeclaration); + const root = (getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ParameterDeclaration); // A parameter initializer or binding pattern initializer within a parameter cannot refer to itself - if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializer)) { - error(errorLocation, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(associatedDeclarationForContainingInitializer.name)); + if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializerOrBindingName)) { + error(errorLocation, Diagnostics.Parameter_0_cannot_reference_itself, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name)); } // And it cannot refer to any declarations which come after it - else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializer.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) { - error(errorLocation, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializer.name), declarationNameToString(errorLocation)); + else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializerOrBindingName.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) { + error(errorLocation, Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), declarationNameToString(errorLocation)); } } if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 17b3dd829bd..03f42608454 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1477,11 +1477,11 @@ "category": "Error", "code": 2371 }, - "Parameter '{0}' cannot be referenced in its initializer.": { + "Parameter '{0}' cannot reference itself.": { "category": "Error", "code": 2372 }, - "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it.": { + "Parameter '{0}' cannot reference identifier '{1}' declared after it.": { "category": "Error", "code": 2373 }, diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 2b6e19cd179..ed854342245 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -4,11 +4,14 @@ namespace ts { enableEmitNotification: noop, enableSubstitution: noop, endLexicalEnvironment: returnUndefined, - getCompilerOptions: notImplemented, + getCompilerOptions: () => ({}), getEmitHost: notImplemented, getEmitResolver: notImplemented, + setLexicalEnvironmentFlags: noop, + getLexicalEnvironmentFlags: () => 0, hoistFunctionDeclaration: noop, hoistVariableDeclaration: noop, + addInitializationStatement: noop, isEmitNotificationEnabled: notImplemented, isSubstitutionEnabled: notImplemented, onEmitNode: noop, @@ -852,13 +855,13 @@ namespace ts { * This function needs to be called whenever we transform the statement * list of a source file, namespace, or function-like body. */ - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number, visitor?: (node: Node) => VisitResult): number; - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined; - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined { + export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number, visitor?: (node: Node) => VisitResult, filter?: (node: Node) => boolean): number; + export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter?: (node: Node) => boolean): number | undefined; + export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter: (node: Node) => boolean = returnTrue): number | undefined { const numStatements = source.length; while (statementOffset !== undefined && statementOffset < numStatements) { const statement = source[statementOffset]; - if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { + if (getEmitFlags(statement) & EmitFlags.CustomPrologue && filter(statement)) { append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); } else { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index a3784a62a82..bd794d88482 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -148,8 +148,12 @@ namespace ts { const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; + let lexicalEnvironmentStatements: Statement[]; + let lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = []; let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; + let lexicalEnvironmentStatementsStack: Statement[][] = []; + let lexicalEnvironmentFlagsStack: LexicalEnvironmentFlags[] = []; let lexicalEnvironmentStackOffset = 0; let lexicalEnvironmentSuspended = false; let emitHelpers: EmitHelper[] | undefined; @@ -168,8 +172,11 @@ namespace ts { suspendLexicalEnvironment, resumeLexicalEnvironment, endLexicalEnvironment, + setLexicalEnvironmentFlags, + getLexicalEnvironmentFlags, hoistVariableDeclaration, hoistFunctionDeclaration, + addInitializationStatement, requestEmitHelper, readEmitHelpers, enableSubstitution, @@ -313,6 +320,9 @@ namespace ts { else { lexicalEnvironmentVariableDeclarations.push(decl); } + if (lexicalEnvironmentFlags & LexicalEnvironmentFlags.InParameters) { + lexicalEnvironmentFlags |= LexicalEnvironmentFlags.VariablesHoistedInParameters; + } } /** @@ -321,6 +331,7 @@ namespace ts { function hoistFunctionDeclaration(func: FunctionDeclaration): void { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + setEmitFlags(func, EmitFlags.CustomPrologue); if (!lexicalEnvironmentFunctionDeclarations) { lexicalEnvironmentFunctionDeclarations = [func]; } @@ -329,6 +340,21 @@ namespace ts { } } + /** + * Adds an initialization statement to the top of the lexical environment. + */ + function addInitializationStatement(node: Statement): void { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + setEmitFlags(node, EmitFlags.CustomPrologue); + if (!lexicalEnvironmentStatements) { + lexicalEnvironmentStatements = [node]; + } + else { + lexicalEnvironmentStatements.push(node); + } + } + /** * Starts a new lexical environment. Any existing hoisted variable or function declarations * are pushed onto a stack, and the related storage variables are reset. @@ -344,9 +370,13 @@ namespace ts { // transformation. lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; + lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentStatements; + lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFlags; lexicalEnvironmentStackOffset++; lexicalEnvironmentVariableDeclarations = undefined!; lexicalEnvironmentFunctionDeclarations = undefined!; + lexicalEnvironmentStatements = undefined!; + lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; } /** Suspends the current lexical environment, usually after visiting a parameter list. */ @@ -375,7 +405,9 @@ namespace ts { Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); let statements: Statement[] | undefined; - if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) { + if (lexicalEnvironmentVariableDeclarations || + lexicalEnvironmentFunctionDeclarations || + lexicalEnvironmentStatements) { if (lexicalEnvironmentFunctionDeclarations) { statements = [...lexicalEnvironmentFunctionDeclarations]; } @@ -395,19 +427,42 @@ namespace ts { statements.push(statement); } } + + if (lexicalEnvironmentStatements) { + if (!statements) { + statements = [...lexicalEnvironmentStatements]; + } + else { + statements = [...statements, ...lexicalEnvironmentStatements]; + } + } } // Restore the previous lexical environment. lexicalEnvironmentStackOffset--; lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; + lexicalEnvironmentStatements = lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset]; + lexicalEnvironmentFlags = lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset]; if (lexicalEnvironmentStackOffset === 0) { lexicalEnvironmentVariableDeclarationsStack = []; lexicalEnvironmentFunctionDeclarationsStack = []; + lexicalEnvironmentStatementsStack = []; + lexicalEnvironmentFlagsStack = []; } return statements; } + function setLexicalEnvironmentFlags(flags: LexicalEnvironmentFlags, value: boolean): void { + lexicalEnvironmentFlags = value ? + lexicalEnvironmentFlags | flags : + lexicalEnvironmentFlags & ~flags; + } + + function getLexicalEnvironmentFlags(): LexicalEnvironmentFlags { + return lexicalEnvironmentFlags; + } + function requestEmitHelper(helper: EmitHelper): void { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 692f353b00e..05b7cda9efc 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -606,7 +606,7 @@ namespace ts { createConstructor( /*decorators*/ undefined, /*modifiers*/ undefined, - parameters, + parameters ?? [], body ), constructor || node diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 6bffbe3b299..3e2e88d15c2 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1853,6 +1853,8 @@ namespace ts { // ensureUseStrict is false because no new prologue-directive should be added. // addStandardPrologue will put already-existing directives at the beginning of the target statement-array statementOffset = addStandardPrologue(prologue, body.statements, /*ensureUseStrict*/ false); + statementOffset = addCustomPrologue(statements, body.statements, statementOffset, visitor, isHoistedFunction); + statementOffset = addCustomPrologue(statements, body.statements, statementOffset, visitor, isHoistedVariableStatement); } multiLine = addDefaultValueAssignmentsIfNeeded(statements, node) || multiLine; diff --git a/src/compiler/transformers/es2020.ts b/src/compiler/transformers/es2020.ts index 453b3b405f4..8cf31697520 100644 --- a/src/compiler/transformers/es2020.ts +++ b/src/compiler/transformers/es2020.ts @@ -1,209 +1,213 @@ /*@internal*/ namespace ts { - export function transformES2020(context: TransformationContext) { - const { - hoistVariableDeclaration, - } = context; + export function transformES2020(context: TransformationContext) { + const { + hoistVariableDeclaration, + } = context; - return chainBundle(transformSourceFile); + return chainBundle(transformSourceFile); - function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile) { - return node; - } + function transformSourceFile(node: SourceFile) { + if (node.isDeclarationFile) { + return node; + } - return visitEachChild(node, visitor, context); - } + return visitEachChild(node, visitor, context); + } - function visitor(node: Node): VisitResult { - if ((node.transformFlags & TransformFlags.ContainsES2020) === 0) { - return node; - } - switch (node.kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.CallExpression: - if (node.flags & NodeFlags.OptionalChain) { - const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false); - Debug.assertNotNode(updated, isSyntheticReference); - return updated; - } - return visitEachChild(node, visitor, context); - case SyntaxKind.BinaryExpression: - if ((node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { - return transformNullishCoalescingExpression(node); - } - return visitEachChild(node, visitor, context); - case SyntaxKind.DeleteExpression: - return visitDeleteExpression(node as DeleteExpression); - default: - return visitEachChild(node, visitor, context); - } - } + function visitor(node: Node): VisitResult { + if ((node.transformFlags & TransformFlags.ContainsES2020) === 0) { + return node; + } + switch (node.kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + if (node.flags & NodeFlags.OptionalChain) { + const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false); + Debug.assertNotNode(updated, isSyntheticReference); + return updated; + } + return visitEachChild(node, visitor, context); + case SyntaxKind.BinaryExpression: + if ((node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { + return transformNullishCoalescingExpression(node); + } + return visitEachChild(node, visitor, context); + case SyntaxKind.DeleteExpression: + return visitDeleteExpression(node as DeleteExpression); + default: + return visitEachChild(node, visitor, context); + } + } - function flattenChain(chain: OptionalChain) { - Debug.assertNotNode(chain, isNonNullChain); - const links: OptionalChain[] = [chain]; - while (!chain.questionDotToken && !isTaggedTemplateExpression(chain)) { - chain = cast(skipPartiallyEmittedExpressions(chain.expression), isOptionalChain); - Debug.assertNotNode(chain, isNonNullChain); - links.unshift(chain); - } - return { expression: chain.expression, chain: links }; - } + function flattenChain(chain: OptionalChain) { + Debug.assertNotNode(chain, isNonNullChain); + const links: OptionalChain[] = [chain]; + while (!chain.questionDotToken && !isTaggedTemplateExpression(chain)) { + chain = cast(skipPartiallyEmittedExpressions(chain.expression), isOptionalChain); + Debug.assertNotNode(chain, isNonNullChain); + links.unshift(chain); + } + return { expression: chain.expression, chain: links }; + } - function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { - const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); - if (isSyntheticReference(expression)) { - // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } - // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } - return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg); - } - return updateParen(node, expression); - } + function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { + const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); + if (isSyntheticReference(expression)) { + // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } + // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } + return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg); + } + return updateParen(node, expression); + } - function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { - if (isOptionalChain(node)) { - // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg, isDelete); - } + function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { + if (isOptionalChain(node)) { + // If `node` is an optional chain, then it is the outermost chain of an optional expression. + return visitOptionalExpression(node, captureThisArg, isDelete); + } - let expression: Expression = visitNode(node.expression, visitor, isExpression); - Debug.assertNotNode(expression, isSyntheticReference); + let expression: Expression = visitNode(node.expression, visitor, isExpression); + Debug.assertNotNode(expression, isSyntheticReference); - let thisArg: Expression | undefined; - if (captureThisArg) { - if (shouldCaptureInTempVariable(expression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - expression = createAssignment(thisArg, expression); - } - else { - thisArg = expression; - } - } + let thisArg: Expression | undefined; + if (captureThisArg) { + if (shouldCaptureInTempVariable(expression)) { + thisArg = createTempVariable(hoistVariableDeclaration); + expression = createAssignment(thisArg, expression); + // if (inParameterInitializer) tempVariableInParameter = true; + } + else { + thisArg = expression; + } + } - expression = node.kind === SyntaxKind.PropertyAccessExpression - ? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) - : updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); - return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression; - } + expression = node.kind === SyntaxKind.PropertyAccessExpression + ? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) + : updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); + return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression; + } - function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { - if (isOptionalChain(node)) { - // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false); - } - return visitEachChild(node, visitor, context); - } + function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { + if (isOptionalChain(node)) { + // If `node` is an optional chain, then it is the outermost chain of an optional expression. + return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false); + } + return visitEachChild(node, visitor, context); + } - function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { - switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); - case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); - default: return visitNode(node, visitor, isExpression); - } - } + function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { + switch (node.kind) { + case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); + case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); + default: return visitNode(node, visitor, isExpression); + } + } - function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { - const { expression, chain } = flattenChain(node); - const left = visitNonOptionalExpression(expression, isCallChain(chain[0]), /*isDelete*/ false); - const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; - let leftExpression = isSyntheticReference(left) ? left.expression : left; - let capturedLeft: Expression = leftExpression; - if (shouldCaptureInTempVariable(leftExpression)) { - capturedLeft = createTempVariable(hoistVariableDeclaration); - leftExpression = createAssignment(capturedLeft, leftExpression); - } - let rightExpression = capturedLeft; - let thisArg: Expression | undefined; - for (let i = 0; i < chain.length; i++) { - const segment = chain[i]; - switch (segment.kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - if (i === chain.length - 1 && captureThisArg) { - if (shouldCaptureInTempVariable(rightExpression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - rightExpression = createAssignment(thisArg, rightExpression); - } - else { - thisArg = rightExpression; - } - } - rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression - ? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) - : createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); - break; - case SyntaxKind.CallExpression: - if (i === 0 && leftThisArg) { - rightExpression = createFunctionCall( - rightExpression, - leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg, - visitNodes(segment.arguments, visitor, isExpression) - ); - } - else { - rightExpression = createCall( - rightExpression, - /*typeArguments*/ undefined, - visitNodes(segment.arguments, visitor, isExpression) - ); - } - break; - } - setOriginalNode(rightExpression, segment); - } + function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { + const { expression, chain } = flattenChain(node); + const left = visitNonOptionalExpression(expression, isCallChain(chain[0]), /*isDelete*/ false); + const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; + let leftExpression = isSyntheticReference(left) ? left.expression : left; + let capturedLeft: Expression = leftExpression; + if (shouldCaptureInTempVariable(leftExpression)) { + capturedLeft = createTempVariable(hoistVariableDeclaration); + leftExpression = createAssignment(capturedLeft, leftExpression); + // if (inParameterInitializer) tempVariableInParameter = true; + } + let rightExpression = capturedLeft; + let thisArg: Expression | undefined; + for (let i = 0; i < chain.length; i++) { + const segment = chain[i]; + switch (segment.kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + if (i === chain.length - 1 && captureThisArg) { + if (shouldCaptureInTempVariable(rightExpression)) { + thisArg = createTempVariable(hoistVariableDeclaration); + rightExpression = createAssignment(thisArg, rightExpression); + // if (inParameterInitializer) tempVariableInParameter = true; + } + else { + thisArg = rightExpression; + } + } + rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression + ? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) + : createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); + break; + case SyntaxKind.CallExpression: + if (i === 0 && leftThisArg) { + rightExpression = createFunctionCall( + rightExpression, + leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg, + visitNodes(segment.arguments, visitor, isExpression) + ); + } + else { + rightExpression = createCall( + rightExpression, + /*typeArguments*/ undefined, + visitNodes(segment.arguments, visitor, isExpression) + ); + } + break; + } + setOriginalNode(rightExpression, segment); + } - const target = isDelete - ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) - : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); - return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; - } + const target = isDelete + ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) + : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); + return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; + } - function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) { - return createBinary( - createBinary( - left, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createNull() - ), - createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), - createBinary( - right, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createVoidZero() - ) - ); - } + function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) { + return createBinary( + createBinary( + left, + createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + createNull() + ), + createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), + createBinary( + right, + createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + createVoidZero() + ) + ); + } - function transformNullishCoalescingExpression(node: BinaryExpression) { - let left = visitNode(node.left, visitor, isExpression); - let right = left; - if (shouldCaptureInTempVariable(left)) { - right = createTempVariable(hoistVariableDeclaration); - left = createAssignment(right, left); - } - return createConditional( - createNotNullCondition(left, right), - right, - visitNode(node.right, visitor, isExpression), - ); - } + function transformNullishCoalescingExpression(node: BinaryExpression) { + let left = visitNode(node.left, visitor, isExpression); + let right = left; + if (shouldCaptureInTempVariable(left)) { + right = createTempVariable(hoistVariableDeclaration); + left = createAssignment(right, left); + // if (inParameterInitializer) tempVariableInParameter = true; + } + return createConditional( + createNotNullCondition(left, right), + right, + visitNode(node.right, visitor, isExpression), + ); + } - function shouldCaptureInTempVariable(expression: Expression): boolean { - // don't capture identifiers and `this` in a temporary variable - // `super` cannot be captured as it's no real variable - return !isIdentifier(expression) && - expression.kind !== SyntaxKind.ThisKeyword && - expression.kind !== SyntaxKind.SuperKeyword; - } + function shouldCaptureInTempVariable(expression: Expression): boolean { + // don't capture identifiers and `this` in a temporary variable + // `super` cannot be captured as it's no real variable + return !isIdentifier(expression) && + expression.kind !== SyntaxKind.ThisKeyword && + expression.kind !== SyntaxKind.SuperKeyword; + } - function visitDeleteExpression(node: DeleteExpression) { - return isOptionalChain(skipParentheses(node.expression)) - ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) - : updateDelete(node, visitNode(node.expression, visitor, isExpression)); - } - } + function visitDeleteExpression(node: DeleteExpression) { + return isOptionalChain(skipParentheses(node.expression)) + ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) + : updateDelete(node, visitNode(node.expression, visitor, isExpression)); + } + } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 70bc9b01528..8cf06d4ab4e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4323,6 +4323,7 @@ namespace ts { instantiations?: Map; // Instantiations of generic type alias (undefined if non-generic) isExhaustive?: boolean; // Is node an exhaustive switch statement skipDirectInference?: true; // Flag set by the API `getContextualType` call on a node when `Completions` is passed to force the checker to skip making inferences to a node's type + declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter. } export const enum TypeFlags { @@ -5994,6 +5995,13 @@ namespace ts { set?: Expression; } + /* @internal */ + export const enum LexicalEnvironmentFlags { + None = 0, + InParameters = 1 << 0, // currently visiting a parameter list + VariablesHoistedInParameters = 1 << 1 // a temp variable was hoisted while visiting a parameter list + } + export interface TransformationContext { /*@internal*/ getEmitResolver(): EmitResolver; /*@internal*/ getEmitHost(): EmitHost; @@ -6004,6 +6012,9 @@ namespace ts { /** Starts a new lexical environment. */ startLexicalEnvironment(): void; + /* @internal */ setLexicalEnvironmentFlags(flags: LexicalEnvironmentFlags, value: boolean): void; + /* @internal */ getLexicalEnvironmentFlags(): LexicalEnvironmentFlags; + /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; @@ -6019,6 +6030,10 @@ namespace ts { /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + /** Adds an initialization statement to the top of the lexical environment. */ + /* @internal */ + addInitializationStatement(node: Statement): void; + /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bab1fe7b02b..9e1d338d8d7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1092,6 +1092,26 @@ namespace ts { && (node).expression.kind === SyntaxKind.StringLiteral; } + export function isCustomPrologue(node: Statement) { + return !!(getEmitFlags(node) & EmitFlags.CustomPrologue); + } + + export function isHoistedFunction(node: Statement) { + return isCustomPrologue(node) + && isFunctionDeclaration(node); + } + + function isHoistedVariable(node: VariableDeclaration) { + return isIdentifier(node.name) + && !node.initializer; + } + + export function isHoistedVariableStatement(node: Statement) { + return isCustomPrologue(node) + && isVariableStatement(node) + && every(node.declarationList.declarations, isHoistedVariable); + } + export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { return node.kind !== SyntaxKind.JsxText ? getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index a7a331d4bff..c119eff97de 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -520,11 +520,18 @@ namespace ts { return result; } + function findSpanEnd(array: readonly T[], test: (value: T) => boolean, start: number) { + let i = start; + while (i < array.length && test(array[i])) { + i++; + } + return i; + } + /** * Merges generated lexical declarations into a new statement list. */ export function mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined): NodeArray; - /** * Appends generated lexical declarations to an array of statements. */ @@ -534,9 +541,91 @@ namespace ts { return statements; } - return isNodeArray(statements) - ? setTextRange(createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements) - : insertStatementsAfterStandardPrologue(statements, declarations); + // When we merge new lexical statements into an existing statement list, we merge them in the following manner: + // + // Given: + // + // | Left | Right | + // |------------------------------------|-------------------------------------| + // | [standard prologues (left)] | [standard prologues (right)] | + // | [hoisted functions (left)] | [hoisted functions (right)] | + // | [hoisted variables (left)] | [hoisted variables (right)] | + // | [lexical init statements (left)] | [lexical init statements (right)] | + // | [other statements (left)] | | + // + // The resulting statement list will be: + // + // | Result | + // |-------------------------------------| + // | [standard prologues (right)] | + // | [standard prologues (left)] | + // | [hoisted functions (right)] | + // | [hoisted functions (left)] | + // | [hoisted variables (right)] | + // | [hoisted variables (left)] | + // | [lexical init statements (right)] | + // | [lexical init statements (left)] | + // | [other statements (left)] | + // + // NOTE: It is expected that new lexical init statements must be evaluated before existing lexical init statements, + // as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state. + + // find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom + const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0); + const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd); + const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd); + + // find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom + const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0); + const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd); + const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd); + const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd); + Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues"); + + // splice prologues from the right into the left. We do this in reverse order + // so that we don't need to recompute the index on the left when we insert items. + const left = isNodeArray(statements) ? statements.slice() : statements; + + // splice other custom prologues from right into left + if (rightCustomPrologueEnd > rightHoistedVariablesEnd) { + left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd)); + } + + // splice hoisted variables from right into left + if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) { + left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd)); + } + + // splice hoisted functions from right into left + if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) { + left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd)); + } + + // splice standard prologues from right into left (that are not already in left) + if (rightStandardPrologueEnd > 0) { + if (leftStandardPrologueEnd === 0) { + left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd)); + } + else { + const leftPrologues = createMap(); + for (let i = 0; i < leftStandardPrologueEnd; i++) { + const leftPrologue = statements[i] as PrologueDirective; + leftPrologues.set(leftPrologue.expression.text, true); + } + for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) { + const rightPrologue = declarations[i] as PrologueDirective; + if (!leftPrologues.has(rightPrologue.expression.text)) { + left.unshift(rightPrologue); + } + } + } + } + + if (isNodeArray(statements)) { + return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements); + } + + return statements; } /** diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index fa611bc9bde..b21af6186db 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -149,13 +149,124 @@ namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ + export function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray): NodeArray; + export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray | undefined): NodeArray | undefined; export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) { + let updated: NodeArray | undefined; context.startLexicalEnvironment(); - const updated = nodesVisitor(nodes, visitor, isParameterDeclaration); + if (nodes) { + context.setLexicalEnvironmentFlags(LexicalEnvironmentFlags.InParameters, true); + updated = nodesVisitor(nodes, visitor, isParameterDeclaration); + + // As of ES2015, any runtime execution of that occurs in for a parameter (such as evaluating an + // initializer or a binding pattern), occurs in its own lexical scope. As a result, any expression + // that we might transform that introduces a temporary variable would fail as the temporary variable + // exists in a different lexical scope. To address this, we move any binding patterns and initializers + // in a parameter list to the body if we detect a variable being hoisted while visiting a parameter list + // when the emit target is greater than ES2015. + if (context.getLexicalEnvironmentFlags() & LexicalEnvironmentFlags.VariablesHoistedInParameters && + getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015) { + updated = addDefaultValueAssignmentsIfNeeded(updated, context); + } + context.setLexicalEnvironmentFlags(LexicalEnvironmentFlags.InParameters, false); + } context.suspendLexicalEnvironment(); return updated; } + function addDefaultValueAssignmentsIfNeeded(parameters: NodeArray, context: TransformationContext) { + let result: ParameterDeclaration[] | undefined; + for (let i = 0; i < parameters.length; i++) { + const parameter = parameters[i]; + const updated = addDefaultValueAssignmentIfNeeded(parameter, context); + if (result || updated !== parameter) { + if (!result) result = parameters.slice(0, i); + result[i] = updated; + } + } + if (result) { + return setTextRange(createNodeArray(result, parameters.hasTrailingComma), parameters); + } + return parameters; + } + + function addDefaultValueAssignmentIfNeeded(parameter: ParameterDeclaration, context: TransformationContext) { + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. + return parameter.dotDotDotToken ? parameter : + isBindingPattern(parameter.name) ? addDefaultValueAssignmentForBindingPattern(parameter, context) : + parameter.initializer ? addDefaultValueAssignmentForInitializer(parameter, parameter.name, parameter.initializer, context) : + parameter; + } + + function addDefaultValueAssignmentForBindingPattern(parameter: ParameterDeclaration, context: TransformationContext) { + context.addInitializationStatement( + createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([ + createVariableDeclaration( + parameter.name, + parameter.type, + parameter.initializer ? + createConditional( + createStrictEquality( + getGeneratedNameForNode(parameter), + createVoidZero() + ), + parameter.initializer, + getGeneratedNameForNode(parameter) + ) : + getGeneratedNameForNode(parameter) + ), + ]) + ) + ); + return updateParameter(parameter, + parameter.decorators, + parameter.modifiers, + parameter.dotDotDotToken, + getGeneratedNameForNode(parameter), + parameter.questionToken, + parameter.type, + /*initializer*/ undefined); + } + + function addDefaultValueAssignmentForInitializer(parameter: ParameterDeclaration, name: Identifier, initializer: Expression, context: TransformationContext) { + context.addInitializationStatement( + createIf( + createTypeCheck(getSynthesizedClone(name), "undefined"), + setEmitFlags( + setTextRange( + createBlock([ + createExpressionStatement( + setEmitFlags( + setTextRange( + createAssignment( + setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap), + setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments) + ), + parameter + ), + EmitFlags.NoComments + ) + ) + ]), + parameter + ), + EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments + ) + ) + ); + return updateParameter(parameter, + parameter.decorators, + parameter.modifiers, + parameter.dotDotDotToken, + parameter.name, + parameter.questionToken, + parameter.type, + /*initializer*/ undefined); + } + /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. diff --git a/tests/baselines/reference/FunctionDeclaration3_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration3_es6.errors.txt index 409baef3a50..cdc50037d65 100644 --- a/tests/baselines/reference/FunctionDeclaration3_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration3_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration3_es6.ts(1,20): error TS2372: Parameter 'yield' cannot be referenced in its initializer. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration3_es6.ts(1,20): error TS2372: Parameter 'yield' cannot reference itself. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration3_es6.ts (1 errors) ==== function f(yield = yield) { ~~~~~ -!!! error TS2372: Parameter 'yield' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'yield' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index db6b0bc4905..e45bd38e2de 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4460,7 +4460,8 @@ declare namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray): NodeArray; + function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray | undefined): NodeArray | undefined; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3ec2b8046b9..62e8560ae48 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4460,7 +4460,8 @@ declare namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray): NodeArray; + function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: (nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) => NodeArray | undefined): NodeArray | undefined; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. diff --git a/tests/baselines/reference/asyncArrowFunction3_es2017.errors.txt b/tests/baselines/reference/asyncArrowFunction3_es2017.errors.txt index 1c1fd711760..64b47bc6cd5 100644 --- a/tests/baselines/reference/asyncArrowFunction3_es2017.errors.txt +++ b/tests/baselines/reference/asyncArrowFunction3_es2017.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction3_es2017.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction3_es2017.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction3_es2017.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt b/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt index 01c74ab3620..8540c900559 100644 --- a/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt +++ b/tests/baselines/reference/asyncArrowFunction3_es5.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/asyncArrowFunction3_es6.errors.txt b/tests/baselines/reference/asyncArrowFunction3_es6.errors.txt index d0f56df51da..cfa4edcca4a 100644 --- a/tests/baselines/reference/asyncArrowFunction3_es6.errors.txt +++ b/tests/baselines/reference/asyncArrowFunction3_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction3_es6.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction3_es6.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction3_es6.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/asyncFunctionDeclaration3_es2017.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration3_es2017.errors.txt index 53a85074834..599d481f319 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration3_es2017.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration3_es2017.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration3_es2017.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration3_es2017.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration3_es2017.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt index 1192e396a64..c5b84f0602d 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration3_es5.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/asyncFunctionDeclaration3_es6.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration3_es6.errors.txt index a480bf3d2b8..76ccd1269c6 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration3_es6.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration3_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration3_es6.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer. +tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration3_es6.ts(1,20): error TS2372: Parameter 'await' cannot reference itself. ==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration3_es6.ts (1 errors) ==== function f(await = await) { ~~~~~ -!!! error TS2372: Parameter 'await' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'await' cannot reference itself. } \ No newline at end of file diff --git a/tests/baselines/reference/capturedParametersInInitializers1.errors.txt b/tests/baselines/reference/capturedParametersInInitializers1.errors.txt index fce7c6ee488..bbd19e7f64d 100644 --- a/tests/baselines/reference/capturedParametersInInitializers1.errors.txt +++ b/tests/baselines/reference/capturedParametersInInitializers1.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/capturedParametersInInitializers1.ts(18,20): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. -tests/cases/compiler/capturedParametersInInitializers1.ts(22,26): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. -tests/cases/compiler/capturedParametersInInitializers1.ts(38,21): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +tests/cases/compiler/capturedParametersInInitializers1.ts(18,20): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. +tests/cases/compiler/capturedParametersInInitializers1.ts(22,26): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. +tests/cases/compiler/capturedParametersInInitializers1.ts(38,21): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. ==== tests/cases/compiler/capturedParametersInInitializers1.ts (3 errors) ==== @@ -23,13 +23,13 @@ tests/cases/compiler/capturedParametersInInitializers1.ts(38,21): error TS2373: // error - used before declaration function foo4(y = {z}, z = 1) { ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. } // error - used before declaration, IIFEs are inlined function foo5(y = (() => z)(), z = 1) { ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. } // ok - IIFE inside another function @@ -47,6 +47,6 @@ tests/cases/compiler/capturedParametersInInitializers1.ts(38,21): error TS2373: // error - used as computed name of method function foo9(y = {[z]() { return z; }}, z = 1) { ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. } \ No newline at end of file diff --git a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt index df6c71f544b..4647aea937c 100644 --- a/tests/baselines/reference/capturedParametersInInitializers2.errors.txt +++ b/tests/baselines/reference/capturedParametersInInitializers2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/compiler/capturedParametersInInitializers2.ts(3,20): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. -tests/cases/compiler/capturedParametersInInitializers2.ts(4,14): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. -tests/cases/compiler/capturedParametersInInitializers2.ts(6,10): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +tests/cases/compiler/capturedParametersInInitializers2.ts(3,20): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. +tests/cases/compiler/capturedParametersInInitializers2.ts(4,14): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. +tests/cases/compiler/capturedParametersInInitializers2.ts(6,10): error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. tests/cases/compiler/capturedParametersInInitializers2.ts(13,26): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. -tests/cases/compiler/capturedParametersInInitializers2.ts(13,27): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. +tests/cases/compiler/capturedParametersInInitializers2.ts(13,27): error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. ==== tests/cases/compiler/capturedParametersInInitializers2.ts (5 errors) ==== @@ -10,14 +10,14 @@ tests/cases/compiler/capturedParametersInInitializers2.ts(13,27): error TS2373: y = class { static c = x; ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. get [x]() {return x;} ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. constructor() { x; } [z]() { return z; } ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'z' declared after it. }, x = 1, z = 2 @@ -28,5 +28,5 @@ tests/cases/compiler/capturedParametersInInitializers2.ts(13,27): error TS2373: ~~~ !!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'x' declared after it. } \ No newline at end of file diff --git a/tests/baselines/reference/capturedParametersInInitializers2.js b/tests/baselines/reference/capturedParametersInInitializers2.js index 53d5da5d445..da1f63b58e6 100644 --- a/tests/baselines/reference/capturedParametersInInitializers2.js +++ b/tests/baselines/reference/capturedParametersInInitializers2.js @@ -16,6 +16,7 @@ function foo2(y = class {[x] = x}, x = 1) { //// [capturedParametersInInitializers2.js] function foo(y, x, z) { + var _a; if (y === void 0) { y = (_a = /** @class */ (function () { function class_1() { x; @@ -32,10 +33,10 @@ function foo(y, x, z) { _a); } if (x === void 0) { x = 1; } if (z === void 0) { z = 2; } - var _a; y.c; } function foo2(y, x) { + var _a, _b; if (y === void 0) { y = (_b = /** @class */ (function () { function class_2() { this[_a] = x; @@ -45,5 +46,4 @@ function foo2(y, x) { _a = x, _b); } if (x === void 0) { x = 1; } - var _a, _b; } diff --git a/tests/baselines/reference/circularOptionalityRemoval.errors.txt b/tests/baselines/reference/circularOptionalityRemoval.errors.txt index 2b60b5b6621..b1c55b70f04 100644 --- a/tests/baselines/reference/circularOptionalityRemoval.errors.txt +++ b/tests/baselines/reference/circularOptionalityRemoval.errors.txt @@ -1,11 +1,11 @@ tests/cases/compiler/circularOptionalityRemoval.ts(2,14): error TS2502: 'x' is referenced directly or indirectly in its own type annotation. -tests/cases/compiler/circularOptionalityRemoval.ts(2,38): error TS2372: Parameter 'x' cannot be referenced in its initializer. +tests/cases/compiler/circularOptionalityRemoval.ts(2,38): error TS2372: Parameter 'x' cannot reference itself. tests/cases/compiler/circularOptionalityRemoval.ts(2,38): error TS2532: Object is possibly 'undefined'. -tests/cases/compiler/circularOptionalityRemoval.ts(2,46): error TS2372: Parameter 'x' cannot be referenced in its initializer. +tests/cases/compiler/circularOptionalityRemoval.ts(2,46): error TS2372: Parameter 'x' cannot reference itself. tests/cases/compiler/circularOptionalityRemoval.ts(5,14): error TS1015: Parameter cannot have question mark and initializer. tests/cases/compiler/circularOptionalityRemoval.ts(5,14): error TS2502: 'x' is referenced directly or indirectly in its own type annotation. tests/cases/compiler/circularOptionalityRemoval.ts(5,27): error TS2304: Cannot find name 'someCondition'. -tests/cases/compiler/circularOptionalityRemoval.ts(5,54): error TS2372: Parameter 'x' cannot be referenced in its initializer. +tests/cases/compiler/circularOptionalityRemoval.ts(5,54): error TS2372: Parameter 'x' cannot reference itself. ==== tests/cases/compiler/circularOptionalityRemoval.ts (8 errors) ==== @@ -14,11 +14,11 @@ tests/cases/compiler/circularOptionalityRemoval.ts(5,54): error TS2372: Paramete ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2502: 'x' is referenced directly or indirectly in its own type annotation. ~ -!!! error TS2372: Parameter 'x' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'x' cannot reference itself. ~ !!! error TS2532: Object is possibly 'undefined'. ~ -!!! error TS2372: Parameter 'x' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'x' cannot reference itself. // Report from user function fn2(x?: string = someCondition ? 'value1' : x) { } @@ -29,4 +29,4 @@ tests/cases/compiler/circularOptionalityRemoval.ts(5,54): error TS2372: Paramete ~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'someCondition'. ~ -!!! error TS2372: Parameter 'x' cannot be referenced in its initializer. \ No newline at end of file +!!! error TS2372: Parameter 'x' cannot reference itself. \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es2015).js b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es2015).js new file mode 100644 index 00000000000..707f001650a --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es2015).js @@ -0,0 +1,10 @@ +//// [classWithStaticFieldInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +(({ [class { static x = 1 }.x]: b = "" }) => {})(); + +//// [classWithStaticFieldInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +((_a) => { var _b; var { [(_b = class { + }, + _b.x = 1, + _b).x]: b = "" } = _a; })(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es5).js b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es5).js new file mode 100644 index 00000000000..32ac07f7cd1 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=es5).js @@ -0,0 +1,16 @@ +//// [classWithStaticFieldInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +(({ [class { static x = 1 }.x]: b = "" }) => {})(); + +//// [classWithStaticFieldInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +(function (_a) { + var _b; + var _c = (_b = /** @class */ (function () { + function class_1() { + } + return class_1; + }()), + _b.x = 1, + _b).x, _d = _a[_c], b = _d === void 0 ? "" : _d; +})(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=esnext).js b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=esnext).js new file mode 100644 index 00000000000..707f001650a --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern(target=esnext).js @@ -0,0 +1,10 @@ +//// [classWithStaticFieldInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +(({ [class { static x = 1 }.x]: b = "" }) => {})(); + +//// [classWithStaticFieldInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +((_a) => { var _b; var { [(_b = class { + }, + _b.x = 1, + _b).x]: b = "" } = _a; })(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es2015).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es2015).errors.txt new file mode 100644 index 00000000000..b2ca477fe31 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es2015).errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(3,20): error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(6,57): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + (({ [class extends C { static x = 1 }.x]: b = "" }) => { var C; })(); + ~ +!!! error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. + + const x = ""; + (({ [class extends C { static x = 1 }.x]: b = "" }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es5).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es5).errors.txt new file mode 100644 index 00000000000..b2ca477fe31 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=es5).errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(3,20): error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(6,57): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + (({ [class extends C { static x = 1 }.x]: b = "" }) => { var C; })(); + ~ +!!! error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. + + const x = ""; + (({ [class extends C { static x = 1 }.x]: b = "" }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=esnext).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=esnext).errors.txt new file mode 100644 index 00000000000..b2ca477fe31 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterBindingPattern.2(target=esnext).errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(3,20): error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts(6,57): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + (({ [class extends C { static x = 1 }.x]: b = "" }) => { var C; })(); + ~ +!!! error TS2373: Parameter '{ [class extends C { static x = 1 }.x]: b = "" }' cannot reference identifier 'C' declared after it. + + const x = ""; + (({ [class extends C { static x = 1 }.x]: b = "" }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es2015).js b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es2015).js new file mode 100644 index 00000000000..fd89bcefa8b --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es2015).js @@ -0,0 +1,10 @@ +//// [classWithStaticFieldInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +((b = class { static x = 1 }) => {})(); + +//// [classWithStaticFieldInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +((b) => { var _a; if (b === void 0) { b = (_a = class { + }, + _a.x = 1, + _a); } })(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es5).js b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es5).js new file mode 100644 index 00000000000..30142396a8e --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=es5).js @@ -0,0 +1,16 @@ +//// [classWithStaticFieldInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +((b = class { static x = 1 }) => {})(); + +//// [classWithStaticFieldInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +(function (b) { + var _a; + if (b === void 0) { b = (_a = /** @class */ (function () { + function class_1() { + } + return class_1; + }()), + _a.x = 1, + _a); } +})(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=esnext).js b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=esnext).js new file mode 100644 index 00000000000..fd89bcefa8b --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer(target=esnext).js @@ -0,0 +1,10 @@ +//// [classWithStaticFieldInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +((b = class { static x = 1 }) => {})(); + +//// [classWithStaticFieldInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +((b) => { var _a; if (b === void 0) { b = (_a = class { + }, + _a.x = 1, + _a); } })(); diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es2015).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es2015).errors.txt new file mode 100644 index 00000000000..56fefb8b502 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es2015).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(3,21): error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(6,45): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + ((b = class extends C { static x = 1 }) => { var C; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. + + const x = ""; + ((b = class extends C { static x = 1 }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es5).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es5).errors.txt new file mode 100644 index 00000000000..56fefb8b502 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=es5).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(3,21): error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(6,45): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + ((b = class extends C { static x = 1 }) => { var C; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. + + const x = ""; + ((b = class extends C { static x = 1 }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=esnext).errors.txt b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=esnext).errors.txt new file mode 100644 index 00000000000..56fefb8b502 --- /dev/null +++ b/tests/baselines/reference/classWithStaticFieldInParameterInitializer.2(target=esnext).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(3,21): error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. +tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts(6,45): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + class C {} + ((b = class extends C { static x = 1 }) => { var C; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'C' declared after it. + + const x = ""; + ((b = class extends C { static x = 1 }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.errors.txt b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.errors.txt index eff1e1a6593..af2d5b6fbd6 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.errors.txt +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(2,22): error TS2448: Block-scoped variable 'e' used before its declaration. tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(3,22): error TS2448: Block-scoped variable 'i' used before its declaration. -tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(7,27): error TS2372: Parameter 'e' cannot be referenced in its initializer. -tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(9,27): error TS2373: Initializer of parameter 'h' cannot reference identifier 'i' declared after it. +tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(7,27): error TS2372: Parameter 'e' cannot reference itself. +tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts(9,27): error TS2373: Parameter 'h' cannot reference identifier 'i' declared after it. ==== tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment3.ts (4 errors) ==== @@ -19,10 +19,10 @@ tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAss })([1]); (function ([c, d = c, e = e]) { // error for e = e ~ -!!! error TS2372: Parameter 'e' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'e' cannot reference itself. })([1]); (function ([f, g = f, h = i, i = f]) { // error for h = i ~ -!!! error TS2373: Initializer of parameter 'h' cannot reference identifier 'i' declared after it. +!!! error TS2373: Parameter 'h' cannot reference identifier 'i' declared after it. })([1]) \ No newline at end of file diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index 5ed54e044d2..5a9ebea09be 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. -tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. +tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. +tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. ==== tests/cases/conformance/functions/functionImplementationErrors.ts (3 errors) ==== @@ -37,14 +37,14 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error // Function signature with parameter initializer referencing in scope local variable function f6(n = m) { ~ -!!! error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. +!!! error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. var m = 4; } // Function signature with initializer referencing other parameter to the right function f7(n = m, m?) { ~ -!!! error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. +!!! error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. } // FunctionExpression with non -void return type annotation with a throw, no return, and other code diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es2015).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es2015).js new file mode 100644 index 00000000000..c7736309aba --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es2015).js @@ -0,0 +1,9 @@ +//// [nullishCoalescingOperatorInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +(({ [a() ?? "d"]: c = "" }) => {})(); + +//// [nullishCoalescingOperatorInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((_a) => { var _b; var { [(_b = a()) !== null && _b !== void 0 ? _b : "d"]: c = "" } = _a; })(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es5).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es5).js new file mode 100644 index 00000000000..ea103f59da6 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=es5).js @@ -0,0 +1,12 @@ +//// [nullishCoalescingOperatorInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +(({ [a() ?? "d"]: c = "" }) => {})(); + +//// [nullishCoalescingOperatorInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +var a = function () { return undefined; }; +(function (_a) { + var _b; + var _c = (_b = a()) !== null && _b !== void 0 ? _b : "d", _d = _a[_c], c = _d === void 0 ? "" : _d; +})(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=esnext).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=esnext).js new file mode 100644 index 00000000000..07a1b1e9e73 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern(target=esnext).js @@ -0,0 +1,9 @@ +//// [nullishCoalescingOperatorInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +(({ [a() ?? "d"]: c = "" }) => {})(); + +//// [nullishCoalescingOperatorInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +(({ [a() ?? "d"]: c = "" }) => { })(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es2015).errors.txt b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es2015).errors.txt new file mode 100644 index 00000000000..6319b92a19f --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es2015).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts(3,6): error TS2373: Parameter '{ [a() ?? "d"]: c = "" }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts(6,31): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): string | undefined => undefined; + (({ [a() ?? "d"]: c = "" }) => { var a; })(); + ~ +!!! error TS2373: Parameter '{ [a() ?? "d"]: c = "" }' cannot reference identifier 'a' declared after it. + + const x = ""; + (({ [a() ?? "d"]: c = "", d = x }) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es5).errors.txt b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es5).errors.txt new file mode 100644 index 00000000000..6319b92a19f --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterBindingPattern.2(target=es5).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts(3,6): error TS2373: Parameter '{ [a() ?? "d"]: c = "" }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts(6,31): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): string | undefined => undefined; + (({ [a() ?? "d"]: c = "" }) => { var a; })(); + ~ +!!! error TS2373: Parameter '{ [a() ?? "d"]: c = "" }' cannot reference identifier 'a' declared after it. + + const x = ""; + (({ [a() ?? "d"]: c = "", d = x }) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es2015).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es2015).js new file mode 100644 index 00000000000..f7f2e83221d --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es2015).js @@ -0,0 +1,9 @@ +//// [nullishCoalescingOperatorInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +((b = a() ?? "d") => {})(); + +//// [nullishCoalescingOperatorInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((b) => { var _a; if (b === void 0) { b = (_a = a()) !== null && _a !== void 0 ? _a : "d"; } })(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es5).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es5).js new file mode 100644 index 00000000000..439a4d6ba43 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=es5).js @@ -0,0 +1,12 @@ +//// [nullishCoalescingOperatorInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +((b = a() ?? "d") => {})(); + +//// [nullishCoalescingOperatorInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +var a = function () { return undefined; }; +(function (b) { + var _a; + if (b === void 0) { b = (_a = a()) !== null && _a !== void 0 ? _a : "d"; } +})(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=esnext).js b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=esnext).js new file mode 100644 index 00000000000..e9ae41d6bde --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer(target=esnext).js @@ -0,0 +1,9 @@ +//// [nullishCoalescingOperatorInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +((b = a() ?? "d") => {})(); + +//// [nullishCoalescingOperatorInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((b = a() ?? "d") => { })(); diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es2015).errors.txt b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es2015).errors.txt new file mode 100644 index 00000000000..3c00102f390 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es2015).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts(3,7): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts(6,23): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): string | undefined => undefined; + ((b = a() ?? "d") => { var a; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + + const x = ""; + ((b = a() ?? "d", d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es5).errors.txt b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es5).errors.txt new file mode 100644 index 00000000000..3c00102f390 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInParameterInitializer.2(target=es5).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts(3,7): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts(6,23): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): string | undefined => undefined; + ((b = a() ?? "d") => { var a; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + + const x = ""; + ((b = a() ?? "d", d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es2015).js b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es2015).js new file mode 100644 index 00000000000..3870f17544e --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es2015).js @@ -0,0 +1,9 @@ +//// [optionalChainingInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +(({ [a()?.d]: c = "" }) => {})(); + +//// [optionalChainingInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((_a) => { var _b; var { [(_b = a()) === null || _b === void 0 ? void 0 : _b.d]: c = "" } = _a; })(); diff --git a/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es5).js b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es5).js new file mode 100644 index 00000000000..9fde11940ce --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=es5).js @@ -0,0 +1,12 @@ +//// [optionalChainingInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +(({ [a()?.d]: c = "" }) => {})(); + +//// [optionalChainingInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +var a = function () { return undefined; }; +(function (_a) { + var _b; + var _c = (_b = a()) === null || _b === void 0 ? void 0 : _b.d, _d = _a[_c], c = _d === void 0 ? "" : _d; +})(); diff --git a/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=esnext).js b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=esnext).js new file mode 100644 index 00000000000..088bc3f7eae --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterBindingPattern(target=esnext).js @@ -0,0 +1,9 @@ +//// [optionalChainingInParameterBindingPattern.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +(({ [a()?.d]: c = "" }) => {})(); + +//// [optionalChainingInParameterBindingPattern.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +(({ [a()?.d]: c = "" }) => { })(); diff --git a/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es2015).errors.txt b/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es2015).errors.txt new file mode 100644 index 00000000000..74568e69691 --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es2015).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts(3,6): error TS2373: Parameter '{ [a()?.d]: c = "" }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts(6,24): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): { d: string } | undefined => undefined; + (({ [a()?.d]: c = "" }) => { var a; })(); + ~ +!!! error TS2373: Parameter '{ [a()?.d]: c = "" }' cannot reference identifier 'a' declared after it. + + const x = ""; + (({ [a()?.d]: c }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es5).errors.txt b/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es5).errors.txt new file mode 100644 index 00000000000..74568e69691 --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterBindingPattern.2(target=es5).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts(3,6): error TS2373: Parameter '{ [a()?.d]: c = "" }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts(6,24): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): { d: string } | undefined => undefined; + (({ [a()?.d]: c = "" }) => { var a; })(); + ~ +!!! error TS2373: Parameter '{ [a()?.d]: c = "" }' cannot reference identifier 'a' declared after it. + + const x = ""; + (({ [a()?.d]: c }, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/optionalChainingInParameterInitializer(target=es2015).js b/tests/baselines/reference/optionalChainingInParameterInitializer(target=es2015).js new file mode 100644 index 00000000000..5c8a8ec76ee --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterInitializer(target=es2015).js @@ -0,0 +1,9 @@ +//// [optionalChainingInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +((b = a()?.d) => {})(); + +//// [optionalChainingInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((b) => { var _a; if (b === void 0) { b = (_a = a()) === null || _a === void 0 ? void 0 : _a.d; } })(); diff --git a/tests/baselines/reference/optionalChainingInParameterInitializer(target=es5).js b/tests/baselines/reference/optionalChainingInParameterInitializer(target=es5).js new file mode 100644 index 00000000000..07554c92cb6 --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterInitializer(target=es5).js @@ -0,0 +1,12 @@ +//// [optionalChainingInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +((b = a()?.d) => {})(); + +//// [optionalChainingInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +var a = function () { return undefined; }; +(function (b) { + var _a; + if (b === void 0) { b = (_a = a()) === null || _a === void 0 ? void 0 : _a.d; } +})(); diff --git a/tests/baselines/reference/optionalChainingInParameterInitializer(target=esnext).js b/tests/baselines/reference/optionalChainingInParameterInitializer(target=esnext).js new file mode 100644 index 00000000000..cdda35727ba --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterInitializer(target=esnext).js @@ -0,0 +1,9 @@ +//// [optionalChainingInParameterInitializer.ts] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +((b = a()?.d) => {})(); + +//// [optionalChainingInParameterInitializer.js] +// https://github.com/microsoft/TypeScript/issues/36295 +const a = () => undefined; +((b = a()?.d) => { })(); diff --git a/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es2015).errors.txt b/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es2015).errors.txt new file mode 100644 index 00000000000..80a8657d5bf --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es2015).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts(3,7): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts(6,19): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): { d: string } | undefined => undefined; + ((b = a()?.d) => { var a; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + + const x = ""; + ((b = a()?.d, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es5).errors.txt b/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es5).errors.txt new file mode 100644 index 00000000000..80a8657d5bf --- /dev/null +++ b/tests/baselines/reference/optionalChainingInParameterInitializer.2(target=es5).errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts(3,7): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts(6,19): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + const a = (): { d: string } | undefined => undefined; + ((b = a()?.d) => { var a; })(); + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + + const x = ""; + ((b = a()?.d, d = x) => { var x; })(); + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. \ No newline at end of file diff --git a/tests/baselines/reference/optionalParamReferencingOtherParams2.errors.txt b/tests/baselines/reference/optionalParamReferencingOtherParams2.errors.txt index fa89c3ed761..19eb916515a 100644 --- a/tests/baselines/reference/optionalParamReferencingOtherParams2.errors.txt +++ b/tests/baselines/reference/optionalParamReferencingOtherParams2.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/optionalParamReferencingOtherParams2.ts(2,29): error TS2373: Initializer of parameter 'y' cannot reference identifier 'b' declared after it. +tests/cases/compiler/optionalParamReferencingOtherParams2.ts(2,29): error TS2373: Parameter 'y' cannot reference identifier 'b' declared after it. ==== tests/cases/compiler/optionalParamReferencingOtherParams2.ts (1 errors) ==== var a = 1; function strange(x = a, y = b) { ~ -!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'y' cannot reference identifier 'b' declared after it. var b = ""; return y; } \ No newline at end of file diff --git a/tests/baselines/reference/optionalParamReferencingOtherParams3.errors.txt b/tests/baselines/reference/optionalParamReferencingOtherParams3.errors.txt index f2b8d3d9127..b278a97dee7 100644 --- a/tests/baselines/reference/optionalParamReferencingOtherParams3.errors.txt +++ b/tests/baselines/reference/optionalParamReferencingOtherParams3.errors.txt @@ -1,10 +1,10 @@ -tests/cases/compiler/optionalParamReferencingOtherParams3.ts(1,20): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/compiler/optionalParamReferencingOtherParams3.ts(1,20): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. ==== tests/cases/compiler/optionalParamReferencingOtherParams3.ts (1 errors) ==== function right(a = b, b = a) { ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. a; b; } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es2015).errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es2015).errors.txt new file mode 100644 index 00000000000..dda50bbc2fd --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es2015).errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(5,18): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(5,32): error TS2373: Parameter '{ b = a(), ...x }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(11,35): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts (3 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + + function a(): any {} + + function b({ b = a(), ...x } = a()) { + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + ~ +!!! error TS2373: Parameter '{ b = a(), ...x }' cannot reference identifier 'a' declared after it. + var a; + } + + const x = ""; + + function c({ b, ...c } = a(), d = x) { + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + var x; + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es5).errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es5).errors.txt new file mode 100644 index 00000000000..dda50bbc2fd --- /dev/null +++ b/tests/baselines/reference/parameterInitializersForwardReferencing.2(target=es5).errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(5,18): error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(5,32): error TS2373: Parameter '{ b = a(), ...x }' cannot reference identifier 'a' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts(11,35): error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + + +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts (3 errors) ==== + // https://github.com/microsoft/TypeScript/issues/36295 + + function a(): any {} + + function b({ b = a(), ...x } = a()) { + ~ +!!! error TS2373: Parameter 'b' cannot reference identifier 'a' declared after it. + ~ +!!! error TS2373: Parameter '{ b = a(), ...x }' cannot reference identifier 'a' declared after it. + var a; + } + + const x = ""; + + function c({ b, ...c } = a(), d = x) { + ~ +!!! error TS2373: Parameter 'd' cannot reference identifier 'x' declared after it. + var x; + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing.errors.txt index 22fe5ce558d..1bc24be31f6 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing.errors.txt @@ -1,13 +1,13 @@ -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(6,20): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(11,21): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(11,28): error TS2373: Initializer of parameter 'b' cannot reference identifier 'c' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(17,21): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(23,25): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(32,21): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(33,16): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,14): error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,21): error TS2373: Initializer of parameter 'b' cannot reference identifier 'c' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,28): error TS2373: Initializer of parameter 'c' cannot reference identifier 'd' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(6,20): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(11,21): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(11,28): error TS2373: Parameter 'b' cannot reference identifier 'c' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(17,21): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(23,25): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(32,21): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(33,16): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,14): error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,21): error TS2373: Parameter 'b' cannot reference identifier 'c' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37,28): error TS2373: Parameter 'c' cannot reference identifier 'd' declared after it. ==== tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts (10 errors) ==== @@ -18,16 +18,16 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37, function right(a = b, b = a) { ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. a; b; } function right2(a = b, b = c, c = a) { ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. ~ -!!! error TS2373: Initializer of parameter 'b' cannot reference identifier 'c' declared after it. +!!! error TS2373: Parameter 'b' cannot reference identifier 'c' declared after it. a; b; c; @@ -35,7 +35,7 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37, function inside(a = b) { ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. var b; } @@ -43,7 +43,7 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37, var b; function inside(a = b) { // Still an error because b is declared inside the function ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. var b; } } @@ -54,20 +54,20 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing.ts(37, class C { constructor(a = b, b = 1) { } ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. method(a = b, b = 1) { } ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. } // Function expressions var x = (a = b, b = c, c = d) => { var d; }; ~ -!!! error TS2373: Initializer of parameter 'a' cannot reference identifier 'b' declared after it. +!!! error TS2373: Parameter 'a' cannot reference identifier 'b' declared after it. ~ -!!! error TS2373: Initializer of parameter 'b' cannot reference identifier 'c' declared after it. +!!! error TS2373: Parameter 'b' cannot reference identifier 'c' declared after it. ~ -!!! error TS2373: Initializer of parameter 'c' cannot reference identifier 'd' declared after it. +!!! error TS2373: Parameter 'c' cannot reference identifier 'd' declared after it. // Should not produce errors - can reference later parameters if they occur within a function expression initializer. function f(a, b = function () { return c; }, c = b()) { diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt index 91d200adbcd..3c8b2fcdc48 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt @@ -1,16 +1,17 @@ -tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer. -tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot reference itself. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot reference itself. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29,15): error TS2373: Parameter '{[foo]: bar}' cannot reference identifier 'foo' declared after it. tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29,15): error TS2448: Block-scoped variable 'foo' used before its declaration. -==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (5 errors) ==== +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (6 errors) ==== let foo: string = ""; function f1 (bar = foo) { // unexpected compiler error; works at runtime ~~~ -!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +!!! error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. var foo: number = 2; return bar; // returns 1 } @@ -22,7 +23,7 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29 function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime ~~~ -!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +!!! error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. return bar; } @@ -32,18 +33,20 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29 function f5 (a = a) { ~ -!!! error TS2372: Parameter 'a' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'a' cannot reference itself. return a } function f6 (async = async) { ~~~~~ -!!! error TS2372: Parameter 'async' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'async' cannot reference itself. return async } function f7({[foo]: bar}: any[]) { ~~~ +!!! error TS2373: Parameter '{[foo]: bar}' cannot reference identifier 'foo' declared after it. + ~~~ !!! error TS2448: Block-scoped variable 'foo' used before its declaration. !!! related TS2728 tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts:30:9: 'foo' is declared here. let foo: number = 2; diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt index c65f327161e..fee18ea4964 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. -tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer. -tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(13,20): error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(21,18): error TS2372: Parameter 'a' cannot reference itself. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(25,22): error TS2372: Parameter 'async' cannot reference itself. tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(29,15): error TS2537: Type 'any[]' has no matching index signature for type 'string'. @@ -19,7 +19,7 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime ~~~ -!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +!!! error TS2373: Parameter 'bar' cannot reference identifier 'foo' declared after it. return bar; } @@ -29,13 +29,13 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t function f5 (a = a) { ~ -!!! error TS2372: Parameter 'a' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'a' cannot reference itself. return a } function f6 (async = async) { ~~~~~ -!!! error TS2372: Parameter 'async' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'async' cannot reference itself. return async } diff --git a/tests/baselines/reference/selfReferencesInFunctionParameters.errors.txt b/tests/baselines/reference/selfReferencesInFunctionParameters.errors.txt index 32955b0bdc2..6642da1d4ee 100644 --- a/tests/baselines/reference/selfReferencesInFunctionParameters.errors.txt +++ b/tests/baselines/reference/selfReferencesInFunctionParameters.errors.txt @@ -1,28 +1,28 @@ -tests/cases/compiler/selfReferencesInFunctionParameters.ts(1,26): error TS2372: Parameter 'x' cannot be referenced in its initializer. -tests/cases/compiler/selfReferencesInFunctionParameters.ts(4,35): error TS2372: Parameter 'x' cannot be referenced in its initializer. -tests/cases/compiler/selfReferencesInFunctionParameters.ts(8,28): error TS2372: Parameter 'y' cannot be referenced in its initializer. -tests/cases/compiler/selfReferencesInFunctionParameters.ts(11,29): error TS2372: Parameter 'b' cannot be referenced in its initializer. +tests/cases/compiler/selfReferencesInFunctionParameters.ts(1,26): error TS2372: Parameter 'x' cannot reference itself. +tests/cases/compiler/selfReferencesInFunctionParameters.ts(4,35): error TS2372: Parameter 'x' cannot reference itself. +tests/cases/compiler/selfReferencesInFunctionParameters.ts(8,28): error TS2372: Parameter 'y' cannot reference itself. +tests/cases/compiler/selfReferencesInFunctionParameters.ts(11,29): error TS2372: Parameter 'b' cannot reference itself. ==== tests/cases/compiler/selfReferencesInFunctionParameters.ts (4 errors) ==== function foo(x: number = x) { ~ -!!! error TS2372: Parameter 'x' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'x' cannot reference itself. } function bar(x0 = "", x: number = x) { ~ -!!! error TS2372: Parameter 'x' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'x' cannot reference itself. } class C { constructor(x = 1, y = y) { ~ -!!! error TS2372: Parameter 'y' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'y' cannot reference itself. } bar(a = "", b: string = b.toString()) { ~ -!!! error TS2372: Parameter 'b' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'b' cannot reference itself. } } \ No newline at end of file diff --git a/tests/baselines/reference/witness.errors.txt b/tests/baselines/reference/witness.errors.txt index efaed3cc43c..c005239eb96 100644 --- a/tests/baselines/reference/witness.errors.txt +++ b/tests/baselines/reference/witness.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/witness/witness.ts(4,21): error TS2372: Parameter 'pInit' cannot be referenced in its initializer. +tests/cases/conformance/types/witness/witness.ts(4,21): error TS2372: Parameter 'pInit' cannot reference itself. tests/cases/conformance/types/witness/witness.ts(8,14): error TS2729: Property 'x' is used before its initialization. tests/cases/conformance/types/witness/witness.ts(28,12): error TS2695: Left side of comma operator is unused and has no side effects. tests/cases/conformance/types/witness/witness.ts(29,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'co1' must be of type 'any', but here has type 'number'. @@ -23,7 +23,7 @@ tests/cases/conformance/types/witness/witness.ts(128,19): error TS2729: Property var pInit: any; function fn(pInit = pInit) { ~~~~~ -!!! error TS2372: Parameter 'pInit' cannot be referenced in its initializer. +!!! error TS2372: Parameter 'pInit' cannot reference itself. var pInit: any; } class InitClass { diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts new file mode 100644 index 00000000000..839eb3c87a9 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +class C {} +(({ [class extends C { static x = 1 }.x]: b = "" }) => { var C; })(); + +const x = ""; +(({ [class extends C { static x = 1 }.x]: b = "" }, d = x) => { var x; })(); diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.3.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.3.ts new file mode 100644 index 00000000000..7f55d82804f --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.3.ts @@ -0,0 +1,11 @@ +// @target: esnext +// @noTypesAndSymbols: true +// @noEmit: true +// @useDefineForClassFields: true + +// https://github.com/microsoft/TypeScript/issues/36295 +class C {} +(({ [class extends C { static x = 1 }.x]: b = "" }) => { var C; })(); + +const x = ""; +(({ [class extends C { static x = 1 }.x]: b = "" }, d = x) => { var x; })(); diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.ts new file mode 100644 index 00000000000..1d6c683dc74 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterBindingPattern.ts @@ -0,0 +1,5 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +(({ [class { static x = 1 }.x]: b = "" }) => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts new file mode 100644 index 00000000000..e70f19006df --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +class C {} +((b = class extends C { static x = 1 }) => { var C; })(); + +const x = ""; +((b = class extends C { static x = 1 }, d = x) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.3.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.3.ts new file mode 100644 index 00000000000..ba2b2db8e25 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.3.ts @@ -0,0 +1,11 @@ +// @target: esnext +// @noTypesAndSymbols: true +// @noEmit: true +// @useDefineForClassFields: true + +// https://github.com/microsoft/TypeScript/issues/36295 +class C {} +((b = class extends C { static x = 1 }) => { var C; })(); + +const x = ""; +((b = class extends C { static x = 1 }, d = x) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.ts b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.ts new file mode 100644 index 00000000000..8b32f84feb3 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/classWithStaticFieldInParameterInitializer.ts @@ -0,0 +1,5 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +((b = class { static x = 1 }) => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts new file mode 100644 index 00000000000..5925fe4d863 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +(({ [a() ?? "d"]: c = "" }) => { var a; })(); + +const x = ""; +(({ [a() ?? "d"]: c = "", d = x }) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.ts new file mode 100644 index 00000000000..1231cb5d0fe --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterBindingPattern.ts @@ -0,0 +1,6 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +(({ [a() ?? "d"]: c = "" }) => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts new file mode 100644 index 00000000000..c3da31aa203 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +((b = a() ?? "d") => { var a; })(); + +const x = ""; +((b = a() ?? "d", d = x) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.ts new file mode 100644 index 00000000000..f8c5da30425 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInParameterInitializer.ts @@ -0,0 +1,6 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): string | undefined => undefined; +((b = a() ?? "d") => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts new file mode 100644 index 00000000000..423e8a46513 --- /dev/null +++ b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +(({ [a()?.d]: c = "" }) => { var a; })(); + +const x = ""; +(({ [a()?.d]: c }, d = x) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts new file mode 100644 index 00000000000..38cabea7aee --- /dev/null +++ b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts @@ -0,0 +1,6 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +(({ [a()?.d]: c = "" }) => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts new file mode 100644 index 00000000000..707be27f114 --- /dev/null +++ b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.2.ts @@ -0,0 +1,10 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +((b = a()?.d) => { var a; })(); + +const x = ""; +((b = a()?.d, d = x) => { var x; })(); \ No newline at end of file diff --git a/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts new file mode 100644 index 00000000000..867887fc260 --- /dev/null +++ b/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts @@ -0,0 +1,6 @@ +// @target: esnext,es2015,es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 +const a = (): { d: string } | undefined => undefined; +((b = a()?.d) => {})(); \ No newline at end of file diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts new file mode 100644 index 00000000000..7aa08e2dbf0 --- /dev/null +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing.2.ts @@ -0,0 +1,17 @@ +// @target: es5, es2015, esnext +// @noEmit: true +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/36295 + +function a(): any {} + +function b({ b = a(), ...x } = a()) { + var a; +} + +const x = ""; + +function c({ b, ...c } = a(), d = x) { + var x; +} \ No newline at end of file From 689822c1838dd0462f9fb514bad5e94fc96fb68e Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 24 Apr 2020 09:52:18 -0700 Subject: [PATCH 23/38] convertToAsyncFunction: Disable for `.then` with both fulfillment and rejection handlers (#38152) * Disable convert to async for `.then` with both fulfillment and rejection handlers * Delete baselines * Also disable refactor for 3+ arguments --- src/services/suggestionDiagnostics.ts | 13 ++++++++- .../services/convertToAsyncFunction.ts | 13 ++++++--- .../convertToAsyncFunction_Rej.ts | 17 ----------- .../convertToAsyncFunction_RejNoBrackets.ts | 17 ----------- .../convertToAsyncFunction_RejRef.ts | 29 ------------------- ...onvertToAsyncFunction_ResRejNoArgsArrow.js | 17 ----------- ...onvertToAsyncFunction_ResRejNoArgsArrow.ts | 17 ----------- 7 files changed, 21 insertions(+), 102 deletions(-) delete mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Rej.ts delete mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejNoBrackets.ts delete mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejRef.ts delete mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.js delete mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.ts diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index a80bd58c6d7..09607d8ab8a 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -156,7 +156,18 @@ namespace ts { } function isPromiseHandler(node: Node): node is CallExpression { - return isCallExpression(node) && (hasPropertyAccessExpressionWithName(node, "then") || hasPropertyAccessExpressionWithName(node, "catch")); + return isCallExpression(node) && ( + hasPropertyAccessExpressionWithName(node, "then") && hasSupportedNumberOfArguments(node) || + hasPropertyAccessExpressionWithName(node, "catch")); + } + + function hasSupportedNumberOfArguments(node: CallExpression) { + if (node.arguments.length > 2) return false; + if (node.arguments.length < 2) return true; + return some(node.arguments, arg => { + return arg.kind === SyntaxKind.NullKeyword || + isIdentifier(arg) && arg.text === "undefined"; + }); } // should be kept up to date with getTransformationBody in convertToAsyncFunction.ts diff --git a/src/testRunner/unittests/services/convertToAsyncFunction.ts b/src/testRunner/unittests/services/convertToAsyncFunction.ts index 2a362316075..999e1580a98 100644 --- a/src/testRunner/unittests/services/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/services/convertToAsyncFunction.ts @@ -558,13 +558,13 @@ function [#|f|]():void{ } ` ); - _testConvertToAsyncFunction("convertToAsyncFunction_Rej", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Rej", ` function [#|f|]():Promise { return fetch('https://typescriptlang.org').then(result => { console.log(result); }, rejection => { console.log("rejected:", rejection); }); } ` ); - _testConvertToAsyncFunction("convertToAsyncFunction_RejRef", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_RejRef", ` function [#|f|]():Promise { return fetch('https://typescriptlang.org').then(res, rej); } @@ -576,7 +576,7 @@ function rej(err){ } ` ); - _testConvertToAsyncFunction("convertToAsyncFunction_RejNoBrackets", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_RejNoBrackets", ` function [#|f|]():Promise { return fetch('https://typescriptlang.org').then(result => console.log(result), rejection => console.log("rejected:", rejection)); } @@ -1238,7 +1238,7 @@ function [#|f|]() { } `); - _testConvertToAsyncFunction("convertToAsyncFunction_ResRejNoArgsArrow", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_ResRejNoArgsArrow", ` function [#|f|]() { return Promise.resolve().then(() => 1, () => "a"); } @@ -1436,5 +1436,10 @@ function [#|get|]() { .catch>(() => ({ success: false })); } `); + + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_threeArguments", ` +function [#|f|]() { + return Promise.resolve().then(undefined, undefined, () => 1); +}`); }); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Rej.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Rej.ts deleted file mode 100644 index bf3ee9c420c..00000000000 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Rej.ts +++ /dev/null @@ -1,17 +0,0 @@ -// ==ORIGINAL== - -function /*[#|*/f/*|]*/():Promise { - return fetch('https://typescriptlang.org').then(result => { console.log(result); }, rejection => { console.log("rejected:", rejection); }); -} - -// ==ASYNC FUNCTION::Convert to async function== - -async function f():Promise { - try { - const result = await fetch('https://typescriptlang.org'); - console.log(result); - } - catch (rejection) { - console.log("rejected:", rejection); - } -} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejNoBrackets.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejNoBrackets.ts deleted file mode 100644 index 8169745f5bd..00000000000 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejNoBrackets.ts +++ /dev/null @@ -1,17 +0,0 @@ -// ==ORIGINAL== - -function /*[#|*/f/*|]*/():Promise { - return fetch('https://typescriptlang.org').then(result => console.log(result), rejection => console.log("rejected:", rejection)); -} - -// ==ASYNC FUNCTION::Convert to async function== - -async function f():Promise { - try { - const result = await fetch('https://typescriptlang.org'); - return console.log(result); - } - catch (rejection) { - return console.log("rejected:", rejection); - } -} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejRef.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejRef.ts deleted file mode 100644 index 77fadff7ee9..00000000000 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_RejRef.ts +++ /dev/null @@ -1,29 +0,0 @@ -// ==ORIGINAL== - -function /*[#|*/f/*|]*/():Promise { - return fetch('https://typescriptlang.org').then(res, rej); -} -function res(result){ - console.log(result); -} -function rej(err){ - console.log(err); -} - -// ==ASYNC FUNCTION::Convert to async function== - -async function f():Promise { - try { - const result = await fetch('https://typescriptlang.org'); - return res(result); - } - catch (err) { - return rej(err); - } -} -function res(result){ - console.log(result); -} -function rej(err){ - console.log(err); -} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.js deleted file mode 100644 index 0b4a430f505..00000000000 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.js +++ /dev/null @@ -1,17 +0,0 @@ -// ==ORIGINAL== - - function /*[#|*/f/*|]*/() { - return Promise.resolve().then(() => 1, () => "a"); - } - -// ==ASYNC FUNCTION::Convert to async function== - - async function f() { - try { - await Promise.resolve(); - return 1; - } - catch (e) { - return "a"; - } - } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.ts deleted file mode 100644 index 0b4a430f505..00000000000 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_ResRejNoArgsArrow.ts +++ /dev/null @@ -1,17 +0,0 @@ -// ==ORIGINAL== - - function /*[#|*/f/*|]*/() { - return Promise.resolve().then(() => 1, () => "a"); - } - -// ==ASYNC FUNCTION::Convert to async function== - - async function f() { - try { - await Promise.resolve(); - return 1; - } - catch (e) { - return "a"; - } - } From 38ff7762ec3b9eccf63161ddb449ab9a86975401 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 24 Apr 2020 12:10:29 -0700 Subject: [PATCH 24/38] Fix temp variable scoping in async generators (#38121) --- src/compiler/transformers/es2018.ts | 2 +- ...OperatorInAsyncGenerator(target=es2015).js | 21 ++++++++++++ ...ingOperatorInAsyncGenerator(target=es5).js | 33 +++++++++++++++++++ ...OperatorInAsyncGenerator(target=esnext).js | 18 ++++++++++ ...llishCoalescingOperatorInAsyncGenerator.ts | 12 +++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es2015).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es5).js create mode 100644 tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=esnext).js create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInAsyncGenerator.ts diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index 9050ebc601b..a3ae750f6e7 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -1115,7 +1115,7 @@ namespace ts { context.requestEmitHelper(asyncGeneratorHelper); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return createCall( getUnscopedHelperName("__asyncGenerator"), diff --git a/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es2015).js b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es2015).js new file mode 100644 index 00000000000..6cbc459a37f --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es2015).js @@ -0,0 +1,21 @@ +//// [nullishCoalescingOperatorInAsyncGenerator.ts] +// https://github.com/microsoft/TypeScript/issues/37686 +async function* f(a: { b?: number }) { + let c = a.b ?? 10; + while (c) { + yield c--; + } +} + + +//// [nullishCoalescingOperatorInAsyncGenerator.js] +// https://github.com/microsoft/TypeScript/issues/37686 +function f(a) { + var _a; + return __asyncGenerator(this, arguments, function* f_1() { + let c = (_a = a.b) !== null && _a !== void 0 ? _a : 10; + while (c) { + yield yield __await(c--); + } + }); +} diff --git a/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es5).js b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es5).js new file mode 100644 index 00000000000..972189a54d3 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=es5).js @@ -0,0 +1,33 @@ +//// [nullishCoalescingOperatorInAsyncGenerator.ts] +// https://github.com/microsoft/TypeScript/issues/37686 +async function* f(a: { b?: number }) { + let c = a.b ?? 10; + while (c) { + yield c--; + } +} + + +//// [nullishCoalescingOperatorInAsyncGenerator.js] +// https://github.com/microsoft/TypeScript/issues/37686 +function f(a) { + var _a; + return __asyncGenerator(this, arguments, function f_1() { + var c; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + c = (_a = a.b) !== null && _a !== void 0 ? _a : 10; + _b.label = 1; + case 1: + if (!c) return [3 /*break*/, 4]; + return [4 /*yield*/, __await(c--)]; + case 2: return [4 /*yield*/, _b.sent()]; + case 3: + _b.sent(); + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=esnext).js b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=esnext).js new file mode 100644 index 00000000000..430355c3d42 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperatorInAsyncGenerator(target=esnext).js @@ -0,0 +1,18 @@ +//// [nullishCoalescingOperatorInAsyncGenerator.ts] +// https://github.com/microsoft/TypeScript/issues/37686 +async function* f(a: { b?: number }) { + let c = a.b ?? 10; + while (c) { + yield c--; + } +} + + +//// [nullishCoalescingOperatorInAsyncGenerator.js] +// https://github.com/microsoft/TypeScript/issues/37686 +async function* f(a) { + let c = a.b ?? 10; + while (c) { + yield c--; + } +} diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInAsyncGenerator.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInAsyncGenerator.ts new file mode 100644 index 00000000000..54f6923c3e6 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperatorInAsyncGenerator.ts @@ -0,0 +1,12 @@ +// @target: esnext,es2015,es5 +// @lib: esnext +// @noEmitHelpers: true +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/37686 +async function* f(a: { b?: number }) { + let c = a.b ?? 10; + while (c) { + yield c--; + } +} From fe140acc09b9dbe98cdc4f5cbc100b3bbaab8bed Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 24 Apr 2020 13:02:17 -0700 Subject: [PATCH 25/38] Fix truthiness call check for this-property access (#38163) --- src/compiler/checker.ts | 4 +++- .../truthinessCallExpressionCoercion1.errors.txt | 5 +++++ .../reference/truthinessCallExpressionCoercion1.js | 9 +++++++++ .../truthinessCallExpressionCoercion1.symbols | 12 ++++++++++++ .../truthinessCallExpressionCoercion1.types | 13 +++++++++++++ .../compiler/truthinessCallExpressionCoercion1.ts | 5 +++++ 6 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52a667a1451..e1cda181eee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31909,7 +31909,9 @@ namespace ts { let childExpression = childNode.parent; while (testedExpression && childExpression) { - if (isIdentifier(testedExpression) && isIdentifier(childExpression)) { + if (isIdentifier(testedExpression) && isIdentifier(childExpression) || + testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword + ) { return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression); } diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt index 6a32d1f050a..e30041e220a 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt @@ -80,6 +80,11 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(61,9): error TS2774: T // ok this.maybeIsUser ? console.log('this.maybeIsUser') : undefined; + + // ok + if (this.isUser) { + this.isUser(); + } } } \ No newline at end of file diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.js b/tests/baselines/reference/truthinessCallExpressionCoercion1.js index 4415cedf596..ecb76aadf89 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.js +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.js @@ -63,6 +63,11 @@ class Foo { // ok this.maybeIsUser ? console.log('this.maybeIsUser') : undefined; + + // ok + if (this.isUser) { + this.isUser(); + } } } @@ -117,6 +122,10 @@ var Foo = /** @class */ (function () { this.isUser ? console.log('this.isUser') : undefined; // ok this.maybeIsUser ? console.log('this.maybeIsUser') : undefined; + // ok + if (this.isUser) { + this.isUser(); + } }; return Foo; }()); diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.symbols b/tests/baselines/reference/truthinessCallExpressionCoercion1.symbols index 1f729481ac6..aace0d3c556 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.symbols +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.symbols @@ -170,6 +170,18 @@ class Foo { >console : Symbol(console, Decl(lib.dom.d.ts, --, --)) >log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) >undefined : Symbol(undefined) + + // ok + if (this.isUser) { +>this.isUser : Symbol(Foo.isUser, Decl(truthinessCallExpressionCoercion1.ts, 52, 32)) +>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion1.ts, 49, 1)) +>isUser : Symbol(Foo.isUser, Decl(truthinessCallExpressionCoercion1.ts, 52, 32)) + + this.isUser(); +>this.isUser : Symbol(Foo.isUser, Decl(truthinessCallExpressionCoercion1.ts, 52, 32)) +>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion1.ts, 49, 1)) +>isUser : Symbol(Foo.isUser, Decl(truthinessCallExpressionCoercion1.ts, 52, 32)) + } } } diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.types b/tests/baselines/reference/truthinessCallExpressionCoercion1.types index 8c53f481c42..bcbde0d35f6 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.types +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.types @@ -223,6 +223,19 @@ class Foo { >log : (...data: any[]) => void >'this.maybeIsUser' : "this.maybeIsUser" >undefined : undefined + + // ok + if (this.isUser) { +>this.isUser : () => boolean +>this : this +>isUser : () => boolean + + this.isUser(); +>this.isUser() : boolean +>this.isUser : () => boolean +>this : this +>isUser : () => boolean + } } } diff --git a/tests/cases/compiler/truthinessCallExpressionCoercion1.ts b/tests/cases/compiler/truthinessCallExpressionCoercion1.ts index 04331cbeadd..6835a434aa4 100644 --- a/tests/cases/compiler/truthinessCallExpressionCoercion1.ts +++ b/tests/cases/compiler/truthinessCallExpressionCoercion1.ts @@ -64,5 +64,10 @@ class Foo { // ok this.maybeIsUser ? console.log('this.maybeIsUser') : undefined; + + // ok + if (this.isUser) { + this.isUser(); + } } } From 1785d6c707248ae1225f0e4797300f5f210f40f8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 24 Apr 2020 13:10:34 -0700 Subject: [PATCH 26/38] Special-case export assigned namespaces in getSpecifierForModuleSymbol so they behave like their containing module symbol (#38151) --- src/compiler/checker.ts | 18 +++- ...nedNamespaceNoTripleSlashTypesReference.js | 82 +++++++++++++++++++ ...mespaceNoTripleSlashTypesReference.symbols | 71 ++++++++++++++++ ...NamespaceNoTripleSlashTypesReference.types | 61 ++++++++++++++ ...nedNamespaceNoTripleSlashTypesReference.ts | 36 ++++++++ 5 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.js create mode 100644 tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.symbols create mode 100644 tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.types create mode 100644 tests/cases/compiler/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1cda181eee..b69320f2e4f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3517,12 +3517,16 @@ namespace ts { return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined); function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) { - const fileSymbol = getExternalModuleContainer(d); - const exported = fileSymbol && fileSymbol.exports && fileSymbol.exports.get(InternalSymbolName.ExportEquals); - return exported && container && getSymbolIfSameReference(exported, container) ? fileSymbol : undefined; + return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container); } } + function getFileSymbolIfFileSymbolExportEqualsContainer(d: Declaration, container: Symbol) { + const fileSymbol = getExternalModuleContainer(d); + const exported = fileSymbol && fileSymbol.exports && fileSymbol.exports.get(InternalSymbolName.ExportEquals); + return exported && getSymbolIfSameReference(exported, container) ? fileSymbol : undefined; + } + function getAliasForSymbolInContainer(container: Symbol, symbol: Symbol) { if (container === getParentOfSymbol(symbol)) { // fast path, `symbol` is either already the alias or isn't aliased @@ -5138,7 +5142,13 @@ namespace ts { } function getSpecifierForModuleSymbol(symbol: Symbol, context: NodeBuilderContext) { - const file = getDeclarationOfKind(symbol, SyntaxKind.SourceFile); + let file = getDeclarationOfKind(symbol, SyntaxKind.SourceFile); + if (!file) { + const equivalentFileSymbol = firstDefined(symbol.declarations, d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol)); + if (equivalentFileSymbol) { + file = getDeclarationOfKind(equivalentFileSymbol, SyntaxKind.SourceFile); + } + } if (file && file.moduleName !== undefined) { // Use the amd name if it is available return file.moduleName; diff --git a/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.js b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.js new file mode 100644 index 00000000000..8f147063de0 --- /dev/null +++ b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.js @@ -0,0 +1,82 @@ +//// [tests/cases/compiler/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts] //// + +//// [index.d.ts] +export = React; + +declare namespace React { + export type Component = { x: T, y: U, z: V }; + export interface DOMAttributes { } +} +//// [index.d.ts] +import { + Component +} from 'react' +export {}; + +declare module 'react' { + interface DOMAttributes { + css?: any + } +} + +//// [get-comp.ts] +import {Component} from 'react'; + +export function getComp(): Component { + return {} as any as Component +} +//// [inferred-comp-export.ts] +import { getComp } from "./get-comp"; + +// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it +// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder +export const obj = { + comp: getComp() +} +//// [some-other-file.ts] +export * from '@emotion/core'; + + +//// [get-comp.js] +"use strict"; +exports.__esModule = true; +exports.getComp = void 0; +function getComp() { + return {}; +} +exports.getComp = getComp; +//// [inferred-comp-export.js] +"use strict"; +exports.__esModule = true; +exports.obj = void 0; +var get_comp_1 = require("./get-comp"); +// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it +// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder +exports.obj = { + comp: get_comp_1.getComp() +}; +//// [some-other-file.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); +} +exports.__esModule = true; +__exportStar(require("@emotion/core"), exports); + + +//// [get-comp.d.ts] +import { Component } from 'react'; +export declare function getComp(): Component; +//// [inferred-comp-export.d.ts] +export declare const obj: { + comp: import("react").Component; +}; +//// [some-other-file.d.ts] +export * from '@emotion/core'; diff --git a/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.symbols b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.symbols new file mode 100644 index 00000000000..87304e8e84f --- /dev/null +++ b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.symbols @@ -0,0 +1,71 @@ +=== tests/cases/compiler/node_modules/@types/react/index.d.ts === +export = React; +>React : Symbol(React, Decl(index.d.ts, 0, 15), Decl(index.d.ts, 3, 10)) + +declare namespace React { +>React : Symbol(React, Decl(index.d.ts, 0, 15), Decl(index.d.ts, 3, 10)) + + export type Component = { x: T, y: U, z: V }; +>Component : Symbol(Component, Decl(index.d.ts, 2, 25)) +>T : Symbol(T, Decl(index.d.ts, 3, 26)) +>U : Symbol(U, Decl(index.d.ts, 3, 34)) +>V : Symbol(V, Decl(index.d.ts, 3, 42)) +>x : Symbol(x, Decl(index.d.ts, 3, 54)) +>T : Symbol(T, Decl(index.d.ts, 3, 26)) +>y : Symbol(y, Decl(index.d.ts, 3, 60)) +>U : Symbol(U, Decl(index.d.ts, 3, 34)) +>z : Symbol(z, Decl(index.d.ts, 3, 66)) +>V : Symbol(V, Decl(index.d.ts, 3, 42)) + + export interface DOMAttributes { } +>DOMAttributes : Symbol(DOMAttributes, Decl(index.d.ts, 3, 74), Decl(index.d.ts, 5, 24)) +>T : Symbol(T, Decl(index.d.ts, 4, 35), Decl(index.d.ts, 6, 28)) +} +=== tests/cases/compiler/node_modules/@emotion/core/index.d.ts === +import { + Component +>Component : Symbol(Component, Decl(index.d.ts, 0, 8)) + +} from 'react' +export {}; + +declare module 'react' { +>'react' : Symbol(React, Decl(index.d.ts, 0, 15), Decl(index.d.ts, 3, 10)) + + interface DOMAttributes { +>DOMAttributes : Symbol(DOMAttributes, Decl(index.d.ts, 3, 74), Decl(index.d.ts, 5, 24)) +>T : Symbol(T, Decl(index.d.ts, 4, 35), Decl(index.d.ts, 6, 28)) + + css?: any +>css : Symbol(DOMAttributes.css, Decl(index.d.ts, 6, 32)) + } +} + +=== tests/cases/compiler/src/get-comp.ts === +import {Component} from 'react'; +>Component : Symbol(Component, Decl(get-comp.ts, 0, 8)) + +export function getComp(): Component { +>getComp : Symbol(getComp, Decl(get-comp.ts, 0, 32)) +>Component : Symbol(Component, Decl(get-comp.ts, 0, 8)) + + return {} as any as Component +>Component : Symbol(Component, Decl(get-comp.ts, 0, 8)) +} +=== tests/cases/compiler/src/inferred-comp-export.ts === +import { getComp } from "./get-comp"; +>getComp : Symbol(getComp, Decl(inferred-comp-export.ts, 0, 8)) + +// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it +// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder +export const obj = { +>obj : Symbol(obj, Decl(inferred-comp-export.ts, 4, 12)) + + comp: getComp() +>comp : Symbol(comp, Decl(inferred-comp-export.ts, 4, 20)) +>getComp : Symbol(getComp, Decl(inferred-comp-export.ts, 0, 8)) +} +=== tests/cases/compiler/src/some-other-file.ts === +export * from '@emotion/core'; +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.types b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.types new file mode 100644 index 00000000000..c3232b4406e --- /dev/null +++ b/tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.types @@ -0,0 +1,61 @@ +=== tests/cases/compiler/node_modules/@types/react/index.d.ts === +export = React; +>React : any + +declare namespace React { + export type Component = { x: T, y: U, z: V }; +>Component : Component +>x : T +>y : U +>z : V + + export interface DOMAttributes { } +} +=== tests/cases/compiler/node_modules/@emotion/core/index.d.ts === +import { + Component +>Component : any + +} from 'react' +export {}; + +declare module 'react' { +>'react' : error + + interface DOMAttributes { + css?: any +>css : any + } +} + +=== tests/cases/compiler/src/get-comp.ts === +import {Component} from 'react'; +>Component : any + +export function getComp(): Component { +>getComp : () => Component + + return {} as any as Component +>{} as any as Component : Component +>{} as any : any +>{} : {} +} +=== tests/cases/compiler/src/inferred-comp-export.ts === +import { getComp } from "./get-comp"; +>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component + +// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it +// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder +export const obj = { +>obj : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component; } +>{ comp: getComp()} : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component; } + + comp: getComp() +>comp : import("tests/cases/compiler/node_modules/@types/react/index").Component +>getComp() : import("tests/cases/compiler/node_modules/@types/react/index").Component +>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component +} +=== tests/cases/compiler/src/some-other-file.ts === +export * from '@emotion/core'; +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/cases/compiler/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts b/tests/cases/compiler/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts new file mode 100644 index 00000000000..a71625b77e4 --- /dev/null +++ b/tests/cases/compiler/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.ts @@ -0,0 +1,36 @@ +// @declaration: true +// @filename: node_modules/@types/react/index.d.ts +export = React; + +declare namespace React { + export type Component = { x: T, y: U, z: V }; + export interface DOMAttributes { } +} +// @filename: node_modules/@emotion/core/index.d.ts +import { + Component +} from 'react' +export {}; + +declare module 'react' { + interface DOMAttributes { + css?: any + } +} + +// @filename: src/get-comp.ts +import {Component} from 'react'; + +export function getComp(): Component { + return {} as any as Component +} +// @filename: src/inferred-comp-export.ts +import { getComp } from "./get-comp"; + +// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it +// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder +export const obj = { + comp: getComp() +} +// @filename: src/some-other-file.ts +export * from '@emotion/core'; From ce95d9ca6be1526ffea041150141f9de4ed4b4e6 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 24 Apr 2020 13:49:48 -0700 Subject: [PATCH 27/38] Fix values and types merging in JS module exports (#37896) * Fix values and types merging in JS module exports * Fix everything * Share `setValueDeclaration` between binder (local merge) and checker (cross-file merge) * Revert accidental changes to baselines * Update baseline from master merge --- src/compiler/binder.ts | 10 ---- src/compiler/checker.ts | 45 +++++++++++++----- src/compiler/utilities.ts | 11 +++++ ...DeclarationsClassExtendsVisibility.symbols | 2 +- .../jsDeclarationsClassStatic.symbols | 2 +- .../jsDeclarationsCrossfileMerge.symbols | 2 +- ...nedClassExpressionAnonymousWithSub.symbols | 2 +- ...rtAssignedClassExpressionShadowing.symbols | 2 +- ...jsDeclarationsExportSubAssignments.symbols | 2 +- ...MemberMergedWithModuleAugmentation.symbols | 43 +++++++++++++++++ ...rtMemberMergedWithModuleAugmentation.types | 46 +++++++++++++++++++ ...erMergedWithModuleAugmentation2.errors.txt | 27 +++++++++++ ...emberMergedWithModuleAugmentation2.symbols | 25 ++++++++++ ...tMemberMergedWithModuleAugmentation2.types | 31 +++++++++++++ .../reference/moduleExportAlias2.symbols | 2 +- .../reference/moduleExportAlias4.symbols | 2 +- .../moduleExportAliasImported.symbols | 2 +- ...uleExportPropertyAssignmentDefault.symbols | 2 +- ...xportWithExportPropertyAssignment3.symbols | 12 ++--- ...xportWithExportPropertyAssignment4.symbols | 6 +-- .../reference/typedefCrossModule2.types | 26 +++++------ .../reference/typedefCrossModule4.types | 8 ++-- ...xportMemberMergedWithModuleAugmentation.ts | 26 +++++++++++ ...portMemberMergedWithModuleAugmentation2.ts | 17 +++++++ ...mpletionsImportModuleAugmentationWithJS.ts | 41 +++++++++++++++++ 25 files changed, 337 insertions(+), 57 deletions(-) create mode 100644 tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.symbols create mode 100644 tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.types create mode 100644 tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.errors.txt create mode 100644 tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.symbols create mode 100644 tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.types create mode 100644 tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation.ts create mode 100644 tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation2.ts create mode 100644 tests/cases/fourslash/completionsImportModuleAugmentationWithJS.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 3cde8be7ea1..356b2fd18f6 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -320,16 +320,6 @@ namespace ts { } } - function setValueDeclaration(symbol: Symbol, node: Declaration): void { - const { valueDeclaration } = symbol; - if (!valueDeclaration || - (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || - (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) { - // other kinds of value declarations take precedence over modules and assignment declarations - symbol.valueDeclaration = node; - } - } - // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. function getDeclarationName(node: Declaration): __String | undefined { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b69320f2e4f..f5754baff48 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1115,12 +1115,8 @@ namespace ts { target.constEnumOnlyModule = false; } target.flags |= source.flags; - if (source.valueDeclaration && - (!target.valueDeclaration || - isAssignmentDeclaration(target.valueDeclaration) && !isAssignmentDeclaration(source.valueDeclaration) || - isEffectiveModuleDeclaration(target.valueDeclaration) && !isEffectiveModuleDeclaration(source.valueDeclaration))) { - // other kinds of value declarations take precedence over modules and assignment declarations - target.valueDeclaration = source.valueDeclaration; + if (source.valueDeclaration) { + setValueDeclaration(target, source.valueDeclaration); } addRange(target.declarations, source.declarations); if (source.members) { @@ -7724,11 +7720,38 @@ namespace ts { resolvedSymbol.exports = createSymbolTable(); } (resolvedSymbol || symbol).exports!.forEach((s, name) => { - if (members.has(name)) { - const exportedMember = exportedType.members.get(name)!; - const union = createSymbol(s.flags | exportedMember.flags, name); - union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); - members.set(name, union); + const exportedMember = members.get(name)!; + if (exportedMember && exportedMember !== s) { + if (s.flags & SymbolFlags.Value) { + // If the member has an additional value-like declaration, union the types from the two declarations, + // but issue an error if they occurred in two different files. The purpose is to support a JS file with + // a pattern like: + // + // module.exports = { a: true }; + // module.exports.a = 3; + // + // but we may have a JS file with `module.exports = { a: true }` along with a TypeScript module augmentation + // declaring an `export const a: number`. In that case, we issue a duplicate identifier error, because + // it's unclear what that's supposed to mean, so it's probably a mistake. + if (getSourceFileOfNode(s.valueDeclaration) !== getSourceFileOfNode(exportedMember.valueDeclaration)) { + const unescapedName = unescapeLeadingUnderscores(s.escapedName); + const exportedMemberName = tryCast(exportedMember.valueDeclaration, isNamedDeclaration)?.name || exportedMember.valueDeclaration; + addRelatedInfo( + error(s.valueDeclaration, Diagnostics.Duplicate_identifier_0, unescapedName), + createDiagnosticForNode(exportedMemberName, Diagnostics._0_was_also_declared_here, unescapedName)); + addRelatedInfo( + error(exportedMemberName, Diagnostics.Duplicate_identifier_0, unescapedName), + createDiagnosticForNode(s.valueDeclaration, Diagnostics._0_was_also_declared_here, unescapedName)); + } + const union = createSymbol(s.flags | exportedMember.flags, name); + union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); + union.valueDeclaration = exportedMember.valueDeclaration; + union.declarations = concatenate(exportedMember.declarations, s.declarations); + members.set(name, union); + } + else { + members.set(name, mergeSymbol(s, exportedMember)); + } } else { members.set(name, s); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9e1d338d8d7..97231acf60b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2314,6 +2314,17 @@ namespace ts { !!getJSDocTypeTag(expr.parent); } + export function setValueDeclaration(symbol: Symbol, node: Declaration): void { + const { valueDeclaration } = symbol; + if (!valueDeclaration || + !(node.flags & NodeFlags.Ambient && !(valueDeclaration.flags & NodeFlags.Ambient)) && + (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || + (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) { + // other kinds of value declarations take precedence over modules and assignment declarations + symbol.valueDeclaration = node; + } + } + export function isFunctionSymbol(symbol: Symbol | undefined) { if (!symbol || !symbol.valueDeclaration) { return false; diff --git a/tests/baselines/reference/jsDeclarationsClassExtendsVisibility.symbols b/tests/baselines/reference/jsDeclarationsClassExtendsVisibility.symbols index cbf083c36f8..a59d302e7f0 100644 --- a/tests/baselines/reference/jsDeclarationsClassExtendsVisibility.symbols +++ b/tests/baselines/reference/jsDeclarationsClassExtendsVisibility.symbols @@ -25,7 +25,7 @@ module.exports = Foo; >Foo : Symbol(Foo, Decl(cls.js, 4, 2)) module.exports.Strings = Strings; ->module.exports.Strings : Symbol(Strings) +>module.exports.Strings : Symbol(Strings, Decl(cls.js, 6, 21)) >module.exports : Symbol(Strings, Decl(cls.js, 6, 21)) >module : Symbol(module, Decl(cls.js, 5, 24)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/cls", Decl(cls.js, 0, 0)) diff --git a/tests/baselines/reference/jsDeclarationsClassStatic.symbols b/tests/baselines/reference/jsDeclarationsClassStatic.symbols index d79d144e509..8687099bbe3 100644 --- a/tests/baselines/reference/jsDeclarationsClassStatic.symbols +++ b/tests/baselines/reference/jsDeclarationsClassStatic.symbols @@ -34,7 +34,7 @@ module.exports = Handler; >Handler : Symbol(Handler, Decl(source.js, 0, 0), Decl(source.js, 7, 1)) module.exports.Strings = Strings ->module.exports.Strings : Symbol(Strings) +>module.exports.Strings : Symbol(Strings, Decl(source.js, 14, 25)) >module.exports : Symbol(Strings, Decl(source.js, 14, 25)) >module : Symbol(module, Decl(source.js, 12, 1)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/source", Decl(source.js, 0, 0)) diff --git a/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols b/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols index 99455853c4c..64753e212be 100644 --- a/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols +++ b/tests/baselines/reference/jsDeclarationsCrossfileMerge.symbols @@ -13,7 +13,7 @@ module.exports = m.default; >default : Symbol(default, Decl(exporter.js, 0, 22)) module.exports.memberName = "thing"; ->module.exports.memberName : Symbol(memberName) +>module.exports.memberName : Symbol(memberName, Decl(index.js, 2, 27)) >module.exports : Symbol(memberName, Decl(index.js, 2, 27)) >module : Symbol(module, Decl(index.js, 0, 32)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0)) diff --git a/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionAnonymousWithSub.symbols b/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionAnonymousWithSub.symbols index 228bb10cccc..aa5df49712f 100644 --- a/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionAnonymousWithSub.symbols +++ b/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionAnonymousWithSub.symbols @@ -18,7 +18,7 @@ module.exports = class { } } module.exports.Sub = class { ->module.exports.Sub : Symbol(Sub) +>module.exports.Sub : Symbol(Sub, Decl(index.js, 7, 1)) >module.exports : Symbol(Sub, Decl(index.js, 7, 1)) >module : Symbol(module, Decl(index.js, 0, 0), Decl(index.js, 10, 27)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0)) diff --git a/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionShadowing.symbols b/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionShadowing.symbols index 40a6fb56147..a911c06ee2e 100644 --- a/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionShadowing.symbols +++ b/tests/baselines/reference/jsDeclarationsExportAssignedClassExpressionShadowing.symbols @@ -27,7 +27,7 @@ module.exports = class Q { } } module.exports.Another = Q; ->module.exports.Another : Symbol(Another) +>module.exports.Another : Symbol(Another, Decl(index.js, 10, 1)) >module.exports : Symbol(Another, Decl(index.js, 10, 1)) >module : Symbol(module, Decl(index.js, 5, 1)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0)) diff --git a/tests/baselines/reference/jsDeclarationsExportSubAssignments.symbols b/tests/baselines/reference/jsDeclarationsExportSubAssignments.symbols index a764b8e99d7..5939221ce90 100644 --- a/tests/baselines/reference/jsDeclarationsExportSubAssignments.symbols +++ b/tests/baselines/reference/jsDeclarationsExportSubAssignments.symbols @@ -19,7 +19,7 @@ module.exports = Foo; >Foo : Symbol(Foo, Decl(cls.js, 3, 2)) module.exports.Strings = Strings; ->module.exports.Strings : Symbol(Strings) +>module.exports.Strings : Symbol(Strings, Decl(cls.js, 5, 21)) >module.exports : Symbol(Strings, Decl(cls.js, 5, 21)) >module : Symbol(module, Decl(cls.js, 4, 12)) >exports : Symbol("tests/cases/conformance/jsdoc/declarations/cls", Decl(cls.js, 0, 0)) diff --git a/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.symbols b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.symbols new file mode 100644 index 00000000000..e11817cab0b --- /dev/null +++ b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.symbols @@ -0,0 +1,43 @@ +=== /test.js === +class Abcde { +>Abcde : Symbol(Abcde, Decl(test.js, 0, 0)) + + /** @type {string} */ + x; +>x : Symbol(Abcde.x, Decl(test.js, 0, 13)) +} + +module.exports = { +>module.exports : Symbol("/test", Decl(test.js, 0, 0)) +>module : Symbol("/test.js", Decl(test.js, 3, 1), Decl(index.ts, 0, 31)) +>exports : Symbol("/test.js", Decl(test.js, 3, 1), Decl(index.ts, 0, 31)) + + Abcde +>Abcde : Symbol(Abcde, Decl(test.js, 5, 18)) + +}; + +=== /index.ts === +import { Abcde } from "./test"; +>Abcde : Symbol(Abcde, Decl(index.ts, 0, 8)) + +declare module "./test" { +>"./test" : Symbol("/test.js", Decl(test.js, 3, 1), Decl(index.ts, 0, 31)) + + interface Abcde { b: string } +>Abcde : Symbol(Abcde, Decl(index.ts, 2, 25), Decl(test.js, 5, 18)) +>b : Symbol(Abcde.b, Decl(index.ts, 3, 19)) +} + +new Abcde().x; +>new Abcde().x : Symbol(Abcde.x, Decl(test.js, 0, 13)) +>Abcde : Symbol(Abcde, Decl(index.ts, 0, 8)) +>x : Symbol(Abcde.x, Decl(test.js, 0, 13)) + +// Bug: the type meaning from /test.js does not +// propagate through the object literal export. +const x: Abcde = { b: "" }; +>x : Symbol(x, Decl(index.ts, 10, 5)) +>Abcde : Symbol(Abcde, Decl(index.ts, 0, 8)) +>b : Symbol(b, Decl(index.ts, 10, 18)) + diff --git a/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.types b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.types new file mode 100644 index 00000000000..e53d62ff173 --- /dev/null +++ b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation.types @@ -0,0 +1,46 @@ +=== /test.js === +class Abcde { +>Abcde : Abcde + + /** @type {string} */ + x; +>x : string +} + +module.exports = { +>module.exports = { Abcde} : { Abcde: typeof Abcde; } +>module.exports : { Abcde: typeof Abcde; } +>module : { "\"/test\"": { Abcde: typeof Abcde; }; } +>exports : { Abcde: typeof Abcde; } +>{ Abcde} : { Abcde: typeof Abcde; } + + Abcde +>Abcde : typeof Abcde + +}; + +=== /index.ts === +import { Abcde } from "./test"; +>Abcde : typeof Abcde + +declare module "./test" { +>"./test" : { Abcde: typeof Abcde; } + + interface Abcde { b: string } +>b : string +} + +new Abcde().x; +>new Abcde().x : string +>new Abcde() : Abcde +>Abcde : typeof Abcde +>x : string + +// Bug: the type meaning from /test.js does not +// propagate through the object literal export. +const x: Abcde = { b: "" }; +>x : Abcde +>{ b: "" } : { b: string; } +>b : string +>"" : "" + diff --git a/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.errors.txt b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.errors.txt new file mode 100644 index 00000000000..44a0efae0da --- /dev/null +++ b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.errors.txt @@ -0,0 +1,27 @@ +/index.ts(4,16): error TS2300: Duplicate identifier 'a'. +/index.ts(7,3): error TS2339: Property 'toFixed' does not exist on type 'string'. +/test.js(2,3): error TS2300: Duplicate identifier 'a'. + + +==== /test.js (1 errors) ==== + module.exports = { + a: "ok" + ~ +!!! error TS2300: Duplicate identifier 'a'. +!!! related TS6203 /index.ts:4:16: 'a' was also declared here. + }; + +==== /index.ts (2 errors) ==== + import { a } from "./test"; + + declare module "./test" { + export const a: number; + ~ +!!! error TS2300: Duplicate identifier 'a'. +!!! related TS6203 /test.js:2:3: 'a' was also declared here. + } + + a.toFixed(); + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.symbols b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.symbols new file mode 100644 index 00000000000..02da41d876c --- /dev/null +++ b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.symbols @@ -0,0 +1,25 @@ +=== /test.js === +module.exports = { +>module.exports : Symbol("/test", Decl(test.js, 0, 0)) +>module : Symbol("/test.js", Decl(test.js, 0, 0), Decl(index.ts, 0, 27)) +>exports : Symbol("/test.js", Decl(test.js, 0, 0), Decl(index.ts, 0, 27)) + + a: "ok" +>a : Symbol(a, Decl(test.js, 0, 18)) + +}; + +=== /index.ts === +import { a } from "./test"; +>a : Symbol(a, Decl(index.ts, 0, 8)) + +declare module "./test" { +>"./test" : Symbol("/test.js", Decl(test.js, 0, 0), Decl(index.ts, 0, 27)) + + export const a: number; +>a : Symbol(a, Decl(index.ts, 3, 14)) +} + +a.toFixed(); +>a : Symbol(a, Decl(index.ts, 0, 8)) + diff --git a/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.types b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.types new file mode 100644 index 00000000000..fa6e940f60b --- /dev/null +++ b/tests/baselines/reference/jsExportMemberMergedWithModuleAugmentation2.types @@ -0,0 +1,31 @@ +=== /test.js === +module.exports = { +>module.exports = { a: "ok"} : { a: string | number; } +>module.exports : { a: string | number; } +>module : { "\"/test\"": { a: string | number; }; } +>exports : { a: string | number; } +>{ a: "ok"} : { a: string; } + + a: "ok" +>a : string +>"ok" : "ok" + +}; + +=== /index.ts === +import { a } from "./test"; +>a : string + +declare module "./test" { +>"./test" : { a: string | number; } + + export const a: number; +>a : number +} + +a.toFixed(); +>a.toFixed() : any +>a.toFixed : any +>a : string +>toFixed : any + diff --git a/tests/baselines/reference/moduleExportAlias2.symbols b/tests/baselines/reference/moduleExportAlias2.symbols index f6ebc315313..6dc88d4d8c9 100644 --- a/tests/baselines/reference/moduleExportAlias2.symbols +++ b/tests/baselines/reference/moduleExportAlias2.symbols @@ -37,7 +37,7 @@ exports = module.exports = C >C : Symbol(C, Decl(semver.js, 2, 22)) exports.f = n => n + 1 ->exports.f : Symbol(f) +>exports.f : Symbol(f, Decl(semver.js, 1, 28)) >exports : Symbol(f, Decl(semver.js, 1, 28)) >f : Symbol(f, Decl(semver.js, 1, 28)) >n : Symbol(n, Decl(semver.js, 2, 11)) diff --git a/tests/baselines/reference/moduleExportAlias4.symbols b/tests/baselines/reference/moduleExportAlias4.symbols index a3e2e2d5938..fd149513b7b 100644 --- a/tests/baselines/reference/moduleExportAlias4.symbols +++ b/tests/baselines/reference/moduleExportAlias4.symbols @@ -12,7 +12,7 @@ module.exports = class C {} >C : Symbol(C, Decl(bug24024.js, 2, 16)) module.exports.D = class D { } ->module.exports.D : Symbol(D) +>module.exports.D : Symbol(D, Decl(bug24024.js, 2, 27)) >module.exports : Symbol(D, Decl(bug24024.js, 2, 27)) >module : Symbol(module, Decl(bug24024.js, 1, 31)) >exports : Symbol("tests/cases/conformance/salsa/bug24024", Decl(bug24024.js, 0, 0)) diff --git a/tests/baselines/reference/moduleExportAliasImported.symbols b/tests/baselines/reference/moduleExportAliasImported.symbols index 9649cc0a3b6..298e439a0d7 100644 --- a/tests/baselines/reference/moduleExportAliasImported.symbols +++ b/tests/baselines/reference/moduleExportAliasImported.symbols @@ -1,6 +1,6 @@ === tests/cases/conformance/salsa/bug28014.js === exports.version = 1 ->exports.version : Symbol(version) +>exports.version : Symbol(version, Decl(bug28014.js, 0, 0)) >exports : Symbol(version, Decl(bug28014.js, 0, 0)) >version : Symbol(version, Decl(bug28014.js, 0, 0)) diff --git a/tests/baselines/reference/moduleExportPropertyAssignmentDefault.symbols b/tests/baselines/reference/moduleExportPropertyAssignmentDefault.symbols index 8e704e5fe0d..0645e00f000 100644 --- a/tests/baselines/reference/moduleExportPropertyAssignmentDefault.symbols +++ b/tests/baselines/reference/moduleExportPropertyAssignmentDefault.symbols @@ -9,7 +9,7 @@ module.exports = axios // both assignments should be ok >axios : Symbol(axios, Decl(axios.js, 0, 3)) module.exports.default = axios ->module.exports.default : Symbol(default) +>module.exports.default : Symbol(default, Decl(axios.js, 1, 22)) >module.exports : Symbol(default, Decl(axios.js, 1, 22)) >module : Symbol(module, Decl(axios.js, 0, 14)) >exports : Symbol("tests/cases/conformance/salsa/axios", Decl(axios.js, 0, 0)) diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols index 3ee790d7680..1c4aa535f61 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols @@ -13,14 +13,14 @@ mod1.justExport.toFixed() >toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' ->mod1.bothBefore : Symbol(bothBefore) +>mod1.bothBefore : Symbol(bothBefore, Decl(mod1.js, 3, 18), Decl(mod1.js, 0, 0)) >mod1 : Symbol(mod1, Decl(a.js, 1, 3)) ->bothBefore : Symbol(bothBefore) +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 3, 18), Decl(mod1.js, 0, 0)) mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' ->mod1.bothAfter : Symbol(bothAfter) +>mod1.bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18), Decl(mod1.js, 6, 1)) >mod1 : Symbol(mod1, Decl(a.js, 1, 3)) ->bothAfter : Symbol(bothAfter) +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18), Decl(mod1.js, 6, 1)) mod1.justProperty.length >mod1.justProperty.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) @@ -41,7 +41,7 @@ declare function require(name: string): any; === tests/cases/conformance/salsa/mod1.js === /// module.exports.bothBefore = 'string' ->module.exports.bothBefore : Symbol(bothBefore) +>module.exports.bothBefore : Symbol(bothBefore, Decl(mod1.js, 3, 18), Decl(mod1.js, 0, 0)) >module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) >module : Symbol(module, Decl(mod1.js, 0, 0)) >exports : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) @@ -62,7 +62,7 @@ module.exports = { >bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18)) } module.exports.bothAfter = 'string' ->module.exports.bothAfter : Symbol(bothAfter) +>module.exports.bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18), Decl(mod1.js, 6, 1)) >module.exports : Symbol(bothAfter, Decl(mod1.js, 6, 1)) >module : Symbol(module, Decl(mod1.js, 0, 0)) >exports : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols index ad044856870..76fecbc0b2c 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols @@ -41,7 +41,7 @@ declare function require(name: string): any; === tests/cases/conformance/salsa/mod1.js === /// module.exports.bothBefore = 'string' ->module.exports.bothBefore : Symbol(bothBefore) +>module.exports.bothBefore : Symbol(bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) >module.exports : Symbol(bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) >module : Symbol(module, Decl(mod1.js, 0, 0)) >exports : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) @@ -75,14 +75,14 @@ function A() { >p : Symbol(A.p, Decl(mod1.js, 6, 14)) } module.exports.bothAfter = 'string' ->module.exports.bothAfter : Symbol(bothAfter) +>module.exports.bothAfter : Symbol(bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) >module.exports : Symbol(bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) >module : Symbol(module, Decl(mod1.js, 0, 0)) >exports : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) >bothAfter : Symbol(bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) module.exports.justProperty = 'string' ->module.exports.justProperty : Symbol(justProperty) +>module.exports.justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) >module.exports : Symbol(justProperty, Decl(mod1.js, 9, 35)) >module : Symbol(module, Decl(mod1.js, 0, 0)) >exports : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) diff --git a/tests/baselines/reference/typedefCrossModule2.types b/tests/baselines/reference/typedefCrossModule2.types index c1afae93d85..9a1b0922f9e 100644 --- a/tests/baselines/reference/typedefCrossModule2.types +++ b/tests/baselines/reference/typedefCrossModule2.types @@ -1,7 +1,7 @@ === tests/cases/conformance/jsdoc/use.js === var mod = require('./mod1.js'); ->mod : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } ->require('./mod1.js') : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>mod : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } +>require('./mod1.js') : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >require : any >'./mod1.js' : "./mod1.js" @@ -17,7 +17,7 @@ var bbb = new mod.Baz(); >bbb : any >new mod.Baz() : any >mod.Baz : any ->mod : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>mod : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >Baz : any === tests/cases/conformance/jsdoc/mod1.js === @@ -31,16 +31,16 @@ class Foo { } // should error exports.Bar = class { } >exports.Bar = class { } : typeof Bar >exports.Bar : typeof Bar ->exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >Bar : typeof Bar >class { } : typeof Bar /** @typedef {number} Baz */ module.exports = { ->module.exports = { Baz: class { }} : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } ->module.exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } ->module : { "\"tests/cases/conformance/jsdoc/mod1\"": { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; }; } ->exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>module.exports = { Baz: class { }} : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } +>module.exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } +>module : { "\"tests/cases/conformance/jsdoc/mod1\"": { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; }; } +>exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >{ Baz: class { }} : { Baz: typeof Baz; } Baz: class { } @@ -59,16 +59,16 @@ var Qux = 2; exports.Quid = 2; >exports.Quid = 2 : 2 >exports.Quid : number ->exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >Quid : number >2 : 2 /** @typedef {number} Quack */ module.exports = { ->module.exports = { Quack: 2} : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } ->module.exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } ->module : { "\"tests/cases/conformance/jsdoc/mod1\"": { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; }; } ->exports : { Baz: any; Bar: typeof Bar; Quid: number; } | { Quack: any; Bar: typeof Bar; Quid: number; } +>module.exports = { Quack: 2} : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } +>module.exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } +>module : { "\"tests/cases/conformance/jsdoc/mod1\"": { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; }; } +>exports : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; } >{ Quack: 2} : { Quack: number; } Quack: 2 diff --git a/tests/baselines/reference/typedefCrossModule4.types b/tests/baselines/reference/typedefCrossModule4.types index 61c2dace77c..eb01fe95625 100644 --- a/tests/baselines/reference/typedefCrossModule4.types +++ b/tests/baselines/reference/typedefCrossModule4.types @@ -4,10 +4,10 @@ class Bar { } >Bar : Bar module.exports = { Foo: Bar }; ->module.exports = { Foo: Bar } : { Foo: any; } ->module.exports : { Foo: any; } ->module : { "\"tests/cases/conformance/jsdoc/mod3\"": { Foo: any; }; } ->exports : { Foo: any; } +>module.exports = { Foo: Bar } : { Foo: typeof Bar; } +>module.exports : { Foo: typeof Bar; } +>module : { "\"tests/cases/conformance/jsdoc/mod3\"": { Foo: typeof Bar; }; } +>exports : { Foo: typeof Bar; } >{ Foo: Bar } : { Foo: typeof Bar; } >Foo : typeof Bar >Bar : typeof Bar diff --git a/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation.ts b/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation.ts new file mode 100644 index 00000000000..1c129be3646 --- /dev/null +++ b/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation.ts @@ -0,0 +1,26 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /test.js +class Abcde { + /** @type {string} */ + x; +} + +module.exports = { + Abcde +}; + +// @Filename: /index.ts +import { Abcde } from "./test"; + +declare module "./test" { + interface Abcde { b: string } +} + +new Abcde().x; + +// Bug: the type meaning from /test.js does not +// propagate through the object literal export. +const x: Abcde = { b: "" }; diff --git a/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation2.ts b/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation2.ts new file mode 100644 index 00000000000..7ef22ee7ec9 --- /dev/null +++ b/tests/cases/compiler/jsExportMemberMergedWithModuleAugmentation2.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /test.js +module.exports = { + a: "ok" +}; + +// @Filename: /index.ts +import { a } from "./test"; + +declare module "./test" { + export const a: number; +} + +a.toFixed(); diff --git a/tests/cases/fourslash/completionsImportModuleAugmentationWithJS.ts b/tests/cases/fourslash/completionsImportModuleAugmentationWithJS.ts new file mode 100644 index 00000000000..8ea84247d84 --- /dev/null +++ b/tests/cases/fourslash/completionsImportModuleAugmentationWithJS.ts @@ -0,0 +1,41 @@ +// #37833 + +/// + +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /test.js +////class Abcde { +//// x +////} +//// +////module.exports = { +//// Abcde +////}; + +// @Filename: /index.ts +////export {}; +////declare module "./test" { +//// interface Abcde { b: string } +////} +//// +////Abcde/**/ + +verify.applyCodeActionFromCompletion("", { + name: "Abcde", + source: "/test", + description: `Import 'Abcde' from module "./test"`, + newFileContent: `import { Abcde } from "./test"; + +export {}; +declare module "./test" { + interface Abcde { b: string } +} + +Abcde`, + preferences: { + includeCompletionsForModuleExports: true + } +}); From 31b81bafe734d800ad25239a62705b38a29367e0 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Fri, 24 Apr 2020 23:50:34 +0300 Subject: [PATCH 28/38] fix(38138): show suggestions for identifier in class property initializer (#38157) --- src/services/completions.ts | 8 ++++- .../completionsClassPropertiesAssignment.ts | 31 ++++++++++--------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index bb08fe7d549..a1e98a03d87 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2685,10 +2685,16 @@ namespace ts.Completions { return cls; } break; - case SyntaxKind.Identifier: // class c extends React.Component { a: () => 1\n compon| } + case SyntaxKind.Identifier: { + // class c { public prop = c| } + if (isPropertyDeclaration(location.parent) && location.parent.initializer === location) { + return undefined; + } + // class c extends React.Component { a: () => 1\n compon| } if (isFromObjectTypeDeclaration(location)) { return findAncestor(location, isObjectTypeDeclaration); } + } } if (!contextToken) return undefined; diff --git a/tests/cases/fourslash/completionsClassPropertiesAssignment.ts b/tests/cases/fourslash/completionsClassPropertiesAssignment.ts index a3be4038c36..cb9aa111df0 100644 --- a/tests/cases/fourslash/completionsClassPropertiesAssignment.ts +++ b/tests/cases/fourslash/completionsClassPropertiesAssignment.ts @@ -1,29 +1,32 @@ /// ////class Class1 { -//// protected a = /*1*/ -//// private b = /*2*/ -//// public c = /*3*/ -//// public d = this./*4*/ +//// public a = this./*0*/ +//// protected b = /*1*/ +//// private c = /*2*/ +//// public d = /*3*/ ////} //// ////class Class2 { -//// a = /*5*/ +//// a = /*4*/ ////} ////class Class3 { -//// a = /*6*/ +//// a = /*5*/ ////} //// ////const prop = 'prop'; ////class Class4 { -//// [prop] = /*7*/ +//// [prop] = /*6*/ ////} const exact = completion.globalsPlus(["Class1", "Class2", "Class3", "prop", "Class4"]); -verify.completions({ marker: ["1"], exact }); -verify.completions({ marker: ["2"], exact }); -verify.completions({ marker: ["3"], exact }); -verify.completions({ marker: ["4"], exact: ['a', 'b', 'c', 'd'], isGlobalCompletion: false }); -verify.completions({ marker: ["5"], exact }); -verify.completions({ marker: ["6"], exact }); -verify.completions({ marker: ["7"], exact }); +const markers = ["1", "2", "3", "4", "5", "6"]; + +verify.completions({ marker: "0", exact: ['a', 'b', 'c', 'd'], isGlobalCompletion: false }); +verify.completions({ marker: markers, exact }); + +for (let marker of markers) { + goTo.marker(marker); + edit.insert("c"); + verify.completions({ exact }); +} From d28e38f57306af063e1ee84432f8efa6e7c22093 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 24 Apr 2020 14:30:28 -0700 Subject: [PATCH 29/38] Revert "make splice `deleteCount` required in es5.d.ts (#32643)" (#38169) This reverts commit ddcf139668c3a0aeda1da6a0d44887735ad37cdf. --- src/lib/es2015.core.d.ts | 9 -------- src/lib/es5.d.ts | 2 +- tests/baselines/reference/arraySlice.types | 4 ++-- tests/baselines/reference/invalidSplice.types | 4 ++-- .../jsDeclarationsImportTypeBundled.types | 8 +++---- ...tionsTypeReassignmentFromDeclaration.types | 8 +++---- ...ionsTypeReassignmentFromDeclaration2.types | 8 +++---- tests/baselines/reference/parserharness.types | 4 ++-- .../reference/restInvalidArgumentType.types | 2 +- .../restParameterWithBindingPattern3.types | 2 +- .../restPropertyWithBindingPattern.types | 4 ++-- .../baselines/reference/spliceES5.errors.txt | 11 ---------- tests/baselines/reference/spliceES5.js | 10 --------- tests/baselines/reference/spliceES5.symbols | 12 ----------- tests/baselines/reference/spliceES5.types | 21 ------------------- tests/baselines/reference/spliceES6.js | 10 --------- tests/baselines/reference/spliceES6.symbols | 12 ----------- tests/baselines/reference/spliceES6.types | 21 ------------------- .../reference/spreadInvalidArgumentType.types | 4 ++-- ...ymousTypeNotReferencingTypeParameter.types | 20 +++++++++--------- ...ingsWithOverloadResolution3_ES6.errors.txt | 2 +- tests/cases/compiler/spliceES5.ts | 4 ---- tests/cases/compiler/spliceES6.ts | 4 ---- 23 files changed, 36 insertions(+), 150 deletions(-) delete mode 100644 tests/baselines/reference/spliceES5.errors.txt delete mode 100644 tests/baselines/reference/spliceES5.js delete mode 100644 tests/baselines/reference/spliceES5.symbols delete mode 100644 tests/baselines/reference/spliceES5.types delete mode 100644 tests/baselines/reference/spliceES6.js delete mode 100644 tests/baselines/reference/spliceES6.symbols delete mode 100644 tests/baselines/reference/spliceES6.types delete mode 100644 tests/cases/compiler/spliceES5.ts delete mode 100644 tests/cases/compiler/spliceES6.ts diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index ef7dd1f69f7..1487891d524 100644 --- a/src/lib/es2015.core.d.ts +++ b/src/lib/es2015.core.d.ts @@ -42,15 +42,6 @@ interface Array { * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): this; - - /** - * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. - * @param start The zero-based location in the array from which to start removing elements. - * @param deleteCount The number of elements to remove. If deleteCount is omitted, or if its value is equal to or larger - * than array.length - start (that is, if it is equal to or greater than the number of elements left in the array, - * starting at start), then all the elements from start to the end of the array will be deleted. - */ - splice(start: number, deleteCount?: number): T[]; } interface ArrayConstructor { diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 9b981d69fc0..478f78f772a 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1254,7 +1254,7 @@ interface Array { * @param start The zero-based location in the array from which to start removing elements. * @param deleteCount The number of elements to remove. */ - splice(start: number, deleteCount: number): T[]; + splice(start: number, deleteCount?: number): T[]; /** * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. * @param start The zero-based location in the array from which to start removing elements. diff --git a/tests/baselines/reference/arraySlice.types b/tests/baselines/reference/arraySlice.types index bc65a26cebf..d1ee482ccaa 100644 --- a/tests/baselines/reference/arraySlice.types +++ b/tests/baselines/reference/arraySlice.types @@ -4,9 +4,9 @@ var arr: string[] | number[]; arr.splice(1, 1); >arr.splice(1, 1) : string[] | number[] ->arr.splice : { (start: number, deleteCount: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } +>arr.splice : { (start: number, deleteCount?: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } >arr : string[] | number[] ->splice : { (start: number, deleteCount: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } +>splice : { (start: number, deleteCount?: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } >1 : 1 >1 : 1 diff --git a/tests/baselines/reference/invalidSplice.types b/tests/baselines/reference/invalidSplice.types index a3ba1dde360..9ff59021725 100644 --- a/tests/baselines/reference/invalidSplice.types +++ b/tests/baselines/reference/invalidSplice.types @@ -2,9 +2,9 @@ var arr = [].splice(0,3,4,5); >arr : any[] >[].splice(0,3,4,5) : any[] ->[].splice : { (start: number, deleteCount: number): any[]; (start: number, deleteCount: number, ...items: any[]): any[]; } +>[].splice : { (start: number, deleteCount?: number): any[]; (start: number, deleteCount: number, ...items: any[]): any[]; } >[] : undefined[] ->splice : { (start: number, deleteCount: number): any[]; (start: number, deleteCount: number, ...items: any[]): any[]; } +>splice : { (start: number, deleteCount?: number): any[]; (start: number, deleteCount: number, ...items: any[]): any[]; } >0 : 0 >3 : 3 >4 : 4 diff --git a/tests/baselines/reference/jsDeclarationsImportTypeBundled.types b/tests/baselines/reference/jsDeclarationsImportTypeBundled.types index 6bb9bb74f52..0fac842568c 100644 --- a/tests/baselines/reference/jsDeclarationsImportTypeBundled.types +++ b/tests/baselines/reference/jsDeclarationsImportTypeBundled.types @@ -28,9 +28,9 @@ const items = [{x: 12}]; >12 : 12 module.exports = items; ->module.exports = items : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } ->module.exports : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } ->module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; }; } ->exports : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } +>module.exports = items : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount?: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } +>module.exports : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount?: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } +>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount?: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; }; } +>exports : { [n: number]: { x: number; }; length: number; toString(): string; toLocaleString(): string; pop(): { x: number; }; push(...items: { x: number; }[]): number; concat(...items: ConcatArray<{ x: number; }>[]): { x: number; }[]; concat(...items: ({ x: number; } | ConcatArray<{ x: number; }>)[]): { x: number; }[]; join(separator?: string): string; reverse(): { x: number; }[]; shift(): { x: number; }; slice(start?: number, end?: number): { x: number; }[]; sort(compareFn?: (a: { x: number; }, b: { x: number; }) => number): { x: number; }[]; splice(start: number, deleteCount?: number): { x: number; }[]; splice(start: number, deleteCount: number, ...items: { x: number; }[]): { x: number; }[]; unshift(...items: { x: number; }[]): number; indexOf(searchElement: { x: number; }, fromIndex?: number): number; lastIndexOf(searchElement: { x: number; }, fromIndex?: number): number; every(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => void, thisArg?: any): void; map(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => unknown, thisArg?: any): { x: number; }[]; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduce(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: { x: number; }, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => { x: number; }, initialValue: { x: number; }): { x: number; }; reduceRight(callbackfn: (previousValue: U, currentValue: { x: number; }, currentIndex: number, array: { x: number; }[]) => U, initialValue: U): U; } >items : { x: number; }[] diff --git a/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration.types b/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration.types index 92279bc2347..f684be1a540 100644 --- a/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration.types +++ b/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration.types @@ -16,9 +16,9 @@ const items = []; >[] : undefined[] module.exports = items; ->module.exports = items : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } ->module.exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } ->module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }; } ->exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module.exports = items : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module.exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }; } +>exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } >items : Item[] diff --git a/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration2.types b/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration2.types index e4a85bef283..525b934644b 100644 --- a/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration2.types +++ b/tests/baselines/reference/jsDeclarationsTypeReassignmentFromDeclaration2.types @@ -7,10 +7,10 @@ const items = require("./some-mod")(); >"./some-mod" : "./some-mod" module.exports = items; ->module.exports = items : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } ->module.exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } ->module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }; } ->exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; splice(start: number, deleteCount?: number): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module.exports = items : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module.exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } +>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }; } +>exports : { [n: number]: Item; length: number; toString(): string; toLocaleString(): string; pop(): Item; push(...items: Item[]): number; concat(...items: ConcatArray[]): Item[]; concat(...items: (Item | ConcatArray)[]): Item[]; join(separator?: string): string; reverse(): Item[]; shift(): Item; slice(start?: number, end?: number): Item[]; sort(compareFn?: (a: Item, b: Item) => number): Item[]; splice(start: number, deleteCount?: number): Item[]; splice(start: number, deleteCount: number, ...items: Item[]): Item[]; unshift(...items: Item[]): number; indexOf(searchElement: Item, fromIndex?: number): number; lastIndexOf(searchElement: Item, fromIndex?: number): number; every(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: Item, index: number, array: Item[]) => void, thisArg?: any): void; map(callbackfn: (value: Item, index: number, array: Item[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: Item, index: number, array: Item[]) => unknown, thisArg?: any): Item[]; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduce(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduce(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item): Item; reduceRight(callbackfn: (previousValue: Item, currentValue: Item, currentIndex: number, array: Item[]) => Item, initialValue: Item): Item; reduceRight(callbackfn: (previousValue: U, currentValue: Item, currentIndex: number, array: Item[]) => U, initialValue: U): U; find(predicate: (this: void, value: Item, index: number, obj: Item[]) => value is S, thisArg?: any): S; find(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): Item; findIndex(predicate: (value: Item, index: number, obj: Item[]) => unknown, thisArg?: any): number; fill(value: Item, start?: number, end?: number): Item[]; copyWithin(target: number, start: number, end?: number): Item[]; [Symbol.iterator](): IterableIterator; entries(): IterableIterator<[number, Item]>; keys(): IterableIterator; values(): IterableIterator; [Symbol.unscopables](): { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; } >items : Item[] === tests/cases/conformance/jsdoc/declarations/some-mod.d.ts === diff --git a/tests/baselines/reference/parserharness.types b/tests/baselines/reference/parserharness.types index c9b501d8754..793efe35fd7 100644 --- a/tests/baselines/reference/parserharness.types +++ b/tests/baselines/reference/parserharness.types @@ -6383,11 +6383,11 @@ module Harness { this.editRanges.splice(0, this.maxScriptVersions - this.editRanges.length); >this.editRanges.splice(0, this.maxScriptVersions - this.editRanges.length) : { length: number; editRange: any; }[] ->this.editRanges.splice : { (start: number, deleteCount: number): { length: number; editRange: any; }[]; (start: number, deleteCount: number, ...items: { length: number; editRange: any; }[]): { length: number; editRange: any; }[]; } +>this.editRanges.splice : { (start: number, deleteCount?: number): { length: number; editRange: any; }[]; (start: number, deleteCount: number, ...items: { length: number; editRange: any; }[]): { length: number; editRange: any; }[]; } >this.editRanges : { length: number; editRange: any; }[] >this : this >editRanges : { length: number; editRange: any; }[] ->splice : { (start: number, deleteCount: number): { length: number; editRange: any; }[]; (start: number, deleteCount: number, ...items: { length: number; editRange: any; }[]): { length: number; editRange: any; }[]; } +>splice : { (start: number, deleteCount?: number): { length: number; editRange: any; }[]; (start: number, deleteCount: number, ...items: { length: number; editRange: any; }[]): { length: number; editRange: any; }[]; } >0 : 0 >this.maxScriptVersions - this.editRanges.length : number >this.maxScriptVersions : number diff --git a/tests/baselines/reference/restInvalidArgumentType.types b/tests/baselines/reference/restInvalidArgumentType.types index 0a3b66362f8..638634e8bea 100644 --- a/tests/baselines/reference/restInvalidArgumentType.types +++ b/tests/baselines/reference/restInvalidArgumentType.types @@ -71,7 +71,7 @@ function f(p1: T, p2: T[]) { >p1 : T var {...r2} = p2; // OK ->r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] var {...r3} = t; // Error, generic type paramter diff --git a/tests/baselines/reference/restParameterWithBindingPattern3.types b/tests/baselines/reference/restParameterWithBindingPattern3.types index 6b5a195ae3d..b98f0cdd367 100644 --- a/tests/baselines/reference/restParameterWithBindingPattern3.types +++ b/tests/baselines/reference/restParameterWithBindingPattern3.types @@ -31,5 +31,5 @@ function e(...{0: a = 1, 1: b = true, ...rest: rest}: [boolean, string, number]) >b : string >true : true >rest : any ->rest : { [n: number]: string | number | boolean; 0: boolean; 1: string; 2: number; length: 3; toString(): string; toLocaleString(): string; pop(): string | number | boolean; push(...items: (string | number | boolean)[]): number; concat(...items: ConcatArray[]): (string | number | boolean)[]; concat(...items: (string | number | boolean | ConcatArray)[]): (string | number | boolean)[]; join(separator?: string): string; reverse(): (string | number | boolean)[]; shift(): string | number | boolean; slice(start?: number, end?: number): (string | number | boolean)[]; sort(compareFn?: (a: string | number | boolean, b: string | number | boolean) => number): [boolean, string, number]; splice(start: number, deleteCount: number): (string | number | boolean)[]; splice(start: number, deleteCount: number, ...items: (string | number | boolean)[]): (string | number | boolean)[]; unshift(...items: (string | number | boolean)[]): number; indexOf(searchElement: string | number | boolean, fromIndex?: number): number; lastIndexOf(searchElement: string | number | boolean, fromIndex?: number): number; every(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => void, thisArg?: any): void; map(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): (string | number | boolean)[]; reduce(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean): string | number | boolean; reduce(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean, initialValue: string | number | boolean): string | number | boolean; reduce(callbackfn: (previousValue: U, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean): string | number | boolean; reduceRight(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean, initialValue: string | number | boolean): string | number | boolean; reduceRight(callbackfn: (previousValue: U, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => U, initialValue: U): U; } +>rest : { [n: number]: string | number | boolean; 0: boolean; 1: string; 2: number; length: 3; toString(): string; toLocaleString(): string; pop(): string | number | boolean; push(...items: (string | number | boolean)[]): number; concat(...items: ConcatArray[]): (string | number | boolean)[]; concat(...items: (string | number | boolean | ConcatArray)[]): (string | number | boolean)[]; join(separator?: string): string; reverse(): (string | number | boolean)[]; shift(): string | number | boolean; slice(start?: number, end?: number): (string | number | boolean)[]; sort(compareFn?: (a: string | number | boolean, b: string | number | boolean) => number): [boolean, string, number]; splice(start: number, deleteCount?: number): (string | number | boolean)[]; splice(start: number, deleteCount: number, ...items: (string | number | boolean)[]): (string | number | boolean)[]; unshift(...items: (string | number | boolean)[]): number; indexOf(searchElement: string | number | boolean, fromIndex?: number): number; lastIndexOf(searchElement: string | number | boolean, fromIndex?: number): number; every(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => void, thisArg?: any): void; map(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: string | number | boolean, index: number, array: (string | number | boolean)[]) => unknown, thisArg?: any): (string | number | boolean)[]; reduce(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean): string | number | boolean; reduce(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean, initialValue: string | number | boolean): string | number | boolean; reduce(callbackfn: (previousValue: U, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean): string | number | boolean; reduceRight(callbackfn: (previousValue: string | number | boolean, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => string | number | boolean, initialValue: string | number | boolean): string | number | boolean; reduceRight(callbackfn: (previousValue: U, currentValue: string | number | boolean, currentIndex: number, array: (string | number | boolean)[]) => U, initialValue: U): U; } diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.types b/tests/baselines/reference/restPropertyWithBindingPattern.types index e079b7857ee..55bd7fd95f6 100644 --- a/tests/baselines/reference/restPropertyWithBindingPattern.types +++ b/tests/baselines/reference/restPropertyWithBindingPattern.types @@ -17,14 +17,14 @@ ({...[]} = {}); >({...[]} = {}) : {} >{...[]} = {} : {} ->{...[]} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } +>{...[]} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } >[] : undefined[] >{} : {} ({...([])} = {}); >({...([])} = {}) : {} >{...([])} = {} : {} ->{...([])} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } +>{...([])} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } >([]) : undefined[] >[] : undefined[] >{} : {} diff --git a/tests/baselines/reference/spliceES5.errors.txt b/tests/baselines/reference/spliceES5.errors.txt deleted file mode 100644 index 448bb37fd2e..00000000000 --- a/tests/baselines/reference/spliceES5.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/spliceES5.ts(2,16): error TS2555: Expected at least 2 arguments, but got 1. - - -==== tests/cases/compiler/spliceES5.ts (1 errors) ==== - // see #32638 - var arr1 = [0].splice(0) - ~~~~~~~~~ -!!! error TS2555: Expected at least 2 arguments, but got 1. -!!! related TS6210 /.ts/lib.es5.d.ts:1277:27: An argument for 'deleteCount' was not provided. - var arr2 = [0].splice(0, 1) - \ No newline at end of file diff --git a/tests/baselines/reference/spliceES5.js b/tests/baselines/reference/spliceES5.js deleted file mode 100644 index d0239c19cb8..00000000000 --- a/tests/baselines/reference/spliceES5.js +++ /dev/null @@ -1,10 +0,0 @@ -//// [spliceES5.ts] -// see #32638 -var arr1 = [0].splice(0) -var arr2 = [0].splice(0, 1) - - -//// [spliceES5.js] -// see #32638 -var arr1 = [0].splice(0); -var arr2 = [0].splice(0, 1); diff --git a/tests/baselines/reference/spliceES5.symbols b/tests/baselines/reference/spliceES5.symbols deleted file mode 100644 index fa0b1a5566d..00000000000 --- a/tests/baselines/reference/spliceES5.symbols +++ /dev/null @@ -1,12 +0,0 @@ -=== tests/cases/compiler/spliceES5.ts === -// see #32638 -var arr1 = [0].splice(0) ->arr1 : Symbol(arr1, Decl(spliceES5.ts, 1, 3)) ->[0].splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var arr2 = [0].splice(0, 1) ->arr2 : Symbol(arr2, Decl(spliceES5.ts, 2, 3)) ->[0].splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) ->splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - diff --git a/tests/baselines/reference/spliceES5.types b/tests/baselines/reference/spliceES5.types deleted file mode 100644 index 42da61a080a..00000000000 --- a/tests/baselines/reference/spliceES5.types +++ /dev/null @@ -1,21 +0,0 @@ -=== tests/cases/compiler/spliceES5.ts === -// see #32638 -var arr1 = [0].splice(0) ->arr1 : number[] ->[0].splice(0) : number[] ->[0].splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } ->[0] : number[] ->0 : 0 ->splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } ->0 : 0 - -var arr2 = [0].splice(0, 1) ->arr2 : number[] ->[0].splice(0, 1) : number[] ->[0].splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } ->[0] : number[] ->0 : 0 ->splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; } ->0 : 0 ->1 : 1 - diff --git a/tests/baselines/reference/spliceES6.js b/tests/baselines/reference/spliceES6.js deleted file mode 100644 index 3fe0519ede9..00000000000 --- a/tests/baselines/reference/spliceES6.js +++ /dev/null @@ -1,10 +0,0 @@ -//// [spliceES6.ts] -// see #32638 -var arr1 = [0].splice(0) -var arr2 = [0].splice(0, 1) - - -//// [spliceES6.js] -// see #32638 -var arr1 = [0].splice(0); -var arr2 = [0].splice(0, 1); diff --git a/tests/baselines/reference/spliceES6.symbols b/tests/baselines/reference/spliceES6.symbols deleted file mode 100644 index cbfb2a7ef37..00000000000 --- a/tests/baselines/reference/spliceES6.symbols +++ /dev/null @@ -1,12 +0,0 @@ -=== tests/cases/compiler/spliceES6.ts === -// see #32638 -var arr1 = [0].splice(0) ->arr1 : Symbol(arr1, Decl(spliceES6.ts, 1, 3)) ->[0].splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) ->splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) - -var arr2 = [0].splice(0, 1) ->arr2 : Symbol(arr2, Decl(spliceES6.ts, 2, 3)) ->[0].splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) ->splice : Symbol(Array.splice, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) - diff --git a/tests/baselines/reference/spliceES6.types b/tests/baselines/reference/spliceES6.types deleted file mode 100644 index fc73c584c44..00000000000 --- a/tests/baselines/reference/spliceES6.types +++ /dev/null @@ -1,21 +0,0 @@ -=== tests/cases/compiler/spliceES6.ts === -// see #32638 -var arr1 = [0].splice(0) ->arr1 : number[] ->[0].splice(0) : number[] ->[0].splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; (start: number, deleteCount?: number): number[]; } ->[0] : number[] ->0 : 0 ->splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; (start: number, deleteCount?: number): number[]; } ->0 : 0 - -var arr2 = [0].splice(0, 1) ->arr2 : number[] ->[0].splice(0, 1) : number[] ->[0].splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; (start: number, deleteCount?: number): number[]; } ->[0] : number[] ->0 : 0 ->splice : { (start: number, deleteCount: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; (start: number, deleteCount?: number): number[]; } ->0 : 0 ->1 : 1 - diff --git a/tests/baselines/reference/spreadInvalidArgumentType.types b/tests/baselines/reference/spreadInvalidArgumentType.types index 2dae3fe38ef..ec1b7faa9ec 100644 --- a/tests/baselines/reference/spreadInvalidArgumentType.types +++ b/tests/baselines/reference/spreadInvalidArgumentType.types @@ -73,8 +73,8 @@ function f(p1: T, p2: T[]) { >p1 : T var o2 = { ...p2 }; // OK ->o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } ->{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] var o3 = { ...t }; // OK, generic type paramter diff --git a/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types b/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types index 35c7db17f2f..cd907c26ec8 100644 --- a/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types +++ b/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types @@ -319,9 +319,9 @@ class ListWrapper { >index : number >value : T >list.splice(index, 0, value) : T[] ->list.splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>list.splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >list : T[] ->splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >index : number >0 : 0 >value : T @@ -341,9 +341,9 @@ class ListWrapper { list.splice(index, 1); >list.splice(index, 1) : T[] ->list.splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>list.splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >list : T[] ->splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >index : number >1 : 1 @@ -380,9 +380,9 @@ class ListWrapper { list.splice(index, 1); >list.splice(index, 1) : T[] ->list.splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>list.splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >list : T[] ->splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >index : number >1 : 1 } @@ -410,9 +410,9 @@ class ListWrapper { list.splice(index, 1); >list.splice(index, 1) : T[] ->list.splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>list.splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >list : T[] ->splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >index : number >1 : 1 @@ -543,9 +543,9 @@ class ListWrapper { >from : number >length : number >l.splice(from, length) : T[] ->l.splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>l.splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >l : T[] ->splice : { (start: number, deleteCount: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } +>splice : { (start: number, deleteCount?: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; } >from : number >length : number diff --git a/tests/baselines/reference/taggedTemplateStringsWithOverloadResolution3_ES6.errors.txt b/tests/baselines/reference/taggedTemplateStringsWithOverloadResolution3_ES6.errors.txt index 3d0389b8502..95eb021c88b 100644 --- a/tests/baselines/reference/taggedTemplateStringsWithOverloadResolution3_ES6.errors.txt +++ b/tests/baselines/reference/taggedTemplateStringsWithOverloadResolution3_ES6.errors.txt @@ -113,7 +113,7 @@ tests/cases/conformance/es6/templates/taggedTemplateStringsWithOverloadResolutio fn5 `${ (n) => n.toFixed() }`; // will error; 'n' should have type 'string'. ~~~~~~~ !!! error TS2551: Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'? -!!! related TS2728 /.ts/lib.es2015.core.d.ts:481:5: 'fixed' is declared here. +!!! related TS2728 /.ts/lib.es2015.core.d.ts:472:5: 'fixed' is declared here. fn5 `${ (n) => n.substr(0) }`; \ No newline at end of file diff --git a/tests/cases/compiler/spliceES5.ts b/tests/cases/compiler/spliceES5.ts deleted file mode 100644 index 6955fa44c22..00000000000 --- a/tests/cases/compiler/spliceES5.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @target: es5 -// see #32638 -var arr1 = [0].splice(0) -var arr2 = [0].splice(0, 1) diff --git a/tests/cases/compiler/spliceES6.ts b/tests/cases/compiler/spliceES6.ts deleted file mode 100644 index 0f1aa8223fd..00000000000 --- a/tests/cases/compiler/spliceES6.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @target: es6 -// see #32638 -var arr1 = [0].splice(0) -var arr2 = [0].splice(0, 1) From 968943f355c54b0cf6cc4efde10b57ff2cfa5bcb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 24 Apr 2020 14:59:41 -0700 Subject: [PATCH 30/38] Reset error variable in downlevel for-await-of loop (#38170) * Rename forAwait tests * Reset error var in for-await loop --- src/compiler/transformers/es2018.ts | 163 +++++++++++++++--- ....js => emitter.forAwait(target=es2015).js} | 52 +++++- ...> emitter.forAwait(target=es2015).symbols} | 27 ++- ... => emitter.forAwait(target=es2015).types} | 26 ++- ....js => emitter.forAwait(target=es2017).js} | 52 +++++- ...> emitter.forAwait(target=es2017).symbols} | 27 ++- ... => emitter.forAwait(target=es2017).types} | 27 ++- ....js => emitter.forAwait(target=es2018).js} | 23 ++- ...> emitter.forAwait(target=es2018).symbols} | 26 ++- ... => emitter.forAwait(target=es2018).types} | 27 ++- ...es5.js => emitter.forAwait(target=es5).js} | 98 ++++++++++- ...s => emitter.forAwait(target=es5).symbols} | 27 ++- ...pes => emitter.forAwait(target=es5).types} | 27 ++- .../forAwait/emitter.forAwait.es2015.ts | 42 ----- .../forAwait/emitter.forAwait.es2017.ts | 42 ----- .../es5/forAwait/emitter.forAwait.es5.ts | 42 ----- .../emitter.forAwait.ts} | 11 +- 17 files changed, 532 insertions(+), 207 deletions(-) rename tests/baselines/reference/{emitter.forAwait.es2015.js => emitter.forAwait(target=es2015).js} (81%) rename tests/baselines/reference/{emitter.forAwait.es2017.symbols => emitter.forAwait(target=es2015).symbols} (63%) rename tests/baselines/reference/{emitter.forAwait.es2018.types => emitter.forAwait(target=es2015).types} (56%) rename tests/baselines/reference/{emitter.forAwait.es2017.js => emitter.forAwait(target=es2017).js} (79%) rename tests/baselines/reference/{emitter.forAwait.es2015.symbols => emitter.forAwait(target=es2017).symbols} (63%) rename tests/baselines/reference/{emitter.forAwait.es2015.types => emitter.forAwait(target=es2017).types} (56%) rename tests/baselines/reference/{emitter.forAwait.es2018.js => emitter.forAwait(target=es2018).js} (73%) rename tests/baselines/reference/{emitter.forAwait.es2018.symbols => emitter.forAwait(target=es2018).symbols} (63%) rename tests/baselines/reference/{emitter.forAwait.es2017.types => emitter.forAwait(target=es2018).types} (56%) rename tests/baselines/reference/{emitter.forAwait.es5.js => emitter.forAwait(target=es5).js} (83%) rename tests/baselines/reference/{emitter.forAwait.es5.symbols => emitter.forAwait(target=es5).symbols} (63%) rename tests/baselines/reference/{emitter.forAwait.es5.types => emitter.forAwait(target=es5).types} (56%) delete mode 100644 tests/cases/conformance/emitter/es2015/forAwait/emitter.forAwait.es2015.ts delete mode 100644 tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts delete mode 100644 tests/cases/conformance/emitter/es5/forAwait/emitter.forAwait.es5.ts rename tests/cases/conformance/{emitter/es2018/forAwait/emitter.forAwait.es2018.ts => statements/for-await-ofStatements/emitter.forAwait.ts} (74%) diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index a3ae750f6e7..16d67fcef38 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -5,6 +5,38 @@ namespace ts { AsyncMethodsWithSuper = 1 << 0 } + // Facts we track as we traverse the tree + const enum HierarchyFacts { + None = 0, + + // + // Ancestor facts + // + + HasLexicalThis = 1 << 0, + IterationContainer = 1 << 1, + // NOTE: do not add more ancestor flags without also updating AncestorFactsMask below. + + // + // Ancestor masks + // + + AncestorFactsMask = (IterationContainer << 1) - 1, + + SourceFileIncludes = HasLexicalThis, + SourceFileExcludes = IterationContainer, + StrictModeSourceFileIncludes = None, + + ClassOrFunctionIncludes = HasLexicalThis, + ClassOrFunctionExcludes = IterationContainer, + + ArrowFunctionIncludes = None, + ArrowFunctionExcludes = ClassOrFunctionExcludes, + + IterationStatementIncludes = IterationContainer, + IterationStatementExcludes = None, + } + export function transformES2018(context: TransformationContext) { const { resumeLexicalEnvironment, @@ -26,7 +58,7 @@ namespace ts { let enabledSubstitutions: ESNextSubstitutionFlags; let enclosingFunctionFlags: FunctionFlags; let enclosingSuperContainerFlags: NodeCheckFlags = 0; - let hasLexicalThis: boolean; + let hierarchyFacts: HierarchyFacts = 0; let currentSourceFile: SourceFile; let taggedTemplateStringDeclarations: VariableDeclaration[]; @@ -40,6 +72,30 @@ namespace ts { return chainBundle(transformSourceFile); + function affectsSubtree(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) { + return hierarchyFacts !== (hierarchyFacts & ~excludeFacts | includeFacts); + } + + /** + * Sets the `HierarchyFacts` for this node prior to visiting this node's subtree, returning the facts set prior to modification. + * @param excludeFacts The existing `HierarchyFacts` to reset before visiting the subtree. + * @param includeFacts The new `HierarchyFacts` to set before visiting the subtree. + */ + function enterSubtree(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) { + const ancestorFacts = hierarchyFacts; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & HierarchyFacts.AncestorFactsMask; + return ancestorFacts; + } + + /** + * Restores the `HierarchyFacts` for this node's ancestor after visiting this node's + * subtree. + * @param ancestorFacts The `HierarchyFacts` of the ancestor to restore after visiting the subtree. + */ + function exitSubtree(ancestorFacts: HierarchyFacts) { + hierarchyFacts = ancestorFacts; + } + function recordTaggedTemplateString(temp: Identifier) { taggedTemplateStringDeclarations = append( taggedTemplateStringDeclarations, @@ -75,11 +131,11 @@ namespace ts { return node; } - function doWithLexicalThis(cb: (value: T) => U, value: T) { - if (!hasLexicalThis) { - hasLexicalThis = true; + function doWithHierarchyFacts(cb: (value: T) => U, value: T, excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) { + if (affectsSubtree(excludeFacts, includeFacts)) { + const ancestorFacts = enterSubtree(excludeFacts, includeFacts); const result = cb(value); - hasLexicalThis = false; + exitSubtree(ancestorFacts); return result; } return cb(value); @@ -112,26 +168,66 @@ namespace ts { return visitVariableStatement(node as VariableStatement); case SyntaxKind.VariableDeclaration: return visitVariableDeclaration(node as VariableDeclaration); + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForInStatement: + return doWithHierarchyFacts( + visitDefault, + node, + HierarchyFacts.IterationStatementExcludes, + HierarchyFacts.IterationStatementIncludes); case SyntaxKind.ForOfStatement: return visitForOfStatement(node as ForOfStatement, /*outermostLabeledStatement*/ undefined); case SyntaxKind.ForStatement: - return visitForStatement(node as ForStatement); + return doWithHierarchyFacts( + visitForStatement, + node as ForStatement, + HierarchyFacts.IterationStatementExcludes, + HierarchyFacts.IterationStatementIncludes); case SyntaxKind.VoidExpression: return visitVoidExpression(node as VoidExpression); case SyntaxKind.Constructor: - return doWithLexicalThis(visitConstructorDeclaration, node as ConstructorDeclaration); + return doWithHierarchyFacts( + visitConstructorDeclaration, + node as ConstructorDeclaration, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.MethodDeclaration: - return doWithLexicalThis(visitMethodDeclaration, node as MethodDeclaration); + return doWithHierarchyFacts( + visitMethodDeclaration, + node as MethodDeclaration, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.GetAccessor: - return doWithLexicalThis(visitGetAccessorDeclaration, node as GetAccessorDeclaration); + return doWithHierarchyFacts( + visitGetAccessorDeclaration, + node as GetAccessorDeclaration, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.SetAccessor: - return doWithLexicalThis(visitSetAccessorDeclaration, node as SetAccessorDeclaration); + return doWithHierarchyFacts( + visitSetAccessorDeclaration, + node as SetAccessorDeclaration, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.FunctionDeclaration: - return doWithLexicalThis(visitFunctionDeclaration, node as FunctionDeclaration); + return doWithHierarchyFacts( + visitFunctionDeclaration, + node as FunctionDeclaration, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.FunctionExpression: - return doWithLexicalThis(visitFunctionExpression, node as FunctionExpression); + return doWithHierarchyFacts( + visitFunctionExpression, + node as FunctionExpression, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); case SyntaxKind.ArrowFunction: - return visitArrowFunction(node as ArrowFunction); + return doWithHierarchyFacts( + visitArrowFunction, + node as ArrowFunction, + HierarchyFacts.ArrowFunctionExcludes, + HierarchyFacts.ArrowFunctionIncludes); case SyntaxKind.Parameter: return visitParameter(node as ParameterDeclaration); case SyntaxKind.ExpressionStatement: @@ -152,7 +248,11 @@ namespace ts { return visitEachChild(node, visitor, context); case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - return doWithLexicalThis(visitDefault, node); + return doWithHierarchyFacts( + visitDefault, + node, + HierarchyFacts.ClassOrFunctionExcludes, + HierarchyFacts.ClassOrFunctionIncludes); default: return visitEachChild(node, visitor, context); } @@ -231,7 +331,7 @@ namespace ts { if (statement.kind === SyntaxKind.ForOfStatement && (statement).awaitModifier) { return visitForOfStatement(statement, node); } - return restoreEnclosingLabel(visitEachChild(statement, visitor, context), node); + return restoreEnclosingLabel(visitNode(statement, visitor, isStatement, liftToBlock), node); } return visitEachChild(node, visitor, context); } @@ -311,14 +411,20 @@ namespace ts { } function visitSourceFile(node: SourceFile): SourceFile { + const ancestorFacts = enterSubtree( + HierarchyFacts.SourceFileExcludes, + isEffectiveStrictModeSourceFile(node, compilerOptions) ? + HierarchyFacts.StrictModeSourceFileIncludes : + HierarchyFacts.SourceFileIncludes); exportedVariableStatement = false; - hasLexicalThis = !isEffectiveStrictModeSourceFile(node, compilerOptions); const visited = visitEachChild(node, visitor, context); const statement = concatenate(visited.statements, taggedTemplateStringDeclarations && [ createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList(taggedTemplateStringDeclarations)) ]); - return updateSourceFileNode(visited, setTextRange(createNodeArray(statement), node.statements)); + const result = updateSourceFileNode(visited, setTextRange(createNodeArray(statement), node.statements)); + exitSubtree(ancestorFacts); + return result; } function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -441,15 +547,15 @@ namespace ts { * @param node A ForOfStatement. */ function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { + const ancestorFacts = enterSubtree(HierarchyFacts.IterationStatementExcludes, HierarchyFacts.IterationStatementIncludes); if (node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { node = transformForOfStatementWithObjectRest(node); } - if (node.awaitModifier) { - return transformForAwaitOfStatement(node, outermostLabeledStatement); - } - else { - return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); - } + const result = node.awaitModifier ? + transformForAwaitOfStatement(node, outermostLabeledStatement, ancestorFacts) : + restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); + exitSubtree(ancestorFacts); + return result; } function transformForOfStatementWithObjectRest(node: ForOfStatement) { @@ -528,7 +634,7 @@ namespace ts { : createAwait(expression); } - function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined) { + function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts) { const expression = visitNode(node.expression, visitor, isExpression); const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined); const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined); @@ -544,13 +650,18 @@ namespace ts { hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); + // if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration + const initializer = ancestorFacts & HierarchyFacts.IterationContainer ? + inlineExpressions([createAssignment(errorRecord, createVoidZero()), callValues]) : + callValues; + const forStatement = setEmitFlags( setTextRange( createFor( /*initializer*/ setEmitFlags( setTextRange( createVariableDeclarationList([ - setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, callValues), node.expression), + setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, initializer), node.expression), createVariableDeclaration(result) ]), node.expression @@ -809,7 +920,7 @@ namespace ts { visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset) ) ), - hasLexicalThis + !!(hierarchyFacts & HierarchyFacts.HasLexicalThis) ) ); diff --git a/tests/baselines/reference/emitter.forAwait.es2015.js b/tests/baselines/reference/emitter.forAwait(target=es2015).js similarity index 81% rename from tests/baselines/reference/emitter.forAwait.es2015.js rename to tests/baselines/reference/emitter.forAwait(target=es2015).js index 2b2cc3ce08d..a651bbbb92c 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.js +++ b/tests/baselines/reference/emitter.forAwait(target=es2015).js @@ -1,4 +1,4 @@ -//// [tests/cases/conformance/emitter/es2015/forAwait/emitter.forAwait.es2015.ts] //// +//// [tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts] //// //// [file1.ts] async function f1() { @@ -40,6 +40,15 @@ async function* f6() { continue outer; } } +//// [file7.ts] +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y: any; + for (;;) { + for await (const x of y) { + } + } +} //// [file1.js] var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { @@ -264,3 +273,44 @@ function f6() { } }); } +//// [file7.js] +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +// https://github.com/microsoft/TypeScript/issues/36166 +function f7() { + return __asyncGenerator(this, arguments, function* f7_1() { + var e_1, _a; + let y; + for (;;) { + try { + for (var y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { + const x = y_1_1.value; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1)); + } + finally { if (e_1) throw e_1.error; } + } + } + }); +} diff --git a/tests/baselines/reference/emitter.forAwait.es2017.symbols b/tests/baselines/reference/emitter.forAwait(target=es2015).symbols similarity index 63% rename from tests/baselines/reference/emitter.forAwait.es2017.symbols rename to tests/baselines/reference/emitter.forAwait(target=es2015).symbols index 184d26c1266..f32170c889a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.symbols +++ b/tests/baselines/reference/emitter.forAwait(target=es2015).symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : Symbol(f1, Decl(file1.ts, 0, 0)) @@ -10,7 +10,7 @@ async function f1() { >y : Symbol(y, Decl(file1.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : Symbol(f2, Decl(file2.ts, 0, 0)) @@ -23,7 +23,7 @@ async function f2() { >y : Symbol(y, Decl(file2.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : Symbol(f3, Decl(file3.ts, 0, 0)) @@ -35,7 +35,7 @@ async function* f3() { >y : Symbol(y, Decl(file3.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : Symbol(f4, Decl(file4.ts, 0, 0)) @@ -48,7 +48,7 @@ async function* f4() { >y : Symbol(y, Decl(file4.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2017/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : Symbol(f5, Decl(file5.ts, 0, 0)) @@ -63,7 +63,7 @@ async function f5() { continue outer; } } -=== tests/cases/conformance/emitter/es2017/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : Symbol(f6, Decl(file6.ts, 0, 0)) @@ -78,3 +78,18 @@ async function* f6() { continue outer; } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : Symbol(f7, Decl(file7.ts, 0, 0)) + + let y: any; +>y : Symbol(y, Decl(file7.ts, 2, 7)) + + for (;;) { + for await (const x of y) { +>x : Symbol(x, Decl(file7.ts, 4, 24)) +>y : Symbol(y, Decl(file7.ts, 2, 7)) + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2018.types b/tests/baselines/reference/emitter.forAwait(target=es2015).types similarity index 56% rename from tests/baselines/reference/emitter.forAwait.es2018.types rename to tests/baselines/reference/emitter.forAwait(target=es2015).types index a9b3a94dead..406f669ab3a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2018.types +++ b/tests/baselines/reference/emitter.forAwait(target=es2015).types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2018/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : () => Promise @@ -10,7 +10,7 @@ async function f1() { >y : any } } -=== tests/cases/conformance/emitter/es2018/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : () => Promise @@ -23,7 +23,7 @@ async function f2() { >y : any } } -=== tests/cases/conformance/emitter/es2018/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : () => AsyncGenerator @@ -35,7 +35,7 @@ async function* f3() { >y : any } } -=== tests/cases/conformance/emitter/es2018/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : () => AsyncGenerator @@ -48,7 +48,7 @@ async function* f4() { >y : any } } -=== tests/cases/conformance/emitter/es2018/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : () => Promise @@ -65,7 +65,7 @@ async function f5() { >outer : any } } -=== tests/cases/conformance/emitter/es2018/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : () => AsyncGenerator @@ -82,4 +82,18 @@ async function* f6() { >outer : any } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : () => AsyncGenerator + let y: any; +>y : any + + for (;;) { + for await (const x of y) { +>x : any +>y : any + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2017.js b/tests/baselines/reference/emitter.forAwait(target=es2017).js similarity index 79% rename from tests/baselines/reference/emitter.forAwait.es2017.js rename to tests/baselines/reference/emitter.forAwait(target=es2017).js index dd0e8aede2b..e7ab46bccc5 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.js +++ b/tests/baselines/reference/emitter.forAwait(target=es2017).js @@ -1,4 +1,4 @@ -//// [tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts] //// +//// [tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts] //// //// [file1.ts] async function f1() { @@ -40,6 +40,15 @@ async function* f6() { continue outer; } } +//// [file7.ts] +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y: any; + for (;;) { + for await (const x of y) { + } + } +} //// [file1.js] var __asyncValues = (this && this.__asyncValues) || function (o) { @@ -231,3 +240,44 @@ function f6() { } }); } +//// [file7.js] +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +// https://github.com/microsoft/TypeScript/issues/36166 +function f7() { + return __asyncGenerator(this, arguments, function* f7_1() { + var e_1, _a; + let y; + for (;;) { + try { + for (var y_1 = (e_1 = void 0, __asyncValues(y)), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { + const x = y_1_1.value; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (y_1_1 && !y_1_1.done && (_a = y_1.return)) yield __await(_a.call(y_1)); + } + finally { if (e_1) throw e_1.error; } + } + } + }); +} diff --git a/tests/baselines/reference/emitter.forAwait.es2015.symbols b/tests/baselines/reference/emitter.forAwait(target=es2017).symbols similarity index 63% rename from tests/baselines/reference/emitter.forAwait.es2015.symbols rename to tests/baselines/reference/emitter.forAwait(target=es2017).symbols index bc75908f601..f32170c889a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.symbols +++ b/tests/baselines/reference/emitter.forAwait(target=es2017).symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2015/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : Symbol(f1, Decl(file1.ts, 0, 0)) @@ -10,7 +10,7 @@ async function f1() { >y : Symbol(y, Decl(file1.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2015/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : Symbol(f2, Decl(file2.ts, 0, 0)) @@ -23,7 +23,7 @@ async function f2() { >y : Symbol(y, Decl(file2.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2015/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : Symbol(f3, Decl(file3.ts, 0, 0)) @@ -35,7 +35,7 @@ async function* f3() { >y : Symbol(y, Decl(file3.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2015/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : Symbol(f4, Decl(file4.ts, 0, 0)) @@ -48,7 +48,7 @@ async function* f4() { >y : Symbol(y, Decl(file4.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2015/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : Symbol(f5, Decl(file5.ts, 0, 0)) @@ -63,7 +63,7 @@ async function f5() { continue outer; } } -=== tests/cases/conformance/emitter/es2015/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : Symbol(f6, Decl(file6.ts, 0, 0)) @@ -78,3 +78,18 @@ async function* f6() { continue outer; } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : Symbol(f7, Decl(file7.ts, 0, 0)) + + let y: any; +>y : Symbol(y, Decl(file7.ts, 2, 7)) + + for (;;) { + for await (const x of y) { +>x : Symbol(x, Decl(file7.ts, 4, 24)) +>y : Symbol(y, Decl(file7.ts, 2, 7)) + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2015.types b/tests/baselines/reference/emitter.forAwait(target=es2017).types similarity index 56% rename from tests/baselines/reference/emitter.forAwait.es2015.types rename to tests/baselines/reference/emitter.forAwait(target=es2017).types index 3c345386c37..406f669ab3a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.types +++ b/tests/baselines/reference/emitter.forAwait(target=es2017).types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2015/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : () => Promise @@ -10,7 +10,7 @@ async function f1() { >y : any } } -=== tests/cases/conformance/emitter/es2015/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : () => Promise @@ -23,7 +23,7 @@ async function f2() { >y : any } } -=== tests/cases/conformance/emitter/es2015/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : () => AsyncGenerator @@ -35,7 +35,7 @@ async function* f3() { >y : any } } -=== tests/cases/conformance/emitter/es2015/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : () => AsyncGenerator @@ -48,7 +48,7 @@ async function* f4() { >y : any } } -=== tests/cases/conformance/emitter/es2015/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : () => Promise @@ -65,7 +65,7 @@ async function f5() { >outer : any } } -=== tests/cases/conformance/emitter/es2015/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : () => AsyncGenerator @@ -82,3 +82,18 @@ async function* f6() { >outer : any } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : () => AsyncGenerator + + let y: any; +>y : any + + for (;;) { + for await (const x of y) { +>x : any +>y : any + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2018.js b/tests/baselines/reference/emitter.forAwait(target=es2018).js similarity index 73% rename from tests/baselines/reference/emitter.forAwait.es2018.js rename to tests/baselines/reference/emitter.forAwait(target=es2018).js index f9ae2b1bd95..f111d9d4bc1 100644 --- a/tests/baselines/reference/emitter.forAwait.es2018.js +++ b/tests/baselines/reference/emitter.forAwait(target=es2018).js @@ -1,4 +1,4 @@ -//// [tests/cases/conformance/emitter/es2018/forAwait/emitter.forAwait.es2018.ts] //// +//// [tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts] //// //// [file1.ts] async function f1() { @@ -39,8 +39,16 @@ async function* f6() { outer: for await (const x of y) { continue outer; } -} - +} +//// [file7.ts] +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y: any; + for (;;) { + for await (const x of y) { + } + } +} //// [file1.js] async function f1() { @@ -82,3 +90,12 @@ async function* f6() { continue outer; } } +//// [file7.js] +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y; + for (;;) { + for await (const x of y) { + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2018.symbols b/tests/baselines/reference/emitter.forAwait(target=es2018).symbols similarity index 63% rename from tests/baselines/reference/emitter.forAwait.es2018.symbols rename to tests/baselines/reference/emitter.forAwait(target=es2018).symbols index c1beab7fb78..f32170c889a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2018.symbols +++ b/tests/baselines/reference/emitter.forAwait(target=es2018).symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2018/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : Symbol(f1, Decl(file1.ts, 0, 0)) @@ -10,7 +10,7 @@ async function f1() { >y : Symbol(y, Decl(file1.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2018/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : Symbol(f2, Decl(file2.ts, 0, 0)) @@ -23,7 +23,7 @@ async function f2() { >y : Symbol(y, Decl(file2.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2018/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : Symbol(f3, Decl(file3.ts, 0, 0)) @@ -35,7 +35,7 @@ async function* f3() { >y : Symbol(y, Decl(file3.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es2018/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : Symbol(f4, Decl(file4.ts, 0, 0)) @@ -48,7 +48,7 @@ async function* f4() { >y : Symbol(y, Decl(file4.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es2018/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : Symbol(f5, Decl(file5.ts, 0, 0)) @@ -63,7 +63,7 @@ async function f5() { continue outer; } } -=== tests/cases/conformance/emitter/es2018/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : Symbol(f6, Decl(file6.ts, 0, 0)) @@ -78,4 +78,18 @@ async function* f6() { continue outer; } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : Symbol(f7, Decl(file7.ts, 0, 0)) + let y: any; +>y : Symbol(y, Decl(file7.ts, 2, 7)) + + for (;;) { + for await (const x of y) { +>x : Symbol(x, Decl(file7.ts, 4, 24)) +>y : Symbol(y, Decl(file7.ts, 2, 7)) + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es2017.types b/tests/baselines/reference/emitter.forAwait(target=es2018).types similarity index 56% rename from tests/baselines/reference/emitter.forAwait.es2017.types rename to tests/baselines/reference/emitter.forAwait(target=es2018).types index 19642ddd677..406f669ab3a 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.types +++ b/tests/baselines/reference/emitter.forAwait(target=es2018).types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es2017/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : () => Promise @@ -10,7 +10,7 @@ async function f1() { >y : any } } -=== tests/cases/conformance/emitter/es2017/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : () => Promise @@ -23,7 +23,7 @@ async function f2() { >y : any } } -=== tests/cases/conformance/emitter/es2017/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : () => AsyncGenerator @@ -35,7 +35,7 @@ async function* f3() { >y : any } } -=== tests/cases/conformance/emitter/es2017/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : () => AsyncGenerator @@ -48,7 +48,7 @@ async function* f4() { >y : any } } -=== tests/cases/conformance/emitter/es2017/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : () => Promise @@ -65,7 +65,7 @@ async function f5() { >outer : any } } -=== tests/cases/conformance/emitter/es2017/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : () => AsyncGenerator @@ -82,3 +82,18 @@ async function* f6() { >outer : any } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : () => AsyncGenerator + + let y: any; +>y : any + + for (;;) { + for await (const x of y) { +>x : any +>y : any + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es5.js b/tests/baselines/reference/emitter.forAwait(target=es5).js similarity index 83% rename from tests/baselines/reference/emitter.forAwait.es5.js rename to tests/baselines/reference/emitter.forAwait(target=es5).js index f33af25dcc1..5b182d16d5c 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.js +++ b/tests/baselines/reference/emitter.forAwait(target=es5).js @@ -1,4 +1,4 @@ -//// [tests/cases/conformance/emitter/es5/forAwait/emitter.forAwait.es5.ts] //// +//// [tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts] //// //// [file1.ts] async function f1() { @@ -40,6 +40,15 @@ async function* f6() { continue outer; } } +//// [file7.ts] +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y: any; + for (;;) { + for await (const x of y) { + } + } +} //// [file1.js] var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { @@ -544,3 +553,90 @@ function f6() { }); }); } +//// [file7.js] +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +// https://github.com/microsoft/TypeScript/issues/36166 +function f7() { + return __asyncGenerator(this, arguments, function f7_1() { + var y, y_1, y_1_1, x, e_1_1; + var e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _b.trys.push([0, 5, 6, 11]); + y_1 = (e_1 = void 0, __asyncValues(y)); + _b.label = 1; + case 1: return [4 /*yield*/, __await(y_1.next())]; + case 2: + if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 4]; + x = y_1_1.value; + _b.label = 3; + case 3: return [3 /*break*/, 1]; + case 4: return [3 /*break*/, 11]; + case 5: + e_1_1 = _b.sent(); + e_1 = { error: e_1_1 }; + return [3 /*break*/, 11]; + case 6: + _b.trys.push([6, , 9, 10]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 8]; + return [4 /*yield*/, __await(_a.call(y_1))]; + case 7: + _b.sent(); + _b.label = 8; + case 8: return [3 /*break*/, 10]; + case 9: + if (e_1) throw e_1.error; + return [7 /*endfinally*/]; + case 10: return [7 /*endfinally*/]; + case 11: return [3 /*break*/, 0]; + case 12: return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/emitter.forAwait.es5.symbols b/tests/baselines/reference/emitter.forAwait(target=es5).symbols similarity index 63% rename from tests/baselines/reference/emitter.forAwait.es5.symbols rename to tests/baselines/reference/emitter.forAwait(target=es5).symbols index 05fb915c0fc..f32170c889a 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.symbols +++ b/tests/baselines/reference/emitter.forAwait(target=es5).symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es5/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : Symbol(f1, Decl(file1.ts, 0, 0)) @@ -10,7 +10,7 @@ async function f1() { >y : Symbol(y, Decl(file1.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es5/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : Symbol(f2, Decl(file2.ts, 0, 0)) @@ -23,7 +23,7 @@ async function f2() { >y : Symbol(y, Decl(file2.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es5/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : Symbol(f3, Decl(file3.ts, 0, 0)) @@ -35,7 +35,7 @@ async function* f3() { >y : Symbol(y, Decl(file3.ts, 1, 7)) } } -=== tests/cases/conformance/emitter/es5/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : Symbol(f4, Decl(file4.ts, 0, 0)) @@ -48,7 +48,7 @@ async function* f4() { >y : Symbol(y, Decl(file4.ts, 1, 15)) } } -=== tests/cases/conformance/emitter/es5/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : Symbol(f5, Decl(file5.ts, 0, 0)) @@ -63,7 +63,7 @@ async function f5() { continue outer; } } -=== tests/cases/conformance/emitter/es5/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : Symbol(f6, Decl(file6.ts, 0, 0)) @@ -78,3 +78,18 @@ async function* f6() { continue outer; } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : Symbol(f7, Decl(file7.ts, 0, 0)) + + let y: any; +>y : Symbol(y, Decl(file7.ts, 2, 7)) + + for (;;) { + for await (const x of y) { +>x : Symbol(x, Decl(file7.ts, 4, 24)) +>y : Symbol(y, Decl(file7.ts, 2, 7)) + } + } +} diff --git a/tests/baselines/reference/emitter.forAwait.es5.types b/tests/baselines/reference/emitter.forAwait(target=es5).types similarity index 56% rename from tests/baselines/reference/emitter.forAwait.es5.types rename to tests/baselines/reference/emitter.forAwait(target=es5).types index 1452be304b6..406f669ab3a 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.types +++ b/tests/baselines/reference/emitter.forAwait(target=es5).types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/emitter/es5/forAwait/file1.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file1.ts === async function f1() { >f1 : () => Promise @@ -10,7 +10,7 @@ async function f1() { >y : any } } -=== tests/cases/conformance/emitter/es5/forAwait/file2.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file2.ts === async function f2() { >f2 : () => Promise @@ -23,7 +23,7 @@ async function f2() { >y : any } } -=== tests/cases/conformance/emitter/es5/forAwait/file3.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file3.ts === async function* f3() { >f3 : () => AsyncGenerator @@ -35,7 +35,7 @@ async function* f3() { >y : any } } -=== tests/cases/conformance/emitter/es5/forAwait/file4.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file4.ts === async function* f4() { >f4 : () => AsyncGenerator @@ -48,7 +48,7 @@ async function* f4() { >y : any } } -=== tests/cases/conformance/emitter/es5/forAwait/file5.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file5.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { >f5 : () => Promise @@ -65,7 +65,7 @@ async function f5() { >outer : any } } -=== tests/cases/conformance/emitter/es5/forAwait/file6.ts === +=== tests/cases/conformance/statements/for-await-ofStatements/file6.ts === // https://github.com/Microsoft/TypeScript/issues/21363 async function* f6() { >f6 : () => AsyncGenerator @@ -82,3 +82,18 @@ async function* f6() { >outer : any } } +=== tests/cases/conformance/statements/for-await-ofStatements/file7.ts === +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { +>f7 : () => AsyncGenerator + + let y: any; +>y : any + + for (;;) { + for await (const x of y) { +>x : any +>y : any + } + } +} diff --git a/tests/cases/conformance/emitter/es2015/forAwait/emitter.forAwait.es2015.ts b/tests/cases/conformance/emitter/es2015/forAwait/emitter.forAwait.es2015.ts deleted file mode 100644 index 64b44e901e2..00000000000 --- a/tests/cases/conformance/emitter/es2015/forAwait/emitter.forAwait.es2015.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @target: es2015 -// @lib: esnext -// @filename: file1.ts -async function f1() { - let y: any; - for await (const x of y) { - } -} -// @filename: file2.ts -async function f2() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file3.ts -async function* f3() { - let y: any; - for await (const x of y) { - } -} -// @filename: file4.ts -async function* f4() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file5.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function f5() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} -// @filename: file6.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function* f6() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} \ No newline at end of file diff --git a/tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts b/tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts deleted file mode 100644 index f9d9fc3d4d9..00000000000 --- a/tests/cases/conformance/emitter/es2017/forAwait/emitter.forAwait.es2017.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @target: es2017 -// @lib: esnext -// @filename: file1.ts -async function f1() { - let y: any; - for await (const x of y) { - } -} -// @filename: file2.ts -async function f2() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file3.ts -async function* f3() { - let y: any; - for await (const x of y) { - } -} -// @filename: file4.ts -async function* f4() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file5.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function f5() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} -// @filename: file6.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function* f6() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} \ No newline at end of file diff --git a/tests/cases/conformance/emitter/es5/forAwait/emitter.forAwait.es5.ts b/tests/cases/conformance/emitter/es5/forAwait/emitter.forAwait.es5.ts deleted file mode 100644 index a441b0da2bd..00000000000 --- a/tests/cases/conformance/emitter/es5/forAwait/emitter.forAwait.es5.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @target: es5 -// @lib: esnext -// @filename: file1.ts -async function f1() { - let y: any; - for await (const x of y) { - } -} -// @filename: file2.ts -async function f2() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file3.ts -async function* f3() { - let y: any; - for await (const x of y) { - } -} -// @filename: file4.ts -async function* f4() { - let x: any, y: any; - for await (x of y) { - } -} -// @filename: file5.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function f5() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} -// @filename: file6.ts -// https://github.com/Microsoft/TypeScript/issues/21363 -async function* f6() { - let y: any; - outer: for await (const x of y) { - continue outer; - } -} \ No newline at end of file diff --git a/tests/cases/conformance/emitter/es2018/forAwait/emitter.forAwait.es2018.ts b/tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts similarity index 74% rename from tests/cases/conformance/emitter/es2018/forAwait/emitter.forAwait.es2018.ts rename to tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts index 02e875fb7e4..f61bc343261 100644 --- a/tests/cases/conformance/emitter/es2018/forAwait/emitter.forAwait.es2018.ts +++ b/tests/cases/conformance/statements/for-await-ofStatements/emitter.forAwait.ts @@ -1,4 +1,4 @@ -// @target: es2018 +// @target: es2018,es2017,es2015,es5 // @lib: esnext // @filename: file1.ts async function f1() { @@ -40,3 +40,12 @@ async function* f6() { continue outer; } } +// @filename: file7.ts +// https://github.com/microsoft/TypeScript/issues/36166 +async function* f7() { + let y: any; + for (;;) { + for await (const x of y) { + } + } +} \ No newline at end of file From b0b677649af966efe0fd6ef0b67ef9d2dbf1ccf4 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 24 Apr 2020 22:10:50 +0000 Subject: [PATCH 31/38] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 581fe36aa7f..d5e8c5cbdd1 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -10197,6 +10197,15 @@ + + + + + + + + + From 84c83da3a9cc2050997a7fd53d650d648fb128f3 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 24 Apr 2020 16:04:33 -0700 Subject: [PATCH 32/38] Revert #37106 (#38172) --- src/compiler/checker.ts | 2 +- tests/baselines/reference/inKeywordTypeguard.errors.txt | 5 ++++- tests/baselines/reference/inKeywordTypeguard.types | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f5754baff48..7cefe80e77e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20555,7 +20555,7 @@ namespace ts { } function narrowByInKeyword(type: Type, literal: LiteralExpression, assumeTrue: boolean) { - if (type.flags & (TypeFlags.Union | TypeFlags.Object | TypeFlags.Intersection) || isThisTypeParameter(type)) { + if (type.flags & (TypeFlags.Union | TypeFlags.Object) || isThisTypeParameter(type)) { const propName = escapeLeadingUnderscores(literal.text); return filterType(type, t => isTypePresencePossible(t, propName, assumeTrue)); } diff --git a/tests/baselines/reference/inKeywordTypeguard.errors.txt b/tests/baselines/reference/inKeywordTypeguard.errors.txt index f5885acfc88..5aa04b17042 100644 --- a/tests/baselines/reference/inKeywordTypeguard.errors.txt +++ b/tests/baselines/reference/inKeywordTypeguard.errors.txt @@ -19,9 +19,10 @@ tests/cases/compiler/inKeywordTypeguard.ts(74,32): error TS2339: Property 'a' do tests/cases/compiler/inKeywordTypeguard.ts(82,39): error TS2339: Property 'b' does not exist on type 'A'. tests/cases/compiler/inKeywordTypeguard.ts(84,39): error TS2339: Property 'a' does not exist on type 'B'. tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'. +tests/cases/compiler/inKeywordTypeguard.ts(103,13): error TS2322: Type '{ a: string; } & { b: string; }' is not assignable to type 'never'. -==== tests/cases/compiler/inKeywordTypeguard.ts (17 errors) ==== +==== tests/cases/compiler/inKeywordTypeguard.ts (18 errors) ==== class A { a: string; } class B { b: string; } @@ -163,6 +164,8 @@ tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' do let s: string = x.a; } else { let n: never = x; + ~ +!!! error TS2322: Type '{ a: string; } & { b: string; }' is not assignable to type 'never'. } } \ No newline at end of file diff --git a/tests/baselines/reference/inKeywordTypeguard.types b/tests/baselines/reference/inKeywordTypeguard.types index bd77a8da45e..b15ab47d454 100644 --- a/tests/baselines/reference/inKeywordTypeguard.types +++ b/tests/baselines/reference/inKeywordTypeguard.types @@ -318,7 +318,7 @@ function positiveIntersectionTest(x: { a: string } & { b: string }) { } else { let n: never = x; >n : never ->x : never +>x : { a: string; } & { b: string; } } } From 1b8c68d7463e22903978bcb4a8c7dc8e3f7b3beb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 24 Apr 2020 16:05:18 -0700 Subject: [PATCH 33/38] Revert "Add check for delete expression must be optional (#37921)" (#38154) This reverts commit 39beb1d011a6bc412a67e1dfa2ec1cb1de438b4f. --- src/compiler/checker.ts | 15 +- src/compiler/diagnosticMessages.json | 4 - .../controlFlowDeleteOperator.errors.txt | 5 +- .../reference/deleteChain.errors.txt | 66 --------- ...ionMustBeOptional(strict=false).errors.txt | 46 ------ ...eExpressionMustBeOptional(strict=false).js | 57 -------- ...essionMustBeOptional(strict=false).symbols | 118 --------------- ...pressionMustBeOptional(strict=false).types | 137 ------------------ ...sionMustBeOptional(strict=true).errors.txt | 52 ------- ...teExpressionMustBeOptional(strict=true).js | 58 -------- ...ressionMustBeOptional(strict=true).symbols | 118 --------------- ...xpressionMustBeOptional(strict=true).types | 137 ------------------ .../reference/privateNamesNoDelete.errors.txt | 5 +- .../deleteExpressionMustBeOptional.ts | 42 ------ 14 files changed, 4 insertions(+), 856 deletions(-) delete mode 100644 tests/baselines/reference/deleteChain.errors.txt delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols delete mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types delete mode 100644 tests/cases/compiler/deleteExpressionMustBeOptional.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7cefe80e77e..0bf27e3f07b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27682,23 +27682,12 @@ namespace ts { } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); - if (symbol) { - if (isReadonlySymbol(symbol)) { - error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); - } - - checkDeleteExpressionMustBeOptional(expr, getTypeOfSymbol(symbol)); + if (symbol && isReadonlySymbol(symbol)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); } return booleanType; } - function checkDeleteExpressionMustBeOptional(expr: AccessExpression, type: Type) { - const AnyOrUnknownOrNeverFlags = TypeFlags.AnyOrUnknown | TypeFlags.Never; - if (strictNullChecks && !(type.flags & AnyOrUnknownOrNeverFlags) && !(getFalsyFlags(type) & TypeFlags.Undefined)) { - error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); - } - } - function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); return typeofType; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 03f42608454..1df368c4286 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2963,10 +2963,6 @@ "category": "Error", "code": 2789 }, - "The operand of a 'delete' operator must be optional.": { - "category": "Error", - "code": 2790 - }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt index f5a6823a778..91ec2aa0de8 100644 --- a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt +++ b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt @@ -1,8 +1,7 @@ -tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(10,12): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error TS2703: The operand of a 'delete' operator must be a property reference. -==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (2 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (1 errors) ==== function f() { let x: { a?: number | string, b: number | string } = { b: 1 }; x.a; @@ -13,8 +12,6 @@ tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error T x.b; delete x.a; delete x.b; - ~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. x.a; x.b; x; diff --git a/tests/baselines/reference/deleteChain.errors.txt b/tests/baselines/reference/deleteChain.errors.txt deleted file mode 100644 index dd716419573..00000000000 --- a/tests/baselines/reference/deleteChain.errors.txt +++ /dev/null @@ -1,66 +0,0 @@ -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(2,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(3,9): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(6,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(7,9): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(10,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(11,9): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(14,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(15,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(16,9): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(19,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(20,9): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(23,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(24,9): error TS2790: The operand of a 'delete' operator must be optional. - - -==== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts (13 errors) ==== - declare const o1: undefined | { b: string }; - delete o1?.b; - ~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o1?.b); - ~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - - declare const o2: undefined | { b: { c: string } }; - delete o2?.b.c; - ~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o2?.b.c); - ~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - - declare const o3: { b: undefined | { c: string } }; - delete o3.b?.c; - ~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o3.b?.c); - ~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - - declare const o4: { b?: { c: { d?: { e: string } } } }; - delete o4.b?.c.d?.e; - ~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o4.b?.c.d)?.e; - ~~~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o4.b?.c.d?.e); - ~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - - declare const o5: { b?(): { c: { d?: { e: string } } } }; - delete o5.b?.().c.d?.e; - ~~~~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o5.b?.().c.d?.e); - ~~~~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - - declare const o6: { b?: { c: { d?: { e: string } } } }; - delete o6.b?.['c'].d?.['e']; - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete (o6.b?.['c'].d?.['e']); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt deleted file mode 100644 index 8a876cb6350..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt +++ /dev/null @@ -1,46 +0,0 @@ -tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. - - -==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (1 errors) ==== - interface Foo { - a: number - b: number | undefined - c: number | null - d?: number - e: number | undefined | null - f?: number | undefined | null - g: unknown - h: any - i: never - } - - interface AA { - [s: string]: number - } - - type BB = { - [P in keyof any]: number - } - - declare const f: Foo - declare const a: AA - declare const b: BB - - delete f.a - delete f.b - delete f.c - delete f.d - delete f.e - delete f.f - delete f.g - delete f.h - delete f.i - delete f.j - ~ -!!! error TS2339: Property 'j' does not exist on type 'Foo'. - - delete a.a - delete a.b - - delete b.a - delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js deleted file mode 100644 index 268c76175bf..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js +++ /dev/null @@ -1,57 +0,0 @@ -//// [deleteExpressionMustBeOptional.ts] -interface Foo { - a: number - b: number | undefined - c: number | null - d?: number - e: number | undefined | null - f?: number | undefined | null - g: unknown - h: any - i: never -} - -interface AA { - [s: string]: number -} - -type BB = { - [P in keyof any]: number -} - -declare const f: Foo -declare const a: AA -declare const b: BB - -delete f.a -delete f.b -delete f.c -delete f.d -delete f.e -delete f.f -delete f.g -delete f.h -delete f.i -delete f.j - -delete a.a -delete a.b - -delete b.a -delete b.b - -//// [deleteExpressionMustBeOptional.js] -delete f.a; -delete f.b; -delete f.c; -delete f.d; -delete f.e; -delete f.f; -delete f.g; -delete f.h; -delete f.i; -delete f.j; -delete a.a; -delete a.b; -delete b.a; -delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols deleted file mode 100644 index aad7423a133..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols +++ /dev/null @@ -1,118 +0,0 @@ -=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === -interface Foo { ->Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) - - a: number ->a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) - - b: number | undefined ->b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) - - c: number | null ->c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) - - d?: number ->d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) - - e: number | undefined | null ->e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) - - f?: number | undefined | null ->f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) - - g: unknown ->g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) - - h: any ->h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) - - i: never ->i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) -} - -interface AA { ->AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) - - [s: string]: number ->s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) -} - -type BB = { ->BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) - - [P in keyof any]: number ->P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) -} - -declare const f: Foo ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) - -declare const a: AA ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) ->AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) - -declare const b: BB ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) ->BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) - -delete f.a ->f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) - -delete f.b ->f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) - -delete f.c ->f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) - -delete f.d ->f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) - -delete f.e ->f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) - -delete f.f ->f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) - -delete f.g ->f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) - -delete f.h ->f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) - -delete f.i ->f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) - -delete f.j ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) - -delete a.a ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) - -delete a.b ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) - -delete b.a ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) - -delete b.b ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) - diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types deleted file mode 100644 index 371bb25e96d..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types +++ /dev/null @@ -1,137 +0,0 @@ -=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === -interface Foo { - a: number ->a : number - - b: number | undefined ->b : number - - c: number | null ->c : number ->null : null - - d?: number ->d : number - - e: number | undefined | null ->e : number ->null : null - - f?: number | undefined | null ->f : number ->null : null - - g: unknown ->g : unknown - - h: any ->h : any - - i: never ->i : never -} - -interface AA { - [s: string]: number ->s : string -} - -type BB = { ->BB : BB - - [P in keyof any]: number -} - -declare const f: Foo ->f : Foo - -declare const a: AA ->a : AA - -declare const b: BB ->b : BB - -delete f.a ->delete f.a : boolean ->f.a : number ->f : Foo ->a : number - -delete f.b ->delete f.b : boolean ->f.b : number ->f : Foo ->b : number - -delete f.c ->delete f.c : boolean ->f.c : number ->f : Foo ->c : number - -delete f.d ->delete f.d : boolean ->f.d : number ->f : Foo ->d : number - -delete f.e ->delete f.e : boolean ->f.e : number ->f : Foo ->e : number - -delete f.f ->delete f.f : boolean ->f.f : number ->f : Foo ->f : number - -delete f.g ->delete f.g : boolean ->f.g : unknown ->f : Foo ->g : unknown - -delete f.h ->delete f.h : boolean ->f.h : any ->f : Foo ->h : any - -delete f.i ->delete f.i : boolean ->f.i : never ->f : Foo ->i : never - -delete f.j ->delete f.j : boolean ->f.j : any ->f : Foo ->j : any - -delete a.a ->delete a.a : boolean ->a.a : number ->a : AA ->a : number - -delete a.b ->delete a.b : boolean ->a.b : number ->a : AA ->b : number - -delete b.a ->delete b.a : boolean ->b.a : number ->b : BB ->a : number - -delete b.b ->delete b.b : boolean ->b.b : number ->b : BB ->b : number - diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt deleted file mode 100644 index b1cabc96009..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt +++ /dev/null @@ -1,52 +0,0 @@ -tests/cases/compiler/deleteExpressionMustBeOptional.ts(25,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/compiler/deleteExpressionMustBeOptional.ts(27,8): error TS2790: The operand of a 'delete' operator must be optional. -tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. - - -==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (3 errors) ==== - interface Foo { - a: number - b: number | undefined - c: number | null - d?: number - e: number | undefined | null - f?: number | undefined | null - g: unknown - h: any - i: never - } - - interface AA { - [s: string]: number - } - - type BB = { - [P in keyof any]: number - } - - declare const f: Foo - declare const a: AA - declare const b: BB - - delete f.a - ~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete f.b - delete f.c - ~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - delete f.d - delete f.e - delete f.f - delete f.g - delete f.h - delete f.i - delete f.j - ~ -!!! error TS2339: Property 'j' does not exist on type 'Foo'. - - delete a.a - delete a.b - - delete b.a - delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js deleted file mode 100644 index ca81456b4f4..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js +++ /dev/null @@ -1,58 +0,0 @@ -//// [deleteExpressionMustBeOptional.ts] -interface Foo { - a: number - b: number | undefined - c: number | null - d?: number - e: number | undefined | null - f?: number | undefined | null - g: unknown - h: any - i: never -} - -interface AA { - [s: string]: number -} - -type BB = { - [P in keyof any]: number -} - -declare const f: Foo -declare const a: AA -declare const b: BB - -delete f.a -delete f.b -delete f.c -delete f.d -delete f.e -delete f.f -delete f.g -delete f.h -delete f.i -delete f.j - -delete a.a -delete a.b - -delete b.a -delete b.b - -//// [deleteExpressionMustBeOptional.js] -"use strict"; -delete f.a; -delete f.b; -delete f.c; -delete f.d; -delete f.e; -delete f.f; -delete f.g; -delete f.h; -delete f.i; -delete f.j; -delete a.a; -delete a.b; -delete b.a; -delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols deleted file mode 100644 index aad7423a133..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols +++ /dev/null @@ -1,118 +0,0 @@ -=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === -interface Foo { ->Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) - - a: number ->a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) - - b: number | undefined ->b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) - - c: number | null ->c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) - - d?: number ->d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) - - e: number | undefined | null ->e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) - - f?: number | undefined | null ->f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) - - g: unknown ->g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) - - h: any ->h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) - - i: never ->i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) -} - -interface AA { ->AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) - - [s: string]: number ->s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) -} - -type BB = { ->BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) - - [P in keyof any]: number ->P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) -} - -declare const f: Foo ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) - -declare const a: AA ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) ->AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) - -declare const b: BB ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) ->BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) - -delete f.a ->f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) - -delete f.b ->f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) - -delete f.c ->f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) - -delete f.d ->f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) - -delete f.e ->f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) - -delete f.f ->f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) - -delete f.g ->f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) - -delete f.h ->f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) - -delete f.i ->f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) ->i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) - -delete f.j ->f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) - -delete a.a ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) - -delete a.b ->a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) - -delete b.a ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) - -delete b.b ->b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) - diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types deleted file mode 100644 index a3d6f52b7c4..00000000000 --- a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types +++ /dev/null @@ -1,137 +0,0 @@ -=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === -interface Foo { - a: number ->a : number - - b: number | undefined ->b : number | undefined - - c: number | null ->c : number | null ->null : null - - d?: number ->d : number | undefined - - e: number | undefined | null ->e : number | null | undefined ->null : null - - f?: number | undefined | null ->f : number | null | undefined ->null : null - - g: unknown ->g : unknown - - h: any ->h : any - - i: never ->i : never -} - -interface AA { - [s: string]: number ->s : string -} - -type BB = { ->BB : BB - - [P in keyof any]: number -} - -declare const f: Foo ->f : Foo - -declare const a: AA ->a : AA - -declare const b: BB ->b : BB - -delete f.a ->delete f.a : boolean ->f.a : number ->f : Foo ->a : number - -delete f.b ->delete f.b : boolean ->f.b : number | undefined ->f : Foo ->b : number | undefined - -delete f.c ->delete f.c : boolean ->f.c : number | null ->f : Foo ->c : number | null - -delete f.d ->delete f.d : boolean ->f.d : number | undefined ->f : Foo ->d : number | undefined - -delete f.e ->delete f.e : boolean ->f.e : number | null | undefined ->f : Foo ->e : number | null | undefined - -delete f.f ->delete f.f : boolean ->f.f : number | null | undefined ->f : Foo ->f : number | null | undefined - -delete f.g ->delete f.g : boolean ->f.g : unknown ->f : Foo ->g : unknown - -delete f.h ->delete f.h : boolean ->f.h : any ->f : Foo ->h : any - -delete f.i ->delete f.i : boolean ->f.i : never ->f : Foo ->i : never - -delete f.j ->delete f.j : boolean ->f.j : any ->f : Foo ->j : any - -delete a.a ->delete a.a : boolean ->a.a : number ->a : AA ->a : number - -delete a.b ->delete a.b : boolean ->a.b : number ->a : AA ->b : number - -delete b.a ->delete b.a : boolean ->b.a : number ->b : BB ->a : number - -delete b.b ->delete b.b : boolean ->b.b : number ->b : BB ->b : number - diff --git a/tests/baselines/reference/privateNamesNoDelete.errors.txt b/tests/baselines/reference/privateNamesNoDelete.errors.txt index e2fc11cb4ac..d593fe107a1 100644 --- a/tests/baselines/reference/privateNamesNoDelete.errors.txt +++ b/tests/baselines/reference/privateNamesNoDelete.errors.txt @@ -1,15 +1,12 @@ -tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS18011: The operand of a 'delete' operator cannot be a private identifier. -==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (2 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ==== class A { #v = 1; constructor() { delete this.#v; // Error: The operand of a delete operator cannot be a private name. ~~~~~~~ -!!! error TS2790: The operand of a 'delete' operator must be optional. - ~~~~~~~ !!! error TS18011: The operand of a 'delete' operator cannot be a private identifier. } } diff --git a/tests/cases/compiler/deleteExpressionMustBeOptional.ts b/tests/cases/compiler/deleteExpressionMustBeOptional.ts deleted file mode 100644 index 9f84d9ea2f1..00000000000 --- a/tests/cases/compiler/deleteExpressionMustBeOptional.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @strict: true, false - -interface Foo { - a: number - b: number | undefined - c: number | null - d?: number - e: number | undefined | null - f?: number | undefined | null - g: unknown - h: any - i: never -} - -interface AA { - [s: string]: number -} - -type BB = { - [P in keyof any]: number -} - -declare const f: Foo -declare const a: AA -declare const b: BB - -delete f.a -delete f.b -delete f.c -delete f.d -delete f.e -delete f.f -delete f.g -delete f.h -delete f.i -delete f.j - -delete a.a -delete a.b - -delete b.a -delete b.b \ No newline at end of file From 4a5eeb0bb21bbcc795bf8edb7d391bb3694c295a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 24 Apr 2020 18:33:30 -0700 Subject: [PATCH 34/38] Skip comparing optional property flag when comparing against discriminant properties (#38101) --- src/compiler/checker.ts | 8 ++++---- .../reference/unionRelationshipCheckPasses.js | 7 +++++++ .../reference/unionRelationshipCheckPasses.symbols | 7 +++++++ .../reference/unionRelationshipCheckPasses.types | 10 ++++++++++ tests/cases/compiler/unionRelationshipCheckPasses.ts | 2 ++ 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/unionRelationshipCheckPasses.js create mode 100644 tests/baselines/reference/unionRelationshipCheckPasses.symbols create mode 100644 tests/baselines/reference/unionRelationshipCheckPasses.types create mode 100644 tests/cases/compiler/unionRelationshipCheckPasses.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0bf27e3f07b..25e25e43757 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16639,7 +16639,7 @@ namespace ts { if (!targetProperty) continue outer; if (sourceProperty === targetProperty) continue; // We compare the source property to the target in the context of a single discriminant type. - const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None); + const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation); // If the target property could not be found, or if the properties were not related, // then this constituent is not a match. if (!related) { @@ -16737,7 +16737,7 @@ namespace ts { } } - function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary { const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) { @@ -16780,7 +16780,7 @@ namespace ts { return Ternary.False; } // When checking for comparability, be more lenient with optional properties. - if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) { + if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) { // TypeScript 1.0 spec (April 2014): 3.8.3 // S is a subtype of a type T, and T is a supertype of S if ... // S' and T are object types and, for each member M in T.. @@ -16910,7 +16910,7 @@ namespace ts { if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) { const sourceProp = getPropertyOfType(source, name); if (sourceProp && sourceProp !== targetProp) { - const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState); + const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation); if (!related) { return Ternary.False; } diff --git a/tests/baselines/reference/unionRelationshipCheckPasses.js b/tests/baselines/reference/unionRelationshipCheckPasses.js new file mode 100644 index 00000000000..65e90ed34e8 --- /dev/null +++ b/tests/baselines/reference/unionRelationshipCheckPasses.js @@ -0,0 +1,7 @@ +//// [unionRelationshipCheckPasses.ts] +const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined }; + + +//// [unionRelationshipCheckPasses.js] +"use strict"; +var item = null; diff --git a/tests/baselines/reference/unionRelationshipCheckPasses.symbols b/tests/baselines/reference/unionRelationshipCheckPasses.symbols new file mode 100644 index 00000000000..3fda4578bdb --- /dev/null +++ b/tests/baselines/reference/unionRelationshipCheckPasses.symbols @@ -0,0 +1,7 @@ +=== tests/cases/compiler/unionRelationshipCheckPasses.ts === +const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined }; +>item : Symbol(item, Decl(unionRelationshipCheckPasses.ts, 0, 5)) +>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 13)) +>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 35)) +>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 68)) + diff --git a/tests/baselines/reference/unionRelationshipCheckPasses.types b/tests/baselines/reference/unionRelationshipCheckPasses.types new file mode 100644 index 00000000000..e0e582916bb --- /dev/null +++ b/tests/baselines/reference/unionRelationshipCheckPasses.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/unionRelationshipCheckPasses.ts === +const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined }; +>item : { foo?: undefined; } | { foo: number; } +>foo : undefined +>foo : number +>null as any as { foo?: number | undefined } : { foo?: number | undefined; } +>null as any : any +>null : null +>foo : number | undefined + diff --git a/tests/cases/compiler/unionRelationshipCheckPasses.ts b/tests/cases/compiler/unionRelationshipCheckPasses.ts new file mode 100644 index 00000000000..cec4cffbf08 --- /dev/null +++ b/tests/cases/compiler/unionRelationshipCheckPasses.ts @@ -0,0 +1,2 @@ +// @strict: true +const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined }; From 730bec81d1a6f903c4ee6c020e23a411230ac855 Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 25 Apr 2020 04:11:05 +0000 Subject: [PATCH 35/38] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 19 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 9 +++++++++ .../diagnosticMessages.generated.json.lcl | 17 +++++++++++++---- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9202ae5f4c0..a9eebf3b5b4 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3202,7 +3202,7 @@ - + @@ -5650,7 +5650,7 @@ - + @@ -10206,6 +10206,15 @@ + + + + + + + + + @@ -10330,7 +10339,7 @@ - + @@ -11125,7 +11134,7 @@ - + @@ -11686,7 +11695,7 @@ - + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 81b11ca7e68..439b7e2aff7 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -10209,6 +10209,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index ee5f3358f1b..89a10086f4c 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3186,7 +3186,7 @@ - + @@ -7821,7 +7821,7 @@ - + @@ -10187,6 +10187,15 @@ + + + + + + + + + @@ -11106,7 +11115,7 @@ - + @@ -11667,7 +11676,7 @@ - + From 6a6c83cf9acec4a7932675dfed9181dea0ca0afe Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 27 Apr 2020 13:23:45 -0700 Subject: [PATCH 36/38] Revert "Revert "Add check for delete expression must be optional (#37921)" (#38154)" (#38173) This reverts commit 1b8c68d7463e22903978bcb4a8c7dc8e3f7b3beb. --- src/compiler/checker.ts | 15 +- src/compiler/diagnosticMessages.json | 4 + .../controlFlowDeleteOperator.errors.txt | 5 +- .../reference/deleteChain.errors.txt | 66 +++++++++ ...ionMustBeOptional(strict=false).errors.txt | 46 ++++++ ...eExpressionMustBeOptional(strict=false).js | 57 ++++++++ ...essionMustBeOptional(strict=false).symbols | 118 +++++++++++++++ ...pressionMustBeOptional(strict=false).types | 137 ++++++++++++++++++ ...sionMustBeOptional(strict=true).errors.txt | 52 +++++++ ...teExpressionMustBeOptional(strict=true).js | 58 ++++++++ ...ressionMustBeOptional(strict=true).symbols | 118 +++++++++++++++ ...xpressionMustBeOptional(strict=true).types | 137 ++++++++++++++++++ .../reference/privateNamesNoDelete.errors.txt | 5 +- .../deleteExpressionMustBeOptional.ts | 42 ++++++ 14 files changed, 856 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/deleteChain.errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols create mode 100644 tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types create mode 100644 tests/cases/compiler/deleteExpressionMustBeOptional.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 25e25e43757..93276c42cb3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27682,12 +27682,23 @@ namespace ts { } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); - if (symbol && isReadonlySymbol(symbol)) { - error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); + if (symbol) { + if (isReadonlySymbol(symbol)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); + } + + checkDeleteExpressionMustBeOptional(expr, getTypeOfSymbol(symbol)); } return booleanType; } + function checkDeleteExpressionMustBeOptional(expr: AccessExpression, type: Type) { + const AnyOrUnknownOrNeverFlags = TypeFlags.AnyOrUnknown | TypeFlags.Never; + if (strictNullChecks && !(type.flags & AnyOrUnknownOrNeverFlags) && !(getFalsyFlags(type) & TypeFlags.Undefined)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); + } + } + function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); return typeofType; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1df368c4286..03f42608454 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2963,6 +2963,10 @@ "category": "Error", "code": 2789 }, + "The operand of a 'delete' operator must be optional.": { + "category": "Error", + "code": 2790 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt index 91ec2aa0de8..f5a6823a778 100644 --- a/tests/baselines/reference/controlFlowDeleteOperator.errors.txt +++ b/tests/baselines/reference/controlFlowDeleteOperator.errors.txt @@ -1,7 +1,8 @@ +tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(10,12): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error TS2703: The operand of a 'delete' operator must be a property reference. -==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (1 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts (2 errors) ==== function f() { let x: { a?: number | string, b: number | string } = { b: 1 }; x.a; @@ -12,6 +13,8 @@ tests/cases/conformance/controlFlow/controlFlowDeleteOperator.ts(14,12): error T x.b; delete x.a; delete x.b; + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. x.a; x.b; x; diff --git a/tests/baselines/reference/deleteChain.errors.txt b/tests/baselines/reference/deleteChain.errors.txt new file mode 100644 index 00000000000..dd716419573 --- /dev/null +++ b/tests/baselines/reference/deleteChain.errors.txt @@ -0,0 +1,66 @@ +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(2,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(3,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(6,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(7,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(10,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(11,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(14,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(15,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(16,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(19,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(20,9): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(23,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts(24,9): error TS2790: The operand of a 'delete' operator must be optional. + + +==== tests/cases/conformance/expressions/optionalChaining/delete/deleteChain.ts (13 errors) ==== + declare const o1: undefined | { b: string }; + delete o1?.b; + ~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o1?.b); + ~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o2: undefined | { b: { c: string } }; + delete o2?.b.c; + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o2?.b.c); + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o3: { b: undefined | { c: string } }; + delete o3.b?.c; + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o3.b?.c); + ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o4: { b?: { c: { d?: { e: string } } } }; + delete o4.b?.c.d?.e; + ~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o4.b?.c.d)?.e; + ~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o4.b?.c.d?.e); + ~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o5: { b?(): { c: { d?: { e: string } } } }; + delete o5.b?.().c.d?.e; + ~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o5.b?.().c.d?.e); + ~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + + declare const o6: { b?: { c: { d?: { e: string } } } }; + delete o6.b?.['c'].d?.['e']; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete (o6.b?.['c'].d?.['e']); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt new file mode 100644 index 00000000000..8a876cb6350 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).errors.txt @@ -0,0 +1,46 @@ +tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. + + +==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (1 errors) ==== + interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never + } + + interface AA { + [s: string]: number + } + + type BB = { + [P in keyof any]: number + } + + declare const f: Foo + declare const a: AA + declare const b: BB + + delete f.a + delete f.b + delete f.c + delete f.d + delete f.e + delete f.f + delete f.g + delete f.h + delete f.i + delete f.j + ~ +!!! error TS2339: Property 'j' does not exist on type 'Foo'. + + delete a.a + delete a.b + + delete b.a + delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js new file mode 100644 index 00000000000..268c76175bf --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).js @@ -0,0 +1,57 @@ +//// [deleteExpressionMustBeOptional.ts] +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b + +//// [deleteExpressionMustBeOptional.js] +delete f.a; +delete f.b; +delete f.c; +delete f.d; +delete f.e; +delete f.f; +delete f.g; +delete f.h; +delete f.i; +delete f.j; +delete a.a; +delete a.b; +delete b.a; +delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols new file mode 100644 index 00000000000..aad7423a133 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).symbols @@ -0,0 +1,118 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + + a: number +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + + b: number | undefined +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + + c: number | null +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + + d?: number +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + + e: number | undefined | null +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + + f?: number | undefined | null +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + + g: unknown +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + + h: any +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + + i: never +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +} + +interface AA { +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + + [s: string]: number +>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) +} + +type BB = { +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + + [P in keyof any]: number +>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) +} + +declare const f: Foo +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + +declare const a: AA +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + +declare const b: BB +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + +delete f.a +>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + +delete f.b +>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + +delete f.c +>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + +delete f.d +>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + +delete f.e +>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + +delete f.f +>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + +delete f.g +>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + +delete f.h +>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + +delete f.i +>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) + +delete f.j +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) + +delete a.a +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete a.b +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete b.a +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + +delete b.b +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types new file mode 100644 index 00000000000..371bb25e96d --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=false).types @@ -0,0 +1,137 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { + a: number +>a : number + + b: number | undefined +>b : number + + c: number | null +>c : number +>null : null + + d?: number +>d : number + + e: number | undefined | null +>e : number +>null : null + + f?: number | undefined | null +>f : number +>null : null + + g: unknown +>g : unknown + + h: any +>h : any + + i: never +>i : never +} + +interface AA { + [s: string]: number +>s : string +} + +type BB = { +>BB : BB + + [P in keyof any]: number +} + +declare const f: Foo +>f : Foo + +declare const a: AA +>a : AA + +declare const b: BB +>b : BB + +delete f.a +>delete f.a : boolean +>f.a : number +>f : Foo +>a : number + +delete f.b +>delete f.b : boolean +>f.b : number +>f : Foo +>b : number + +delete f.c +>delete f.c : boolean +>f.c : number +>f : Foo +>c : number + +delete f.d +>delete f.d : boolean +>f.d : number +>f : Foo +>d : number + +delete f.e +>delete f.e : boolean +>f.e : number +>f : Foo +>e : number + +delete f.f +>delete f.f : boolean +>f.f : number +>f : Foo +>f : number + +delete f.g +>delete f.g : boolean +>f.g : unknown +>f : Foo +>g : unknown + +delete f.h +>delete f.h : boolean +>f.h : any +>f : Foo +>h : any + +delete f.i +>delete f.i : boolean +>f.i : never +>f : Foo +>i : never + +delete f.j +>delete f.j : boolean +>f.j : any +>f : Foo +>j : any + +delete a.a +>delete a.a : boolean +>a.a : number +>a : AA +>a : number + +delete a.b +>delete a.b : boolean +>a.b : number +>a : AA +>b : number + +delete b.a +>delete b.a : boolean +>b.a : number +>b : BB +>a : number + +delete b.b +>delete b.b : boolean +>b.b : number +>b : BB +>b : number + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt new file mode 100644 index 00000000000..b1cabc96009 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).errors.txt @@ -0,0 +1,52 @@ +tests/cases/compiler/deleteExpressionMustBeOptional.ts(25,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/compiler/deleteExpressionMustBeOptional.ts(27,8): error TS2790: The operand of a 'delete' operator must be optional. +tests/cases/compiler/deleteExpressionMustBeOptional.ts(34,10): error TS2339: Property 'j' does not exist on type 'Foo'. + + +==== tests/cases/compiler/deleteExpressionMustBeOptional.ts (3 errors) ==== + interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never + } + + interface AA { + [s: string]: number + } + + type BB = { + [P in keyof any]: number + } + + declare const f: Foo + declare const a: AA + declare const b: BB + + delete f.a + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete f.b + delete f.c + ~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + delete f.d + delete f.e + delete f.f + delete f.g + delete f.h + delete f.i + delete f.j + ~ +!!! error TS2339: Property 'j' does not exist on type 'Foo'. + + delete a.a + delete a.b + + delete b.a + delete b.b \ No newline at end of file diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js new file mode 100644 index 00000000000..ca81456b4f4 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).js @@ -0,0 +1,58 @@ +//// [deleteExpressionMustBeOptional.ts] +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b + +//// [deleteExpressionMustBeOptional.js] +"use strict"; +delete f.a; +delete f.b; +delete f.c; +delete f.d; +delete f.e; +delete f.f; +delete f.g; +delete f.h; +delete f.i; +delete f.j; +delete a.a; +delete a.b; +delete b.a; +delete b.b; diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols new file mode 100644 index 00000000000..aad7423a133 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).symbols @@ -0,0 +1,118 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + + a: number +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + + b: number | undefined +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + + c: number | null +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + + d?: number +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + + e: number | undefined | null +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + + f?: number | undefined | null +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + + g: unknown +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + + h: any +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + + i: never +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +} + +interface AA { +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + + [s: string]: number +>s : Symbol(s, Decl(deleteExpressionMustBeOptional.ts, 13, 5)) +} + +type BB = { +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + + [P in keyof any]: number +>P : Symbol(P, Decl(deleteExpressionMustBeOptional.ts, 17, 5)) +} + +declare const f: Foo +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>Foo : Symbol(Foo, Decl(deleteExpressionMustBeOptional.ts, 0, 0)) + +declare const a: AA +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) +>AA : Symbol(AA, Decl(deleteExpressionMustBeOptional.ts, 10, 1)) + +declare const b: BB +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) +>BB : Symbol(BB, Decl(deleteExpressionMustBeOptional.ts, 14, 1)) + +delete f.a +>f.a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>a : Symbol(Foo.a, Decl(deleteExpressionMustBeOptional.ts, 0, 15)) + +delete f.b +>f.b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>b : Symbol(Foo.b, Decl(deleteExpressionMustBeOptional.ts, 1, 13)) + +delete f.c +>f.c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>c : Symbol(Foo.c, Decl(deleteExpressionMustBeOptional.ts, 2, 25)) + +delete f.d +>f.d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>d : Symbol(Foo.d, Decl(deleteExpressionMustBeOptional.ts, 3, 20)) + +delete f.e +>f.e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>e : Symbol(Foo.e, Decl(deleteExpressionMustBeOptional.ts, 4, 14)) + +delete f.f +>f.f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>f : Symbol(Foo.f, Decl(deleteExpressionMustBeOptional.ts, 5, 32)) + +delete f.g +>f.g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>g : Symbol(Foo.g, Decl(deleteExpressionMustBeOptional.ts, 6, 33)) + +delete f.h +>f.h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>h : Symbol(Foo.h, Decl(deleteExpressionMustBeOptional.ts, 7, 14)) + +delete f.i +>f.i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) +>i : Symbol(Foo.i, Decl(deleteExpressionMustBeOptional.ts, 8, 10)) + +delete f.j +>f : Symbol(f, Decl(deleteExpressionMustBeOptional.ts, 20, 13)) + +delete a.a +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete a.b +>a : Symbol(a, Decl(deleteExpressionMustBeOptional.ts, 21, 13)) + +delete b.a +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + +delete b.b +>b : Symbol(b, Decl(deleteExpressionMustBeOptional.ts, 22, 13)) + diff --git a/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types new file mode 100644 index 00000000000..a3d6f52b7c4 --- /dev/null +++ b/tests/baselines/reference/deleteExpressionMustBeOptional(strict=true).types @@ -0,0 +1,137 @@ +=== tests/cases/compiler/deleteExpressionMustBeOptional.ts === +interface Foo { + a: number +>a : number + + b: number | undefined +>b : number | undefined + + c: number | null +>c : number | null +>null : null + + d?: number +>d : number | undefined + + e: number | undefined | null +>e : number | null | undefined +>null : null + + f?: number | undefined | null +>f : number | null | undefined +>null : null + + g: unknown +>g : unknown + + h: any +>h : any + + i: never +>i : never +} + +interface AA { + [s: string]: number +>s : string +} + +type BB = { +>BB : BB + + [P in keyof any]: number +} + +declare const f: Foo +>f : Foo + +declare const a: AA +>a : AA + +declare const b: BB +>b : BB + +delete f.a +>delete f.a : boolean +>f.a : number +>f : Foo +>a : number + +delete f.b +>delete f.b : boolean +>f.b : number | undefined +>f : Foo +>b : number | undefined + +delete f.c +>delete f.c : boolean +>f.c : number | null +>f : Foo +>c : number | null + +delete f.d +>delete f.d : boolean +>f.d : number | undefined +>f : Foo +>d : number | undefined + +delete f.e +>delete f.e : boolean +>f.e : number | null | undefined +>f : Foo +>e : number | null | undefined + +delete f.f +>delete f.f : boolean +>f.f : number | null | undefined +>f : Foo +>f : number | null | undefined + +delete f.g +>delete f.g : boolean +>f.g : unknown +>f : Foo +>g : unknown + +delete f.h +>delete f.h : boolean +>f.h : any +>f : Foo +>h : any + +delete f.i +>delete f.i : boolean +>f.i : never +>f : Foo +>i : never + +delete f.j +>delete f.j : boolean +>f.j : any +>f : Foo +>j : any + +delete a.a +>delete a.a : boolean +>a.a : number +>a : AA +>a : number + +delete a.b +>delete a.b : boolean +>a.b : number +>a : AA +>b : number + +delete b.a +>delete b.a : boolean +>b.a : number +>b : BB +>a : number + +delete b.b +>delete b.b : boolean +>b.b : number +>b : BB +>b : number + diff --git a/tests/baselines/reference/privateNamesNoDelete.errors.txt b/tests/baselines/reference/privateNamesNoDelete.errors.txt index d593fe107a1..e2fc11cb4ac 100644 --- a/tests/baselines/reference/privateNamesNoDelete.errors.txt +++ b/tests/baselines/reference/privateNamesNoDelete.errors.txt @@ -1,12 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS2790: The operand of a 'delete' operator must be optional. tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(4,16): error TS18011: The operand of a 'delete' operator cannot be a private identifier. -==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (2 errors) ==== class A { #v = 1; constructor() { delete this.#v; // Error: The operand of a delete operator cannot be a private name. ~~~~~~~ +!!! error TS2790: The operand of a 'delete' operator must be optional. + ~~~~~~~ !!! error TS18011: The operand of a 'delete' operator cannot be a private identifier. } } diff --git a/tests/cases/compiler/deleteExpressionMustBeOptional.ts b/tests/cases/compiler/deleteExpressionMustBeOptional.ts new file mode 100644 index 00000000000..9f84d9ea2f1 --- /dev/null +++ b/tests/cases/compiler/deleteExpressionMustBeOptional.ts @@ -0,0 +1,42 @@ +// @strict: true, false + +interface Foo { + a: number + b: number | undefined + c: number | null + d?: number + e: number | undefined | null + f?: number | undefined | null + g: unknown + h: any + i: never +} + +interface AA { + [s: string]: number +} + +type BB = { + [P in keyof any]: number +} + +declare const f: Foo +declare const a: AA +declare const b: BB + +delete f.a +delete f.b +delete f.c +delete f.d +delete f.e +delete f.f +delete f.g +delete f.h +delete f.i +delete f.j + +delete a.a +delete a.b + +delete b.a +delete b.b \ No newline at end of file From 466d0c0ecb07dd8740483475b67d9e8adacf04aa Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 27 Apr 2020 14:09:58 -0700 Subject: [PATCH 37/38] Bump version number to 4.0 (#38215) --- package.json | 2 +- src/compiler/corePublic.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 824e08f2f49..6fa73b0e28c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "3.9.0", + "version": "4.0.0", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index c3a258cd84e..835779639dc 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -1,7 +1,7 @@ namespace ts { // WARNING: The script `configurePrerelease.ts` uses a regexp to parse out these values. // If changing the text in this section, be sure to test `configurePrerelease` too. - export const versionMajorMinor = "3.9"; + export const versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ export const version = `${versionMajorMinor}.0-dev`; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e45bd38e2de..27bd23efaa3 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -14,7 +14,7 @@ and limitations under the License. ***************************************************************************** */ declare namespace ts { - const versionMajorMinor = "3.9"; + const versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ const version: string; /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 62e8560ae48..068380e2ad5 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -14,7 +14,7 @@ and limitations under the License. ***************************************************************************** */ declare namespace ts { - const versionMajorMinor = "3.9"; + const versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ const version: string; /** From 167f954ec7cf456238cad4f2006fb330c53bba8e Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Mon, 27 Apr 2020 16:18:39 -0700 Subject: [PATCH 38/38] Handle undefined in indent helper (#38217) * Handle undefined in indent helper Telemetry shows that it's called with undefined (probably `stderr` in an error scenario?). * Add undefined to parameter type --- src/typingsInstaller/nodeTypingsInstaller.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index 56b490e709d..ab050fd60bf 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -246,7 +246,9 @@ namespace ts.server.typingsInstaller { const installer = new NodeTypingsInstaller(globalTypingsCacheLocation!, typingSafeListLocation!, typesMapLocation!, npmLocation, validateDefaultNpmLocation, /*throttleLimit*/5, log); // TODO: GH#18217 installer.listen(); - function indent(newline: string, str: string): string { - return `${newline} ` + str.replace(/\r?\n/, `${newline} `); + function indent(newline: string, str: string | undefined): string { + return str && str.length + ? `${newline} ` + str.replace(/\r?\n/, `${newline} `) + : ""; } }