From ff43d464fc74e2617de0f8675961193a2f53a34f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Oct 2015 16:36:15 -0700 Subject: [PATCH 01/44] Add test case --- .../ambientClassDeclarationWithExtends.js | 13 ++++++++++++ ...ambientClassDeclarationWithExtends.symbols | 19 ++++++++++++++++++ .../ambientClassDeclarationWithExtends.types | 20 +++++++++++++++++++ .../ambientClassDeclarationWithExtends.ts | 8 ++++++++ 4 files changed, 60 insertions(+) diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.js b/tests/baselines/reference/ambientClassDeclarationWithExtends.js index 5fd4d5b4b28..5a31486bcf0 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.js +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.js @@ -1,6 +1,19 @@ //// [ambientClassDeclarationWithExtends.ts] declare class A { } declare class B extends A { } + +declare class C { + public foo; +} +namespace D { var x; } +declare class D extends C { } + +var d: C = new D(); //// [ambientClassDeclarationWithExtends.js] +var D; +(function (D) { + var x; +})(D || (D = {})); +var d = new D(); diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols index 71d1e1a66d8..ba678910a9c 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols @@ -6,3 +6,22 @@ declare class B extends A { } >B : Symbol(B, Decl(ambientClassDeclarationWithExtends.ts, 0, 19)) >A : Symbol(A, Decl(ambientClassDeclarationWithExtends.ts, 0, 0)) +declare class C { +>C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) + + public foo; +>foo : Symbol(foo, Decl(ambientClassDeclarationWithExtends.ts, 3, 17)) +} +namespace D { var x; } +>D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) +>x : Symbol(x, Decl(ambientClassDeclarationWithExtends.ts, 6, 17)) + +declare class D extends C { } +>D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) +>C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) + +var d: C = new D(); +>d : Symbol(d, Decl(ambientClassDeclarationWithExtends.ts, 9, 3)) +>C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) +>D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) + diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.types b/tests/baselines/reference/ambientClassDeclarationWithExtends.types index 7609856882b..528496e753d 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.types +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.types @@ -6,3 +6,23 @@ declare class B extends A { } >B : B >A : A +declare class C { +>C : C + + public foo; +>foo : any +} +namespace D { var x; } +>D : typeof D +>x : any + +declare class D extends C { } +>D : D +>C : C + +var d: C = new D(); +>d : C +>C : C +>new D() : D +>D : typeof D + diff --git a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts index 0c5d8d156bf..554a436c5ef 100644 --- a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts +++ b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts @@ -1,2 +1,10 @@ declare class A { } declare class B extends A { } + +declare class C { + public foo; +} +namespace D { var x; } +declare class D extends C { } + +var d: C = new D(); From 08c78fbe76d87d0e15ca67ac106583e9687ff9cb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Oct 2015 16:39:53 -0700 Subject: [PATCH 02/44] Check for ClassDeclaration in getBaseTypeNodeOfClass Previously, it just used valueDeclaration. Now, it searches the declarations. --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 551f428ca9a..86754ff93d0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2766,7 +2766,10 @@ namespace ts { } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments { - return getClassExtendsHeritageClauseElement(type.symbol.valueDeclaration); + let classDeclaration = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration); + if (classDeclaration) { + return getClassExtendsHeritageClauseElement(classDeclaration as ClassLikeDeclaration); + } } function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { From 440d01f0bde14d13cc2ca054439caaadcb5009ac Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 9 Oct 2015 10:12:17 -0700 Subject: [PATCH 03/44] Fall back to valueDeclaration Fall back to `valueDeclaration` in getBaseTypeNodeOfClass when no ClassDeclaration exists. --- src/compiler/checker.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86754ff93d0..6c233a57ef4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2766,10 +2766,9 @@ namespace ts { } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments { - let classDeclaration = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration); - if (classDeclaration) { - return getClassExtendsHeritageClauseElement(classDeclaration as ClassLikeDeclaration); - } + let classDeclaration = + getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration) || type.symbol.valueDeclaration; + return getClassExtendsHeritageClauseElement(classDeclaration as ClassLikeDeclaration); } function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { From 9e8031cfc3f889caacd79d98951b125265ab38ff Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 9 Oct 2015 14:19:49 -0700 Subject: [PATCH 04/44] Non-namespace merges override `valueDeclaration` Instead of searching `declarations` for a class declaration, make the binder and checker merge `valueDeclaration` such that non-namespace merges always have their `valueDeclaration` win. --- src/compiler/binder.ts | 4 +- src/compiler/checker.ts | 10 ++-- .../ambientClassDeclarationWithExtends.js | 25 +++++++++- ...ambientClassDeclarationWithExtends.symbols | 49 ++++++++++++++----- .../ambientClassDeclarationWithExtends.types | 26 +++++++++- .../ambientClassDeclarationWithExtends.ts | 13 +++++ 6 files changed, 106 insertions(+), 21 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 65768332360..813a7e2cd43 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -130,7 +130,9 @@ namespace ts { symbol.members = {}; } - if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) { + if (symbolFlags & SymbolFlags.Value && + (!symbol.valueDeclaration || symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { + // other kinds of value declarations take precedence over modules symbol.valueDeclaration = node; } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c233a57ef4..d22266d951f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -293,7 +293,11 @@ namespace ts { target.constEnumOnlyModule = false; } target.flags |= source.flags; - if (!target.valueDeclaration && source.valueDeclaration) target.valueDeclaration = source.valueDeclaration; + if (source.valueDeclaration && + (!target.valueDeclaration || target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { + // other kinds of value declarations take precedence over modules + target.valueDeclaration = source.valueDeclaration; + } forEach(source.declarations, node => { target.declarations.push(node); }); @@ -2766,9 +2770,7 @@ namespace ts { } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments { - let classDeclaration = - getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration) || type.symbol.valueDeclaration; - return getClassExtendsHeritageClauseElement(classDeclaration as ClassLikeDeclaration); + return getClassExtendsHeritageClauseElement(type.symbol.valueDeclaration); } function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.js b/tests/baselines/reference/ambientClassDeclarationWithExtends.js index 5a31486bcf0..940efb8899f 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.js +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.js @@ -1,4 +1,6 @@ -//// [ambientClassDeclarationWithExtends.ts] +//// [tests/cases/compiler/ambientClassDeclarationWithExtends.ts] //// + +//// [ambientClassDeclarationExtends_singleFile.ts] declare class A { } declare class B extends A { } @@ -10,10 +12,29 @@ declare class D extends C { } var d: C = new D(); +//// [ambientClassDeclarationExtends_file1.ts] + +declare class E { + public bar; +} +namespace F { var y; } -//// [ambientClassDeclarationWithExtends.js] +//// [ambientClassDeclarationExtends_file2.ts] + +declare class F extends E { } +var f: E = new F(); + + +//// [ambientClassDeclarationExtends_singleFile.js] var D; (function (D) { var x; })(D || (D = {})); var d = new D(); +//// [ambientClassDeclarationExtends_file1.js] +var F; +(function (F) { + var y; +})(F || (F = {})); +//// [ambientClassDeclarationExtends_file2.js] +var f = new F(); diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols index ba678910a9c..023ae6bf582 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols @@ -1,27 +1,50 @@ -=== tests/cases/compiler/ambientClassDeclarationWithExtends.ts === +=== tests/cases/compiler/ambientClassDeclarationExtends_singleFile.ts === declare class A { } ->A : Symbol(A, Decl(ambientClassDeclarationWithExtends.ts, 0, 0)) +>A : Symbol(A, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 0)) declare class B extends A { } ->B : Symbol(B, Decl(ambientClassDeclarationWithExtends.ts, 0, 19)) ->A : Symbol(A, Decl(ambientClassDeclarationWithExtends.ts, 0, 0)) +>B : Symbol(B, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 19)) +>A : Symbol(A, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 0)) declare class C { ->C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) +>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29)) public foo; ->foo : Symbol(foo, Decl(ambientClassDeclarationWithExtends.ts, 3, 17)) +>foo : Symbol(foo, Decl(ambientClassDeclarationExtends_singleFile.ts, 3, 17)) } namespace D { var x; } ->D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) ->x : Symbol(x, Decl(ambientClassDeclarationWithExtends.ts, 6, 17)) +>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22)) +>x : Symbol(x, Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 17)) declare class D extends C { } ->D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) ->C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) +>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22)) +>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29)) var d: C = new D(); ->d : Symbol(d, Decl(ambientClassDeclarationWithExtends.ts, 9, 3)) ->C : Symbol(C, Decl(ambientClassDeclarationWithExtends.ts, 1, 29)) ->D : Symbol(D, Decl(ambientClassDeclarationWithExtends.ts, 5, 1), Decl(ambientClassDeclarationWithExtends.ts, 6, 22)) +>d : Symbol(d, Decl(ambientClassDeclarationExtends_singleFile.ts, 9, 3)) +>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29)) +>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22)) + +=== tests/cases/compiler/ambientClassDeclarationExtends_file1.ts === + +declare class E { +>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0)) + + public bar; +>bar : Symbol(bar, Decl(ambientClassDeclarationExtends_file1.ts, 1, 17)) +} +namespace F { var y; } +>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0)) +>y : Symbol(y, Decl(ambientClassDeclarationExtends_file1.ts, 4, 17)) + +=== tests/cases/compiler/ambientClassDeclarationExtends_file2.ts === + +declare class F extends E { } +>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0)) +>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0)) + +var f: E = new F(); +>f : Symbol(f, Decl(ambientClassDeclarationExtends_file2.ts, 2, 3)) +>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0)) +>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0)) diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.types b/tests/baselines/reference/ambientClassDeclarationWithExtends.types index 528496e753d..c7f22eeb65f 100644 --- a/tests/baselines/reference/ambientClassDeclarationWithExtends.types +++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.types @@ -1,4 +1,4 @@ -=== tests/cases/compiler/ambientClassDeclarationWithExtends.ts === +=== tests/cases/compiler/ambientClassDeclarationExtends_singleFile.ts === declare class A { } >A : A @@ -26,3 +26,27 @@ var d: C = new D(); >new D() : D >D : typeof D +=== tests/cases/compiler/ambientClassDeclarationExtends_file1.ts === + +declare class E { +>E : E + + public bar; +>bar : any +} +namespace F { var y; } +>F : typeof F +>y : any + +=== tests/cases/compiler/ambientClassDeclarationExtends_file2.ts === + +declare class F extends E { } +>F : F +>E : E + +var f: E = new F(); +>f : E +>E : E +>new F() : F +>F : typeof F + diff --git a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts index 554a436c5ef..ca26f1b2a44 100644 --- a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts +++ b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts @@ -1,3 +1,4 @@ +// @Filename: ambientClassDeclarationExtends_singleFile.ts declare class A { } declare class B extends A { } @@ -8,3 +9,15 @@ namespace D { var x; } declare class D extends C { } var d: C = new D(); + +// @Filename: ambientClassDeclarationExtends_file1.ts + +declare class E { + public bar; +} +namespace F { var y; } + +// @Filename: ambientClassDeclarationExtends_file2.ts + +declare class F extends E { } +var f: E = new F(); From ec2eac53bf15f1729cbcc0c41b9928f53dd2e057 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Sun, 11 Oct 2015 15:33:17 -0700 Subject: [PATCH 05/44] Improved non-namespace overriding Per @ahejlsberg's suggestion, only overwrite a namespace `valueDeclaration` if the new declaration is not a namespace itself. This means that if there are multiple namespace declarations, and nothing else, `valueDeclaration` will be the first namespace declaration, not the last. --- src/compiler/binder.ts | 3 ++- src/compiler/checker.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 813a7e2cd43..57d610c931e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -131,7 +131,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Value && - (!symbol.valueDeclaration || symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { + (!symbol.valueDeclaration || + (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && node.kind !== SyntaxKind.ModuleDeclaration))) { // other kinds of value declarations take precedence over modules symbol.valueDeclaration = node; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d22266d951f..6b3ddf9da32 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -294,7 +294,8 @@ namespace ts { } target.flags |= source.flags; if (source.valueDeclaration && - (!target.valueDeclaration || target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { + (!target.valueDeclaration || + (target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && source.valueDeclaration.kind !== SyntaxKind.ModuleDeclaration))) { // other kinds of value declarations take precedence over modules target.valueDeclaration = source.valueDeclaration; } From 062495c426e549ed68b5c75161e94e10be4ed06e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 28 Oct 2015 13:48:32 -0700 Subject: [PATCH 06/44] naive change and new tests --- src/compiler/checker.ts | 6 +++--- .../expressions/typeGuards/typeGuardNesting.ts | 4 ++++ .../expressions/typeGuards/typeGuardRedundancy.ts | 9 +++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5370e7c4f02..033614d2b41 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6369,7 +6369,7 @@ namespace ts { // Assumed result is true. If check was not for a primitive type, remove all primitive types if (!typeInfo) { return removeTypesFromUnionType(type, /*typeKind*/ TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.Boolean | TypeFlags.ESSymbol, - /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ false); + /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true); } // Check was for a primitive type, return that primitive type if it is a subtype if (isTypeSubtypeOf(typeInfo.type, type)) { @@ -6377,12 +6377,12 @@ namespace ts { } // Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is // union of enum types and other types. - return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ false, /*allowEmptyUnionResult*/ false); + return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ false, /*allowEmptyUnionResult*/ true); } else { // Assumed result is false. If check was for a primitive type, remove that primitive type if (typeInfo) { - return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ false); + return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true); } // Otherwise we don't have enough information to do anything. return type; diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts new file mode 100644 index 00000000000..b06b5880800 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts @@ -0,0 +1,4 @@ +let strOrBool: string|boolean; +if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { + var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts new file mode 100644 index 00000000000..4e9e3137d78 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts @@ -0,0 +1,9 @@ +var x: string|number; + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; \ No newline at end of file From febda00f1b430761df7e0e90bbb99cf8c99e4653 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 28 Oct 2015 16:06:40 -0700 Subject: [PATCH 07/44] Improve type narrowing algorithm with typeof --- src/compiler/checker.ts | 35 +++---- tests/baselines/reference/symbolType18.types | 2 +- tests/baselines/reference/typeGuardNesting.js | 11 +++ .../reference/typeGuardNesting.symbols | 14 +++ .../reference/typeGuardNesting.types | 30 ++++++ .../typeGuardOfFormTypeOfOther.types | 12 +-- .../reference/typeGuardRedundancy.js | 17 ++++ .../reference/typeGuardRedundancy.symbols | 48 ++++++++++ .../reference/typeGuardRedundancy.types | 84 ++++++++++++++++ .../reference/typeGuardsWithAny.errors.txt | 49 ---------- .../reference/typeGuardsWithAny.symbols | 61 ++++++++++++ .../reference/typeGuardsWithAny.types | 96 +++++++++++++++++++ 12 files changed, 382 insertions(+), 77 deletions(-) create mode 100644 tests/baselines/reference/typeGuardNesting.js create mode 100644 tests/baselines/reference/typeGuardNesting.symbols create mode 100644 tests/baselines/reference/typeGuardNesting.types create mode 100644 tests/baselines/reference/typeGuardRedundancy.js create mode 100644 tests/baselines/reference/typeGuardRedundancy.symbols create mode 100644 tests/baselines/reference/typeGuardRedundancy.types delete mode 100644 tests/baselines/reference/typeGuardsWithAny.errors.txt create mode 100644 tests/baselines/reference/typeGuardsWithAny.symbols create mode 100644 tests/baselines/reference/typeGuardsWithAny.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 033614d2b41..ad6e72d68bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6338,6 +6338,10 @@ namespace ts { // Stop at the first containing function or module declaration break loop; } + // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type + if (narrowedType === getUnionType(emptyArray)) { + narrowedType = type; + } // Use narrowed type if construct contains no assignments to variable if (narrowedType !== type) { if (isVariableAssignedWithin(symbol, node)) { @@ -6352,6 +6356,9 @@ namespace ts { return type; function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + if (!(type.flags & TypeFlags.Union)) { + return type; + } // Check that we have 'typeof ' on the left and string literal on the right if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) { return type; @@ -6361,31 +6368,17 @@ namespace ts { if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(left.expression) !== symbol) { return type; } - let typeInfo = primitiveTypeInfo[right.text]; if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } + let typeInfo = primitiveTypeInfo[right.text]; + let flags = typeInfo ? typeInfo.flags : (assumeTrue = !assumeTrue, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean); + let union = type as UnionType; if (assumeTrue) { - // Assumed result is true. If check was not for a primitive type, remove all primitive types - if (!typeInfo) { - return removeTypesFromUnionType(type, /*typeKind*/ TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.Boolean | TypeFlags.ESSymbol, - /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true); - } - // Check was for a primitive type, return that primitive type if it is a subtype - if (isTypeSubtypeOf(typeInfo.type, type)) { - return typeInfo.type; - } - // Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is - // union of enum types and other types. - return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ false, /*allowEmptyUnionResult*/ true); + return getUnionType(filter(union.types, t => !!(t.flags & flags))); } else { - // Assumed result is false. If check was for a primitive type, remove that primitive type - if (typeInfo) { - return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true); - } - // Otherwise we don't have enough information to do anything. - return type; + return getUnionType(filter(union.types, t => !(t.flags & flags))); } } @@ -6399,7 +6392,7 @@ namespace ts { // and the second operand was false. We narrow with those assumptions and union the two resulting types. return getUnionType([ narrowType(type, expr.left, /*assumeTrue*/ false), - narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ false) + narrowType(type, expr.right, /*assumeTrue*/ false) ]); } } @@ -6410,7 +6403,7 @@ namespace ts { // and the second operand was true. We narrow with those assumptions and union the two resulting types. return getUnionType([ narrowType(type, expr.left, /*assumeTrue*/ true), - narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ true) + narrowType(type, expr.right, /*assumeTrue*/ true) ]); } else { diff --git a/tests/baselines/reference/symbolType18.types b/tests/baselines/reference/symbolType18.types index db4fb30378f..68c43215136 100644 --- a/tests/baselines/reference/symbolType18.types +++ b/tests/baselines/reference/symbolType18.types @@ -21,5 +21,5 @@ if (typeof x === "object") { } else { x; ->x : symbol | Foo +>x : symbol } diff --git a/tests/baselines/reference/typeGuardNesting.js b/tests/baselines/reference/typeGuardNesting.js new file mode 100644 index 00000000000..4c9a64c2851 --- /dev/null +++ b/tests/baselines/reference/typeGuardNesting.js @@ -0,0 +1,11 @@ +//// [typeGuardNesting.ts] +let strOrBool: string|boolean; +if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { + var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; +} + +//// [typeGuardNesting.js] +var strOrBool; +if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { + var label = (typeof strOrBool === 'string') ? strOrBool : "other string"; +} diff --git a/tests/baselines/reference/typeGuardNesting.symbols b/tests/baselines/reference/typeGuardNesting.symbols new file mode 100644 index 00000000000..f0cfb1f1eed --- /dev/null +++ b/tests/baselines/reference/typeGuardNesting.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts === +let strOrBool: string|boolean; +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + +if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; +>label : Symbol(label, Decl(typeGuardNesting.ts, 2, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +} diff --git a/tests/baselines/reference/typeGuardNesting.types b/tests/baselines/reference/typeGuardNesting.types new file mode 100644 index 00000000000..9f79974635d --- /dev/null +++ b/tests/baselines/reference/typeGuardNesting.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts === +let strOrBool: string|boolean; +>strOrBool : string | boolean + +if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { +>(typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string' : boolean +>(typeof strOrBool === 'boolean' && !strOrBool) : boolean +>typeof strOrBool === 'boolean' && !strOrBool : boolean +>typeof strOrBool === 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : string | boolean +>'boolean' : string +>!strOrBool : boolean +>strOrBool : boolean +>typeof strOrBool === 'string' : boolean +>typeof strOrBool : string +>strOrBool : string | boolean +>'string' : string + + var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; +>label : string +>(typeof strOrBool === 'string') ? strOrBool : "other string" : string +>(typeof strOrBool === 'string') : boolean +>typeof strOrBool === 'string' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'string' : string +>strOrBool : string +>"other string" : string +} diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types index e0fd443ef63..8150c3ec25d 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types @@ -63,7 +63,7 @@ else { var r2: string | C = strOrC; // string | C >r2 : string | C >C : C ->strOrC : string | C +>strOrC : string } if (typeof numOrC === "Object") { >typeof numOrC === "Object" : boolean @@ -80,7 +80,7 @@ else { var r3: number | C = numOrC; // number | C >r3 : number | C >C : C ->numOrC : number | C +>numOrC : number } if (typeof boolOrC === "Object") { >typeof boolOrC === "Object" : boolean @@ -97,7 +97,7 @@ else { var r4: boolean | C = boolOrC; // boolean | C >r4 : boolean | C >C : C ->boolOrC : boolean | C +>boolOrC : boolean } // Narrowing occurs only if target type is a subtype of variable type @@ -129,7 +129,7 @@ if (typeof strOrC !== "Object") { var r2: string | C = strOrC; // string | C >r2 : string | C >C : C ->strOrC : string | C +>strOrC : string } else { c = strOrC; // C @@ -146,7 +146,7 @@ if (typeof numOrC !== "Object") { var r3: number | C = numOrC; // number | C >r3 : number | C >C : C ->numOrC : number | C +>numOrC : number } else { c = numOrC; // C @@ -163,7 +163,7 @@ if (typeof boolOrC !== "Object") { var r4: boolean | C = boolOrC; // boolean | C >r4 : boolean | C >C : C ->boolOrC : boolean | C +>boolOrC : boolean } else { c = boolOrC; // C diff --git a/tests/baselines/reference/typeGuardRedundancy.js b/tests/baselines/reference/typeGuardRedundancy.js new file mode 100644 index 00000000000..1dfa964cbc9 --- /dev/null +++ b/tests/baselines/reference/typeGuardRedundancy.js @@ -0,0 +1,17 @@ +//// [typeGuardRedundancy.ts] +var x: string|number; + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; + +//// [typeGuardRedundancy.js] +var x; +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; diff --git a/tests/baselines/reference/typeGuardRedundancy.symbols b/tests/baselines/reference/typeGuardRedundancy.symbols new file mode 100644 index 00000000000..356061407ad --- /dev/null +++ b/tests/baselines/reference/typeGuardRedundancy.symbols @@ -0,0 +1,48 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts === +var x: string|number; +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +>r1 : Symbol(r1, Decl(typeGuardRedundancy.ts, 2, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +>r2 : Symbol(r2, Decl(typeGuardRedundancy.ts, 4, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +>r3 : Symbol(r3, Decl(typeGuardRedundancy.ts, 6, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; +>r4 : Symbol(r4, Decl(typeGuardRedundancy.ts, 8, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/typeGuardRedundancy.types b/tests/baselines/reference/typeGuardRedundancy.types new file mode 100644 index 00000000000..1507ceb850e --- /dev/null +++ b/tests/baselines/reference/typeGuardRedundancy.types @@ -0,0 +1,84 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts === +var x: string|number; +>x : string | number + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +>r1 : (from: number, length?: number) => string +>typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string +>typeof x === "string" && typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : string +>"string" : string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +>r2 : (fractionDigits?: number) => string +>!(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string +>!(typeof x === "string" && typeof x === "string") : boolean +>(typeof x === "string" && typeof x === "string") : boolean +>typeof x === "string" && typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : string +>"string" : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +>r3 : (from: number, length?: number) => string +>typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string +>typeof x === "string" || typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : number +>"string" : string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; +>r4 : (fractionDigits?: number) => string +>!(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string +>!(typeof x === "string" || typeof x === "string") : boolean +>(typeof x === "string" || typeof x === "string") : boolean +>typeof x === "string" || typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : number +>"string" : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string + diff --git a/tests/baselines/reference/typeGuardsWithAny.errors.txt b/tests/baselines/reference/typeGuardsWithAny.errors.txt deleted file mode 100644 index 653c89c7554..00000000000 --- a/tests/baselines/reference/typeGuardsWithAny.errors.txt +++ /dev/null @@ -1,49 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(11,7): error TS2339: Property 'p' does not exist on type 'string'. -tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(18,7): error TS2339: Property 'p' does not exist on type 'number'. -tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(25,7): error TS2339: Property 'p' does not exist on type 'boolean'. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts (3 errors) ==== - var x: any = { p: 0 }; - - if (x instanceof Object) { - x.p; // No error, type any unaffected by instanceof type guard - } - else { - x.p; // No error, type any unaffected by instanceof type guard - } - - if (typeof x === "string") { - x.p; // Error, type any narrowed by primitive type check - ~ -!!! error TS2339: Property 'p' does not exist on type 'string'. - } - else { - x.p; // No error, type unaffected in this branch - } - - if (typeof x === "number") { - x.p; // Error, type any narrowed by primitive type check - ~ -!!! error TS2339: Property 'p' does not exist on type 'number'. - } - else { - x.p; // No error, type unaffected in this branch - } - - if (typeof x === "boolean") { - x.p; // Error, type any narrowed by primitive type check - ~ -!!! error TS2339: Property 'p' does not exist on type 'boolean'. - } - else { - x.p; // No error, type unaffected in this branch - } - - if (typeof x === "object") { - x.p; // No error, type any only affected by primitive type check - } - else { - x.p; // No error, type unaffected in this branch - } - \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsWithAny.symbols b/tests/baselines/reference/typeGuardsWithAny.symbols new file mode 100644 index 00000000000..90405d762a1 --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.symbols @@ -0,0 +1,61 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === +var x: any = { p: 0 }; +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +>p : Symbol(p, Decl(typeGuardsWithAny.ts, 0, 14)) + +if (x instanceof Object) { +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + x.p; // No error, type any unaffected by instanceof type guard +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} +else { + x.p; // No error, type any unaffected by instanceof type guard +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} + +if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) + + x.p; // Error, type any narrowed by primitive type check +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} +else { + x.p; // No error, type unaffected in this branch +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} + +if (typeof x === "number") { +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) + + x.p; // Error, type any narrowed by primitive type check +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} +else { + x.p; // No error, type unaffected in this branch +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} + +if (typeof x === "boolean") { +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) + + x.p; // Error, type any narrowed by primitive type check +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} +else { + x.p; // No error, type unaffected in this branch +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} + +if (typeof x === "object") { +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) + + x.p; // No error, type any only affected by primitive type check +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} +else { + x.p; // No error, type unaffected in this branch +>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) +} + diff --git a/tests/baselines/reference/typeGuardsWithAny.types b/tests/baselines/reference/typeGuardsWithAny.types new file mode 100644 index 00000000000..12a4326e99d --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === +var x: any = { p: 0 }; +>x : any +>{ p: 0 } : { p: number; } +>p : number +>0 : number + +if (x instanceof Object) { +>x instanceof Object : boolean +>x : any +>Object : ObjectConstructor + + x.p; // No error, type any unaffected by instanceof type guard +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type any unaffected by instanceof type guard +>x.p : any +>x : any +>p : any +} + +if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : any +>"string" : string + + x.p; // Error, type any narrowed by primitive type check +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type unaffected in this branch +>x.p : any +>x : any +>p : any +} + +if (typeof x === "number") { +>typeof x === "number" : boolean +>typeof x : string +>x : any +>"number" : string + + x.p; // Error, type any narrowed by primitive type check +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type unaffected in this branch +>x.p : any +>x : any +>p : any +} + +if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : any +>"boolean" : string + + x.p; // Error, type any narrowed by primitive type check +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type unaffected in this branch +>x.p : any +>x : any +>p : any +} + +if (typeof x === "object") { +>typeof x === "object" : boolean +>typeof x : string +>x : any +>"object" : string + + x.p; // No error, type any only affected by primitive type check +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type unaffected in this branch +>x.p : any +>x : any +>p : any +} + From 168c664639a6c7d01439f39b1d3bd3edd58bada3 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 28 Oct 2015 16:29:36 -0700 Subject: [PATCH 08/44] restore any narrowing --- src/compiler/checker.ts | 11 ++- .../reference/typeGuardsWithAny.errors.txt | 49 ++++++++++ .../reference/typeGuardsWithAny.symbols | 61 ------------ .../reference/typeGuardsWithAny.types | 96 ------------------- 4 files changed, 57 insertions(+), 160 deletions(-) create mode 100644 tests/baselines/reference/typeGuardsWithAny.errors.txt delete mode 100644 tests/baselines/reference/typeGuardsWithAny.symbols delete mode 100644 tests/baselines/reference/typeGuardsWithAny.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ad6e72d68bd..93b644b07a4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6356,9 +6356,6 @@ namespace ts { return type; function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { - if (!(type.flags & TypeFlags.Union)) { - return type; - } // Check that we have 'typeof ' on the left and string literal on the right if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) { return type; @@ -6372,6 +6369,14 @@ namespace ts { assumeTrue = !assumeTrue; } let typeInfo = primitiveTypeInfo[right.text]; + // If the type to be narrowed is any and we're affirmatively checking against a primitive, return the primitive + if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) { + return typeInfo.type; + } + // At this point we can bail if it's not a union + if (!(type.flags & TypeFlags.Union)) { + return type; + } let flags = typeInfo ? typeInfo.flags : (assumeTrue = !assumeTrue, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean); let union = type as UnionType; if (assumeTrue) { diff --git a/tests/baselines/reference/typeGuardsWithAny.errors.txt b/tests/baselines/reference/typeGuardsWithAny.errors.txt new file mode 100644 index 00000000000..653c89c7554 --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.errors.txt @@ -0,0 +1,49 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(11,7): error TS2339: Property 'p' does not exist on type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(18,7): error TS2339: Property 'p' does not exist on type 'number'. +tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(25,7): error TS2339: Property 'p' does not exist on type 'boolean'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts (3 errors) ==== + var x: any = { p: 0 }; + + if (x instanceof Object) { + x.p; // No error, type any unaffected by instanceof type guard + } + else { + x.p; // No error, type any unaffected by instanceof type guard + } + + if (typeof x === "string") { + x.p; // Error, type any narrowed by primitive type check + ~ +!!! error TS2339: Property 'p' does not exist on type 'string'. + } + else { + x.p; // No error, type unaffected in this branch + } + + if (typeof x === "number") { + x.p; // Error, type any narrowed by primitive type check + ~ +!!! error TS2339: Property 'p' does not exist on type 'number'. + } + else { + x.p; // No error, type unaffected in this branch + } + + if (typeof x === "boolean") { + x.p; // Error, type any narrowed by primitive type check + ~ +!!! error TS2339: Property 'p' does not exist on type 'boolean'. + } + else { + x.p; // No error, type unaffected in this branch + } + + if (typeof x === "object") { + x.p; // No error, type any only affected by primitive type check + } + else { + x.p; // No error, type unaffected in this branch + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsWithAny.symbols b/tests/baselines/reference/typeGuardsWithAny.symbols deleted file mode 100644 index 90405d762a1..00000000000 --- a/tests/baselines/reference/typeGuardsWithAny.symbols +++ /dev/null @@ -1,61 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === -var x: any = { p: 0 }; ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) ->p : Symbol(p, Decl(typeGuardsWithAny.ts, 0, 14)) - -if (x instanceof Object) { ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) ->Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) - - x.p; // No error, type any unaffected by instanceof type guard ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} -else { - x.p; // No error, type any unaffected by instanceof type guard ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} - -if (typeof x === "string") { ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) - - x.p; // Error, type any narrowed by primitive type check ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} -else { - x.p; // No error, type unaffected in this branch ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} - -if (typeof x === "number") { ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) - - x.p; // Error, type any narrowed by primitive type check ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} -else { - x.p; // No error, type unaffected in this branch ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} - -if (typeof x === "boolean") { ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) - - x.p; // Error, type any narrowed by primitive type check ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} -else { - x.p; // No error, type unaffected in this branch ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} - -if (typeof x === "object") { ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) - - x.p; // No error, type any only affected by primitive type check ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} -else { - x.p; // No error, type unaffected in this branch ->x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3)) -} - diff --git a/tests/baselines/reference/typeGuardsWithAny.types b/tests/baselines/reference/typeGuardsWithAny.types deleted file mode 100644 index 12a4326e99d..00000000000 --- a/tests/baselines/reference/typeGuardsWithAny.types +++ /dev/null @@ -1,96 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === -var x: any = { p: 0 }; ->x : any ->{ p: 0 } : { p: number; } ->p : number ->0 : number - -if (x instanceof Object) { ->x instanceof Object : boolean ->x : any ->Object : ObjectConstructor - - x.p; // No error, type any unaffected by instanceof type guard ->x.p : any ->x : any ->p : any -} -else { - x.p; // No error, type any unaffected by instanceof type guard ->x.p : any ->x : any ->p : any -} - -if (typeof x === "string") { ->typeof x === "string" : boolean ->typeof x : string ->x : any ->"string" : string - - x.p; // Error, type any narrowed by primitive type check ->x.p : any ->x : any ->p : any -} -else { - x.p; // No error, type unaffected in this branch ->x.p : any ->x : any ->p : any -} - -if (typeof x === "number") { ->typeof x === "number" : boolean ->typeof x : string ->x : any ->"number" : string - - x.p; // Error, type any narrowed by primitive type check ->x.p : any ->x : any ->p : any -} -else { - x.p; // No error, type unaffected in this branch ->x.p : any ->x : any ->p : any -} - -if (typeof x === "boolean") { ->typeof x === "boolean" : boolean ->typeof x : string ->x : any ->"boolean" : string - - x.p; // Error, type any narrowed by primitive type check ->x.p : any ->x : any ->p : any -} -else { - x.p; // No error, type unaffected in this branch ->x.p : any ->x : any ->p : any -} - -if (typeof x === "object") { ->typeof x === "object" : boolean ->typeof x : string ->x : any ->"object" : string - - x.p; // No error, type any only affected by primitive type check ->x.p : any ->x : any ->p : any -} -else { - x.p; // No error, type unaffected in this branch ->x.p : any ->x : any ->p : any -} - From 9f12bc8a1b0d100e87d336d8303fe5cf9fe09045 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 29 Oct 2015 17:51:36 -0700 Subject: [PATCH 09/44] feedback from pr, new tests --- src/compiler/checker.ts | 61 +++++------ tests/baselines/reference/typeGuardEnums.js | 41 +++++++ .../reference/typeGuardEnums.symbols | 34 ++++++ .../baselines/reference/typeGuardEnums.types | 40 +++++++ tests/baselines/reference/typeGuardNesting.js | 26 ++++- .../reference/typeGuardNesting.symbols | 44 +++++++- .../reference/typeGuardNesting.types | 100 +++++++++++++++++- .../reference/typeGuardOfFormTypeOfOther.js | 24 ++--- .../typeGuardOfFormTypeOfOther.symbols | 18 ++-- .../typeGuardOfFormTypeOfOther.types | 30 +++--- .../typeGuardTautologicalConsistiency.js | 24 +++++ .../typeGuardTautologicalConsistiency.symbols | 23 ++++ .../typeGuardTautologicalConsistiency.types | 36 +++++++ .../expressions/typeGuards/typeGuardEnums.ts | 18 ++++ .../typeGuards/typeGuardNesting.ts | 14 ++- .../typeGuards/typeGuardOfFormTypeOfOther.ts | 12 +-- .../typeGuardTautologicalConsistiency.ts | 11 ++ 17 files changed, 463 insertions(+), 93 deletions(-) create mode 100644 tests/baselines/reference/typeGuardEnums.js create mode 100644 tests/baselines/reference/typeGuardEnums.symbols create mode 100644 tests/baselines/reference/typeGuardEnums.types create mode 100644 tests/baselines/reference/typeGuardTautologicalConsistiency.js create mode 100644 tests/baselines/reference/typeGuardTautologicalConsistiency.symbols create mode 100644 tests/baselines/reference/typeGuardTautologicalConsistiency.types create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 93b644b07a4..4e8cb7cc340 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6177,27 +6177,6 @@ namespace ts { Debug.fail("should not get here"); } - // For a union type, remove all constituent types that are of the given type kind (when isOfTypeKind is true) - // or not of the given type kind (when isOfTypeKind is false) - function removeTypesFromUnionType(type: Type, typeKind: TypeFlags, isOfTypeKind: boolean, allowEmptyUnionResult: boolean): Type { - if (type.flags & TypeFlags.Union) { - let types = (type).types; - if (forEach(types, t => !!(t.flags & typeKind) === isOfTypeKind)) { - // Above we checked if we have anything to remove, now use the opposite test to do the removal - let narrowedType = getUnionType(filter(types, t => !(t.flags & typeKind) === isOfTypeKind)); - if (allowEmptyUnionResult || narrowedType !== emptyObjectType) { - return narrowedType; - } - } - } - else if (allowEmptyUnionResult && !!(type.flags & typeKind) === isOfTypeKind) { - // Use getUnionType(emptyArray) instead of emptyObjectType in case the way empty union types - // are represented ever changes. - return getUnionType(emptyArray); - } - return type; - } - function hasInitializer(node: VariableLikeDeclaration): boolean { return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(node.parent.parent)); } @@ -6296,6 +6275,7 @@ namespace ts { // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { let type = getTypeOfSymbol(symbol); + let originalType = type; // Only narrow when symbol is variable of type any or an object, union, or type parameter type if (node && symbol.flags & SymbolFlags.Variable) { if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { @@ -6338,10 +6318,6 @@ namespace ts { // Stop at the first containing function or module declaration break loop; } - // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type - if (narrowedType === getUnionType(emptyArray)) { - narrowedType = type; - } // Use narrowed type if construct contains no assignments to variable if (narrowedType !== type) { if (isVariableAssignedWithin(symbol, node)) { @@ -6350,6 +6326,11 @@ namespace ts { type = narrowedType; } } + + // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type + if (type === getUnionType(emptyArray)) { + type = originalType; + } } } @@ -6369,22 +6350,24 @@ namespace ts { assumeTrue = !assumeTrue; } let typeInfo = primitiveTypeInfo[right.text]; - // If the type to be narrowed is any and we're affirmatively checking against a primitive, return the primitive + // If the type to be narrowed is any and we're checking a primitive with assumeTrue=true, return the primitive if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) { return typeInfo.type; } - // At this point we can bail if it's not a union - if (!(type.flags & TypeFlags.Union)) { - return type; - } - let flags = typeInfo ? typeInfo.flags : (assumeTrue = !assumeTrue, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean); - let union = type as UnionType; - if (assumeTrue) { - return getUnionType(filter(union.types, t => !!(t.flags & flags))); + let flags: TypeFlags; + if (typeInfo) { + flags = typeInfo.flags; } else { - return getUnionType(filter(union.types, t => !(t.flags & flags))); + assumeTrue = !assumeTrue; + flags = TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean; } + // At this point we can bail if it's not a union + if (!(type.flags & TypeFlags.Union)) { + // If the active non-union type would be removed from a union by this type guard, return an empty union + return (assumeTrue === !!(type.flags & flags)) ? type : getUnionType(emptyArray); + } + return getUnionType(filter((type as UnionType).types, t => assumeTrue === !!(t.flags & flags)), /*noSubtypeReduction*/ true); } function narrowTypeByAnd(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { @@ -12554,7 +12537,13 @@ namespace ts { // After we remove all types that are StringLike, we will know if there was a string constituent // based on whether the remaining type is the same as the initial type. - let arrayType = removeTypesFromUnionType(arrayOrStringType, TypeFlags.StringLike, /*isTypeOfKind*/ true, /*allowEmptyUnionResult*/ true); + let arrayType = arrayOrStringType; + if (arrayOrStringType.flags & TypeFlags.Union) { + arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike))); + } + else if (arrayOrStringType.flags & TypeFlags.StringLike) { + arrayType = getUnionType(emptyArray); + } let hasStringConstituent = arrayOrStringType !== arrayType; let reportedError = false; diff --git a/tests/baselines/reference/typeGuardEnums.js b/tests/baselines/reference/typeGuardEnums.js new file mode 100644 index 00000000000..1eb4b7552c4 --- /dev/null +++ b/tests/baselines/reference/typeGuardEnums.js @@ -0,0 +1,41 @@ +//// [typeGuardEnums.ts] +enum E {} +enum V {} + +let x: number|string|E|V; + +if (typeof x === "number") { + x; // number|E|V +} +else { + x; // string +} + +if (typeof x !== "number") { + x; // string +} +else { + x; // number|E|V +} + + +//// [typeGuardEnums.js] +var E; +(function (E) { +})(E || (E = {})); +var V; +(function (V) { +})(V || (V = {})); +var x; +if (typeof x === "number") { + x; // number|E|V +} +else { + x; // string +} +if (typeof x !== "number") { + x; // string +} +else { + x; // number|E|V +} diff --git a/tests/baselines/reference/typeGuardEnums.symbols b/tests/baselines/reference/typeGuardEnums.symbols new file mode 100644 index 00000000000..8f1a396c481 --- /dev/null +++ b/tests/baselines/reference/typeGuardEnums.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts === +enum E {} +>E : Symbol(E, Decl(typeGuardEnums.ts, 0, 0)) + +enum V {} +>V : Symbol(V, Decl(typeGuardEnums.ts, 0, 9)) + +let x: number|string|E|V; +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) +>E : Symbol(E, Decl(typeGuardEnums.ts, 0, 0)) +>V : Symbol(V, Decl(typeGuardEnums.ts, 0, 9)) + +if (typeof x === "number") { +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) + + x; // number|E|V +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) +} +else { + x; // string +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) +} + +if (typeof x !== "number") { +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) + + x; // string +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) +} +else { + x; // number|E|V +>x : Symbol(x, Decl(typeGuardEnums.ts, 3, 3)) +} + diff --git a/tests/baselines/reference/typeGuardEnums.types b/tests/baselines/reference/typeGuardEnums.types new file mode 100644 index 00000000000..1d39a81d78a --- /dev/null +++ b/tests/baselines/reference/typeGuardEnums.types @@ -0,0 +1,40 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts === +enum E {} +>E : E + +enum V {} +>V : V + +let x: number|string|E|V; +>x : number | string | E | V +>E : E +>V : V + +if (typeof x === "number") { +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | E | V +>"number" : string + + x; // number|E|V +>x : number | E | V +} +else { + x; // string +>x : string +} + +if (typeof x !== "number") { +>typeof x !== "number" : boolean +>typeof x : string +>x : number | string | E | V +>"number" : string + + x; // string +>x : string +} +else { + x; // number|E|V +>x : number | E | V +} + diff --git a/tests/baselines/reference/typeGuardNesting.js b/tests/baselines/reference/typeGuardNesting.js index 4c9a64c2851..364653d0273 100644 --- a/tests/baselines/reference/typeGuardNesting.js +++ b/tests/baselines/reference/typeGuardNesting.js @@ -1,11 +1,31 @@ //// [typeGuardNesting.ts] let strOrBool: string|boolean; if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { - var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; -} + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +} + +if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean') { + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +} + //// [typeGuardNesting.js] var strOrBool; if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { - var label = (typeof strOrBool === 'string') ? strOrBool : "other string"; + var label = (typeof strOrBool === 'string') ? strOrBool : "string"; + var bool = (typeof strOrBool === 'boolean') ? strOrBool : false; + var label2 = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + var bool2 = (typeof strOrBool !== 'string') ? strOrBool : false; +} +if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean') { + var label = (typeof strOrBool === 'string') ? strOrBool : "string"; + var bool = (typeof strOrBool === 'boolean') ? strOrBool : false; + var label2 = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + var bool2 = (typeof strOrBool !== 'string') ? strOrBool : false; } diff --git a/tests/baselines/reference/typeGuardNesting.symbols b/tests/baselines/reference/typeGuardNesting.symbols index f0cfb1f1eed..427db81f3ed 100644 --- a/tests/baselines/reference/typeGuardNesting.symbols +++ b/tests/baselines/reference/typeGuardNesting.symbols @@ -7,8 +7,50 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) >strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) - var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; >label : Symbol(label, Decl(typeGuardNesting.ts, 2, 4)) >strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; +>bool : Symbol(bool, Decl(typeGuardNesting.ts, 3, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; +>label2 : Symbol(label2, Decl(typeGuardNesting.ts, 4, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +>bool2 : Symbol(bool2, Decl(typeGuardNesting.ts, 5, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) >strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) } + +if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean') { +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; +>label : Symbol(label, Decl(typeGuardNesting.ts, 9, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; +>bool : Symbol(bool, Decl(typeGuardNesting.ts, 10, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; +>label2 : Symbol(label2, Decl(typeGuardNesting.ts, 11, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) + + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +>bool2 : Symbol(bool2, Decl(typeGuardNesting.ts, 12, 4)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3)) +} + diff --git a/tests/baselines/reference/typeGuardNesting.types b/tests/baselines/reference/typeGuardNesting.types index 9f79974635d..255e96da89e 100644 --- a/tests/baselines/reference/typeGuardNesting.types +++ b/tests/baselines/reference/typeGuardNesting.types @@ -17,14 +17,108 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >strOrBool : string | boolean >'string' : string - var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; >label : string ->(typeof strOrBool === 'string') ? strOrBool : "other string" : string +>(typeof strOrBool === 'string') ? strOrBool : "string" : string >(typeof strOrBool === 'string') : boolean >typeof strOrBool === 'string' : boolean >typeof strOrBool : string >strOrBool : boolean | string >'string' : string >strOrBool : string ->"other string" : string +>"string" : string + + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; +>bool : boolean +>(typeof strOrBool === 'boolean') ? strOrBool : false : boolean +>(typeof strOrBool === 'boolean') : boolean +>typeof strOrBool === 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'boolean' : string +>strOrBool : boolean +>false : boolean + + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; +>label2 : string +>(typeof strOrBool !== 'boolean') ? strOrBool : "string" : string +>(typeof strOrBool !== 'boolean') : boolean +>typeof strOrBool !== 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'boolean' : string +>strOrBool : string +>"string" : string + + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +>bool2 : boolean +>(typeof strOrBool !== 'string') ? strOrBool : false : boolean +>(typeof strOrBool !== 'string') : boolean +>typeof strOrBool !== 'string' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'string' : string +>strOrBool : boolean +>false : boolean } + +if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean') { +>(typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean' : boolean +>(typeof strOrBool !== 'string' && !strOrBool) : boolean +>typeof strOrBool !== 'string' && !strOrBool : boolean +>typeof strOrBool !== 'string' : boolean +>typeof strOrBool : string +>strOrBool : string | boolean +>'string' : string +>!strOrBool : boolean +>strOrBool : boolean +>typeof strOrBool !== 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : string | boolean +>'boolean' : string + + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; +>label : string +>(typeof strOrBool === 'string') ? strOrBool : "string" : string +>(typeof strOrBool === 'string') : boolean +>typeof strOrBool === 'string' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'string' : string +>strOrBool : string +>"string" : string + + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; +>bool : boolean +>(typeof strOrBool === 'boolean') ? strOrBool : false : boolean +>(typeof strOrBool === 'boolean') : boolean +>typeof strOrBool === 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'boolean' : string +>strOrBool : boolean +>false : boolean + + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; +>label2 : string +>(typeof strOrBool !== 'boolean') ? strOrBool : "string" : string +>(typeof strOrBool !== 'boolean') : boolean +>typeof strOrBool !== 'boolean' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'boolean' : string +>strOrBool : string +>"string" : string + + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +>bool2 : boolean +>(typeof strOrBool !== 'string') ? strOrBool : false : boolean +>(typeof strOrBool !== 'string') : boolean +>typeof strOrBool !== 'string' : boolean +>typeof strOrBool : string +>strOrBool : boolean | string +>'string' : string +>strOrBool : boolean +>false : boolean +} + diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.js b/tests/baselines/reference/typeGuardOfFormTypeOfOther.js index 3bb1a2091f6..d1cb4994196 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.js +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.js @@ -23,19 +23,19 @@ if (typeof strOrC === "Object") { c = strOrC; // C } else { - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string } if (typeof numOrC === "Object") { c = numOrC; // C } else { - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number } if (typeof boolOrC === "Object") { c = boolOrC; // C } else { - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean } // Narrowing occurs only if target type is a subtype of variable type @@ -50,19 +50,19 @@ else { // - when true, narrows the type of x by typeof x === s when false, or // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrC !== "Object") { - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string } else { c = strOrC; // C } if (typeof numOrC !== "Object") { - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number } else { c = numOrC; // C } if (typeof boolOrC !== "Object") { - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean } else { c = boolOrC; // C @@ -104,19 +104,19 @@ if (typeof strOrC === "Object") { c = strOrC; // C } else { - var r2 = strOrC; // string | C + var r2 = strOrC; // string } if (typeof numOrC === "Object") { c = numOrC; // C } else { - var r3 = numOrC; // number | C + var r3 = numOrC; // number } if (typeof boolOrC === "Object") { c = boolOrC; // C } else { - var r4 = boolOrC; // boolean | C + var r4 = boolOrC; // boolean } // Narrowing occurs only if target type is a subtype of variable type if (typeof strOrNumOrBool === "Object") { @@ -129,19 +129,19 @@ else { // - when true, narrows the type of x by typeof x === s when false, or // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrC !== "Object") { - var r2 = strOrC; // string | C + var r2 = strOrC; // string } else { c = strOrC; // C } if (typeof numOrC !== "Object") { - var r3 = numOrC; // number | C + var r3 = numOrC; // number } else { c = numOrC; // C } if (typeof boolOrC !== "Object") { - var r4 = boolOrC; // boolean | C + var r4 = boolOrC; // boolean } else { c = boolOrC; // C diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols b/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols index e3ecffdc2e9..eb120d468dc 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols @@ -56,9 +56,8 @@ if (typeof strOrC === "Object") { >strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) } else { - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string >r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfOther.ts, 24, 7), Decl(typeGuardOfFormTypeOfOther.ts, 51, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) } if (typeof numOrC === "Object") { @@ -69,9 +68,8 @@ if (typeof numOrC === "Object") { >numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) } else { - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number >r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfOther.ts, 30, 7), Decl(typeGuardOfFormTypeOfOther.ts, 57, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) } if (typeof boolOrC === "Object") { @@ -82,9 +80,8 @@ if (typeof boolOrC === "Object") { >boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) } else { - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean >r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfOther.ts, 36, 7), Decl(typeGuardOfFormTypeOfOther.ts, 63, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) } @@ -108,9 +105,8 @@ else { if (typeof strOrC !== "Object") { >strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string >r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfOther.ts, 24, 7), Decl(typeGuardOfFormTypeOfOther.ts, 51, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) } else { @@ -121,9 +117,8 @@ else { if (typeof numOrC !== "Object") { >numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number >r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfOther.ts, 30, 7), Decl(typeGuardOfFormTypeOfOther.ts, 57, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) } else { @@ -134,9 +129,8 @@ else { if (typeof boolOrC !== "Object") { >boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean >r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfOther.ts, 36, 7), Decl(typeGuardOfFormTypeOfOther.ts, 63, 7)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) >boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) } else { diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types index 8150c3ec25d..5cec3567194 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types @@ -60,9 +60,8 @@ if (typeof strOrC === "Object") { >strOrC : C } else { - var r2: string | C = strOrC; // string | C ->r2 : string | C ->C : C + var r2: string = strOrC; // string +>r2 : string >strOrC : string } if (typeof numOrC === "Object") { @@ -77,9 +76,8 @@ if (typeof numOrC === "Object") { >numOrC : C } else { - var r3: number | C = numOrC; // number | C ->r3 : number | C ->C : C + var r3: number = numOrC; // number +>r3 : number >numOrC : number } if (typeof boolOrC === "Object") { @@ -94,9 +92,8 @@ if (typeof boolOrC === "Object") { >boolOrC : C } else { - var r4: boolean | C = boolOrC; // boolean | C ->r4 : boolean | C ->C : C + var r4: boolean = boolOrC; // boolean +>r4 : boolean >boolOrC : boolean } @@ -126,9 +123,8 @@ if (typeof strOrC !== "Object") { >strOrC : string | C >"Object" : string - var r2: string | C = strOrC; // string | C ->r2 : string | C ->C : C + var r2: string = strOrC; // string +>r2 : string >strOrC : string } else { @@ -143,9 +139,8 @@ if (typeof numOrC !== "Object") { >numOrC : number | C >"Object" : string - var r3: number | C = numOrC; // number | C ->r3 : number | C ->C : C + var r3: number = numOrC; // number +>r3 : number >numOrC : number } else { @@ -160,9 +155,8 @@ if (typeof boolOrC !== "Object") { >boolOrC : boolean | C >"Object" : string - var r4: boolean | C = boolOrC; // boolean | C ->r4 : boolean | C ->C : C + var r4: boolean = boolOrC; // boolean +>r4 : boolean >boolOrC : boolean } else { diff --git a/tests/baselines/reference/typeGuardTautologicalConsistiency.js b/tests/baselines/reference/typeGuardTautologicalConsistiency.js new file mode 100644 index 00000000000..1b7fa2021c5 --- /dev/null +++ b/tests/baselines/reference/typeGuardTautologicalConsistiency.js @@ -0,0 +1,24 @@ +//// [typeGuardTautologicalConsistiency.ts] +let stringOrNumber: string | number; + +if (typeof stringOrNumber === "number") { + if (typeof stringOrNumber !== "number") { + stringOrNumber; + } +} + +if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { + stringOrNumber; +} + + +//// [typeGuardTautologicalConsistiency.js] +var stringOrNumber; +if (typeof stringOrNumber === "number") { + if (typeof stringOrNumber !== "number") { + stringOrNumber; + } +} +if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { + stringOrNumber; +} diff --git a/tests/baselines/reference/typeGuardTautologicalConsistiency.symbols b/tests/baselines/reference/typeGuardTautologicalConsistiency.symbols new file mode 100644 index 00000000000..9ee82a5413f --- /dev/null +++ b/tests/baselines/reference/typeGuardTautologicalConsistiency.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts === +let stringOrNumber: string | number; +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) + +if (typeof stringOrNumber === "number") { +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) + + if (typeof stringOrNumber !== "number") { +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) + + stringOrNumber; +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) + } +} + +if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) + + stringOrNumber; +>stringOrNumber : Symbol(stringOrNumber, Decl(typeGuardTautologicalConsistiency.ts, 0, 3)) +} + diff --git a/tests/baselines/reference/typeGuardTautologicalConsistiency.types b/tests/baselines/reference/typeGuardTautologicalConsistiency.types new file mode 100644 index 00000000000..9acb1464761 --- /dev/null +++ b/tests/baselines/reference/typeGuardTautologicalConsistiency.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts === +let stringOrNumber: string | number; +>stringOrNumber : string | number + +if (typeof stringOrNumber === "number") { +>typeof stringOrNumber === "number" : boolean +>typeof stringOrNumber : string +>stringOrNumber : string | number +>"number" : string + + if (typeof stringOrNumber !== "number") { +>typeof stringOrNumber !== "number" : boolean +>typeof stringOrNumber : string +>stringOrNumber : number +>"number" : string + + stringOrNumber; +>stringOrNumber : string + } +} + +if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { +>typeof stringOrNumber === "number" && typeof stringOrNumber !== "number" : boolean +>typeof stringOrNumber === "number" : boolean +>typeof stringOrNumber : string +>stringOrNumber : string | number +>"number" : string +>typeof stringOrNumber !== "number" : boolean +>typeof stringOrNumber : string +>stringOrNumber : number +>"number" : string + + stringOrNumber; +>stringOrNumber : number +} + diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts new file mode 100644 index 00000000000..54e9a1bd8fe --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardEnums.ts @@ -0,0 +1,18 @@ +enum E {} +enum V {} + +let x: number|string|E|V; + +if (typeof x === "number") { + x; // number|E|V +} +else { + x; // string +} + +if (typeof x !== "number") { + x; // string +} +else { + x; // number|E|V +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts index b06b5880800..6423af18a5a 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts @@ -1,4 +1,14 @@ let strOrBool: string|boolean; if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') { - var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string"; -} \ No newline at end of file + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +} + +if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boolean') { + let label: string = (typeof strOrBool === 'string') ? strOrBool : "string"; + let bool: boolean = (typeof strOrBool === 'boolean') ? strOrBool : false; + let label2: string = (typeof strOrBool !== 'boolean') ? strOrBool : "string"; + let bool2: boolean = (typeof strOrBool !== 'string') ? strOrBool : false; +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts index 9d7d555fc18..ac3403d8151 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts @@ -22,19 +22,19 @@ if (typeof strOrC === "Object") { c = strOrC; // C } else { - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string } if (typeof numOrC === "Object") { c = numOrC; // C } else { - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number } if (typeof boolOrC === "Object") { c = boolOrC; // C } else { - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean } // Narrowing occurs only if target type is a subtype of variable type @@ -49,19 +49,19 @@ else { // - when true, narrows the type of x by typeof x === s when false, or // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrC !== "Object") { - var r2: string | C = strOrC; // string | C + var r2: string = strOrC; // string } else { c = strOrC; // C } if (typeof numOrC !== "Object") { - var r3: number | C = numOrC; // number | C + var r3: number = numOrC; // number } else { c = numOrC; // C } if (typeof boolOrC !== "Object") { - var r4: boolean | C = boolOrC; // boolean | C + var r4: boolean = boolOrC; // boolean } else { c = boolOrC; // C diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts new file mode 100644 index 00000000000..9a44603d2d4 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardTautologicalConsistiency.ts @@ -0,0 +1,11 @@ +let stringOrNumber: string | number; + +if (typeof stringOrNumber === "number") { + if (typeof stringOrNumber !== "number") { + stringOrNumber; + } +} + +if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { + stringOrNumber; +} From 19e796dcbd61d77601f27c9cb4bd4fea396d633d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 29 Oct 2015 18:46:06 -0700 Subject: [PATCH 10/44] More correctness --- src/compiler/checker.ts | 72 +++++++++++-------- .../typeGuardTautologicalConsistiency.types | 4 +- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4e8cb7cc340..30edecf3b40 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6275,37 +6275,19 @@ namespace ts { // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { let type = getTypeOfSymbol(symbol); - let originalType = type; // Only narrow when symbol is variable of type any or an object, union, or type parameter type if (node && symbol.flags & SymbolFlags.Variable) { if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { + let originalType = type; + let nodeStack: {node: Node, child: Node}[] = []; loop: while (node.parent) { let child = node; node = node.parent; - let narrowedType = type; switch (node.kind) { case SyntaxKind.IfStatement: - // In a branch of an if statement, narrow based on controlling expression - if (child !== (node).expression) { - narrowedType = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); - } - break; case SyntaxKind.ConditionalExpression: - // In a branch of a conditional expression, narrow based on controlling condition - if (child !== (node).condition) { - narrowedType = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); - } - break; case SyntaxKind.BinaryExpression: - // In the right operand of an && or ||, narrow based on left operand - if (child === (node).right) { - if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { - narrowedType = narrowType(type, (node).left, /*assumeTrue*/ true); - } - else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { - narrowedType = narrowType(type, (node).left, /*assumeTrue*/ false); - } - } + nodeStack.push({node, child}); break; case SyntaxKind.SourceFile: case SyntaxKind.ModuleDeclaration: @@ -6318,12 +6300,42 @@ namespace ts { // Stop at the first containing function or module declaration break loop; } - // Use narrowed type if construct contains no assignments to variable - if (narrowedType !== type) { - if (isVariableAssignedWithin(symbol, node)) { + } + + let nodes: {node: Node, child: Node}; + while (nodes = nodeStack.pop()) { + let {node, child} = nodes; + switch (node.kind) { + case SyntaxKind.IfStatement: + // In a branch of an if statement, narrow based on controlling expression + if (child !== (node).expression) { + type = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); + } break; - } - type = narrowedType; + case SyntaxKind.ConditionalExpression: + // In a branch of a conditional expression, narrow based on controlling condition + if (child !== (node).condition) { + type = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); + } + break; + case SyntaxKind.BinaryExpression: + // In the right operand of an && or ||, narrow based on left operand + if (child === (node).right) { + if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ true); + } + else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ false); + } + } + break; + default: + Debug.fail("Unreachable!"); + } + + // Use original type if construct contains assignments to variable + if (!nodeStack.length && isVariableAssignedWithin(symbol, node)) { + type = originalType; } } @@ -6365,9 +6377,13 @@ namespace ts { // At this point we can bail if it's not a union if (!(type.flags & TypeFlags.Union)) { // If the active non-union type would be removed from a union by this type guard, return an empty union - return (assumeTrue === !!(type.flags & flags)) ? type : getUnionType(emptyArray); + return filterUnion(type) ? type : getUnionType(emptyArray); + } + return getUnionType(filter((type as UnionType).types, filterUnion), /*noSubtypeReduction*/ true); + + function filterUnion(t: Type) { + return assumeTrue === !!(t.flags & flags); } - return getUnionType(filter((type as UnionType).types, t => assumeTrue === !!(t.flags & flags)), /*noSubtypeReduction*/ true); } function narrowTypeByAnd(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { diff --git a/tests/baselines/reference/typeGuardTautologicalConsistiency.types b/tests/baselines/reference/typeGuardTautologicalConsistiency.types index 9acb1464761..d758dcde22b 100644 --- a/tests/baselines/reference/typeGuardTautologicalConsistiency.types +++ b/tests/baselines/reference/typeGuardTautologicalConsistiency.types @@ -15,7 +15,7 @@ if (typeof stringOrNumber === "number") { >"number" : string stringOrNumber; ->stringOrNumber : string +>stringOrNumber : string | number } } @@ -31,6 +31,6 @@ if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { >"number" : string stringOrNumber; ->stringOrNumber : number +>stringOrNumber : string | number } From 0d0c05d1d3c4ef94fc15d17b5f2602729539ec8e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 29 Oct 2015 18:50:11 -0700 Subject: [PATCH 11/44] that feling when you ctrl-z 1 too many times --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30edecf3b40..8ae8ab3d54c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6334,7 +6334,7 @@ namespace ts { } // Use original type if construct contains assignments to variable - if (!nodeStack.length && isVariableAssignedWithin(symbol, node)) { + if (type != originalType && isVariableAssignedWithin(symbol, node)) { type = originalType; } } From d48a4f0cf184f5ff045d027693282c3b1b03c003 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 2 Nov 2015 10:48:59 -0800 Subject: [PATCH 12/44] fix nits --- src/compiler/checker.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ae8ab3d54c..b77faadd011 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -112,6 +112,7 @@ namespace ts { let circularType = createIntrinsicType(TypeFlags.Any, "__circular__"); let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + let emptyUnionType = emptyObjectType; let emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; @@ -4321,7 +4322,7 @@ namespace ts { // a named type that circularly references itself. function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type { if (types.length === 0) { - return emptyObjectType; + return emptyUnionType; } let typeSet: Type[] = []; addTypesToSet(typeSet, types, TypeFlags.Union); @@ -6278,8 +6279,8 @@ namespace ts { // Only narrow when symbol is variable of type any or an object, union, or type parameter type if (node && symbol.flags & SymbolFlags.Variable) { if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { - let originalType = type; - let nodeStack: {node: Node, child: Node}[] = []; + const originalType = type; + const nodeStack: {node: Node, child: Node}[] = []; loop: while (node.parent) { let child = node; node = node.parent; @@ -6304,7 +6305,7 @@ namespace ts { let nodes: {node: Node, child: Node}; while (nodes = nodeStack.pop()) { - let {node, child} = nodes; + const {node, child} = nodes; switch (node.kind) { case SyntaxKind.IfStatement: // In a branch of an if statement, narrow based on controlling expression @@ -6334,13 +6335,13 @@ namespace ts { } // Use original type if construct contains assignments to variable - if (type != originalType && isVariableAssignedWithin(symbol, node)) { + if (type !== originalType && isVariableAssignedWithin(symbol, node)) { type = originalType; } } // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type - if (type === getUnionType(emptyArray)) { + if (type === emptyUnionType) { type = originalType; } } @@ -6368,7 +6369,7 @@ namespace ts { } let flags: TypeFlags; if (typeInfo) { - flags = typeInfo.flags; + flags = typeInfo.flags; } else { assumeTrue = !assumeTrue; @@ -6377,12 +6378,12 @@ namespace ts { // At this point we can bail if it's not a union if (!(type.flags & TypeFlags.Union)) { // If the active non-union type would be removed from a union by this type guard, return an empty union - return filterUnion(type) ? type : getUnionType(emptyArray); + return filterUnion(type) ? type : emptyUnionType; } return getUnionType(filter((type as UnionType).types, filterUnion), /*noSubtypeReduction*/ true); - function filterUnion(t: Type) { - return assumeTrue === !!(t.flags & flags); + function filterUnion(type: Type) { + return assumeTrue === !!(type.flags & flags); } } @@ -12558,7 +12559,7 @@ namespace ts { arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike))); } else if (arrayOrStringType.flags & TypeFlags.StringLike) { - arrayType = getUnionType(emptyArray); + arrayType = emptyUnionType; } let hasStringConstituent = arrayOrStringType !== arrayType; From 77c69daf2e7d67f8ec54947983ce331e672c454c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 3 Nov 2015 14:35:11 -0800 Subject: [PATCH 13/44] const all the things --- src/compiler/checker.ts | 97 ++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b77faadd011..4bdbebaa50b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -33,26 +33,26 @@ namespace ts { // they no longer need the information (for example, if the user started editing again). let cancellationToken: CancellationToken; - let Symbol = objectAllocator.getSymbolConstructor(); - let Type = objectAllocator.getTypeConstructor(); - let Signature = objectAllocator.getSignatureConstructor(); + const Symbol = objectAllocator.getSymbolConstructor(); + const Type = objectAllocator.getTypeConstructor(); + const Signature = objectAllocator.getSignatureConstructor(); let typeCount = 0; let symbolCount = 0; - let emptyArray: any[] = []; - let emptySymbols: SymbolTable = {}; + const emptyArray: any[] = []; + const emptySymbols: SymbolTable = {}; - let compilerOptions = host.getCompilerOptions(); - let languageVersion = compilerOptions.target || ScriptTarget.ES3; - let modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None; + const compilerOptions = host.getCompilerOptions(); + const languageVersion = compilerOptions.target || ScriptTarget.ES3; + const modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None; - let emitResolver = createResolver(); + const emitResolver = createResolver(); - let undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined"); - let argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments"); + const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined"); + const argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments"); - let checker: TypeChecker = { + const checker: TypeChecker = { getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"), getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"), getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount, @@ -97,36 +97,35 @@ namespace ts { isOptionalParameter }; - let unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); - let resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); + const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); + const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); - let anyType = createIntrinsicType(TypeFlags.Any, "any"); - let stringType = createIntrinsicType(TypeFlags.String, "string"); - let numberType = createIntrinsicType(TypeFlags.Number, "number"); - let booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); - let esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); - let voidType = createIntrinsicType(TypeFlags.Void, "void"); - let undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); - let nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); - let unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); - let circularType = createIntrinsicType(TypeFlags.Any, "__circular__"); + const anyType = createIntrinsicType(TypeFlags.Any, "any"); + const stringType = createIntrinsicType(TypeFlags.String, "string"); + const numberType = createIntrinsicType(TypeFlags.Number, "number"); + const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); + const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); + const voidType = createIntrinsicType(TypeFlags.Void, "void"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); + const nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); + const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); - let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - let emptyUnionType = emptyObjectType; - let emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const emptyUnionType = emptyObjectType; + const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; - let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes. anyFunctionType.flags |= TypeFlags.ContainsAnyFunctionType; - let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - let anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, false, false); - let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, false, false); + const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, false, false); + const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, false, false); - let globals: SymbolTable = {}; + const globals: SymbolTable = {}; let globalESSymbolConstructorSymbol: Symbol; @@ -161,29 +160,29 @@ namespace ts { let getGlobalPromiseConstructorLikeType: () => ObjectType; let getGlobalThenableType: () => ObjectType; - let tupleTypes: Map = {}; - let unionTypes: Map = {}; - let intersectionTypes: Map = {}; - let stringLiteralTypes: Map = {}; + const tupleTypes: Map = {}; + const unionTypes: Map = {}; + const intersectionTypes: Map = {}; + const stringLiteralTypes: Map = {}; let emitExtends = false; let emitDecorate = false; let emitParam = false; let emitAwaiter = false; let emitGenerator = false; - let resolutionTargets: TypeSystemEntity[] = []; - let resolutionResults: boolean[] = []; - let resolutionPropertyNames: TypeSystemPropertyName[] = []; + const resolutionTargets: TypeSystemEntity[] = []; + const resolutionResults: boolean[] = []; + const resolutionPropertyNames: TypeSystemPropertyName[] = []; - let mergedSymbols: Symbol[] = []; - let symbolLinks: SymbolLinks[] = []; - let nodeLinks: NodeLinks[] = []; - let potentialThisCollisions: Node[] = []; - let awaitedTypeStack: number[] = []; + const mergedSymbols: Symbol[] = []; + const symbolLinks: SymbolLinks[] = []; + const nodeLinks: NodeLinks[] = []; + const potentialThisCollisions: Node[] = []; + const awaitedTypeStack: number[] = []; - let diagnostics = createDiagnosticCollection(); + const diagnostics = createDiagnosticCollection(); - let primitiveTypeInfo: Map<{ type: Type; flags: TypeFlags }> = { + const primitiveTypeInfo: Map<{ type: Type; flags: TypeFlags }> = { "string": { type: stringType, flags: TypeFlags.StringLike @@ -210,9 +209,9 @@ namespace ts { Element: "Element" }; - let subtypeRelation: Map = {}; - let assignableRelation: Map = {}; - let identityRelation: Map = {}; + const subtypeRelation: Map = {}; + const assignableRelation: Map = {}; + const identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. let _displayBuilder: SymbolDisplayBuilder; From 57f7d7f9dfb05c9e5a87c208e3ab3224be400a73 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Nov 2015 16:44:21 -0800 Subject: [PATCH 14/44] Reword predicate to be more readable --- src/compiler/binder.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 57d610c931e..b33f0b95fa3 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -130,12 +130,14 @@ namespace ts { symbol.members = {}; } - if (symbolFlags & SymbolFlags.Value && - (!symbol.valueDeclaration || - (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && node.kind !== SyntaxKind.ModuleDeclaration))) { - // other kinds of value declarations take precedence over modules - symbol.valueDeclaration = node; - } + if (symbolFlags & SymbolFlags.Value) { + const valueDeclaration = symbol.valueDeclaration; + if (!valueDeclaration || + (valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { + // other kinds of value declarations take precedence over modules + symbol.valueDeclaration = node; + } + } } // Should not be called on a declaration with a computed property name, From f92d24188826e4e132f935a5c8571f0ebab53153 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Tue, 10 Nov 2015 13:36:19 -0800 Subject: [PATCH 15/44] Add file content as a parameter for the tsserver open command --- src/server/editorServices.ts | 10 ++++++---- src/server/protocol.d.ts | 1 + src/server/session.ts | 10 +++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 333cea2745d..45d987ea534 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1006,14 +1006,15 @@ namespace ts.server { /** * @param filename is absolute pathname + * @param fileContent is a known version of the file content that is more up to date */ - openFile(fileName: string, openedByClient: boolean) { + openFile(fileName: string, openedByClient: boolean, fileContent?: string) { fileName = ts.normalizePath(fileName); let info = ts.lookUp(this.filenameToScriptInfo, fileName); if (!info) { let content: string; if (this.host.fileExists(fileName)) { - content = this.host.readFile(fileName); + content = fileContent ? fileContent : this.host.readFile(fileName); } if (!content) { if (openedByClient) { @@ -1060,10 +1061,11 @@ namespace ts.server { /** * Open file whose contents is managed by the client * @param filename is absolute pathname + * @param fileContent is a known version of the file content that is more up to date */ - openClientFile(fileName: string) { + openClientFile(fileName: string, fileContent?: string) { this.openOrUpdateConfiguredProjectForFile(fileName); - const info = this.openFile(fileName, true); + const info = this.openFile(fileName, true, fileContent); this.addOpenFile(info); this.printProjects(); return info; diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index ad1fc5e92de..6354a3a37ae 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -513,6 +513,7 @@ declare namespace ts.server.protocol { * Information found in an "open" request. */ export interface OpenRequestArgs extends FileRequestArgs { + fileContent?: string; } /** diff --git a/src/server/session.ts b/src/server/session.ts index 770256cc9f7..c589c528ec2 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -532,9 +532,13 @@ namespace ts.server { }; } - private openClientFile(fileName: string) { + /** + * @param fileName is the name of the file to be opened + * @param fileContent is a version of the file content that is known to be more up to date + */ + private openClientFile(fileName: string, fileContent?: string) { const file = ts.normalizePath(fileName); - this.projectService.openClientFile(file); + this.projectService.openClientFile(file, fileContent); } private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody { @@ -968,7 +972,7 @@ namespace ts.server { }, [CommandNames.Open]: (request: protocol.Request) => { const openArgs = request.arguments; - this.openClientFile(openArgs.file); + this.openClientFile(openArgs.file, openArgs.fileContent); return {responseRequired: false}; }, [CommandNames.Quickinfo]: (request: protocol.Request) => { From b9778e6d20b9a96f40ece46d08d23df8cfc4c6bd Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 11 Nov 2015 10:31:09 -0800 Subject: [PATCH 16/44] cr feedback --- src/server/editorServices.ts | 6 +++--- src/server/session.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 45d987ea534..889c96b6c4e 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1006,7 +1006,7 @@ namespace ts.server { /** * @param filename is absolute pathname - * @param fileContent is a known version of the file content that is more up to date + * @param fileContent is a known version of the file content that is more up to date than the one on disk */ openFile(fileName: string, openedByClient: boolean, fileContent?: string) { fileName = ts.normalizePath(fileName); @@ -1014,7 +1014,7 @@ namespace ts.server { if (!info) { let content: string; if (this.host.fileExists(fileName)) { - content = fileContent ? fileContent : this.host.readFile(fileName); + content = fileContent || this.host.readFile(fileName); } if (!content) { if (openedByClient) { @@ -1061,7 +1061,7 @@ namespace ts.server { /** * Open file whose contents is managed by the client * @param filename is absolute pathname - * @param fileContent is a known version of the file content that is more up to date + * @param fileContent is a known version of the file content that is more up to date than the one on disk */ openClientFile(fileName: string, fileContent?: string) { this.openOrUpdateConfiguredProjectForFile(fileName); diff --git a/src/server/session.ts b/src/server/session.ts index c589c528ec2..f04f73f644c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -534,7 +534,7 @@ namespace ts.server { /** * @param fileName is the name of the file to be opened - * @param fileContent is a version of the file content that is known to be more up to date + * @param fileContent is a version of the file content that is known to be more up to date than the one on disk */ private openClientFile(fileName: string, fileContent?: string) { const file = ts.normalizePath(fileName); From 87230bcc1bb166fef8f22363f1695beaf5999dec Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 10:55:33 -0800 Subject: [PATCH 17/44] Use 'getContextualType' for 'getContextualType'. --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e22bb18085c..37cbc632f20 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -81,7 +81,7 @@ namespace ts { symbolToString, getAugmentedPropertiesOfType, getRootSymbols, - getContextualType: getApparentTypeOfContextualType, + getContextualType, getFullyQualifiedName, getResolvedSignature, getConstantValue, From df1dd00f35542884a9fc85501c48d599b181ac82 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 12:19:47 -0800 Subject: [PATCH 18/44] Added test. --- ...sPropertyContextuallyTypedByTypeParam01.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts diff --git a/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts new file mode 100644 index 00000000000..357b355971d --- /dev/null +++ b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts @@ -0,0 +1,28 @@ +/// + +////interface IFoo { +//// [|a|]: string; +////} +////class C { +//// method() { +//// var x: T = { +//// [|a|]: "" +//// }; +//// x.[|a|]; +//// } +////} +//// +//// +////var x: IFoo = { +//// [|a|]: "ss" +////}; + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedReference of ranges) { + verify.referencesAtPositionContains(expectedReference); + } +} \ No newline at end of file From 593ba66af107602b33bd4db1da8011aebce4a43d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Nov 2015 14:35:30 -0800 Subject: [PATCH 19/44] Test cases for --sourceMap --inlineSources option --- .../optionsSourcemapInlineSources.js | 7 ++++ .../optionsSourcemapInlineSources.js.map | 2 ++ ...ptionsSourcemapInlineSources.sourcemap.txt | 34 +++++++++++++++++++ .../optionsSourcemapInlineSources.symbols | 5 +++ .../optionsSourcemapInlineSources.types | 6 ++++ .../optionsSourcemapInlineSourcesMapRoot.js | 7 ++++ ...ptionsSourcemapInlineSourcesMapRoot.js.map | 2 ++ ...ourcemapInlineSourcesMapRoot.sourcemap.txt | 34 +++++++++++++++++++ ...tionsSourcemapInlineSourcesMapRoot.symbols | 5 +++ ...optionsSourcemapInlineSourcesMapRoot.types | 6 ++++ ...optionsSourcemapInlineSourcesSourceRoot.js | 7 ++++ ...onsSourcemapInlineSourcesSourceRoot.js.map | 2 ++ ...cemapInlineSourcesSourceRoot.sourcemap.txt | 34 +++++++++++++++++++ ...nsSourcemapInlineSourcesSourceRoot.symbols | 5 +++ ...ionsSourcemapInlineSourcesSourceRoot.types | 6 ++++ .../compiler/optionsSourcemapInlineSources.ts | 4 +++ .../optionsSourcemapInlineSourcesMapRoot.ts | 5 +++ ...optionsSourcemapInlineSourcesSourceRoot.ts | 5 +++ 18 files changed, 176 insertions(+) create mode 100644 tests/baselines/reference/optionsSourcemapInlineSources.js create mode 100644 tests/baselines/reference/optionsSourcemapInlineSources.js.map create mode 100644 tests/baselines/reference/optionsSourcemapInlineSources.sourcemap.txt create mode 100644 tests/baselines/reference/optionsSourcemapInlineSources.symbols create mode 100644 tests/baselines/reference/optionsSourcemapInlineSources.types create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js.map create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.sourcemap.txt create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.symbols create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.types create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js.map create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.sourcemap.txt create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types create mode 100644 tests/cases/compiler/optionsSourcemapInlineSources.ts create mode 100644 tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts create mode 100644 tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts diff --git a/tests/baselines/reference/optionsSourcemapInlineSources.js b/tests/baselines/reference/optionsSourcemapInlineSources.js new file mode 100644 index 00000000000..029575ab992 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSources.js @@ -0,0 +1,7 @@ +//// [optionsSourcemapInlineSources.ts] + +var a = 10; + +//// [optionsSourcemapInlineSources.js] +var a = 10; +//# sourceMappingURL=optionsSourcemapInlineSources.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSources.js.map b/tests/baselines/reference/optionsSourcemapInlineSources.js.map new file mode 100644 index 00000000000..2be06332573 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSources.js.map @@ -0,0 +1,2 @@ +//// [optionsSourcemapInlineSources.js.map] +{"version":3,"file":"optionsSourcemapInlineSources.js","sourceRoot":"","sources":["optionsSourcemapInlineSources.ts"],"names":[],"mappings":"AACA,IAAI,CAAC,GAAG,EAAE,CAAC","sourcesContent":["\nvar a = 10;"]} \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSources.sourcemap.txt b/tests/baselines/reference/optionsSourcemapInlineSources.sourcemap.txt new file mode 100644 index 00000000000..79119d8c687 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSources.sourcemap.txt @@ -0,0 +1,34 @@ +=================================================================== +JsFile: optionsSourcemapInlineSources.js +mapUrl: optionsSourcemapInlineSources.js.map +sourceRoot: +sources: optionsSourcemapInlineSources.ts +sourcesContent: ["\nvar a = 10;"] +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsSourcemapInlineSources.js +sourceFile:optionsSourcemapInlineSources.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=optionsSourcemapInlineSources.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSources.symbols b/tests/baselines/reference/optionsSourcemapInlineSources.symbols new file mode 100644 index 00000000000..50649b86a0d --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSources.symbols @@ -0,0 +1,5 @@ +=== tests/cases/compiler/optionsSourcemapInlineSources.ts === + +var a = 10; +>a : Symbol(a, Decl(optionsSourcemapInlineSources.ts, 1, 3)) + diff --git a/tests/baselines/reference/optionsSourcemapInlineSources.types b/tests/baselines/reference/optionsSourcemapInlineSources.types new file mode 100644 index 00000000000..42fa1839371 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSources.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/optionsSourcemapInlineSources.ts === + +var a = 10; +>a : number +>10 : number + diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js new file mode 100644 index 00000000000..f7100140850 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js @@ -0,0 +1,7 @@ +//// [optionsSourcemapInlineSourcesMapRoot.ts] + +var a = 10; + +//// [optionsSourcemapInlineSourcesMapRoot.js] +var a = 10; +//# sourceMappingURL=local/optionsSourcemapInlineSourcesMapRoot.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js.map b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js.map new file mode 100644 index 00000000000..e99843b577f --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.js.map @@ -0,0 +1,2 @@ +//// [optionsSourcemapInlineSourcesMapRoot.js.map] +{"version":3,"file":"optionsSourcemapInlineSourcesMapRoot.js","sourceRoot":"","sources":["../optionsSourcemapInlineSourcesMapRoot.ts"],"names":[],"mappings":"AACA,IAAI,CAAC,GAAG,EAAE,CAAC","sourcesContent":["\nvar a = 10;"]} \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.sourcemap.txt b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.sourcemap.txt new file mode 100644 index 00000000000..a00040a9c93 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.sourcemap.txt @@ -0,0 +1,34 @@ +=================================================================== +JsFile: optionsSourcemapInlineSourcesMapRoot.js +mapUrl: local/optionsSourcemapInlineSourcesMapRoot.js.map +sourceRoot: +sources: ../optionsSourcemapInlineSourcesMapRoot.ts +sourcesContent: ["\nvar a = 10;"] +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.js +sourceFile:../optionsSourcemapInlineSourcesMapRoot.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=local/optionsSourcemapInlineSourcesMapRoot.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.symbols b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.symbols new file mode 100644 index 00000000000..57833abe2ee --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.symbols @@ -0,0 +1,5 @@ +=== tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts === + +var a = 10; +>a : Symbol(a, Decl(optionsSourcemapInlineSourcesMapRoot.ts, 1, 3)) + diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.types b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.types new file mode 100644 index 00000000000..77abb6f7b11 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesMapRoot.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts === + +var a = 10; +>a : number +>10 : number + diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js new file mode 100644 index 00000000000..948d6536f46 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js @@ -0,0 +1,7 @@ +//// [optionsSourcemapInlineSourcesSourceRoot.ts] + +var a = 10; + +//// [optionsSourcemapInlineSourcesSourceRoot.js] +var a = 10; +//# sourceMappingURL=optionsSourcemapInlineSourcesSourceRoot.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js.map b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js.map new file mode 100644 index 00000000000..ad373e11aab --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.js.map @@ -0,0 +1,2 @@ +//// [optionsSourcemapInlineSourcesSourceRoot.js.map] +{"version":3,"file":"optionsSourcemapInlineSourcesSourceRoot.js","sourceRoot":"local/","sources":["optionsSourcemapInlineSourcesSourceRoot.ts"],"names":[],"mappings":"AACA,IAAI,CAAC,GAAG,EAAE,CAAC","sourcesContent":["\nvar a = 10;"]} \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.sourcemap.txt b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.sourcemap.txt new file mode 100644 index 00000000000..55102f5c1cd --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.sourcemap.txt @@ -0,0 +1,34 @@ +=================================================================== +JsFile: optionsSourcemapInlineSourcesSourceRoot.js +mapUrl: optionsSourcemapInlineSourcesSourceRoot.js.map +sourceRoot: local/ +sources: optionsSourcemapInlineSourcesSourceRoot.ts +sourcesContent: ["\nvar a = 10;"] +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.js +sourceFile:optionsSourcemapInlineSourcesSourceRoot.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=optionsSourcemapInlineSourcesSourceRoot.js.map \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols new file mode 100644 index 00000000000..76f2dc5fdc4 --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols @@ -0,0 +1,5 @@ +=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts === + +var a = 10; +>a : Symbol(a, Decl(optionsSourcemapInlineSourcesSourceRoot.ts, 1, 3)) + diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types new file mode 100644 index 00000000000..3689afc382c --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts === + +var a = 10; +>a : number +>10 : number + diff --git a/tests/cases/compiler/optionsSourcemapInlineSources.ts b/tests/cases/compiler/optionsSourcemapInlineSources.ts new file mode 100644 index 00000000000..dddfb5f84ca --- /dev/null +++ b/tests/cases/compiler/optionsSourcemapInlineSources.ts @@ -0,0 +1,4 @@ +// @sourcemap: true +// @inlineSources: true + +var a = 10; \ No newline at end of file diff --git a/tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts b/tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts new file mode 100644 index 00000000000..c7a74469dc1 --- /dev/null +++ b/tests/cases/compiler/optionsSourcemapInlineSourcesMapRoot.ts @@ -0,0 +1,5 @@ +// @sourcemap: true +// @inlineSources: true +// @mapRoot: local + +var a = 10; \ No newline at end of file diff --git a/tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts b/tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts new file mode 100644 index 00000000000..4fd372658ad --- /dev/null +++ b/tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts @@ -0,0 +1,5 @@ +// @sourcemap: true +// @inlineSources: true +// @sourceRoot: local + +var a = 10; \ No newline at end of file From 8020bf90d6dd2dd24e7a04bf19077780444e22ab Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Nov 2015 14:44:51 -0800 Subject: [PATCH 20/44] Test cases to verify --inlineSourceMap with --sourcemap --mapRoot and --sourceRoot Note that --sourceRoot fails with crash --- .../optionsInlineSourceMapMapRoot.errors.txt | 9 +++++ .../optionsInlineSourceMapMapRoot.js | 7 ++++ ...ptionsInlineSourceMapMapRoot.sourcemap.txt | 33 +++++++++++++++++++ ...optionsInlineSourceMapSourcemap.errors.txt | 7 ++++ .../optionsInlineSourceMapSourcemap.js | 7 ++++ ...ionsInlineSourceMapSourcemap.sourcemap.txt | 33 +++++++++++++++++++ .../compiler/optionsInlineSourceMapMapRoot.ts | 4 +++ .../optionsInlineSourceMapSourceRoot.ts | 4 +++ .../optionsInlineSourceMapSourcemap.ts | 4 +++ 9 files changed, 108 insertions(+) create mode 100644 tests/baselines/reference/optionsInlineSourceMapMapRoot.errors.txt create mode 100644 tests/baselines/reference/optionsInlineSourceMapMapRoot.js create mode 100644 tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourcemap.errors.txt create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourcemap.js create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourcemap.sourcemap.txt create mode 100644 tests/cases/compiler/optionsInlineSourceMapMapRoot.ts create mode 100644 tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts create mode 100644 tests/cases/compiler/optionsInlineSourceMapSourcemap.ts diff --git a/tests/baselines/reference/optionsInlineSourceMapMapRoot.errors.txt b/tests/baselines/reference/optionsInlineSourceMapMapRoot.errors.txt new file mode 100644 index 00000000000..a9efb0e2971 --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapMapRoot.errors.txt @@ -0,0 +1,9 @@ +error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'. +error TS5053: Option 'mapRoot' cannot be specified with option 'inlineSourceMap'. + + +!!! error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'. +!!! error TS5053: Option 'mapRoot' cannot be specified with option 'inlineSourceMap'. +==== tests/cases/compiler/optionsInlineSourceMapMapRoot.ts (0 errors) ==== + + var a = 10; \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapMapRoot.js b/tests/baselines/reference/optionsInlineSourceMapMapRoot.js new file mode 100644 index 00000000000..6389f9eb84a --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapMapRoot.js @@ -0,0 +1,7 @@ +//// [optionsInlineSourceMapMapRoot.ts] + +var a = 10; + +//// [optionsInlineSourceMapMapRoot.js] +var a = 10; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt b/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt new file mode 100644 index 00000000000..e12e2d1096a --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt @@ -0,0 +1,33 @@ +=================================================================== +JsFile: optionsInlineSourceMapMapRoot.js +mapUrl: c:/TypeScript/tests/cases/compiler/optionsInlineSourceMapMapRoot.js.map +sourceRoot: +sources: optionsInlineSourceMapMapRoot.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsInlineSourceMapMapRoot.js +sourceFile:optionsInlineSourceMapMapRoot.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourcemap.errors.txt b/tests/baselines/reference/optionsInlineSourceMapSourcemap.errors.txt new file mode 100644 index 00000000000..e91781ccd77 --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourcemap.errors.txt @@ -0,0 +1,7 @@ +error TS5053: Option 'sourceMap' cannot be specified with option 'inlineSourceMap'. + + +!!! error TS5053: Option 'sourceMap' cannot be specified with option 'inlineSourceMap'. +==== tests/cases/compiler/optionsInlineSourceMapSourcemap.ts (0 errors) ==== + + var a = 10; \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourcemap.js b/tests/baselines/reference/optionsInlineSourceMapSourcemap.js new file mode 100644 index 00000000000..96d468d27da --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourcemap.js @@ -0,0 +1,7 @@ +//// [optionsInlineSourceMapSourcemap.ts] + +var a = 10; + +//// [optionsInlineSourceMapSourcemap.js] +var a = 10; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcFNvdXJjZW1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wdGlvbnNJbmxpbmVTb3VyY2VNYXBTb3VyY2VtYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDIn0= \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourcemap.sourcemap.txt b/tests/baselines/reference/optionsInlineSourceMapSourcemap.sourcemap.txt new file mode 100644 index 00000000000..ecd6c4062c3 --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourcemap.sourcemap.txt @@ -0,0 +1,33 @@ +=================================================================== +JsFile: optionsInlineSourceMapSourcemap.js +mapUrl: optionsInlineSourceMapSourcemap.js.map +sourceRoot: +sources: optionsInlineSourceMapSourcemap.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsInlineSourceMapSourcemap.js +sourceFile:optionsInlineSourceMapSourcemap.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcFNvdXJjZW1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wdGlvbnNJbmxpbmVTb3VyY2VNYXBTb3VyY2VtYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDIn0= \ No newline at end of file diff --git a/tests/cases/compiler/optionsInlineSourceMapMapRoot.ts b/tests/cases/compiler/optionsInlineSourceMapMapRoot.ts new file mode 100644 index 00000000000..ddea5f363c7 --- /dev/null +++ b/tests/cases/compiler/optionsInlineSourceMapMapRoot.ts @@ -0,0 +1,4 @@ +// @mapRoot: local +// @inlineSourceMap: true + +var a = 10; \ No newline at end of file diff --git a/tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts b/tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts new file mode 100644 index 00000000000..b4fdc66e309 --- /dev/null +++ b/tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts @@ -0,0 +1,4 @@ +// @sourceRoot: local +// @inlineSourceMap: true + +var a = 10; \ No newline at end of file diff --git a/tests/cases/compiler/optionsInlineSourceMapSourcemap.ts b/tests/cases/compiler/optionsInlineSourceMapSourcemap.ts new file mode 100644 index 00000000000..d78097985d8 --- /dev/null +++ b/tests/cases/compiler/optionsInlineSourceMapSourcemap.ts @@ -0,0 +1,4 @@ +// @sourcemap: true +// @inlineSourceMap: true + +var a = 10; \ No newline at end of file From 1659300ddba965da7dce4ffb12970a5879dca08a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Nov 2015 12:58:31 -0800 Subject: [PATCH 21/44] Fix the --sourceRoot and --mapRoot option handling --- src/compiler/program.ts | 10 +++--- .../reference/inlineSourceMap2.errors.txt | 2 -- .../optionsInlineSourceMapMapRoot.js | 2 +- ...ptionsInlineSourceMapMapRoot.sourcemap.txt | 10 +++--- .../optionsInlineSourceMapSourceRoot.js | 7 ++++ ...onsInlineSourceMapSourceRoot.sourcemap.txt | 33 +++++++++++++++++++ .../optionsInlineSourceMapSourceRoot.symbols | 5 +++ .../optionsInlineSourceMapSourceRoot.types | 6 ++++ ...ourcemapInlineSourcesSourceRoot.errors.txt | 7 ++++ ...nsSourcemapInlineSourcesSourceRoot.symbols | 5 --- ...ionsSourcemapInlineSourcesSourceRoot.types | 6 ---- 11 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourceRoot.js create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourceRoot.sourcemap.txt create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourceRoot.symbols create mode 100644 tests/baselines/reference/optionsInlineSourceMapSourceRoot.types create mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.errors.txt delete mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols delete mode 100644 tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 08321da82e9..ca0c7d9adaa 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -990,16 +990,15 @@ namespace ts { if (options.mapRoot) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap")); } - if (options.sourceRoot) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceRoot", "inlineSourceMap")); - } } - if (options.inlineSources) { if (!options.sourceMap && !options.inlineSourceMap) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided)); } + if (options.sourceRoot) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceRoot", "inlineSources")); + } } if (options.out && options.outFile) { @@ -1011,10 +1010,9 @@ namespace ts { if (options.mapRoot) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap")); } - if (options.sourceRoot) { + if (options.sourceRoot && !options.inlineSourceMap) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "sourceRoot", "sourceMap")); } - return; } const languageVersion = options.target || ScriptTarget.ES3; diff --git a/tests/baselines/reference/inlineSourceMap2.errors.txt b/tests/baselines/reference/inlineSourceMap2.errors.txt index 24b0fddf942..26db1415593 100644 --- a/tests/baselines/reference/inlineSourceMap2.errors.txt +++ b/tests/baselines/reference/inlineSourceMap2.errors.txt @@ -1,12 +1,10 @@ error TS5053: Option 'mapRoot' cannot be specified with option 'inlineSourceMap'. error TS5053: Option 'sourceMap' cannot be specified with option 'inlineSourceMap'. -error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSourceMap'. tests/cases/compiler/inlineSourceMap2.ts(5,1): error TS2304: Cannot find name 'console'. !!! error TS5053: Option 'mapRoot' cannot be specified with option 'inlineSourceMap'. !!! error TS5053: Option 'sourceMap' cannot be specified with option 'inlineSourceMap'. -!!! error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSourceMap'. ==== tests/cases/compiler/inlineSourceMap2.ts (1 errors) ==== // configuration errors diff --git a/tests/baselines/reference/optionsInlineSourceMapMapRoot.js b/tests/baselines/reference/optionsInlineSourceMapMapRoot.js index 6389f9eb84a..c165c49ec29 100644 --- a/tests/baselines/reference/optionsInlineSourceMapMapRoot.js +++ b/tests/baselines/reference/optionsInlineSourceMapMapRoot.js @@ -4,4 +4,4 @@ var a = 10; //// [optionsInlineSourceMapMapRoot.js] var a = 10; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9vcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt b/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt index e12e2d1096a..32e5f85d02f 100644 --- a/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt +++ b/tests/baselines/reference/optionsInlineSourceMapMapRoot.sourcemap.txt @@ -1,12 +1,12 @@ =================================================================== JsFile: optionsInlineSourceMapMapRoot.js -mapUrl: c:/TypeScript/tests/cases/compiler/optionsInlineSourceMapMapRoot.js.map +mapUrl: local/optionsInlineSourceMapMapRoot.js.map sourceRoot: -sources: optionsInlineSourceMapMapRoot.ts +sources: ../optionsInlineSourceMapMapRoot.ts =================================================================== ------------------------------------------------------------------- emittedFile:tests/cases/compiler/optionsInlineSourceMapMapRoot.js -sourceFile:optionsInlineSourceMapMapRoot.ts +sourceFile:../optionsInlineSourceMapMapRoot.ts ------------------------------------------------------------------- >>>var a = 10; 1 > @@ -15,7 +15,7 @@ sourceFile:optionsInlineSourceMapMapRoot.ts 4 > ^^^ 5 > ^^ 6 > ^ -7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> 1 > > 2 >var @@ -30,4 +30,4 @@ sourceFile:optionsInlineSourceMapMapRoot.ts 5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) 6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) --- ->>>//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file +>>>//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcE1hcFJvb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9vcHRpb25zSW5saW5lU291cmNlTWFwTWFwUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourceRoot.js b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.js new file mode 100644 index 00000000000..748fae7320c --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.js @@ -0,0 +1,7 @@ +//// [optionsInlineSourceMapSourceRoot.ts] + +var a = 10; + +//// [optionsInlineSourceMapSourceRoot.js] +var a = 10; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcFNvdXJjZVJvb3QuanMiLCJzb3VyY2VSb290IjoibG9jYWwvIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwU291cmNlUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourceRoot.sourcemap.txt b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.sourcemap.txt new file mode 100644 index 00000000000..b3f81493aa9 --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.sourcemap.txt @@ -0,0 +1,33 @@ +=================================================================== +JsFile: optionsInlineSourceMapSourceRoot.js +mapUrl: optionsInlineSourceMapSourceRoot.js.map +sourceRoot: local/ +sources: optionsInlineSourceMapSourceRoot.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/optionsInlineSourceMapSourceRoot.js +sourceFile:optionsInlineSourceMapSourceRoot.ts +------------------------------------------------------------------- +>>>var a = 10; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + > +2 >var +3 > a +4 > = +5 > 10 +6 > ; +1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(1, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(1, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(1, 12) Source(2, 12) + SourceIndex(0) +--- +>>>//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9uc0lubGluZVNvdXJjZU1hcFNvdXJjZVJvb3QuanMiLCJzb3VyY2VSb290IjoibG9jYWwvIiwic291cmNlcyI6WyJvcHRpb25zSW5saW5lU291cmNlTWFwU291cmNlUm9vdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/tests/baselines/reference/optionsInlineSourceMapSourceRoot.symbols b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.symbols new file mode 100644 index 00000000000..cf8c0826d8e --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.symbols @@ -0,0 +1,5 @@ +=== tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts === + +var a = 10; +>a : Symbol(a, Decl(optionsInlineSourceMapSourceRoot.ts, 1, 3)) + diff --git a/tests/baselines/reference/optionsInlineSourceMapSourceRoot.types b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.types new file mode 100644 index 00000000000..1f6a5fc9dc6 --- /dev/null +++ b/tests/baselines/reference/optionsInlineSourceMapSourceRoot.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/optionsInlineSourceMapSourceRoot.ts === + +var a = 10; +>a : number +>10 : number + diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.errors.txt b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.errors.txt new file mode 100644 index 00000000000..bfa77ff5a3e --- /dev/null +++ b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.errors.txt @@ -0,0 +1,7 @@ +error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSources'. + + +!!! error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSources'. +==== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts (0 errors) ==== + + var a = 10; \ No newline at end of file diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols deleted file mode 100644 index 76f2dc5fdc4..00000000000 --- a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.symbols +++ /dev/null @@ -1,5 +0,0 @@ -=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts === - -var a = 10; ->a : Symbol(a, Decl(optionsSourcemapInlineSourcesSourceRoot.ts, 1, 3)) - diff --git a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types b/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types deleted file mode 100644 index 3689afc382c..00000000000 --- a/tests/baselines/reference/optionsSourcemapInlineSourcesSourceRoot.types +++ /dev/null @@ -1,6 +0,0 @@ -=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts === - -var a = 10; ->a : number ->10 : number - From 15f505e6aa0a3ec3e701b9e2c30cc40a478b88d0 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 13:30:26 -0800 Subject: [PATCH 22/44] use tslint@next --- package.json | 2 +- scripts/tslint/booleanTriviaRule.ts | 11 +++++------ scripts/tslint/nextLineRule.ts | 4 ++-- scripts/tslint/noNullRule.ts | 4 ++-- scripts/tslint/preferConstRule.ts | 8 ++++---- scripts/tslint/typeOperatorSpacingRule.ts | 4 ++-- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 7b8abfaae43..ebdcb73c082 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "browserify": "latest", "istanbul": "latest", "mocha-fivemat-progress-reporter": "latest", - "tslint": "latest", + "tslint": "next", "tsd": "latest" }, "scripts": { diff --git a/scripts/tslint/booleanTriviaRule.ts b/scripts/tslint/booleanTriviaRule.ts index be32a870ff4..93c312ab870 100644 --- a/scripts/tslint/booleanTriviaRule.ts +++ b/scripts/tslint/booleanTriviaRule.ts @@ -1,6 +1,5 @@ -/// -/// - +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; export class Rule extends Lint.Rules.AbstractRule { public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`; @@ -19,7 +18,7 @@ class BooleanTriviaWalker extends Lint.RuleWalker { visitCallExpression(node: ts.CallExpression) { super.visitCallExpression(node); - if (node.arguments) { + if (node.arguments) { const targetCallSignature = this.checker.getResolvedSignature(node); if (!!targetCallSignature) { const targetParameters = targetCallSignature.getParameters(); @@ -37,7 +36,7 @@ class BooleanTriviaWalker extends Lint.RuleWalker { let triviaContent: string; const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0); if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) { - triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); //+/-2 to remove /**/ + triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/ } if (triviaContent !== param.getName()) { this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent))); @@ -45,6 +44,6 @@ class BooleanTriviaWalker extends Lint.RuleWalker { } } } - } + } } } diff --git a/scripts/tslint/nextLineRule.ts b/scripts/tslint/nextLineRule.ts index 6d803fc7f88..d25652f7bce 100644 --- a/scripts/tslint/nextLineRule.ts +++ b/scripts/tslint/nextLineRule.ts @@ -1,5 +1,5 @@ -/// -/// +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; const OPTION_CATCH = "check-catch"; const OPTION_ELSE = "check-else"; diff --git a/scripts/tslint/noNullRule.ts b/scripts/tslint/noNullRule.ts index 2a2c5bc3717..8e9deca996b 100644 --- a/scripts/tslint/noNullRule.ts +++ b/scripts/tslint/noNullRule.ts @@ -1,5 +1,5 @@ -/// -/// +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; export class Rule extends Lint.Rules.AbstractRule { diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index 29160a9c634..e4ffa396fb7 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -1,5 +1,5 @@ -/// -/// +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; export class Rule extends Lint.Rules.AbstractRule { @@ -101,13 +101,13 @@ class PreferConstWalker extends Lint.RuleWalker { this.visitBindingLiteralExpression(node as (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression)); } } - + private visitBindingLiteralExpression(node: ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) { if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { const pattern = node as ts.ObjectLiteralExpression; for (const element of pattern.properties) { if (element.name.kind === ts.SyntaxKind.Identifier) { - this.markAssignment(element.name as ts.Identifier) + this.markAssignment(element.name as ts.Identifier); } else if (isBindingPattern(element.name)) { this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern); diff --git a/scripts/tslint/typeOperatorSpacingRule.ts b/scripts/tslint/typeOperatorSpacingRule.ts index 23925493340..4196d024768 100644 --- a/scripts/tslint/typeOperatorSpacingRule.ts +++ b/scripts/tslint/typeOperatorSpacingRule.ts @@ -1,5 +1,5 @@ -/// -/// +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; export class Rule extends Lint.Rules.AbstractRule { From 77f8d89883c65733f3690dd01bad8bbbfa76c05a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 13:42:46 -0800 Subject: [PATCH 23/44] because it needs to work with npm 2 as well --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ebdcb73c082..474b35a3e1f 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "clean": "jake clean", "jake": "jake", "lint": "jake lint", - "setup-hooks": "node scripts/link-hooks.js" + "setup-hooks": "node scripts/link-hooks.js", + "postinstall": "npm dedupe" }, "browser": { "buffer": false, From ee10ea1baa39f259c84bc020723d60c8b5f76d0a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 13:58:09 -0800 Subject: [PATCH 24/44] this should work better than dedupe --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 474b35a3e1f..261cdfa64b7 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "istanbul": "latest", "mocha-fivemat-progress-reporter": "latest", "tslint": "next", + "typescript": "next", "tsd": "latest" }, "scripts": { @@ -47,8 +48,7 @@ "clean": "jake clean", "jake": "jake", "lint": "jake lint", - "setup-hooks": "node scripts/link-hooks.js", - "postinstall": "npm dedupe" + "setup-hooks": "node scripts/link-hooks.js" }, "browser": { "buffer": false, From 4720c3592df77ac0be3cef7e427e5ea4d0804f84 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 11 Nov 2015 16:51:29 -0800 Subject: [PATCH 25/44] added missing check if file is specified --- src/services/services.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index 0e2dd513336..d1c87d17239 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2847,8 +2847,11 @@ namespace ts { } function sourceFileUpToDate(sourceFile: SourceFile): boolean { + if (!sourceFile) { + return false; + } let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); - return sourceFile && sourceFile.version === hostCache.getVersion(path); + return sourceFile.version === hostCache.getVersion(path); } function programUpToDate(): boolean { From 40e0ffaff7eceb666e7b37e5198bb0acbcf16846 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 11 Nov 2015 23:22:12 -0800 Subject: [PATCH 26/44] Update authors for release 1.7 --- AUTHORS.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 0ade4c31221..a733520ff4f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -8,6 +8,7 @@ TypeScript is authored by: * Basarat Ali Syed * Ben Duffield * Bill Ticehurst +* Brett Mayen * Bryan Forbes * Caitlin Potter * Chris Bubernak @@ -17,11 +18,14 @@ TypeScript is authored by: * Dan Quirk * Daniel Rosenwasser * David Li -* Dick van den Brink -* Dirk Bäumer +* Denis Nedelyaev +* Dick van den Brink +* Dirk Bäumer +* Eyas Sharaiha * Frank Wallis * Gabriel Isenberg * Gilad Peleg +* Graeme Wicksted * Guillaume Salles * Harald Niesche * Ingvar Stepanyan @@ -31,30 +35,39 @@ TypeScript is authored by: * Jason Ramsay * Jed Mao * Johannes Rieken +* John Vilk * Jonathan Bond-Caron * Jonathan Park * Jonathan Turner * Josh Kalderimis +* Julian Williams * Kagami Sascha Rosylight * Keith Mashinter +* Ken Howard * Kenji Imamula * Lorant Pinter +* Martin VÅ¡etiÄka * Masahiro Wakame * Max Deepfield * Micah Zoltu * Mohamed Hegazy +* Nathan Shively-Sanders * Oleg Mihailik * Oleksandr Chekhovskyi * Paul van Brenk * Pedro Maltez * Philip Bulley * piloopin +* @progre +* Punya Biswal * Ron Buckton * Ryan Cavanaugh +* Ryohei Ikegami +* Sébastien Arod * Sheetal Nandi * Shengping Zhong * Shyyko Serhiy -* Simon Hürlimann +* Simon H�rlimann * Solal Pirelli * Stan Thomas * Steve Lucco @@ -63,8 +76,10 @@ TypeScript is authored by: * togru * Tomas Grubliauskas * TruongSinh Tran-Nguyen +* Viliv Vane * Vladimir Matveev * Wesley Wigham +* York Yao * Yui Tanglertsampan * Zev Spitz * Zhengbo Li \ No newline at end of file From f4929e7b1822f57abedd568edfe57d736fbaae13 Mon Sep 17 00:00:00 2001 From: mihailik Date: Thu, 12 Nov 2015 12:28:37 +0000 Subject: [PATCH 27/44] Encoding bug --- AUTHORS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index a733520ff4f..486a15bf47f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -67,7 +67,7 @@ TypeScript is authored by: * Sheetal Nandi * Shengping Zhong * Shyyko Serhiy -* Simon H�rlimann +* Simon Hürlimann * Solal Pirelli * Stan Thomas * Steve Lucco @@ -82,4 +82,4 @@ TypeScript is authored by: * York Yao * Yui Tanglertsampan * Zev Spitz -* Zhengbo Li \ No newline at end of file +* Zhengbo Li From ebd1b873f168dc742f1e4681e576b1e74ff91b14 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 12 Nov 2015 10:17:47 -0800 Subject: [PATCH 28/44] always check statements in case clause --- src/compiler/checker.ts | 12 +++---- .../checkSwitchStatementIfCaseTypeIsString.js | 27 +++++++++++++++ ...kSwitchStatementIfCaseTypeIsString.symbols | 29 ++++++++++++++++ ...eckSwitchStatementIfCaseTypeIsString.types | 33 +++++++++++++++++++ .../checkSwitchStatementIfCaseTypeIsString.ts | 11 +++++++ 5 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js create mode 100644 tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols create mode 100644 tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types create mode 100644 tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7856e3f4cda..a215eda64c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12886,13 +12886,13 @@ namespace ts { // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. const caseType = checkExpression(caseClause.expression); - // Permit 'number[] | "foo"' to be asserted to 'string'. - if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, TypeFlags.StringLike)) { - return; - } + const expressionTypeIsAssignableToCaseType = + // Permit 'number[] | "foo"' to be asserted to 'string'. + (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, TypeFlags.StringLike)) || + isTypeAssignableTo(expressionType, caseType); - if (!isTypeAssignableTo(expressionType, caseType)) { - // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails + if (!expressionTypeIsAssignableToCaseType) { + // 'expressionType is not assignable to caseType', try the reversed check and report errors if it fails checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js new file mode 100644 index 00000000000..64ea4e67fa8 --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js @@ -0,0 +1,27 @@ +//// [checkSwitchStatementIfCaseTypeIsString.ts] +declare function use(a: any): void; + +class A { + doIt(x: Array): void { + x.forEach((v) => { + switch(v) { + case "test": use(this); + } + }); + } +} + +//// [checkSwitchStatementIfCaseTypeIsString.js] +var A = (function () { + function A() { + } + A.prototype.doIt = function (x) { + var _this = this; + x.forEach(function (v) { + switch (v) { + case "test": use(_this); + } + }); + }; + return A; +})(); diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols new file mode 100644 index 00000000000..6bc994f2a44 --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts === +declare function use(a: any): void; +>use : Symbol(use, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 0)) +>a : Symbol(a, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 21)) + +class A { +>A : Symbol(A, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 35)) + + doIt(x: Array): void { +>doIt : Symbol(doIt, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 2, 9)) +>x : Symbol(x, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 3, 9)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + x.forEach((v) => { +>x.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 3, 9)) +>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) +>v : Symbol(v, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 4, 19)) + + switch(v) { +>v : Symbol(v, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 4, 19)) + + case "test": use(this); +>use : Symbol(use, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 0)) +>this : Symbol(A, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 35)) + } + }); + } +} diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types new file mode 100644 index 00000000000..fa394b4e0bd --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts === +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +class A { +>A : A + + doIt(x: Array): void { +>doIt : (x: string[]) => void +>x : string[] +>Array : T[] + + x.forEach((v) => { +>x.forEach((v) => { switch(v) { case "test": use(this); } }) : void +>x.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void +>x : string[] +>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void +>(v) => { switch(v) { case "test": use(this); } } : (v: string) => void +>v : string + + switch(v) { +>v : string + + case "test": use(this); +>"test" : string +>use(this) : void +>use : (a: any) => void +>this : this + } + }); + } +} diff --git a/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts b/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts new file mode 100644 index 00000000000..931f64a4b29 --- /dev/null +++ b/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts @@ -0,0 +1,11 @@ +declare function use(a: any): void; + +class A { + doIt(x: Array): void { + x.forEach((v) => { + switch(v) { + case "test": use(this); + } + }); + } +} \ No newline at end of file From ea29793acd6a5e83d7177c41448b72da419bfe5f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 12 Nov 2015 11:02:19 -0800 Subject: [PATCH 29/44] Quote only names that need to be quoted, not the reverse --- src/compiler/emitter.ts | 6 +-- .../getEmitOutputTsxFile_React.baseline | 4 +- .../reference/keywordInJsxIdentifier.js | 4 +- .../reference/tsxExternalModuleEmit2.js | 2 +- .../reference/tsxReactEmit7.errors.txt | 50 +++++++++++++++++++ tests/baselines/reference/tsxReactEmit7.js | 33 ++++++++++++ tests/cases/conformance/jsx/tsxReactEmit7.tsx | 22 ++++++++ 7 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/tsxReactEmit7.errors.txt create mode 100644 tests/baselines/reference/tsxReactEmit7.js create mode 100644 tests/cases/conformance/jsx/tsxReactEmit7.tsx diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d0314649b88..372389f9c4a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1592,13 +1592,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /// these emit into an object literal property name, we don't need to be worried /// about keywords, just non-identifier characters function emitAttributeName(name: Identifier) { - if (/[A-Za-z_]+[\w*]/.test(name.text)) { - write("\""); + if (/^[A-Za-z_]+[\w]*$/.test(name.text)) { emit(name); - write("\""); } else { + write("\""); emit(name); + write("\""); } } diff --git a/tests/baselines/reference/getEmitOutputTsxFile_React.baseline b/tests/baselines/reference/getEmitOutputTsxFile_React.baseline index c796f8e78bc..57b55c8a1f8 100644 --- a/tests/baselines/reference/getEmitOutputTsxFile_React.baseline +++ b/tests/baselines/reference/getEmitOutputTsxFile_React.baseline @@ -17,9 +17,9 @@ declare class Bar { EmitSkipped: false FileName : tests/cases/fourslash/inputFile2.js.map -{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,qBAAC,GAAG,KAAC,IAAI,GAAG,CAAE,EAAG,CAAA"}FileName : tests/cases/fourslash/inputFile2.js +{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,qBAAC,GAAG,IAAC,IAAI,EAAG,CAAE,EAAG,CAAA"}FileName : tests/cases/fourslash/inputFile2.js var y = "my div"; -var x = React.createElement("div", {"name": y}); +var x = React.createElement("div", {name: y}); //# sourceMappingURL=inputFile2.js.mapFileName : tests/cases/fourslash/inputFile2.d.ts declare var y: string; declare var x: any; diff --git a/tests/baselines/reference/keywordInJsxIdentifier.js b/tests/baselines/reference/keywordInJsxIdentifier.js index 677a79138e6..39f33449dad 100644 --- a/tests/baselines/reference/keywordInJsxIdentifier.js +++ b/tests/baselines/reference/keywordInJsxIdentifier.js @@ -9,6 +9,6 @@ declare var React: any; //// [keywordInJsxIdentifier.js] React.createElement("foo", {"class-id": true}); -React.createElement("foo", {"class": true}); +React.createElement("foo", {class: true}); React.createElement("foo", {"class-id": "1"}); -React.createElement("foo", {"class": "1"}); +React.createElement("foo", {class: "1"}); diff --git a/tests/baselines/reference/tsxExternalModuleEmit2.js b/tests/baselines/reference/tsxExternalModuleEmit2.js index f8fe6096090..9968fa8d708 100644 --- a/tests/baselines/reference/tsxExternalModuleEmit2.js +++ b/tests/baselines/reference/tsxExternalModuleEmit2.js @@ -20,6 +20,6 @@ declare var Foo, React; //// [app.js] var mod_1 = require('mod'); // Should see mod_1['default'] in emit here -React.createElement(Foo, {"handler": mod_1["default"]}); +React.createElement(Foo, {handler: mod_1["default"]}); // Should see mod_1['default'] in emit here React.createElement(Foo, React.__spread({}, mod_1["default"])); diff --git a/tests/baselines/reference/tsxReactEmit7.errors.txt b/tests/baselines/reference/tsxReactEmit7.errors.txt new file mode 100644 index 00000000000..d2ab2f046e9 --- /dev/null +++ b/tests/baselines/reference/tsxReactEmit7.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/jsx/tsxReactEmit7.tsx(9,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(10,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(11,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(12,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(15,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(16,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(17,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(18,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/tsxReactEmit7.tsx(19,10): error TS2304: Cannot find name 'React'. + + +==== tests/cases/conformance/jsx/tsxReactEmit7.tsx (9 errors) ==== + + declare module JSX { + interface Element { } + interface IntrinsicElements { + [s: string]: any; + } + } + + var m =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var n =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var o =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var p =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + + // Investigation + var a =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var b =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var c =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var d =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + var e =
; + ~~~ +!!! error TS2304: Cannot find name 'React'. + \ No newline at end of file diff --git a/tests/baselines/reference/tsxReactEmit7.js b/tests/baselines/reference/tsxReactEmit7.js new file mode 100644 index 00000000000..6340b321b9c --- /dev/null +++ b/tests/baselines/reference/tsxReactEmit7.js @@ -0,0 +1,33 @@ +//// [tsxReactEmit7.tsx] + +declare module JSX { + interface Element { } + interface IntrinsicElements { + [s: string]: any; + } +} + +var m =
; +var n =
; +var o =
; +var p =
; + +// Investigation +var a =
; +var b =
; +var c =
; +var d =
; +var e =
; + + +//// [tsxReactEmit7.js] +var m = React.createElement("div", {"x-y": "val"}); +var n = React.createElement("div", {"xx-y": "val"}); +var o = React.createElement("div", {"x-yy": "val"}); +var p = React.createElement("div", {"xx-yy": "val"}); +// Investigation +var a = React.createElement("div", {x: "val"}); +var b = React.createElement("div", {xx: "val"}); +var c = React.createElement("div", {xxx: "val"}); +var d = React.createElement("div", {xxxx: "val"}); +var e = React.createElement("div", {xxxxx: "val"}); diff --git a/tests/cases/conformance/jsx/tsxReactEmit7.tsx b/tests/cases/conformance/jsx/tsxReactEmit7.tsx new file mode 100644 index 00000000000..847a55d4719 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxReactEmit7.tsx @@ -0,0 +1,22 @@ +//@jsx: react +//@module: commonjs + +//@filename: file.tsx +declare module JSX { + interface Element { } + interface IntrinsicElements { + [s: string]: any; + } +} + +var m =
; +var n =
; +var o =
; +var p =
; + +// Investigation +var a =
; +var b =
; +var c =
; +var d =
; +var e =
; From 3d9978f677162c22a0b4f5e94759e448c9b4199c Mon Sep 17 00:00:00 2001 From: bootstraponline Date: Thu, 12 Nov 2015 10:38:04 -0500 Subject: [PATCH 30/44] Use https for badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e27e7a99fa7..13e1f3e4786 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build Status](https://travis-ci.org/Microsoft/TypeScript.svg?branch=master)](https://travis-ci.org/Microsoft/TypeScript) -[![npm version](https://badge.fury.io/js/typescript.svg)](http://badge.fury.io/js/typescript) -[![Downloads](http://img.shields.io/npm/dm/TypeScript.svg)](https://npmjs.org/package/typescript) +[![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript) +[![Downloads](https://img.shields.io/npm/dm/TypeScript.svg)](https://www.npmjs.com/package/typescript) # TypeScript From 278b35b354913e81fd1ea6886684ecef6c5e99a1 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 12 Nov 2015 11:16:11 -0800 Subject: [PATCH 31/44] Adding test and comments. Override file content even if already opened. --- src/harness/fourslash.ts | 8 ++++---- src/harness/harnessLanguageService.ts | 8 ++++---- src/server/client.ts | 4 ++-- src/server/editorServices.ts | 3 +++ src/server/protocol.d.ts | 4 ++++ tests/cases/fourslash/fourslash.ts | 8 ++++---- tests/cases/fourslash/server/openFile.ts | 17 +++++++++++++++++ 7 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 tests/cases/fourslash/server/openFile.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 1c8593a9e12..545776ec084 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -385,9 +385,9 @@ namespace FourSlash { } // Opens a file given its 0-based index or fileName - public openFile(index: number): void; - public openFile(name: string): void; - public openFile(indexOrName: any) { + public openFile(index: number, content?: string): void; + public openFile(name: string, content?: string): void; + public openFile(indexOrName: any, content?: string) { const fileToOpen: FourSlashFile = this.findFile(indexOrName); fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName); this.activeFile = fileToOpen; @@ -395,7 +395,7 @@ namespace FourSlash { this.scenarioActions.push(``); // Let the host know that this file is now open - this.languageServiceAdapterHost.openFile(fileToOpen.fileName); + this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content); } public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index faf0ad28eb5..0c267c38f14 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -153,7 +153,7 @@ namespace Harness.LanguageService { throw new Error("No script with name '" + fileName + "'"); } - public openFile(fileName: string): void { + public openFile(fileName: string, content?: string): void { } /** @@ -493,9 +493,9 @@ namespace Harness.LanguageService { this.client = client; } - openFile(fileName: string): void { - super.openFile(fileName); - this.client.openFile(fileName); + openFile(fileName: string, content?: string): void { + super.openFile(fileName, content); + this.client.openFile(fileName, content); } editScript(fileName: string, start: number, end: number, newText: string) { diff --git a/src/server/client.ts b/src/server/client.ts index ae234750d88..08939b2b44a 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -120,8 +120,8 @@ namespace ts.server { return response; } - openFile(fileName: string): void { - var args: protocol.FileRequestArgs = { file: fileName }; + openFile(fileName: string, content?: string): void { + var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content }; this.processRequest(CommandNames.Open, args); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 889c96b6c4e..795bd7db732 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1031,6 +1031,9 @@ namespace ts.server { } } if (info) { + if (fileContent) { + info.svc.reload(fileContent); + } if (openedByClient) { info.isOpen = true; } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 6354a3a37ae..101c8207c9d 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -513,6 +513,10 @@ declare namespace ts.server.protocol { * Information found in an "open" request. */ export interface OpenRequestArgs extends FileRequestArgs { + /** + * Used when a version of the file content is known to be more up to date than the one on disk. + * Then the known content will be used upon opening instead of the disk copy + */ fileContent?: string; } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 41e8d9005f7..f6451e1f1c4 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -169,10 +169,10 @@ module FourSlashInterface { // Opens a file, given either its index as it // appears in the test source, or its filename // as specified in the test metadata - public file(index: number); - public file(name: string); - public file(indexOrName: any) { - FourSlash.currentTestState.openFile(indexOrName); + public file(index: number, content?: string); + public file(name: string, content?: string); + public file(indexOrName: any, content?: string) { + FourSlash.currentTestState.openFile(indexOrName, content); } } diff --git a/tests/cases/fourslash/server/openFile.ts b/tests/cases/fourslash/server/openFile.ts new file mode 100644 index 00000000000..41d2bbe8e53 --- /dev/null +++ b/tests/cases/fourslash/server/openFile.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: test1.ts +////t. + +// @Filename: test.ts +////var t = '10'; + +// @Filename: tsconfig.json +////{ "files": ["test.ts", "test1.ts"] } + +var overridingContent = "var t = 10; t."; +debugger; +goTo.file("test.ts", overridingContent); +goTo.file("test1.ts"); +goTo.eof(); +verify.completionListContains("toExponential"); From a0549fa316d05bd79ab1bb97b32744b9748091a4 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 12 Nov 2015 11:33:44 -0800 Subject: [PATCH 32/44] Fix lint compliant --- src/server/protocol.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 101c8207c9d..3a669753323 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -516,7 +516,7 @@ declare namespace ts.server.protocol { /** * Used when a version of the file content is known to be more up to date than the one on disk. * Then the known content will be used upon opening instead of the disk copy - */ + */ fileContent?: string; } From fe9d73eb5bc08e752793f143c31c713c93ef85d0 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 12 Nov 2015 11:42:21 -0800 Subject: [PATCH 33/44] Remove debugger statement from test --- tests/cases/fourslash/server/openFile.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/server/openFile.ts b/tests/cases/fourslash/server/openFile.ts index 41d2bbe8e53..320e52c9f5e 100644 --- a/tests/cases/fourslash/server/openFile.ts +++ b/tests/cases/fourslash/server/openFile.ts @@ -10,7 +10,6 @@ ////{ "files": ["test.ts", "test1.ts"] } var overridingContent = "var t = 10; t."; -debugger; goTo.file("test.ts", overridingContent); goTo.file("test1.ts"); goTo.eof(); From f90ef92e7c566cb892dea28286f64177be8d2ab0 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 12 Nov 2015 13:37:03 -0800 Subject: [PATCH 34/44] Simplify regex a bit --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 372389f9c4a..84d6f091039 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1592,7 +1592,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /// these emit into an object literal property name, we don't need to be worried /// about keywords, just non-identifier characters function emitAttributeName(name: Identifier) { - if (/^[A-Za-z_]+[\w]*$/.test(name.text)) { + if (/^[A-Za-z_]\w*$/.test(name.text)) { emit(name); } else { From 986d8845029fa0eb9b52b61e270b7c87501ba25e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Nov 2015 14:13:35 -0800 Subject: [PATCH 35/44] Test case for multiline spanning without return statement --- ...apValidationLambdaSpanningMultipleLines.js | 10 ++++ ...lidationLambdaSpanningMultipleLines.js.map | 2 + ...nLambdaSpanningMultipleLines.sourcemap.txt | 51 +++++++++++++++++++ ...idationLambdaSpanningMultipleLines.symbols | 8 +++ ...alidationLambdaSpanningMultipleLines.types | 10 ++++ ...apValidationLambdaSpanningMultipleLines.ts | 4 ++ 6 files changed, 85 insertions(+) create mode 100644 tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js create mode 100644 tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map create mode 100644 tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt create mode 100644 tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols create mode 100644 tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types create mode 100644 tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js new file mode 100644 index 00000000000..ec6b5682edd --- /dev/null +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js @@ -0,0 +1,10 @@ +//// [sourceMapValidationLambdaSpanningMultipleLines.ts] +((item: string) => + item +) + +//// [sourceMapValidationLambdaSpanningMultipleLines.js] +(function (item) { + return item; +}); +//# sourceMappingURL=sourceMapValidationLambdaSpanningMultipleLines.js.map \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map new file mode 100644 index 00000000000..4512ccf1748 --- /dev/null +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map @@ -0,0 +1,2 @@ +//// [sourceMapValidationLambdaSpanningMultipleLines.js.map] +{"version":3,"file":"sourceMapValidationLambdaSpanningMultipleLines.js","sourceRoot":"","sources":["sourceMapValidationLambdaSpanningMultipleLines.ts"],"names":[],"mappings":"AAAA,CAAC,UAAC,IAAY;WACV,IAAI;AAAJ,CAAI,CACP,CAAA"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt new file mode 100644 index 00000000000..0950e268b6e --- /dev/null +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt @@ -0,0 +1,51 @@ +=================================================================== +JsFile: sourceMapValidationLambdaSpanningMultipleLines.js +mapUrl: sourceMapValidationLambdaSpanningMultipleLines.js.map +sourceRoot: +sources: sourceMapValidationLambdaSpanningMultipleLines.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.js +sourceFile:sourceMapValidationLambdaSpanningMultipleLines.ts +------------------------------------------------------------------- +>>>(function (item) { +1 > +2 >^ +3 > ^^^^^^^^^^ +4 > ^^^^ +5 > ^^-> +1 > +2 >( +3 > ( +4 > item: string +1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0) +2 >Emitted(1, 2) Source(1, 2) + SourceIndex(0) +3 >Emitted(1, 12) Source(1, 3) + SourceIndex(0) +4 >Emitted(1, 16) Source(1, 15) + SourceIndex(0) +--- +>>> return item; +1->^^^^^^^^^^^ +2 > ^^^^ +1->) => + > +2 > item +1->Emitted(2, 12) Source(2, 5) + SourceIndex(0) +2 >Emitted(2, 16) Source(2, 9) + SourceIndex(0) +--- +>>>}); +1 > +2 >^ +3 > ^ +4 > ^ +5 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > +2 >item +3 > + > ) +4 > +1 >Emitted(3, 1) Source(2, 5) + SourceIndex(0) +2 >Emitted(3, 2) Source(2, 9) + SourceIndex(0) +3 >Emitted(3, 3) Source(3, 2) + SourceIndex(0) +4 >Emitted(3, 4) Source(3, 2) + SourceIndex(0) +--- +>>>//# sourceMappingURL=sourceMapValidationLambdaSpanningMultipleLines.js.map \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols new file mode 100644 index 00000000000..c7ff4ca9d9f --- /dev/null +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts === +((item: string) => +>item : Symbol(item, Decl(sourceMapValidationLambdaSpanningMultipleLines.ts, 0, 2)) + + item +>item : Symbol(item, Decl(sourceMapValidationLambdaSpanningMultipleLines.ts, 0, 2)) + +) diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types new file mode 100644 index 00000000000..d39119cbd91 --- /dev/null +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts === +((item: string) => +>((item: string) => item) : (item: string) => string +>(item: string) => item : (item: string) => string +>item : string + + item +>item : string + +) diff --git a/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts b/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts new file mode 100644 index 00000000000..57ba843a69c --- /dev/null +++ b/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts @@ -0,0 +1,4 @@ +// @sourcemap: true +((item: string) => + item +) \ No newline at end of file From 127a30e1517685cc6291bb1b83190393a146a7a7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Nov 2015 14:15:33 -0800 Subject: [PATCH 36/44] Fix the sourcemap emit of lambda expression without return on another line Handles #5122 --- src/compiler/emitter.ts | 2 ++ ...eMapValidationLambdaSpanningMultipleLines.js.map | 2 +- ...idationLambdaSpanningMultipleLines.sourcemap.txt | 13 ++++++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d0314649b88..a3c538c36ae 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -5003,8 +5003,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi increaseIndent(); writeLine(); emitLeadingComments(node.body); + emitStart(body); write("return "); emit(body); + emitEnd(body); write(";"); emitTrailingComments(node.body); diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map index 4512ccf1748..c0151106e7c 100644 --- a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationLambdaSpanningMultipleLines.js.map] -{"version":3,"file":"sourceMapValidationLambdaSpanningMultipleLines.js","sourceRoot":"","sources":["sourceMapValidationLambdaSpanningMultipleLines.ts"],"names":[],"mappings":"AAAA,CAAC,UAAC,IAAY;WACV,IAAI;AAAJ,CAAI,CACP,CAAA"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationLambdaSpanningMultipleLines.js","sourceRoot":"","sources":["sourceMapValidationLambdaSpanningMultipleLines.ts"],"names":[],"mappings":"AAAA,CAAC,UAAC,IAAY;IACV,OAAA,IAAI;AAAJ,CAAI,CACP,CAAA"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt index 0950e268b6e..475aa1debef 100644 --- a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt @@ -24,13 +24,16 @@ sourceFile:sourceMapValidationLambdaSpanningMultipleLines.ts 4 >Emitted(1, 16) Source(1, 15) + SourceIndex(0) --- >>> return item; -1->^^^^^^^^^^^ -2 > ^^^^ +1->^^^^ +2 > ^^^^^^^ +3 > ^^^^ 1->) => > -2 > item -1->Emitted(2, 12) Source(2, 5) + SourceIndex(0) -2 >Emitted(2, 16) Source(2, 9) + SourceIndex(0) +2 > +3 > item +1->Emitted(2, 5) Source(2, 5) + SourceIndex(0) +2 >Emitted(2, 12) Source(2, 5) + SourceIndex(0) +3 >Emitted(2, 16) Source(2, 9) + SourceIndex(0) --- >>>}); 1 > From 346253a0d520e24083ab013d247b986cc9b63db9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 11:13:10 -0800 Subject: [PATCH 37/44] test, first pass at a fix --- src/compiler/checker.ts | 4 +++ .../typeGuards/typeGuardTypeOfUndefined.ts | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ec91b255ae6..6f5a3e67d0a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -200,6 +200,10 @@ namespace ts { "symbol": { type: esSymbolType, flags: TypeFlags.ESSymbol + }, + "undefined": { + type: undefinedType, + flags: TypeFlags.ContainsUndefinedOrNull } }; diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts new file mode 100644 index 00000000000..50612449145 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts @@ -0,0 +1,28 @@ +// undefined type guard adds no new type information +function test1(a: any) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + } +} + +function test2(a: any) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + } +} + +function test3(a: any) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } +} + +function test4(a: any) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } +} From b93feb87be769e0fed76b825e2df51b772ad115c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 13 Nov 2015 11:14:51 -0800 Subject: [PATCH 38/44] cleanup test harness code --- src/harness/compilerRunner.ts | 41 ++++---- src/harness/fourslash.ts | 33 ++++-- src/harness/harness.ts | 182 +++++++++++++--------------------- src/harness/projectsRunner.ts | 2 +- src/harness/rwcRunner.ts | 24 +++-- src/harness/test262Runner.ts | 24 +++-- 6 files changed, 141 insertions(+), 165 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 848f229f109..d46d0bde08c 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -49,7 +49,7 @@ class CompilerBaselineRunner extends RunnerBase { let testCaseContent: { settings: Harness.TestCaseParser.CompilerSettings; testUnitData: Harness.TestCaseParser.TestUnitData[]; }; let units: Harness.TestCaseParser.TestUnitData[]; - let tcSettings: Harness.TestCaseParser.CompilerSettings; + let harnessSettings: Harness.TestCaseParser.CompilerSettings; let lastUnit: Harness.TestCaseParser.TestUnitData; let rootDir: string; @@ -58,46 +58,43 @@ class CompilerBaselineRunner extends RunnerBase { let program: ts.Program; let options: ts.CompilerOptions; // equivalent to the files that will be passed on the command line - let toBeCompiled: { unitName: string; content: string }[]; + let toBeCompiled: Harness.Compiler.TestFile[]; // equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files) - let otherFiles: { unitName: string; content: string }[]; - let harnessCompiler: Harness.Compiler.HarnessCompiler; + let otherFiles: Harness.Compiler.TestFile[]; before(() => { justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path. content = Harness.IO.readFile(fileName); testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); units = testCaseContent.testUnitData; - tcSettings = testCaseContent.settings; + harnessSettings = testCaseContent.settings; lastUnit = units[units.length - 1]; rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; - harnessCompiler = Harness.Compiler.getCompiler(); // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. toBeCompiled = []; otherFiles = []; if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) { - toBeCompiled.push({ unitName: rootDir + lastUnit.name, content: lastUnit.content }); + toBeCompiled.push({ unitName: ts.combinePaths(rootDir, lastUnit.name), content: lastUnit.content }); units.forEach(unit => { if (unit.name !== lastUnit.name) { - otherFiles.push({ unitName: rootDir + unit.name, content: unit.content }); + otherFiles.push({ unitName: ts.combinePaths(rootDir, unit.name), content: unit.content }); } }); } else { toBeCompiled = units.map(unit => { - return { unitName: rootDir + unit.name, content: unit.content }; + return { unitName: ts.combinePaths(rootDir, unit.name), content: unit.content }; }); } - options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _program) { - result = compileResult; - // The program will be used by typeWriter - program = _program; - }, function (settings) { - harnessCompiler.setCompilerSettings(tcSettings); - }); + const output = Harness.Compiler.HarnessCompiler.compileFiles( + toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined); + + options = output.options; + result = output.result; + program = output.program; }); after(() => { @@ -107,7 +104,7 @@ class CompilerBaselineRunner extends RunnerBase { content = undefined; testCaseContent = undefined; units = undefined; - tcSettings = undefined; + harnessSettings = undefined; lastUnit = undefined; rootDir = undefined; result = undefined; @@ -115,14 +112,13 @@ class CompilerBaselineRunner extends RunnerBase { options = undefined; toBeCompiled = undefined; otherFiles = undefined; - harnessCompiler = undefined; }); function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string { return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : ""; } - function getErrorBaseline(toBeCompiled: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], result: Harness.Compiler.CompilerResult) { + function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) { return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors); } @@ -184,9 +180,9 @@ class CompilerBaselineRunner extends RunnerBase { } } - const declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) { - harnessCompiler.setCompilerSettings(tcSettings); - }, options); + const declFileCompilationResult = + Harness.Compiler.HarnessCompiler.compileDeclarationFiles( + toBeCompiled, otherFiles, result, harnessSettings, options, /* currentDirectory */ undefined); if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) { jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n"; @@ -367,7 +363,6 @@ class CompilerBaselineRunner extends RunnerBase { public initializeTests() { describe(this.testSuiteName + " tests", () => { describe("Setup compiler for compiler baselines", () => { - const harnessCompiler = Harness.Compiler.getCompiler(); this.parseOptions(); }); diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 1c8593a9e12..23aadb53241 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2383,10 +2383,16 @@ namespace FourSlash { // here we cache the JS output and reuse it for every test. let fourslashJsOutput: string; { - const host = Harness.Compiler.createCompilerHost([{ unitName: Harness.Compiler.fourslashFileName, content: undefined }], + const fourslashFile: Harness.Compiler.TestFileWithPath = { + unitName: Harness.Compiler.fourslashFileName, + content: undefined, + path: ts.toPath(Harness.Compiler.fourslashFileName, Harness.IO.getCurrentDirectory(), Harness.Compiler.getCanonicalFileName) + }; + const host = Harness.Compiler.createCompilerHost([fourslashFile], (fn, contents) => fourslashJsOutput = contents, ts.ScriptTarget.Latest, - Harness.IO.useCaseSensitiveFileNames()); + Harness.IO.useCaseSensitiveFileNames(), + Harness.IO.getCurrentDirectory()); const program = ts.createProgram([Harness.Compiler.fourslashFileName], { noResolve: true, target: ts.ScriptTarget.ES3 }, host); @@ -2400,15 +2406,28 @@ namespace FourSlash { currentTestState = new TestState(basePath, testType, testData); + const currentDirectory = Harness.IO.getCurrentDirectory(); + const useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); + const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + let result = ""; + const fourslashFile: Harness.Compiler.TestFileWithPath = { + unitName: Harness.Compiler.fourslashFileName, + content: undefined, + path: ts.toPath(Harness.Compiler.fourslashFileName, currentDirectory, getCanonicalFileName) + }; + const testFile: Harness.Compiler.TestFileWithPath = { + unitName: fileName, + content: content, + path: ts.toPath(fileName, currentDirectory, getCanonicalFileName) + }; + const host = Harness.Compiler.createCompilerHost( - [ - { unitName: Harness.Compiler.fourslashFileName, content: undefined }, - { unitName: fileName, content: content } - ], + [ fourslashFile, testFile ], (fn, contents) => result = contents, ts.ScriptTarget.Latest, - Harness.IO.useCaseSensitiveFileNames()); + useCaseSensitiveFileNames, + currentDirectory); const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 16c3b2d3488..468517b68f7 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -903,41 +903,34 @@ namespace Harness { } export function createCompilerHost( - inputFiles: { unitName: string; content: string; }[], + inputFiles: TestFileWithPath[], writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void, scriptTarget: ts.ScriptTarget, useCaseSensitiveFileNames: boolean, // the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host - currentDirectory?: string, + currentDirectory: string, newLineKind?: ts.NewLineKind): ts.CompilerHost { // Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames - function getCanonicalFileName(fileName: string): string { - return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - } + const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - const filemap: { [fileName: string]: ts.SourceFile; } = {}; - const getCurrentDirectory = currentDirectory === undefined ? Harness.IO.getCurrentDirectory : () => currentDirectory; + const fileMap: ts.FileMap = ts.createFileMap(); // Register input files - function register(file: { unitName: string; content: string; }) { + function register(file: TestFileWithPath) { if (file.content !== undefined) { const fileName = ts.normalizePath(file.unitName); const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget); - filemap[getCanonicalFileName(fileName)] = sourceFile; - filemap[getCanonicalFileName(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory()))] = sourceFile; + fileMap.set(file.path, sourceFile); } }; inputFiles.forEach(register); function getSourceFile(fn: string, languageVersion: ts.ScriptTarget) { fn = ts.normalizePath(fn); - if (Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(fn))) { - return filemap[getCanonicalFileName(fn)]; - } - else if (currentDirectory) { - const canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory)); - return Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(canonicalAbsolutePath)) ? filemap[canonicalAbsolutePath] : undefined; + const path = ts.toPath(fn, currentDirectory, getCanonicalFileName); + if (fileMap.contains(path)) { + return fileMap.get(path); } else if (fn === fourslashFileName) { const tsFn = "tests/cases/fourslash/" + fourslashFileName; @@ -959,7 +952,7 @@ namespace Harness { Harness.IO.newLine(); return { - getCurrentDirectory, + getCurrentDirectory: () => currentDirectory, getSourceFile, getDefaultLibFileName: options => defaultLibFileName, writeFile, @@ -1034,95 +1027,74 @@ namespace Harness { } } - export class HarnessCompiler { - private inputFiles: { unitName: string; content: string }[] = []; - private compileOptions: ts.CompilerOptions; - private settings: Harness.TestCaseParser.CompilerSettings = {}; + export interface TestFile { + unitName: string; + content: string; + } + export interface TestFileWithPath extends TestFile { + path: ts.Path; + } - private lastErrors: ts.Diagnostic[]; + export interface CompilationOutput { + result: CompilerResult; + program: ts.Program; + options: ts.CompilerOptions & HarnessOptions; + } - public reset() { - this.inputFiles = []; - this.settings = {}; - this.lastErrors = []; - } - - public reportCompilationErrors() { - return this.lastErrors; - } - - public setCompilerSettings(tcSettings: Harness.TestCaseParser.CompilerSettings) { - this.settings = tcSettings; - } - - public addInputFiles(files: { unitName: string; content: string }[]) { - files.forEach(file => this.addInputFile(file)); - } - - public addInputFile(file: { unitName: string; content: string }) { - this.inputFiles.push(file); - } - - public setCompilerOptions(options?: ts.CompilerOptions) { - this.compileOptions = options || { noResolve: false }; - } - - public emitAll(ioHost?: IEmitterIOHost) { - this.compileFiles(this.inputFiles, - /*otherFiles*/ [], - /*onComplete*/ result => { - result.files.forEach(writeFile); - result.declFilesCode.forEach(writeFile); - result.sourceMaps.forEach(writeFile); - }, - /*settingsCallback*/ () => { }, - this.compileOptions); - - function writeFile(file: GeneratedFile) { - ioHost.writeFile(file.fileName, file.code, false); - } - } - - public compileFiles(inputFiles: { unitName: string; content: string }[], - otherFiles: { unitName: string; content: string }[], - onComplete: (result: CompilerResult, program: ts.Program) => void, - settingsCallback?: (settings: ts.CompilerOptions) => void, - options?: ts.CompilerOptions & HarnessOptions, + export namespace HarnessCompiler { + export function compileFiles( + inputFiles: TestFile[], + otherFiles: TestFile[], + harnessSettings: TestCaseParser.CompilerSettings, + compilerOptions: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory?: string) { + currentDirectory: string): CompilationOutput { - options = options || { noResolve: false }; + const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false }; options.target = options.target || ts.ScriptTarget.ES3; options.module = options.module || ts.ModuleKind.None; options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; options.noErrorTruncation = true; options.skipDefaultLibCheck = true; - if (settingsCallback) { - settingsCallback(null); - } - const newLine = "\r\n"; + currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); // Parse settings - setCompilerOptionsFromHarnessSetting(this.settings, options); + let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); + if (harnessSettings) { + setCompilerOptionsFromHarnessSetting(harnessSettings, options); + } + if (options.useCaseSensitiveFileNames !== undefined) { + useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; + } + const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const inputFilesWiithPath = inputFiles.map(f => { + return { unitName: f.unitName, content: f.content, path: ts.toPath(f.unitName, currentDirectory, getCanonicalFileName) }; + }); + const otherFilesWithPath = otherFiles.map(f => { + return { unitName: f.unitName, content: f.content, path: ts.toPath(f.unitName, currentDirectory, getCanonicalFileName) }; + }); // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. // Treat them as library files, so include them in build, but not in baselines. - const includeBuiltFiles: { unitName: string; content: string }[] = []; + const includeBuiltFiles: TestFileWithPath[] = []; if (options.includeBuiltFile) { const builtFileName = libFolder + options.includeBuiltFile; - includeBuiltFiles.push({ unitName: builtFileName, content: normalizeLineEndings(IO.readFile(builtFileName), newLine) }); + const builtFile: TestFileWithPath = { + unitName: builtFileName, + content: normalizeLineEndings(IO.readFile(builtFileName), newLine), + path: ts.toPath(builtFileName, currentDirectory, getCanonicalFileName) + }; + includeBuiltFiles.push(builtFile); } - const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames(); - const fileOutputs: GeneratedFile[] = []; const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); const compilerHost = createCompilerHost( - inputFiles.concat(includeBuiltFiles).concat(otherFiles), + inputFilesWiithPath.concat(includeBuiltFiles).concat(otherFilesWithPath), (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }), options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); const program = ts.createProgram(programFiles, options, compilerHost); @@ -1130,40 +1102,35 @@ namespace Harness { const emitResult = program.emit(); const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); - this.lastErrors = errors; const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); - onComplete(result, program); - - return options; + return { result, program, options }; } - public compileDeclarationFiles(inputFiles: { unitName: string; content: string; }[], - otherFiles: { unitName: string; content: string; }[], + export function compileDeclarationFiles(inputFiles: TestFile[], + otherFiles: TestFile[], result: CompilerResult, - settingsCallback?: (settings: ts.CompilerOptions) => void, - options?: ts.CompilerOptions, + harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions, + options: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory?: string) { + currentDirectory: string) { if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) { throw new Error("There were no errors and declFiles generated did not match number of js files generated"); } - const declInputFiles: { unitName: string; content: string }[] = []; - const declOtherFiles: { unitName: string; content: string }[] = []; - let declResult: Harness.Compiler.CompilerResult; + const declInputFiles: TestFile[] = []; + const declOtherFiles: TestFile[] = []; // if the .d.ts is non-empty, confirm it compiles correctly as well if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) { ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); - this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) { declResult = compileResult; }, - settingsCallback, options, currentDirectory); + const output = this.compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory); - return { declInputFiles, declOtherFiles, declResult }; + return { declInputFiles, declOtherFiles, declResult: output.result }; } - function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) { + function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { if (isDTS(file.unitName)) { dtsFiles.push(file); } @@ -1200,7 +1167,7 @@ namespace Harness { return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); } - function findUnit(fileName: string, units: { unitName: string; content: string; }[]) { + function findUnit(fileName: string, units: TestFile[]) { return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined); } } @@ -1230,7 +1197,7 @@ namespace Harness { return errorOutput; } - export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) { + export function getErrorBaseline(inputFiles: TestFile[], diagnostics: ts.Diagnostic[]) { diagnostics.sort(ts.compareDiagnostics); const outputLines: string[] = []; // Count up all errors that were found in files other than lib.d.ts so we don't miss any @@ -1371,16 +1338,6 @@ namespace Harness { } } - /** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */ - let harnessCompiler: HarnessCompiler; - - /** Returns the singleton harness compiler instance for generating and running tests. - If required a fresh compiler instance will be created, otherwise the existing singleton will be re-used. - */ - export function getCompiler() { - return harnessCompiler = harnessCompiler || new HarnessCompiler(); - } - // This does not need to exist strictly speaking, but many tests will need to be updated if it's removed export function compileString(code: string, unitName: string, callback: (result: CompilerResult) => void) { // NEWTODO: Re-implement 'compileString' @@ -1711,12 +1668,9 @@ namespace Harness { return filePath.indexOf(Harness.libFolder) === 0; } - export function getDefaultLibraryFile(io: Harness.IO): { unitName: string, content: string } { + export function getDefaultLibraryFile(io: Harness.IO): Harness.Compiler.TestFile { const libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts"; - return { - unitName: libFile, - content: io.readFile(libFile) - }; + return { unitName: libFile, content: io.readFile(libFile) }; } if (Error) (Error).stackTraceLimit = 1; diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index f48822f1220..dc6cbfac646 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -349,7 +349,7 @@ class ProjectRunner extends RunnerBase { const inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(), sourceFile => sourceFile.fileName !== "lib.d.ts"), sourceFile => { - return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text }; + return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text, }; }); return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors); diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index a350eda08f3..fc1397b294c 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -27,8 +27,8 @@ namespace RWC { export function runRWCTest(jsonPath: string) { describe("Testing a RWC project: " + jsonPath, () => { - let inputFiles: { unitName: string; content: string; }[] = []; - let otherFiles: { unitName: string; content: string; }[] = []; + let inputFiles: Harness.Compiler.TestFile[] = []; + let otherFiles: Harness.Compiler.TestFile[] = []; let compilerResult: Harness.Compiler.CompilerResult; let compilerOptions: ts.CompilerOptions; let baselineOpts: Harness.Baseline.BaselineOptions = { @@ -55,7 +55,6 @@ namespace RWC { }); it("can compile", () => { - const harnessCompiler = Harness.Compiler.getCompiler(); let opts: ts.ParsedCommandLine; const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath)); @@ -71,8 +70,6 @@ namespace RWC { }); runWithIOLog(ioLog, oldIO => { - harnessCompiler.reset(); - let fileNames = opts.fileNames; const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined); @@ -128,17 +125,21 @@ namespace RWC { opts.options.noLib = true; // Emit the results - compilerOptions = harnessCompiler.compileFiles( + compilerOptions = null; + const output = Harness.Compiler.HarnessCompiler.compileFiles( inputFiles, otherFiles, - newCompilerResults => { compilerResult = newCompilerResults; }, - /*settingsCallback*/ undefined, opts.options, + /* harnessOptions */ undefined, + opts.options, // Since each RWC json file specifies its current directory in its json file, we need // to pass this information in explicitly instead of acquiring it from the process. currentDirectory); + + compilerOptions = output.options; + compilerResult = output.result; }); - function getHarnessCompilerInputUnit(fileName: string) { + function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile { const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)); let content: string = null; try { @@ -201,8 +202,9 @@ namespace RWC { it("has the expected errors in generated declaration files", () => { if (compilerOptions.declaration && !compilerResult.errors.length) { Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => { - const declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult, - /*settingscallback*/ undefined, compilerOptions, currentDirectory); + const declFileCompilationResult = Harness.Compiler.HarnessCompiler.compileDeclarationFiles( + inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory); + if (declFileCompilationResult.declResult.errors.length === 0) { return null; } diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index f25e0c79b63..859f10dc4cc 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -5,9 +5,9 @@ class Test262BaselineRunner extends RunnerBase { private static basePath = "internal/cases/test262"; private static helpersFilePath = "tests/cases/test262-harness/helpers.d.ts"; - private static helperFile = { + private static helperFile: Harness.Compiler.TestFile = { unitName: Test262BaselineRunner.helpersFilePath, - content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath) + content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath), }; private static testFileExtensionRegex = /\.js$/; private static options: ts.CompilerOptions = { @@ -31,7 +31,7 @@ class Test262BaselineRunner extends RunnerBase { let testState: { filename: string; compilerResult: Harness.Compiler.CompilerResult; - inputFiles: { unitName: string; content: string }[]; + inputFiles: Harness.Compiler.TestFile[]; program: ts.Program; }; @@ -40,8 +40,9 @@ class Test262BaselineRunner extends RunnerBase { const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); - const inputFiles = testCaseContent.testUnitData.map(unit => { - return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content }; + const inputFiles: Harness.Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => { + const unitName = Test262BaselineRunner.getTestFilePath(unit.name); + return { unitName, content: unit.content }; }); // Emit the results @@ -52,10 +53,15 @@ class Test262BaselineRunner extends RunnerBase { program: undefined, }; - Harness.Compiler.getCompiler().compileFiles([Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], (compilerResult, program) => { - testState.compilerResult = compilerResult; - testState.program = program; - }, /*settingsCallback*/ undefined, Test262BaselineRunner.options); + const output = Harness.Compiler.HarnessCompiler.compileFiles( + [Test262BaselineRunner.helperFile].concat(inputFiles), + /*otherFiles*/ [], + /* harnessOptions */ undefined, + Test262BaselineRunner.options, + /* currentDirectory */ undefined + ); + testState.compilerResult = output.result; + testState.program = output.program; }); after(() => { From 581f52a7ea72fbce77adfa432cf4cd2a3f983729 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 13:33:54 -0800 Subject: [PATCH 39/44] exhaustive tests --- .../typeGuards/typeGuardTypeOfUndefined.ts | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts index 50612449145..766c5ed8ca2 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts @@ -4,6 +4,12 @@ function test1(a: any) { if (typeof a === "boolean") { a; } + else { + a; + } + } + else { + a; } } @@ -12,6 +18,12 @@ function test2(a: any) { if (typeof a === "boolean") { a; } + else { + a; + } + } + else { + a; } } @@ -19,10 +31,154 @@ function test3(a: any) { if (typeof a === "undefined" || typeof a === "boolean") { a; } + else { + a; + } } function test4(a: any) { if (typeof a !== "undefined" && typeof a === "boolean") { a; } + else { + a; + } +} + +function test5(a: boolean | void) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test6(a: boolean | void) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test7(a: boolean | void) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test8(a: boolean | void) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test9(a: boolean | number) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test10(a: boolean | number) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test11(a: boolean | number) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test12(a: boolean | number) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test13(a: boolean | number | void) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test14(a: boolean | number | void) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test15(a: boolean | number | void) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test16(a: boolean | number | void) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } } From 16d80ebe715e06e20b226d083b492a973e52c4cb Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 14:08:26 -0800 Subject: [PATCH 40/44] ignore undefined type guards --- src/compiler/checker.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6f5a3e67d0a..0a5525edaaf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6479,6 +6479,10 @@ namespace ts { assumeTrue = !assumeTrue; } const typeInfo = primitiveTypeInfo[right.text]; + // Don't narrow `undefined` + if (typeInfo && typeInfo.type === undefinedType) { + return type; + } // If the type to be narrowed is any and we're checking a primitive with assumeTrue=true, return the primitive if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) { return typeInfo.type; From d7ddcc47563aa8f2024b8a81b0bd5f830c42483d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 14:09:13 -0800 Subject: [PATCH 41/44] accept baselines for new test --- .../reference/typeGuardTypeOfUndefined.js | 357 ++++++++++++++ .../typeGuardTypeOfUndefined.symbols | 330 +++++++++++++ .../reference/typeGuardTypeOfUndefined.types | 434 ++++++++++++++++++ 3 files changed, 1121 insertions(+) create mode 100644 tests/baselines/reference/typeGuardTypeOfUndefined.js create mode 100644 tests/baselines/reference/typeGuardTypeOfUndefined.symbols create mode 100644 tests/baselines/reference/typeGuardTypeOfUndefined.types diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.js b/tests/baselines/reference/typeGuardTypeOfUndefined.js new file mode 100644 index 00000000000..a24ff2ec0dc --- /dev/null +++ b/tests/baselines/reference/typeGuardTypeOfUndefined.js @@ -0,0 +1,357 @@ +//// [typeGuardTypeOfUndefined.ts] +// undefined type guard adds no new type information +function test1(a: any) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test2(a: any) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test3(a: any) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test4(a: any) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test5(a: boolean | void) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test6(a: boolean | void) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test7(a: boolean | void) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test8(a: boolean | void) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test9(a: boolean | number) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test10(a: boolean | number) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test11(a: boolean | number) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test12(a: boolean | number) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test13(a: boolean | number | void) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test14(a: boolean | number | void) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} + +function test15(a: boolean | number | void) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} + +function test16(a: boolean | number | void) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} + + +//// [typeGuardTypeOfUndefined.js] +// undefined type guard adds no new type information +function test1(a) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test2(a) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test3(a) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} +function test4(a) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} +function test5(a) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test6(a) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test7(a) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} +function test8(a) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} +function test9(a) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test10(a) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test11(a) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} +function test12(a) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} +function test13(a) { + if (typeof a !== "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test14(a) { + if (typeof a === "undefined") { + if (typeof a === "boolean") { + a; + } + else { + a; + } + } + else { + a; + } +} +function test15(a) { + if (typeof a === "undefined" || typeof a === "boolean") { + a; + } + else { + a; + } +} +function test16(a) { + if (typeof a !== "undefined" && typeof a === "boolean") { + a; + } + else { + a; + } +} diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.symbols b/tests/baselines/reference/typeGuardTypeOfUndefined.symbols new file mode 100644 index 00000000000..d6d36223fe4 --- /dev/null +++ b/tests/baselines/reference/typeGuardTypeOfUndefined.symbols @@ -0,0 +1,330 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts === +// undefined type guard adds no new type information +function test1(a: any) { +>test1 : Symbol(test1, Decl(typeGuardTypeOfUndefined.ts, 0, 0)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + + if (typeof a !== "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15)) + } +} + +function test2(a: any) { +>test2 : Symbol(test2, Decl(typeGuardTypeOfUndefined.ts, 13, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + + if (typeof a === "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15)) + } +} + +function test3(a: any) { +>test3 : Symbol(test3, Decl(typeGuardTypeOfUndefined.ts, 27, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15)) + + if (typeof a === "undefined" || typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15)) + } +} + +function test4(a: any) { +>test4 : Symbol(test4, Decl(typeGuardTypeOfUndefined.ts, 36, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15)) + + if (typeof a !== "undefined" && typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15)) + } +} + +function test5(a: boolean | void) { +>test5 : Symbol(test5, Decl(typeGuardTypeOfUndefined.ts, 45, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + + if (typeof a !== "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15)) + } +} + +function test6(a: boolean | void) { +>test6 : Symbol(test6, Decl(typeGuardTypeOfUndefined.ts, 59, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + + if (typeof a === "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15)) + } +} + +function test7(a: boolean | void) { +>test7 : Symbol(test7, Decl(typeGuardTypeOfUndefined.ts, 73, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15)) + + if (typeof a === "undefined" || typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15)) + } +} + +function test8(a: boolean | void) { +>test8 : Symbol(test8, Decl(typeGuardTypeOfUndefined.ts, 82, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15)) + + if (typeof a !== "undefined" && typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15)) + } +} + +function test9(a: boolean | number) { +>test9 : Symbol(test9, Decl(typeGuardTypeOfUndefined.ts, 91, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + + if (typeof a !== "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15)) + } +} + +function test10(a: boolean | number) { +>test10 : Symbol(test10, Decl(typeGuardTypeOfUndefined.ts, 105, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + + if (typeof a === "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16)) + } +} + +function test11(a: boolean | number) { +>test11 : Symbol(test11, Decl(typeGuardTypeOfUndefined.ts, 119, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16)) + + if (typeof a === "undefined" || typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16)) + } +} + +function test12(a: boolean | number) { +>test12 : Symbol(test12, Decl(typeGuardTypeOfUndefined.ts, 128, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16)) + + if (typeof a !== "undefined" && typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16)) + } +} + +function test13(a: boolean | number | void) { +>test13 : Symbol(test13, Decl(typeGuardTypeOfUndefined.ts, 137, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + + if (typeof a !== "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16)) + } +} + +function test14(a: boolean | number | void) { +>test14 : Symbol(test14, Decl(typeGuardTypeOfUndefined.ts, 151, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + + if (typeof a === "undefined") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + + if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + } + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16)) + } +} + +function test15(a: boolean | number | void) { +>test15 : Symbol(test15, Decl(typeGuardTypeOfUndefined.ts, 165, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16)) + + if (typeof a === "undefined" || typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16)) + } +} + +function test16(a: boolean | number | void) { +>test16 : Symbol(test16, Decl(typeGuardTypeOfUndefined.ts, 174, 1)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16)) + + if (typeof a !== "undefined" && typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16)) +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16)) + + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16)) + } + else { + a; +>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16)) + } +} + diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.types b/tests/baselines/reference/typeGuardTypeOfUndefined.types new file mode 100644 index 00000000000..6cf57e1a1dd --- /dev/null +++ b/tests/baselines/reference/typeGuardTypeOfUndefined.types @@ -0,0 +1,434 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts === +// undefined type guard adds no new type information +function test1(a: any) { +>test1 : (a: any) => void +>a : any + + if (typeof a !== "undefined") { +>typeof a !== "undefined" : boolean +>typeof a : string +>a : any +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : any +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : any + } + } + else { + a; +>a : any + } +} + +function test2(a: any) { +>test2 : (a: any) => void +>a : any + + if (typeof a === "undefined") { +>typeof a === "undefined" : boolean +>typeof a : string +>a : any +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : any +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : any + } + } + else { + a; +>a : any + } +} + +function test3(a: any) { +>test3 : (a: any) => void +>a : any + + if (typeof a === "undefined" || typeof a === "boolean") { +>typeof a === "undefined" || typeof a === "boolean" : boolean +>typeof a === "undefined" : boolean +>typeof a : string +>a : any +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : any +>"boolean" : string + + a; +>a : any + } + else { + a; +>a : any + } +} + +function test4(a: any) { +>test4 : (a: any) => void +>a : any + + if (typeof a !== "undefined" && typeof a === "boolean") { +>typeof a !== "undefined" && typeof a === "boolean" : boolean +>typeof a !== "undefined" : boolean +>typeof a : string +>a : any +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : any +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : any + } +} + +function test5(a: boolean | void) { +>test5 : (a: boolean | void) => void +>a : boolean | void + + if (typeof a !== "undefined") { +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | void +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : void + } + } + else { + a; +>a : boolean | void + } +} + +function test6(a: boolean | void) { +>test6 : (a: boolean | void) => void +>a : boolean | void + + if (typeof a === "undefined") { +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | void +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : void + } + } + else { + a; +>a : boolean | void + } +} + +function test7(a: boolean | void) { +>test7 : (a: boolean | void) => void +>a : boolean | void + + if (typeof a === "undefined" || typeof a === "boolean") { +>typeof a === "undefined" || typeof a === "boolean" : boolean +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | void +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | void +>"boolean" : string + + a; +>a : boolean | void + } + else { + a; +>a : void + } +} + +function test8(a: boolean | void) { +>test8 : (a: boolean | void) => void +>a : boolean | void + + if (typeof a !== "undefined" && typeof a === "boolean") { +>typeof a !== "undefined" && typeof a === "boolean" : boolean +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | void +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : boolean | void + } +} + +function test9(a: boolean | number) { +>test9 : (a: boolean | number) => void +>a : boolean | number + + if (typeof a !== "undefined") { +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | number +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : number + } + } + else { + a; +>a : boolean | number + } +} + +function test10(a: boolean | number) { +>test10 : (a: boolean | number) => void +>a : boolean | number + + if (typeof a === "undefined") { +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | number +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : number + } + } + else { + a; +>a : boolean | number + } +} + +function test11(a: boolean | number) { +>test11 : (a: boolean | number) => void +>a : boolean | number + + if (typeof a === "undefined" || typeof a === "boolean") { +>typeof a === "undefined" || typeof a === "boolean" : boolean +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | number +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number +>"boolean" : string + + a; +>a : boolean | number + } + else { + a; +>a : number + } +} + +function test12(a: boolean | number) { +>test12 : (a: boolean | number) => void +>a : boolean | number + + if (typeof a !== "undefined" && typeof a === "boolean") { +>typeof a !== "undefined" && typeof a === "boolean" : boolean +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | number +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : boolean | number + } +} + +function test13(a: boolean | number | void) { +>test13 : (a: boolean | number | void) => void +>a : boolean | number | void + + if (typeof a !== "undefined") { +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | number | void +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : number | void + } + } + else { + a; +>a : boolean | number | void + } +} + +function test14(a: boolean | number | void) { +>test14 : (a: boolean | number | void) => void +>a : boolean | number | void + + if (typeof a === "undefined") { +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | number | void +>"undefined" : string + + if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : number | void + } + } + else { + a; +>a : boolean | number | void + } +} + +function test15(a: boolean | number | void) { +>test15 : (a: boolean | number | void) => void +>a : boolean | number | void + + if (typeof a === "undefined" || typeof a === "boolean") { +>typeof a === "undefined" || typeof a === "boolean" : boolean +>typeof a === "undefined" : boolean +>typeof a : string +>a : boolean | number | void +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number | void +>"boolean" : string + + a; +>a : boolean | number | void + } + else { + a; +>a : number | void + } +} + +function test16(a: boolean | number | void) { +>test16 : (a: boolean | number | void) => void +>a : boolean | number | void + + if (typeof a !== "undefined" && typeof a === "boolean") { +>typeof a !== "undefined" && typeof a === "boolean" : boolean +>typeof a !== "undefined" : boolean +>typeof a : string +>a : boolean | number | void +>"undefined" : string +>typeof a === "boolean" : boolean +>typeof a : string +>a : boolean | number | void +>"boolean" : string + + a; +>a : boolean + } + else { + a; +>a : boolean | number | void + } +} + From 07626cbe895308c6154d44352fe3b26cf01248fc Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 13 Nov 2015 14:26:48 -0800 Subject: [PATCH 42/44] do not crash if overloads cannot be merged under one symbol --- src/compiler/checker.ts | 12 ++++--- ...edStaticAndInstanceClassMembers.errors.txt | 27 +++++++++++++++ .../mixedStaticAndInstanceClassMembers.js | 34 +++++++++++++++++++ ...nMergedDeclarationsAndOverloads.errors.txt | 23 +++++++++++++ .../nonMergedDeclarationsAndOverloads.js | 19 +++++++++++ .../mixedStaticAndInstanceClassMembers.ts | 15 ++++++++ .../nonMergedDeclarationsAndOverloads.ts | 8 +++++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt create mode 100644 tests/baselines/reference/mixedStaticAndInstanceClassMembers.js create mode 100644 tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt create mode 100644 tests/baselines/reference/nonMergedDeclarationsAndOverloads.js create mode 100644 tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts create mode 100644 tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ec91b255ae6..ec62d80ed59 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11352,11 +11352,15 @@ namespace ts { const errorNode: Node = (subsequentNode).name || subsequentNode; // TODO(jfreeman): These are methods, so handle computed name case if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) { - // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature); - Debug.assert((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)); - const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; - error(errorNode, diagnostic); + // we can get here in two cases + // 1. mixed static and instance class members + // 2. something with the same name was defined before the set of overloads that prevents them from merging + // here we'll report error only for the first case since for second we should already report error in binder + if ((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)) { + const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; + error(errorNode, diagnostic); + } return; } else if (nodeIsPresent((subsequentNode).body)) { diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt new file mode 100644 index 00000000000..d52b17a58a0 --- /dev/null +++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(4,5): error TS2387: Function overload must be static. +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(12,12): error TS2388: Function overload must not be static. +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(13,5): error TS2387: Function overload must be static. + + +==== tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts (3 errors) ==== + class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + ~~ +!!! error TS2387: Function overload must be static. + m1 (a: any): void { + } + } + + class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + ~~ +!!! error TS2388: Function overload must not be static. + m1 (a: any): void { + ~~ +!!! error TS2387: Function overload must be static. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js new file mode 100644 index 00000000000..427bbf65aa1 --- /dev/null +++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js @@ -0,0 +1,34 @@ +//// [mixedStaticAndInstanceClassMembers.ts] +class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + m1 (a: any): void { + } +} + +//// [mixedStaticAndInstanceClassMembers.js] +var A = (function () { + function A() { + } + A.prototype.f = function () { }; + A.prototype.m1 = function (a) { + }; + return A; +})(); +var B = (function () { + function B() { + } + B.prototype.f = function () { }; + B.prototype.m1 = function (a) { + }; + return B; +})(); diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt new file mode 100644 index 00000000000..252cd6880d4 --- /dev/null +++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(2,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(4,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(5,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(6,5): error TS2300: Duplicate identifier 'm1'. + + +==== tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts (4 errors) ==== + class A { + m1: string; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + f() {} + m1 (a: string): void; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + m1 (a: number): void; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + m1 (a: any): void { + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js new file mode 100644 index 00000000000..3ca6a963515 --- /dev/null +++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js @@ -0,0 +1,19 @@ +//// [nonMergedDeclarationsAndOverloads.ts] +class A { + m1: string; + f() {} + m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +//// [nonMergedDeclarationsAndOverloads.js] +var A = (function () { + function A() { + } + A.prototype.f = function () { }; + A.prototype.m1 = function (a) { + }; + return A; +})(); diff --git a/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts new file mode 100644 index 00000000000..6395813b658 --- /dev/null +++ b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts @@ -0,0 +1,15 @@ +class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + m1 (a: any): void { + } +} \ No newline at end of file diff --git a/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts new file mode 100644 index 00000000000..6ec4c6076f2 --- /dev/null +++ b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts @@ -0,0 +1,8 @@ +class A { + m1: string; + f() {} + m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} \ No newline at end of file From 50aab7a05fc79ba29116b19311bca10e112675dd Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 13 Nov 2015 15:10:16 -0800 Subject: [PATCH 43/44] fix typo --- src/harness/harness.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 468517b68f7..aa70087ea31 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1069,7 +1069,7 @@ namespace Harness { useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; } const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - const inputFilesWiithPath = inputFiles.map(f => { + const inputFilesWithPath = inputFiles.map(f => { return { unitName: f.unitName, content: f.content, path: ts.toPath(f.unitName, currentDirectory, getCanonicalFileName) }; }); const otherFilesWithPath = otherFiles.map(f => { @@ -1094,7 +1094,7 @@ namespace Harness { const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); const compilerHost = createCompilerHost( - inputFilesWiithPath.concat(includeBuiltFiles).concat(otherFilesWithPath), + inputFilesWithPath.concat(includeBuiltFiles).concat(otherFilesWithPath), (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }), options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); const program = ts.createProgram(programFiles, options, compilerHost); From e41bfd1ccc753957b94b252ef62b98b011a99d0e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 17:43:53 -0800 Subject: [PATCH 44/44] fix many lints --- src/compiler/checker.ts | 18 +++++----- src/compiler/core.ts | 2 +- src/compiler/emitter.ts | 56 ++++++++++++++++---------------- src/compiler/parser.ts | 44 ++++++++++++------------- src/compiler/program.ts | 14 ++++---- src/compiler/scanner.ts | 4 +-- src/harness/compilerRunner.ts | 10 +++--- src/harness/fourslash.ts | 16 ++++----- src/harness/harness.ts | 6 ++-- src/harness/loggedIO.ts | 2 +- src/harness/sourceMapRecorder.ts | 2 +- src/server/editorServices.ts | 6 ++-- src/server/session.ts | 2 +- 13 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d9efda2003..7f5f73a58db 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -122,8 +122,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, false, false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, false, false); + const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const globals: SymbolTable = {}; @@ -2276,7 +2276,7 @@ namespace ts { return false; } resolutionTargets.push(target); - resolutionResults.push(true); + resolutionResults.push(/*items*/ true); resolutionPropertyNames.push(propertyName); return true; } @@ -3348,7 +3348,7 @@ namespace ts { function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { if (!hasClassBaseType(classType)) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, false, false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); @@ -3973,7 +3973,7 @@ namespace ts { } function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature { - return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true); + return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true); } function getErasedSignature(signature: Signature): Signature { @@ -3983,7 +3983,7 @@ namespace ts { signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper); } else { - signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true); + signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true); } } return signature.erasedSignatureCache; @@ -5099,7 +5099,7 @@ namespace ts { let result = Ternary.True; const sourceTypes = source.types; for (const sourceType of sourceTypes) { - const related = typeRelatedToSomeType(sourceType, target, false); + const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false); if (!related) { return Ternary.False; } @@ -5497,7 +5497,7 @@ namespace ts { const saveErrorInfo = errorInfo; let related = isRelatedTo(s, t, reportErrors); if (!related) { - related = isRelatedTo(t, s, false); + related = isRelatedTo(t, s, /*reportErrors*/ false); if (!related) { if (reportErrors) { reportError(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, @@ -5624,7 +5624,7 @@ namespace ts { let related: Ternary; if (sourceStringType && sourceNumberType) { // If we know for sure we're testing both string and numeric index types then only report errors from the second one - related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors); + related = isRelatedTo(sourceStringType, targetType, /*reportErrors*/ false) || isRelatedTo(sourceNumberType, targetType, reportErrors); } else { related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c866cf41a92..2092a59a545 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -842,7 +842,7 @@ namespace ts { } export function fail(message?: string): void { - Debug.assert(false, message); + Debug.assert(/*expression*/ false, message); } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2ea8c81c7e2..e4cd57542a7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1292,7 +1292,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCommaList(nodes: Node[]) { if (nodes) { - emitList(nodes, 0, nodes.length, /*multiline*/ false, /*trailingComma*/ false); + emitList(nodes, 0, nodes.length, /*multiLine*/ false, /*trailingComma*/ false); } } @@ -2191,7 +2191,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } else if (languageVersion >= ScriptTarget.ES6 || !forEach(elements, isSpreadElementExpression)) { write("["); - emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces:*/ false); + emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces*/ false); write("]"); } else { @@ -2215,7 +2215,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // then try to preserve the original shape of the object literal. // Otherwise just try to preserve the formatting. if (numElements === properties.length) { - emitLinePreservingList(node, properties, /* allowTrailingComma */ languageVersion >= ScriptTarget.ES5, /* spacesBetweenBraces */ true); + emitLinePreservingList(node, properties, /*allowTrailingComma*/ languageVersion >= ScriptTarget.ES5, /*spacesBetweenBraces*/ true); } else { const multiLine = (node.flags & NodeFlags.MultiLine) !== 0; @@ -2765,7 +2765,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(".bind.apply("); emit(target); write(", [void 0].concat("); - emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiline*/ false, /*trailingComma*/ false, /*useConcat*/ false); + emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ false); write(")))"); write("()"); } @@ -2982,7 +2982,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi synthesizedLHS = createSynthesizedNode(SyntaxKind.ElementAccessExpression, /*startsOnNewLine*/ false); - const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldEmitCommaBeforeAssignment*/ false); + const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); synthesizedLHS.expression = identifier; if (leftHandSideExpression.argumentExpression.kind !== SyntaxKind.NumericLiteral && @@ -3001,7 +3001,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("("); synthesizedLHS = createSynthesizedNode(SyntaxKind.PropertyAccessExpression, /*startsOnNewLine*/ false); - const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldemitCommaBeforeAssignment*/ false); + const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); synthesizedLHS.expression = identifier; (synthesizedLHS).dotToken = leftHandSideExpression.dotToken; @@ -3181,10 +3181,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDoStatementWorker(node: DoStatement, loop: ConvertedLoop) { write("do"); if (loop) { - emitConvertedLoopCall(loop, /* emitAsBlock */ true); + emitConvertedLoopCall(loop, /*emitAsBlock*/ true); } else { - emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true); + emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); } if (node.statement.kind === SyntaxKind.Block) { write(" "); @@ -3207,10 +3207,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(")"); if (loop) { - emitConvertedLoopCall(loop, /* emitAsBlock */ true); + emitConvertedLoopCall(loop, /*emitAsBlock*/ true); } else { - emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true); + emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); } } @@ -3532,8 +3532,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(`switch(${loopResultVariable}) {`); increaseIndent(); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /* isBreak */ true, loopResultVariable, outerLoop); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /* isBreak */ false, loopResultVariable, outerLoop); + emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /*isBreak*/ true, loopResultVariable, outerLoop); + emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /*isBreak*/ false, loopResultVariable, outerLoop); decreaseIndent(); writeLine(); @@ -3597,10 +3597,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(")"); if (loop) { - emitConvertedLoopCall(loop, /* emitAsBlock */ true); + emitConvertedLoopCall(loop, /*emitAsBlock*/ true); } else { - emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true); + emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); } } @@ -3638,10 +3638,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitToken(SyntaxKind.CloseParenToken, node.expression.end); if (loop) { - emitConvertedLoopCall(loop, /* emitAsBlock */ true); + emitConvertedLoopCall(loop, /*emitAsBlock*/ true); } else { - emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true); + emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); } } @@ -3781,10 +3781,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (loop) { writeLine(); - emitConvertedLoopCall(loop, /* emitAsBlock */ false); + emitConvertedLoopCall(loop, /*emitAsBlock*/ false); } else { - emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ false); + emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ false); } writeLine(); @@ -3818,11 +3818,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let labelMarker: string; if (node.kind === SyntaxKind.BreakStatement) { labelMarker = `break-${node.label.text}`; - setLabeledJump(convertedLoopState, /* isBreak */ true, node.label.text, labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); } else { labelMarker = `continue-${node.label.text}`; - setLabeledJump(convertedLoopState, /* isBreak */ false, node.label.text, labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); } write(`return "${labelMarker}";`); } @@ -4248,7 +4248,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let index: Expression; const nameIsComputed = propName.kind === SyntaxKind.ComputedPropertyName; if (nameIsComputed) { - index = ensureIdentifier((propName).expression, /* reuseIdentifierExpression */ false); + index = ensureIdentifier((propName).expression, /*reuseIdentifierExpressions*/ false); } else { // We create a synthetic copy of the identifier in order to avoid the rewriting that might @@ -5380,7 +5380,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitEnd(baseTypeElement); } } - emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ false)); + emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false)); if (ctor) { let statements: Node[] = (ctor.body).statements; if (superCall) { @@ -5502,7 +5502,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // // This keeps the expression as an expression, while ensuring that the static parts // of it have been initialized by the time it is used. - const staticProperties = getInitializedProperties(node, /*static:*/ true); + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression; let tempVariable: Identifier; @@ -5564,7 +5564,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi for (var property of staticProperties) { write(","); writeLine(); - emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true); + emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true); } write(","); writeLine(); @@ -5638,7 +5638,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); emitConstructor(node, baseTypeNode); emitMemberFunctionsForES5AndLower(node); - emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true)); + emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true)); writeLine(); emitDecoratorsOfClass(node); writeLine(); @@ -8094,11 +8094,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi * Emit comments associated with node that will not be emitted into JS file */ function emitCommentsOnNotEmittedNode(node: Node) { - emitLeadingCommentsWorker(node, /*isEmittedNode:*/ false); + emitLeadingCommentsWorker(node, /*isEmittedNode*/ false); } function emitLeadingComments(node: Node) { - return emitLeadingCommentsWorker(node, /*isEmittedNode:*/ true); + return emitLeadingCommentsWorker(node, /*isEmittedNode*/ true); } function emitLeadingCommentsWorker(node: Node, isEmittedNode: boolean) { @@ -8127,7 +8127,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment); + emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); } function emitTrailingComments(node: Node) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ac37f608417..9a72593d3b0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -722,10 +722,10 @@ namespace ts { const contextFlagsToClear = context & contextFlags; if (contextFlagsToClear) { // clear the requested context flags - setContextFlag(false, contextFlagsToClear); + setContextFlag(/*val*/ false, contextFlagsToClear); const result = func(); // restore the context flags we just cleared - setContextFlag(true, contextFlagsToClear); + setContextFlag(/*val*/ true, contextFlagsToClear); return result; } @@ -743,10 +743,10 @@ namespace ts { const contextFlagsToSet = context & ~contextFlags; if (contextFlagsToSet) { // set the requested context flags - setContextFlag(true, contextFlagsToSet); + setContextFlag(/*val*/ true, contextFlagsToSet); const result = func(); // reset the context flags we just set - setContextFlag(false, contextFlagsToSet); + setContextFlag(/*val*/ false, contextFlagsToSet); return result; } @@ -1098,11 +1098,11 @@ namespace ts { } function parsePropertyName(): PropertyName { - return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true); + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } function parseSimplePropertyName(): Identifier | LiteralExpression { - return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ false); + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); } function isSimplePropertyName() { @@ -1385,7 +1385,7 @@ namespace ts { function isInSomeParsingContext(): boolean { for (let kind = 0; kind < ParsingContext.Count; kind++) { if (parsingContext & (1 << kind)) { - if (isListElement(kind, /* inErrorRecovery */ true) || isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { return true; } } @@ -1402,7 +1402,7 @@ namespace ts { result.pos = getNodePos(); while (!isListTerminator(kind)) { - if (isListElement(kind, /* inErrorRecovery */ false)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { const element = parseListElement(kind, parseElement); result.push(element); @@ -1751,7 +1751,7 @@ namespace ts { let commaStart = -1; // Meaning the previous token was not a comma while (true) { - if (isListElement(kind, /* inErrorRecovery */ false)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { result.push(parseListElement(kind, parseElement)); commaStart = scanner.getTokenPos(); if (parseOptional(SyntaxKind.CommaToken)) { @@ -1859,7 +1859,7 @@ namespace ts { // Report that we need an identifier. However, report it right after the dot, // and not on the next token. This is because the next token might actually // be an identifier and the error would be quite confusing. - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken*/ true, Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); } } @@ -2609,7 +2609,7 @@ namespace ts { // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator const saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } let expr = parseAssignmentExpressionOrHigher(); @@ -2619,7 +2619,7 @@ namespace ts { } if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return expr; } @@ -2773,7 +2773,7 @@ namespace ts { node.parameters.pos = parameter.pos; node.parameters.end = parameter.end; - node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>"); + node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>"); node.body = parseArrowFunctionExpressionBody(/*isAsync*/ false); return finishNode(node); @@ -3573,7 +3573,7 @@ namespace ts { parseExpected(SyntaxKind.GreaterThanToken); } else { - parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } node = createNode(SyntaxKind.JsxSelfClosingElement, fullStart); @@ -3609,7 +3609,7 @@ namespace ts { parseExpected(SyntaxKind.CloseBraceToken); } else { - parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*advance*/ false); + parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } @@ -3654,7 +3654,7 @@ namespace ts { parseExpected(SyntaxKind.GreaterThanToken); } else { - parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); @@ -3973,7 +3973,7 @@ namespace ts { // function BindingIdentifier[opt](FormalParameters){ FunctionBody } const saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } const node = createNode(SyntaxKind.FunctionExpression); @@ -3993,7 +3993,7 @@ namespace ts { node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return finishNode(node); @@ -4039,13 +4039,13 @@ namespace ts { // arrow function. The body of the function is not in [Decorator] context. const saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } const block = parseBlock(ignoreMissingOpenBrace, diagnosticMessage); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } setYieldContext(savedYieldContext); @@ -6162,7 +6162,7 @@ namespace ts { if (sourceFile.statements.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setNodeParents*/ true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true); } // Make sure we're not trying to incrementally update a source file more than once. Once @@ -6226,7 +6226,7 @@ namespace ts { // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true); + const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true); return result; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ca0c7d9adaa..86fbc2e6259 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -364,13 +364,13 @@ namespace ts { } if (!tryReuseStructureFromOldProgram()) { - forEach(rootNames, name => processRootFile(name, false)); + forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); // Do not process the default library if: // - The '--noLib' flag is used. // - A 'no-default-lib' reference comment is encountered in // processing the root files. if (!skipDefaultLib) { - processRootFile(host.getDefaultLibFileName(options), true); + processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); } } @@ -693,7 +693,7 @@ namespace ts { let imports: LiteralExpression[]; for (const node of file.statements) { - collect(node, /* allowRelativeModuleNames */ true, /* collectOnlyRequireCalls */ false); + collect(node, /*allowRelativeModuleNames*/ true, /*collectOnlyRequireCalls*/ false); } file.imports = imports || emptyArray; @@ -729,7 +729,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): 12.1.6 // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules // only through top - level external module names. Relative external module names are not permitted. - collect(node, /* allowRelativeModuleNames */ false, collectOnlyRequireCalls); + collect(node, /*allowRelativeModuleNames*/ false, collectOnlyRequireCalls); }); } break; @@ -741,7 +741,7 @@ namespace ts { (imports || (imports = [])).push((node).arguments[0]); } else { - forEachChild(node, node => collect(node, allowRelativeModuleNames, /* collectOnlyRequireCalls */ true)); + forEachChild(node, node => collect(node, allowRelativeModuleNames, /*collectOnlyRequireCalls*/ true)); } } } @@ -862,7 +862,7 @@ namespace ts { function processReferencedFiles(file: SourceFile, basePath: string) { forEach(file.referencedFiles, ref => { const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, /* isDefaultLib */ false, file, ref.pos, ref.end); + processSourceFile(referencedFileName, /*isDefaultLib*/ false, file, ref.pos, ref.end); }); } @@ -880,7 +880,7 @@ namespace ts { const resolution = resolutions[i]; setResolvedModule(file, moduleNames[i], resolution); if (resolution && !options.noResolve) { - const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); + const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); if (importedFile && resolution.isExternalLibraryImport) { if (!isExternalModule(importedFile)) { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 9703ef8517b..4289d910608 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1634,11 +1634,11 @@ namespace ts { } function lookAhead(callback: () => T): T { - return speculationHelper(callback, /*isLookahead:*/ true); + return speculationHelper(callback, /*isLookahead*/ true); } function tryScan(callback: () => T): T { - return speculationHelper(callback, /*isLookahead:*/ false); + return speculationHelper(callback, /*isLookahead*/ false); } function setText(newText: string, start: number, length: number) { diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index d46d0bde08c..fd8b248dfe2 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -182,7 +182,7 @@ class CompilerBaselineRunner extends RunnerBase { const declFileCompilationResult = Harness.Compiler.HarnessCompiler.compileDeclarationFiles( - toBeCompiled, otherFiles, result, harnessSettings, options, /* currentDirectory */ undefined); + toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined); if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) { jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n"; @@ -255,8 +255,8 @@ class CompilerBaselineRunner extends RunnerBase { const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); - const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true); - const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false); + const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); + const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ false); const fullResults: ts.Map = {}; const pullResults: ts.Map = {}; @@ -270,14 +270,14 @@ class CompilerBaselineRunner extends RunnerBase { // The second gives symbols for all identifiers. let e1: Error, e2: Error; try { - checkBaseLines(/*isSymbolBaseLine:*/ false); + checkBaseLines(/*isSymbolBaseLine*/ false); } catch (e) { e1 = e; } try { - checkBaseLines(/*isSymbolBaseLine:*/ true); + checkBaseLines(/*isSymbolBaseLine*/ true); } catch (e) { e2 = e; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 839a4521a29..ebc58096d6f 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -514,7 +514,7 @@ namespace FourSlash { this.scenarioActions.push(``); if (actual !== expected) { - this.printErrorLog(false, errors); + this.printErrorLog(/*expectErrors*/ false, errors); const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; Harness.IO.log(errorMsg); this.raiseError(errorMsg); @@ -567,7 +567,7 @@ namespace FourSlash { public verifyMemberListCount(expectedCount: number, negative: boolean) { if (expectedCount === 0) { if (negative) { - this.verifyMemberListIsEmpty(false); + this.verifyMemberListIsEmpty(/*negative*/ false); return; } else { @@ -1347,7 +1347,7 @@ namespace FourSlash { if (this.enableFormatting) { const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { - offset += this.applyEdits(this.activeFile.fileName, edits, true); + offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); // this.checkPostEditInletiants(); } } @@ -1389,7 +1389,7 @@ namespace FourSlash { if (this.enableFormatting) { const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { - offset += this.applyEdits(this.activeFile.fileName, edits, true); + offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); } } } @@ -1449,7 +1449,7 @@ namespace FourSlash { if (this.enableFormatting) { const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { - offset += this.applyEdits(this.activeFile.fileName, edits, true); + offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); // this.checkPostEditInletiants(); } } @@ -1477,7 +1477,7 @@ namespace FourSlash { if (this.enableFormatting) { const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); if (edits.length) { - offset += this.applyEdits(this.activeFile.fileName, edits, true); + offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.checkPostEditInletiants(); } } @@ -1563,7 +1563,7 @@ namespace FourSlash { this.scenarioActions.push(""); const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions); - this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true); + this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); } @@ -1571,7 +1571,7 @@ namespace FourSlash { this.taoInvalidReason = "formatSelection NYI"; const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions); - this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true); + this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index aa70087ea31..9bc36e257ad 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -628,7 +628,7 @@ namespace Harness { function getResolvedPathFromServer(path: string) { const xhr = new XMLHttpRequest(); try { - xhr.open("GET", path + "?resolve", false); + xhr.open("GET", path + "?resolve", /*async*/ false); xhr.send(); } catch (e) { @@ -647,7 +647,7 @@ namespace Harness { export function getFileFromServerSync(url: string): XHRResponse { const xhr = new XMLHttpRequest(); try { - xhr.open("GET", url, false); + xhr.open("GET", url, /*async*/ false); xhr.send(); } catch (e) { @@ -662,7 +662,7 @@ namespace Harness { const xhr = new XMLHttpRequest(); try { const actionMsg = "?action=" + action; - xhr.open("POST", url + actionMsg, false); + xhr.open("POST", url + actionMsg, /*async*/ false); xhr.setRequestHeader("Access-Control-Allow-Origin", "*"); xhr.send(contents); } diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index bf56f1aa3ea..0bae91f7976 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -174,7 +174,7 @@ namespace Playback { return true; } else { - return findResultByFields(replayLog.fileExists, { path }, false); + return findResultByFields(replayLog.fileExists, { path }, /*defaultValue*/ false); } }) ); diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index ce0a6a6528e..75246a9a266 100644 --- a/src/harness/sourceMapRecorder.ts +++ b/src/harness/sourceMapRecorder.ts @@ -190,7 +190,7 @@ namespace Harness.SourceMapRecoder { return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping }; } - createErrorIfCondition(true, "No encoded entry found"); + createErrorIfCondition(/*condition*/ true, "No encoded entry found"); } export function hasCompletedDecoding() { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 795bd7db732..c3cd65e857b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -388,7 +388,7 @@ namespace ts.server { } openReferencedFile(filename: string) { - return this.projectService.openFile(filename, false); + return this.projectService.openFile(filename, /*openedByClient*/ false); } getRootFiles() { @@ -1068,7 +1068,7 @@ namespace ts.server { */ openClientFile(fileName: string, fileContent?: string) { this.openOrUpdateConfiguredProjectForFile(fileName); - const info = this.openFile(fileName, true, fileContent); + const info = this.openFile(fileName, /*openedByClient*/ true, fileContent); this.addOpenFile(info); this.printProjects(); return info; @@ -1277,7 +1277,7 @@ namespace ts.server { for (const fileName of fileNamesToAdd) { let info = this.getScriptInfo(fileName); if (!info) { - info = this.openFile(fileName, false); + info = this.openFile(fileName, /*openedByClient*/ false); } else { // if the root file was opened by client, it would belong to either diff --git a/src/server/session.ts b/src/server/session.ts index f04f73f644c..dae2384ce54 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -901,7 +901,7 @@ namespace ts.server { } getDiagnosticsForProject(delay: number, fileName: string) { - const { configFileName, fileNames } = this.getProjectInfo(fileName, true); + const { configFileName, fileNames } = this.getProjectInfo(fileName, /*needFileNameList*/ true); // No need to analyze lib.d.ts let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0);