From cdf5b7aeb382be8ccc946a687be0c803c6ff89ab Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 7 Jun 2016 17:37:18 -0700 Subject: [PATCH] Add tests --- .../reference/typeGuardsNestedAssignments.js | 86 ++++++++++ .../typeGuardsNestedAssignments.symbols | 113 +++++++++++++ .../typeGuardsNestedAssignments.types | 155 ++++++++++++++++++ .../typeGuardsNestedAssignments.ts | 47 ++++++ 4 files changed, 401 insertions(+) create mode 100644 tests/baselines/reference/typeGuardsNestedAssignments.js create mode 100644 tests/baselines/reference/typeGuardsNestedAssignments.symbols create mode 100644 tests/baselines/reference/typeGuardsNestedAssignments.types create mode 100644 tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts diff --git a/tests/baselines/reference/typeGuardsNestedAssignments.js b/tests/baselines/reference/typeGuardsNestedAssignments.js new file mode 100644 index 00000000000..f37db041006 --- /dev/null +++ b/tests/baselines/reference/typeGuardsNestedAssignments.js @@ -0,0 +1,86 @@ +//// [typeGuardsNestedAssignments.ts] + +class Foo { + x: string; +} + +declare function getFooOrNull(): Foo | null; +declare function getStringOrNumberOrNull(): string | number | null; + +function f1() { + let foo: Foo | null; + if ((foo = getFooOrNull()) !== null) { + foo; // Foo + } +} + +function f2() { + let foo1: Foo | null; + let foo2: Foo | null; + if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { + foo1; // Foo | null + foo2; // Foo + } +} + +function f3() { + let obj: Object | null; + if ((obj = getFooOrNull()) instanceof Foo) { + obj; + } +} + +function f4() { + let x: string | number | null; + if (typeof (x = getStringOrNumberOrNull()) === "number") { + x; + } +} + +// Repro from #8851 + +const re = /./g +let match: RegExpExecArray | null + +while ((match = re.exec("xxx")) != null) { + const length = match[1].length + match[2].length +} + +//// [typeGuardsNestedAssignments.js] +var Foo = (function () { + function Foo() { + } + return Foo; +}()); +function f1() { + var foo; + if ((foo = getFooOrNull()) !== null) { + foo; // Foo + } +} +function f2() { + var foo1; + var foo2; + if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { + foo1; // Foo | null + foo2; // Foo + } +} +function f3() { + var obj; + if ((obj = getFooOrNull()) instanceof Foo) { + obj; + } +} +function f4() { + var x; + if (typeof (x = getStringOrNumberOrNull()) === "number") { + x; + } +} +// Repro from #8851 +var re = /./g; +var match; +while ((match = re.exec("xxx")) != null) { + var length = match[1].length + match[2].length; +} diff --git a/tests/baselines/reference/typeGuardsNestedAssignments.symbols b/tests/baselines/reference/typeGuardsNestedAssignments.symbols new file mode 100644 index 00000000000..1cca9c7de73 --- /dev/null +++ b/tests/baselines/reference/typeGuardsNestedAssignments.symbols @@ -0,0 +1,113 @@ +=== tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts === + +class Foo { +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + + x: string; +>x : Symbol(Foo.x, Decl(typeGuardsNestedAssignments.ts, 1, 11)) +} + +declare function getFooOrNull(): Foo | null; +>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1)) +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + +declare function getStringOrNumberOrNull(): string | number | null; +>getStringOrNumberOrNull : Symbol(getStringOrNumberOrNull, Decl(typeGuardsNestedAssignments.ts, 5, 44)) + +function f1() { +>f1 : Symbol(f1, Decl(typeGuardsNestedAssignments.ts, 6, 67)) + + let foo: Foo | null; +>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7)) +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + + if ((foo = getFooOrNull()) !== null) { +>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7)) +>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1)) + + foo; // Foo +>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7)) + } +} + +function f2() { +>f2 : Symbol(f2, Decl(typeGuardsNestedAssignments.ts, 13, 1)) + + let foo1: Foo | null; +>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7)) +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + + let foo2: Foo | null; +>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7)) +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + + if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { +>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7)) +>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1)) +>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7)) +>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7)) + + foo1; // Foo | null +>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7)) + + foo2; // Foo +>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7)) + } +} + +function f3() { +>f3 : Symbol(f3, Decl(typeGuardsNestedAssignments.ts, 22, 1)) + + let obj: Object | null; +>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + if ((obj = getFooOrNull()) instanceof Foo) { +>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7)) +>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1)) +>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0)) + + obj; +>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7)) + } +} + +function f4() { +>f4 : Symbol(f4, Decl(typeGuardsNestedAssignments.ts, 29, 1)) + + let x: string | number | null; +>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7)) + + if (typeof (x = getStringOrNumberOrNull()) === "number") { +>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7)) +>getStringOrNumberOrNull : Symbol(getStringOrNumberOrNull, Decl(typeGuardsNestedAssignments.ts, 5, 44)) + + x; +>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7)) + } +} + +// Repro from #8851 + +const re = /./g +>re : Symbol(re, Decl(typeGuardsNestedAssignments.ts, 40, 5)) + +let match: RegExpExecArray | null +>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3)) +>RegExpExecArray : Symbol(RegExpExecArray, Decl(lib.d.ts, --, --)) + +while ((match = re.exec("xxx")) != null) { +>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3)) +>re.exec : Symbol(RegExp.exec, Decl(lib.d.ts, --, --)) +>re : Symbol(re, Decl(typeGuardsNestedAssignments.ts, 40, 5)) +>exec : Symbol(RegExp.exec, Decl(lib.d.ts, --, --)) + + const length = match[1].length + match[2].length +>length : Symbol(length, Decl(typeGuardsNestedAssignments.ts, 44, 9)) +>match[1].length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>match[2].length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +} diff --git a/tests/baselines/reference/typeGuardsNestedAssignments.types b/tests/baselines/reference/typeGuardsNestedAssignments.types new file mode 100644 index 00000000000..566a39a9c23 --- /dev/null +++ b/tests/baselines/reference/typeGuardsNestedAssignments.types @@ -0,0 +1,155 @@ +=== tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts === + +class Foo { +>Foo : Foo + + x: string; +>x : string +} + +declare function getFooOrNull(): Foo | null; +>getFooOrNull : () => Foo | null +>Foo : Foo +>null : null + +declare function getStringOrNumberOrNull(): string | number | null; +>getStringOrNumberOrNull : () => string | number | null +>null : null + +function f1() { +>f1 : () => void + + let foo: Foo | null; +>foo : Foo | null +>Foo : Foo +>null : null + + if ((foo = getFooOrNull()) !== null) { +>(foo = getFooOrNull()) !== null : boolean +>(foo = getFooOrNull()) : Foo | null +>foo = getFooOrNull() : Foo | null +>foo : Foo | null +>getFooOrNull() : Foo | null +>getFooOrNull : () => Foo | null +>null : null + + foo; // Foo +>foo : Foo + } +} + +function f2() { +>f2 : () => void + + let foo1: Foo | null; +>foo1 : Foo | null +>Foo : Foo +>null : null + + let foo2: Foo | null; +>foo2 : Foo | null +>Foo : Foo +>null : null + + if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { +>(foo1 = getFooOrNull(), foo2 = foo1) !== null : boolean +>(foo1 = getFooOrNull(), foo2 = foo1) : Foo | null +>foo1 = getFooOrNull(), foo2 = foo1 : Foo | null +>foo1 = getFooOrNull() : Foo | null +>foo1 : Foo | null +>getFooOrNull() : Foo | null +>getFooOrNull : () => Foo | null +>foo2 = foo1 : Foo | null +>foo2 : Foo | null +>foo1 : Foo | null +>null : null + + foo1; // Foo | null +>foo1 : Foo | null + + foo2; // Foo +>foo2 : Foo + } +} + +function f3() { +>f3 : () => void + + let obj: Object | null; +>obj : Object | null +>Object : Object +>null : null + + if ((obj = getFooOrNull()) instanceof Foo) { +>(obj = getFooOrNull()) instanceof Foo : boolean +>(obj = getFooOrNull()) : Foo | null +>obj = getFooOrNull() : Foo | null +>obj : Object | null +>getFooOrNull() : Foo | null +>getFooOrNull : () => Foo | null +>Foo : typeof Foo + + obj; +>obj : Foo + } +} + +function f4() { +>f4 : () => void + + let x: string | number | null; +>x : string | number | null +>null : null + + if (typeof (x = getStringOrNumberOrNull()) === "number") { +>typeof (x = getStringOrNumberOrNull()) === "number" : boolean +>typeof (x = getStringOrNumberOrNull()) : string +>(x = getStringOrNumberOrNull()) : string | number | null +>x = getStringOrNumberOrNull() : string | number | null +>x : string | number | null +>getStringOrNumberOrNull() : string | number | null +>getStringOrNumberOrNull : () => string | number | null +>"number" : string + + x; +>x : number + } +} + +// Repro from #8851 + +const re = /./g +>re : RegExp +>/./g : RegExp + +let match: RegExpExecArray | null +>match : RegExpExecArray | null +>RegExpExecArray : RegExpExecArray +>null : null + +while ((match = re.exec("xxx")) != null) { +>(match = re.exec("xxx")) != null : boolean +>(match = re.exec("xxx")) : RegExpExecArray | null +>match = re.exec("xxx") : RegExpExecArray | null +>match : RegExpExecArray | null +>re.exec("xxx") : RegExpExecArray | null +>re.exec : (string: string) => RegExpExecArray | null +>re : RegExp +>exec : (string: string) => RegExpExecArray | null +>"xxx" : string +>null : null + + const length = match[1].length + match[2].length +>length : number +>match[1].length + match[2].length : number +>match[1].length : number +>match[1] : string +>match : RegExpExecArray +>1 : number +>length : number +>match[2].length : number +>match[2] : string +>match : RegExpExecArray +>2 : number +>length : number +} diff --git a/tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts b/tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts new file mode 100644 index 00000000000..41e3ffe572e --- /dev/null +++ b/tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts @@ -0,0 +1,47 @@ +// @strictNullChecks: true + +class Foo { + x: string; +} + +declare function getFooOrNull(): Foo | null; +declare function getStringOrNumberOrNull(): string | number | null; + +function f1() { + let foo: Foo | null; + if ((foo = getFooOrNull()) !== null) { + foo; // Foo + } +} + +function f2() { + let foo1: Foo | null; + let foo2: Foo | null; + if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { + foo1; // Foo | null + foo2; // Foo + } +} + +function f3() { + let obj: Object | null; + if ((obj = getFooOrNull()) instanceof Foo) { + obj; + } +} + +function f4() { + let x: string | number | null; + if (typeof (x = getStringOrNumberOrNull()) === "number") { + x; + } +} + +// Repro from #8851 + +const re = /./g +let match: RegExpExecArray | null + +while ((match = re.exec("xxx")) != null) { + const length = match[1].length + match[2].length +} \ No newline at end of file